From f64269892111ba2ada330ed7c0afe2ccbbf1410d Mon Sep 17 00:00:00 2001 From: Andrei Kvapil Date: Sun, 10 Dec 2023 20:09:43 +0100 Subject: [PATCH] Preapare release v0.0.1 Signed-off-by: Andrei Kvapil --- .dockerignore | 1 + .gitignore | 1 + LICENSE | 201 + Makefile | 15 + README.md | 560 + dashboards/.gitignore | 1 + dashboards/cache/nginx-vts-stats.json | 3038 +++ .../control-plane/control-plane-status.json | 2571 +++ .../control-plane/deprecated-resources.json | 611 + dashboards/control-plane/dns-coredns.json | 5638 +++++ dashboards/control-plane/kube-etcd3.json | 1602 ++ dashboards/db/cloudnativepg.json | 6320 ++++++ dashboards/db/maria-db.json | 4436 ++++ dashboards/db/redis.json | 1659 ++ dashboards/dotdc/k8s-system-coredns.json | 1558 ++ dashboards/dotdc/k8s-views-global.json | 2943 +++ dashboards/dotdc/k8s-views-namespaces.json | 2260 ++ dashboards/dotdc/k8s-views-pods.json | 2594 +++ dashboards/ingress/controller-detail.json | 10221 +++++++++ dashboards/ingress/controllers.json | 9524 ++++++++ dashboards/ingress/namespace-detail.json | 10382 +++++++++ dashboards/ingress/namespaces.json | 8270 +++++++ dashboards/ingress/vhost-detail.json | 10247 +++++++++ dashboards/ingress/vhosts.json | 8311 +++++++ dashboards/main/capacity-planning.json | 2474 +++ dashboards/main/controller.json | 4353 ++++ dashboards/main/namespace.json | 4266 ++++ dashboards/main/namespaces.json | 3812 ++++ dashboards/main/node.json | 13341 +++++++++++ dashboards/main/nodes.json | 1942 ++ dashboards/main/ntp.json | 1271 ++ dashboards/main/pod.json | 4473 ++++ dashboards/main/volumes.json | 492 + .../victoria-metrics/backupmanager.json | 1756 ++ dashboards/victoria-metrics/operator.json | 1362 ++ .../victoriametrics-cluster.json | 9066 ++++++++ .../victoria-metrics/victoriametrics.json | 5587 +++++ dashboards/victoria-metrics/vmagent.json | 6154 ++++++ dashboards/victoria-metrics/vmalert.json | 3260 +++ hack/download-dashboards.sh | 112 + hack/gen_versions_map.sh | 31 + img/cozystack-logo.svg | 51 + manifests/cozystack-installer.yaml | 94 + packages/apps/Makefile | 20 + packages/apps/http-cache/.helmignore | 23 + packages/apps/http-cache/Chart.yaml | 25 + packages/apps/http-cache/Makefile | 35 + packages/apps/http-cache/README.md | 57 + .../apps/http-cache/images/nginx-cache.json | 14 + .../apps/http-cache/images/nginx-cache.tag | 1 + .../http-cache/images/nginx-cache/Dockerfile | 178 + .../images/nginx-cache/nginx-reloader.sh | 13 + .../templates/haproxy/configmap.yaml | 106 + .../templates/haproxy/deployment.yaml | 45 + .../http-cache/templates/haproxy/service.yaml | 21 + .../http-cache/templates/nginx/configmap.yaml | 162 + .../templates/nginx/deployment.yaml | 140 + .../templates/nginx/nginx-scrape.yaml | 26 + packages/apps/http-cache/values.yaml | 9 + packages/apps/kubernetes/.helmignore | 23 + packages/apps/kubernetes/Chart.yaml | 25 + packages/apps/kubernetes/Makefile | 18 + packages/apps/kubernetes/README.md | 28 + .../images/ubuntu-container-disk.json | 4 + .../images/ubuntu-container-disk.tag | 1 + .../images/ubuntu-container-disk/Dockerfile | 51 + packages/apps/kubernetes/templates/NOTES.txt | 3 + .../apps/kubernetes/templates/_helpers.tpl | 51 + .../kubernetes/templates/cloud-config.yaml | 10 + .../cluster-autoscaler/deployment.yaml | 86 + .../apps/kubernetes/templates/cluster.yaml | 150 + .../apps/kubernetes/templates/csi/deploy.yaml | 126 + .../csi/infra-cluster-service-account.yaml | 32 + .../templates/helmreleases/cilium.yaml | 46 + .../templates/helmreleases/csi.yaml | 28 + .../templates/helmreleases/delete.yaml | 73 + .../templates/kccm/kccm_cluster_role.yaml | 11 + .../kccm/kccm_cluster_role_binding.yaml | 12 + .../kubernetes/templates/kccm/kccm_role.yaml | 42 + .../templates/kccm/kccm_role_binding.yaml | 27 + .../kubernetes/templates/kccm/manager.yaml | 49 + .../templates/kccm/service_account.yaml | 4 + packages/apps/kubernetes/values.schema.json | 11 + packages/apps/kubernetes/values.yaml | 1 + packages/apps/mysql/.helmignore | 23 + packages/apps/mysql/Chart.yaml | 25 + packages/apps/mysql/README.md | 64 + packages/apps/mysql/templates/.gitkeep | 0 .../apps/mysql/templates/backup-cronjob.yaml | 94 + .../apps/mysql/templates/backup-script.yaml | 50 + .../apps/mysql/templates/backup-secret.yaml | 11 + packages/apps/mysql/templates/config.yaml | 35 + packages/apps/mysql/templates/db.yaml | 14 + packages/apps/mysql/templates/mariadb.yaml | 71 + packages/apps/mysql/templates/regsecret.yaml | 10 + packages/apps/mysql/templates/secret.yaml | 9 + packages/apps/mysql/templates/user.yaml | 31 + packages/apps/mysql/values.yaml | 30 + packages/apps/postgres/.helmignore | 23 + packages/apps/postgres/Chart.yaml | 25 + packages/apps/postgres/README.md | 32 + packages/apps/postgres/templates/.gitkeep | 0 .../postgres/templates/backup-cronjob.yaml | 101 + .../postgres/templates/backup-script.yaml | 50 + .../postgres/templates/backup-secret.yaml | 11 + packages/apps/postgres/templates/db.yaml | 18 + .../apps/postgres/templates/external-svc.yaml | 18 + .../apps/postgres/templates/init-job.yaml | 66 + .../apps/postgres/templates/init-script.yaml | 127 + .../apps/postgres/templates/regsecret.yaml | 10 + packages/apps/postgres/values.yaml | 39 + packages/apps/rabbitmq/.helmignore | 23 + packages/apps/rabbitmq/Chart.yaml | 25 + packages/apps/rabbitmq/README.md | 10 + .../apps/rabbitmq/templates/rabbitmq.yaml | 13 + packages/apps/rabbitmq/values.schema.json | 10 + packages/apps/rabbitmq/values.yaml | 1 + packages/apps/redis/.helmignore | 23 + packages/apps/redis/Chart.yaml | 25 + packages/apps/redis/README.md | 10 + .../apps/redis/templates/redisfailover.yaml | 52 + packages/apps/redis/templates/service.yaml | 25 + .../apps/redis/templates/servicescrape.yaml | 46 + packages/apps/redis/values.schema.json | 14 + packages/apps/redis/values.yaml | 2 + packages/apps/tcp-balancer/.helmignore | 23 + packages/apps/tcp-balancer/Chart.yaml | 25 + packages/apps/tcp-balancer/README.md | 9 + .../tcp-balancer/templates/configmap.yaml | 122 + .../tcp-balancer/templates/deployment.yaml | 55 + .../apps/tcp-balancer/templates/service.yaml | 37 + packages/apps/tcp-balancer/values.yaml | 18 + packages/apps/tenant/Chart.yaml | 7 + packages/apps/tenant/README.md | 47 + packages/apps/tenant/templates/_helpers.tpl | 15 + packages/apps/tenant/templates/etcd.yaml | 25 + packages/apps/tenant/templates/ingress.yaml | 26 + .../apps/tenant/templates/monitoring.yaml | 40 + packages/apps/tenant/templates/namespace.yaml | 35 + packages/apps/tenant/templates/tenant.yaml | 84 + packages/apps/tenant/values.schema.json | 27 + packages/apps/tenant/values.yaml | 4 + packages/apps/versions_map | 14 + packages/apps/virtual-machine/.helmignore | 23 + packages/apps/virtual-machine/Chart.yaml | 26 + packages/apps/virtual-machine/README.md | 10 + .../virtual-machine/templates/_helpers.tpl | 51 + .../virtual-machine/templates/service.yaml | 27 + .../apps/virtual-machine/templates/vm.yaml | 65 + .../apps/virtual-machine/values.schema.json | 46 + packages/apps/virtual-machine/values.yaml | 8 + packages/apps/vpn/.helmignore | 23 + packages/apps/vpn/Chart.yaml | 25 + packages/apps/vpn/README.md | 12 + packages/apps/vpn/templates/_helpers.tpl | 51 + packages/apps/vpn/templates/deployment.yaml | 83 + packages/apps/vpn/templates/secret.yaml | 36 + packages/apps/vpn/templates/service.yaml | 29 + packages/apps/vpn/templates/tls.yaml | 21 + packages/apps/vpn/values.yaml | 7 + packages/core/Makefile | 4 + packages/core/installer/Chart.yaml | 2 + packages/core/installer/Makefile | 56 + packages/core/installer/hack/gen-profiles.sh | 63 + packages/core/installer/hack/gen-versions.sh | 20 + packages/core/installer/images/installer.json | 14 + packages/core/installer/images/installer.tag | 1 + .../installer/images/installer/Dockerfile | 24 + packages/core/installer/images/matchbox.json | 14 + packages/core/installer/images/matchbox.tag | 1 + .../core/installer/images/matchbox/Dockerfile | 6 + .../images/matchbox/groups/default.json | 5 + .../images/matchbox/profiles/default.json | 18 + .../images/talos/profiles/initramfs.yaml | 26 + .../images/talos/profiles/installer.yaml | 26 + .../installer/images/talos/profiles/iso.yaml | 26 + .../images/talos/profiles/kernel.yaml | 26 + .../core/installer/templates/cozystack.yaml | 88 + packages/core/platform/Chart.yaml | 2 + packages/core/platform/Makefile | 17 + packages/core/platform/templates/_helpers.tpl | 18 + packages/core/platform/templates/apps.yaml | 51 + .../core/platform/templates/helmreleases.yaml | 744 + .../core/platform/templates/helmrepos.yaml | 34 + .../core/platform/templates/namespaces.yaml | 13 + packages/core/platform/values.yaml | 30 + packages/extra/Makefile | 20 + packages/extra/etcd/Chart.yaml | 6 + .../etcd/templates/check-release-name.yaml | 3 + .../extra/etcd/templates/kamaji-etcd.yaml | 19 + packages/extra/ingress/Chart.yaml | 6 + .../ingress/templates/check-release-name.yaml | 3 + .../ingress/templates/nginx-ingress.yaml | 28 + packages/extra/monitoring/Chart.yaml | 6 + packages/extra/monitoring/dashboards.list | 33 + packages/extra/monitoring/patches/1.diff | 22 + .../templates/check-release-name.yaml | 3 + .../monitoring/templates/dashboards.yaml | 16 + .../monitoring/templates/grafana/db.yaml | 8 + .../monitoring/templates/grafana/grafana.yaml | 88 + .../monitoring/templates/grafana/secret.yaml | 16 + .../templates/oncall/oncall-db.yaml | 11 + .../templates/oncall/oncall-redis.yaml | 66 + .../templates/oncall/oncall-release.yaml | 40 + .../templates/vm/grafana-datasource.yaml | 22 + .../templates/vm/vmalert-scrape.yaml | 17 + .../monitoring/templates/vm/vmalert.yaml | 18 + .../templates/vm/vmalertmanager.yaml | 29 + .../templates/vm/vmcluster-scrape.yaml | 53 + .../monitoring/templates/vm/vmcluster.yaml | 35 + packages/extra/monitoring/values.yaml | 14 + packages/extra/versions_map | 3 + packages/system/Makefile | 12 + packages/system/capi-operator/.helmignore | 3 + packages/system/capi-operator/Chart.yaml | 2 + packages/system/capi-operator/Makefile | 18 + .../charts/cluster-api-operator/.helmignore | 23 + .../charts/cluster-api-operator/Chart.lock | 6 + .../charts/cluster-api-operator/Chart.yaml | 11 + .../crds/cert-manager.crds.yaml | 4482 ++++ .../templates/_helpers.tpl | 24 + .../cluster-api-operator/templates/addon.yaml | 54 + .../templates/bootstrap.yaml | 55 + .../templates/cert-manager.namespace.yaml | 8 + .../templates/control-plane.yaml | 55 + .../templates/core-conditions.yaml | 31 + .../cluster-api-operator/templates/core.yaml | 53 + .../templates/deployment.yaml | 137 + .../templates/infra-conditions.yaml | 60 + .../cluster-api-operator/templates/infra.yaml | 55 + .../templates/operator-components.yaml | 15918 ++++++++++++++ .../charts/cluster-api-operator/values.yaml | 72 + packages/system/capi-providers/Chart.yaml | 2 + packages/system/capi-providers/Makefile | 11 + .../capi-providers/templates/providers.yaml | 26 + .../system/cert-manager-issuers/.helmignore | 2 + .../system/cert-manager-issuers/Chart.yaml | 2 + packages/system/cert-manager-issuers/Makefile | 11 + .../templates/cluster-issuers.yaml | 28 + .../system/cert-manager-issuers/values.yaml | 2 + packages/system/cert-manager/.helmignore | 2 + packages/system/cert-manager/Chart.yaml | 2 + packages/system/cert-manager/Makefile | 17 + .../charts/cert-manager/Chart.yaml | 24 + .../charts/cert-manager/README.md | 271 + .../charts/cert-manager/templates/NOTES.txt | 15 + .../cert-manager/templates/_helpers.tpl | 174 + .../templates/cainjector-deployment.yaml | 117 + .../cainjector-poddisruptionbudget.yaml | 26 + .../templates/cainjector-psp-clusterrole.yaml | 20 + .../cainjector-psp-clusterrolebinding.yaml | 22 + .../templates/cainjector-psp.yaml | 51 + .../templates/cainjector-rbac.yaml | 103 + .../templates/cainjector-serviceaccount.yaml | 27 + .../charts/cert-manager/templates/crds.yaml | 4462 ++++ .../cert-manager/templates/deployment.yaml | 204 + .../templates/networkpolicy-egress.yaml | 23 + .../templates/networkpolicy-webhooks.yaml | 25 + .../templates/poddisruptionbudget.yaml | 26 + .../templates/psp-clusterrole.yaml | 18 + .../templates/psp-clusterrolebinding.yaml | 20 + .../charts/cert-manager/templates/psp.yaml | 49 + .../charts/cert-manager/templates/rbac.yaml | 544 + .../cert-manager/templates/service.yaml | 31 + .../templates/serviceaccount.yaml | 25 + .../templates/servicemonitor.yaml | 45 + .../templates/startupapicheck-job.yaml | 88 + .../startupapicheck-psp-clusterrole.yaml | 24 + ...tartupapicheck-psp-clusterrolebinding.yaml | 26 + .../templates/startupapicheck-psp.yaml | 51 + .../templates/startupapicheck-rbac.yaml | 48 + .../startupapicheck-serviceaccount.yaml | 27 + .../templates/webhook-config.yaml | 25 + .../templates/webhook-deployment.yaml | 185 + .../templates/webhook-mutating-webhook.yaml | 46 + .../webhook-poddisruptionbudget.yaml | 26 + .../templates/webhook-psp-clusterrole.yaml | 18 + .../webhook-psp-clusterrolebinding.yaml | 20 + .../cert-manager/templates/webhook-psp.yaml | 54 + .../cert-manager/templates/webhook-rbac.yaml | 83 + .../templates/webhook-service.yaml | 32 + .../templates/webhook-serviceaccount.yaml | 25 + .../templates/webhook-validating-webhook.yaml | 55 + .../charts/cert-manager/values.yaml | 692 + packages/system/cert-manager/values.yaml | 2 + packages/system/cilium/Chart.yaml | 2 + packages/system/cilium/Makefile | 19 + .../system/cilium/charts/cilium/.helmignore | 24 + .../system/cilium/charts/cilium/Chart.yaml | 141 + packages/system/cilium/charts/cilium/LICENSE | 202 + .../system/cilium/charts/cilium/README.md | 748 + .../cilium/charts/cilium/README.md.gotmpl | 54 + .../cilium/files/agent/poststart-eni.bash | 19 + .../dashboards/cilium-dashboard.json | 8245 +++++++ .../configmap/bootstrap-config.json | 323 + .../dashboards/cilium-operator-dashboard.json | 998 + .../hubble/dashboards/hubble-dashboard.json | 3232 +++ .../hubble-l7-http-metrics-by-workload.json | 1385 ++ .../charts/cilium/files/nodeinit/prestop.bash | 60 + .../charts/cilium/files/nodeinit/startup.bash | 206 + .../charts/cilium/files/spire/init.bash | 48 + .../cilium/files/spire/wait-for-spire.bash | 35 + .../cilium/charts/cilium/templates/NOTES.txt | 22 + .../charts/cilium/templates/_helpers.tpl | 156 + .../templates/cilium-agent/clusterrole.yaml | 142 + .../cilium-agent/clusterrolebinding.yaml | 16 + .../templates/cilium-agent/daemonset.yaml | 955 + .../cilium-agent/dashboards-configmap.yaml | 25 + .../cilium/templates/cilium-agent/role.yaml | 80 + .../templates/cilium-agent/rolebinding.yaml | 75 + .../templates/cilium-agent/service.yaml | 52 + .../cilium-agent/serviceaccount.yaml | 11 + .../cilium-agent/servicemonitor.yaml | 39 + .../templates/cilium-ca-bundle-configmap.yaml | 11 + .../cilium/templates/cilium-ca-secret.yaml | 17 + .../cilium/templates/cilium-configmap.yaml | 1172 + .../templates/cilium-envoy/configmap.yaml | 12 + .../templates/cilium-envoy/daemonset.yaml | 254 + .../templates/cilium-envoy/service.yaml | 27 + .../cilium-envoy/serviceaccount.yaml | 11 + .../cilium-envoy/servicemonitor.yaml | 39 + .../templates/cilium-gateway-api-class.yaml | 10 + .../templates/cilium-ingress-class.yaml | 12 + .../templates/cilium-ingress-service.yaml | 57 + .../templates/cilium-nodeinit/daemonset.yaml | 110 + .../cilium-nodeinit/serviceaccount.yaml | 11 + .../templates/cilium-operator/_helpers.tpl | 36 + .../cilium-operator/clusterrole.yaml | 278 + .../cilium-operator/clusterrolebinding.yaml | 16 + .../cilium-operator/dashboards-configmap.yaml | 25 + .../templates/cilium-operator/deployment.yaml | 333 + .../cilium-operator/poddisruptionbudget.yaml | 24 + .../templates/cilium-operator/role.yaml | 41 + .../cilium-operator/rolebinding.yaml | 37 + .../templates/cilium-operator/secret.yaml | 13 + .../templates/cilium-operator/service.yaml | 23 + .../cilium-operator/serviceaccount.yaml | 15 + .../cilium-operator/servicemonitor.yaml | 40 + .../cilium-preflight/clusterrole.yaml | 142 + .../cilium-preflight/clusterrolebinding.yaml | 16 + .../templates/cilium-preflight/daemonset.yaml | 211 + .../cilium-preflight/deployment.yaml | 103 + .../cilium-preflight/poddisruptionbudget.yaml | 24 + .../cilium-preflight/serviceaccount.yaml | 11 + .../templates/cilium-resource-quota.yaml | 35 + .../templates/cilium-secrets-namespace.yaml | 32 + .../clustermesh-apiserver/_helpers.tpl | 11 + .../clustermesh-apiserver/clusterrole.yaml | 68 + .../clusterrolebinding.yaml | 16 + .../clustermesh-apiserver/deployment.yaml | 407 + .../metrics-service.yaml | 39 + .../poddisruptionbudget.yaml | 22 + .../clustermesh-apiserver/service.yaml | 33 + .../clustermesh-apiserver/serviceaccount.yaml | 11 + .../clustermesh-apiserver/servicemonitor.yaml | 72 + .../tls-certmanager/admin-secret.yaml | 16 + .../tls-certmanager/client-secret.yaml | 14 + .../tls-certmanager/remote-secret.yaml | 14 + .../tls-certmanager/server-secret.yaml | 27 + .../tls-cronjob/_job-spec.tpl | 73 + .../tls-cronjob/ca-secret.yaml | 15 + .../tls-cronjob/cronjob.yaml | 15 + .../tls-cronjob/job.yaml | 17 + .../tls-cronjob/role.yaml | 37 + .../tls-cronjob/rolebinding.yaml | 17 + .../tls-cronjob/serviceaccount.yaml | 11 + .../tls-helm/_helpers.tpl | 37 + .../tls-helm/admin-secret.yaml | 17 + .../tls-helm/ca-secret.yaml | 12 + .../tls-helm/client-secret.yaml | 16 + .../tls-helm/remote-secret.yaml | 16 + .../tls-helm/server-secret.yaml | 18 + .../tls-provided/admin-secret.yaml | 12 + .../tls-provided/ca-secret.yaml | 12 + .../tls-provided/client-secret.yaml | 12 + .../tls-provided/remote-secret.yaml | 12 + .../tls-provided/server-secret.yaml | 12 + .../users-configmap.yaml | 21 + .../templates/clustermesh-config/_helpers.tpl | 25 + .../clustermesh-secret.yaml | 22 + .../kvstoremesh-secret.yaml | 21 + .../cilium-etcd-operator-clusterrole.yaml | 75 + ...lium-etcd-operator-clusterrolebinding.yaml | 16 + .../cilium-etcd-operator-deployment.yaml | 124 + .../cilium-etcd-operator-serviceaccount.yaml | 11 + .../etcd-operator-clusterrole.yaml | 56 + .../etcd-operator-clusterrolebinding.yaml | 16 + .../etcd-operator-serviceaccount.yaml | 11 + .../etcd-operator/poddisruptionbudget.yaml | 24 + .../templates/hubble-relay/configmap.yaml | 47 + .../templates/hubble-relay/deployment.yaml | 168 + .../hubble-relay/metrics-service.yaml | 20 + .../hubble-relay/poddisruptionbudget.yaml | 22 + .../templates/hubble-relay/service.yaml | 26 + .../hubble-relay/serviceaccount.yaml | 11 + .../hubble-relay/servicemonitor.yaml | 34 + .../cilium/templates/hubble-ui/_nginx.tpl | 54 + .../templates/hubble-ui/clusterrole.yaml | 46 + .../hubble-ui/clusterrolebinding.yaml | 16 + .../cilium/templates/hubble-ui/configmap.yaml | 10 + .../templates/hubble-ui/deployment.yaml | 192 + .../cilium/templates/hubble-ui/ingress.yaml | 35 + .../hubble-ui/poddisruptionbudget.yaml | 22 + .../cilium/templates/hubble-ui/service.yaml | 26 + .../templates/hubble-ui/serviceaccount.yaml | 11 + .../hubble/dashboards-configmap.yaml | 25 + .../templates/hubble/metrics-service.yaml | 29 + .../cilium/templates/hubble/peer-service.yaml | 26 + .../templates/hubble/servicemonitor.yaml | 36 + .../tls-certmanager/relay-client-secret.yaml | 18 + .../tls-certmanager/relay-server-secret.yaml | 27 + .../hubble/tls-certmanager/server-secret.yaml | 28 + .../tls-certmanager/ui-client-certs.yaml | 18 + .../hubble/tls-cronjob/_job-spec.tpl | 64 + .../hubble/tls-cronjob/clusterrole.yaml | 34 + .../tls-cronjob/clusterrolebinding.yaml | 16 + .../templates/hubble/tls-cronjob/cronjob.yaml | 20 + .../templates/hubble/tls-cronjob/job.yaml | 18 + .../hubble/tls-cronjob/serviceaccount.yaml | 11 + .../templates/hubble/tls-helm/_helpers.tpl | 31 + .../hubble/tls-helm/relay-client-secret.yaml | 17 + .../hubble/tls-helm/relay-server-secret.yaml | 18 + .../hubble/tls-helm/server-secret.yaml | 18 + .../hubble/tls-helm/ui-client-certs.yaml | 17 + .../tls-provided/relay-client-secret.yaml | 12 + .../tls-provided/relay-server-secret.yaml | 12 + .../hubble/tls-provided/server-secret.yaml | 12 + .../hubble/tls-provided/ui-client-certs.yaml | 12 + .../templates/spire/agent/clusterrole.yaml | 11 + .../spire/agent/clusterrolebinding.yaml | 15 + .../templates/spire/agent/configmap.yaml | 49 + .../templates/spire/agent/daemonset.yaml | 113 + .../templates/spire/agent/serviceaccount.yaml | 7 + .../templates/spire/bundle-configmap.yaml | 7 + .../cilium/templates/spire/namespace.yaml | 6 + .../templates/spire/server/clusterrole.yaml | 22 + .../spire/server/clusterrolebinding.yaml | 14 + .../templates/spire/server/configmap.yaml | 68 + .../cilium/templates/spire/server/role.yaml | 12 + .../templates/spire/server/rolebinding.yaml | 29 + .../templates/spire/server/service.yaml | 24 + .../spire/server/serviceaccount.yaml | 7 + .../templates/spire/server/statefulset.yaml | 110 + .../charts/cilium/templates/validate.yaml | 76 + .../system/cilium/charts/cilium/values.yaml | 3218 +++ .../cilium/charts/cilium/values.yaml.tmpl | 3221 +++ .../system/cilium/patches/fix-cgroups.patch | 21 + packages/system/cilium/templates/cni.yaml | 29 + packages/system/cilium/values.yaml | 27 + packages/system/dashboard/.helmignore | 3 + packages/system/dashboard/Chart.yaml | 2 + packages/system/dashboard/Makefile | 57 + .../dashboard/charts/kubeapps/.helmignore | 24 + .../dashboard/charts/kubeapps/Chart.lock | 12 + .../dashboard/charts/kubeapps/Chart.yaml | 54 + .../dashboard/charts/kubeapps/README.md | 1148 + .../charts/kubeapps/charts/common/.helmignore | 22 + .../charts/kubeapps/charts/common/Chart.yaml | 23 + .../charts/kubeapps/charts/common/README.md | 235 + .../charts/common/templates/_affinities.tpl | 139 + .../charts/common/templates/_capabilities.tpl | 229 + .../charts/common/templates/_errors.tpl | 28 + .../charts/common/templates/_images.tpl | 117 + .../charts/common/templates/_ingress.tpl | 73 + .../charts/common/templates/_labels.tpl | 46 + .../charts/common/templates/_names.tpl | 71 + .../charts/common/templates/_secrets.tpl | 172 + .../charts/common/templates/_storage.tpl | 28 + .../charts/common/templates/_tplvalues.tpl | 38 + .../charts/common/templates/_utils.tpl | 77 + .../charts/common/templates/_warnings.tpl | 19 + .../templates/validations/_cassandra.tpl | 77 + .../common/templates/validations/_mariadb.tpl | 108 + .../common/templates/validations/_mongodb.tpl | 113 + .../common/templates/validations/_mysql.tpl | 108 + .../templates/validations/_postgresql.tpl | 134 + .../common/templates/validations/_redis.tpl | 81 + .../templates/validations/_validations.tpl | 51 + .../charts/kubeapps/charts/common/values.yaml | 8 + .../charts/kubeapps/charts/redis/.helmignore | 21 + .../charts/kubeapps/charts/redis/Chart.lock | 6 + .../charts/kubeapps/charts/redis/Chart.yaml | 36 + .../charts/kubeapps/charts/redis/README.md | 1019 + .../charts/redis/charts/common/.helmignore | 22 + .../charts/redis/charts/common/Chart.yaml | 23 + .../charts/redis/charts/common/README.md | 235 + .../charts/common/templates/_affinities.tpl | 139 + .../charts/common/templates/_capabilities.tpl | 229 + .../redis/charts/common/templates/_errors.tpl | 28 + .../redis/charts/common/templates/_images.tpl | 117 + .../charts/common/templates/_ingress.tpl | 73 + .../redis/charts/common/templates/_labels.tpl | 46 + .../redis/charts/common/templates/_names.tpl | 71 + .../charts/common/templates/_secrets.tpl | 172 + .../charts/common/templates/_storage.tpl | 28 + .../charts/common/templates/_tplvalues.tpl | 38 + .../redis/charts/common/templates/_utils.tpl | 77 + .../charts/common/templates/_warnings.tpl | 19 + .../templates/validations/_cassandra.tpl | 77 + .../common/templates/validations/_mariadb.tpl | 108 + .../common/templates/validations/_mongodb.tpl | 113 + .../common/templates/validations/_mysql.tpl | 108 + .../templates/validations/_postgresql.tpl | 134 + .../common/templates/validations/_redis.tpl | 81 + .../templates/validations/_validations.tpl | 51 + .../charts/redis/charts/common/values.yaml | 8 + .../redis/img/redis-cluster-topology.png | Bin 0 -> 11448 bytes .../charts/redis/img/redis-topology.png | Bin 0 -> 9709 bytes .../kubeapps/charts/redis/templates/NOTES.txt | 191 + .../charts/redis/templates/_helpers.tpl | 328 + .../charts/redis/templates/configmap.yaml | 61 + .../charts/redis/templates/extra-list.yaml | 9 + .../charts/redis/templates/headless-svc.yaml | 33 + .../redis/templates/health-configmap.yaml | 194 + .../redis/templates/master/application.yaml | 532 + .../charts/redis/templates/master/psp.yaml | 47 + .../charts/redis/templates/master/pvc.yaml | 33 + .../redis/templates/master/service.yaml | 59 + .../templates/master/serviceaccount.yaml | 18 + .../charts/redis/templates/metrics-svc.yaml | 41 + .../charts/redis/templates/networkpolicy.yaml | 105 + .../kubeapps/charts/redis/templates/pdb.yaml | 25 + .../charts/redis/templates/podmonitor.yaml | 52 + .../redis/templates/prometheusrule.yaml | 23 + .../redis/templates/replicas/application.yaml | 533 + .../charts/redis/templates/replicas/hpa.yaml | 49 + .../redis/templates/replicas/service.yaml | 56 + .../templates/replicas/serviceaccount.yaml | 18 + .../kubeapps/charts/redis/templates/role.yaml | 29 + .../charts/redis/templates/rolebinding.yaml | 23 + .../redis/templates/scripts-configmap.yaml | 757 + .../redis/templates/secret-svcbind.yaml | 37 + .../charts/redis/templates/secret.yaml | 25 + .../charts/redis/templates/sentinel/hpa.yaml | 49 + .../templates/sentinel/node-services.yaml | 67 + .../templates/sentinel/ports-configmap.yaml | 102 + .../redis/templates/sentinel/service.yaml | 101 + .../redis/templates/sentinel/statefulset.yaml | 785 + .../redis/templates/serviceaccount.yaml | 18 + .../redis/templates/servicemonitor.yaml | 52 + .../charts/redis/templates/tls-secret.yaml | 31 + .../kubeapps/charts/redis/values.schema.json | 163 + .../charts/kubeapps/charts/redis/values.yaml | 1939 ++ .../kubeapps/crds/apprepository-crd.yaml | 116 + .../system/dashboard/charts/kubeapps/images | 1 + .../charts/kubeapps/templates/NOTES.txt | 87 + .../charts/kubeapps/templates/_helpers.tpl | 371 + .../apprepository/apprepositories-secret.yaml | 60 + .../apprepository/apprepositories.yaml | 78 + .../templates/apprepository/deployment.yaml | 156 + .../templates/apprepository/rbac.yaml | 256 + .../apprepository/serviceaccount.yaml | 21 + .../templates/dashboard/configmap.yaml | 92 + .../templates/dashboard/deployment.yaml | 189 + .../kubeapps/templates/dashboard/service.yaml | 30 + .../charts/kubeapps/templates/extra-list.yaml | 9 + .../templates/frontend/configmap.yaml | 139 + .../templates/frontend/deployment.yaml | 311 + .../templates/frontend/oauth2-secret.yaml | 23 + .../kubeapps/templates/frontend/service.yaml | 84 + .../kubeapps/templates/ingress-api.yaml | 115 + .../charts/kubeapps/templates/ingress.yaml | 59 + .../templates/kubeappsapis/configmap.yaml | 21 + .../templates/kubeappsapis/deployment.yaml | 335 + .../kubeapps/templates/kubeappsapis/rbac.yaml | 80 + .../templates/kubeappsapis/rbac_fluxv2.yaml | 58 + .../templates/kubeappsapis/service.yaml | 34 + .../kubeappsapis/serviceaccount.yaml | 21 + .../kubeapps/templates/shared/config.yaml | 19 + .../shared/helm-global-repos-namespace.yaml | 11 + .../kubeapps/templates/tls-secrets.yaml | 44 + .../charts/kubeapps/values.schema.json | 125 + .../dashboard/charts/kubeapps/values.yaml | 2150 ++ .../system/dashboard/images/dashboard.json | 4 + .../system/dashboard/images/dashboard.tag | 1 + .../dashboard/images/dashboard/Dockerfile | 33 + .../images/dashboard/apple-touch-icon.png | Bin 0 -> 7584 bytes .../images/dashboard/favicon-16x16.png | Bin 0 -> 5288 bytes .../images/dashboard/favicon-32x32.png | Bin 0 -> 5269 bytes .../dashboard/images/dashboard/favicon.ico | Bin 0 -> 7406 bytes .../images/dashboard/mstile-144x144.png | Bin 0 -> 7152 bytes .../images/dashboard/mstile-150x150.png | Bin 0 -> 6948 bytes .../images/dashboard/mstile-310x150.png | Bin 0 -> 7029 bytes .../images/dashboard/mstile-310x310.png | Bin 0 -> 9266 bytes .../images/dashboard/mstile-70x70.png | Bin 0 -> 7504 bytes .../images/dashboard/safari-pinned-tab.svg | 49 + .../dashboard/images/kubeapps-apis.json | 4 + .../system/dashboard/images/kubeapps-apis.tag | 1 + .../dashboard/images/kubeapps-apis/Dockerfile | 127 + .../images/kubeapps-apis/dockerfile.diff | 34 + .../images/kubeapps-apis/fix-flux.diff | 28 + .../images/kubeapps-apis/labels.diff | 59 + .../kubeapps-apis/reconcile-strategy.diff | 12 + .../system/dashboard/templates/_helpers.tpl | 13 + .../templates/allow-from-kubeapps.yaml | 14 + packages/system/dashboard/values.yaml | 17 + packages/system/fluxcd/.helmignore | 3 + packages/system/fluxcd/Chart.yaml | 2 + packages/system/fluxcd/Makefile | 15 + .../system/fluxcd/charts/flux2/.helmignore | 25 + .../system/fluxcd/charts/flux2/Chart.yaml | 11 + packages/system/fluxcd/charts/flux2/README.md | 174 + .../fluxcd/charts/flux2/templates/_helper.tpl | 7 + .../templates/aggregate-clusterroles.yaml | 47 + ...cluster-reconciler-clusterrolebinding.yaml | 26 + ...r-reconciler-impersonator-clusterrole.yaml | 19 + ...ciler-impersonator-clusterrolebinding.yaml | 26 + .../templates/crd-controller-clusterrole.yaml | 82 + .../crd-controller-clusterrolebinding.yaml | 38 + .../flux2/templates/extra-manifests.yaml | 4 + .../flux2/templates/helm-controller-sa.yaml | 18 + .../flux2/templates/helm-controller.crds.yaml | 935 + .../flux2/templates/helm-controller.yaml | 133 + .../image-automation-controller-sa.yaml | 18 + .../image-automation-controller.crds.yaml | 326 + .../image-automation-controller.yaml | 135 + .../image-reflector-controller-sa.yaml | 18 + .../image-reflector-controller.crds.yaml | 897 + .../templates/image-reflector-controller.yaml | 139 + .../templates/kustomize-controller-sa.yaml | 18 + .../kustomize-controller-secret.yaml | 18 + .../templates/kustomize-controller.crds.yaml | 1640 ++ .../flux2/templates/kustomize-controller.yaml | 158 + .../notification-controller-ingress.yaml | 49 + .../templates/notification-controller-sa.yaml | 18 + .../notification-controller-service.yaml | 29 + ...tification-controller-webhook-service.yaml | 26 + .../notification-controller.crds.yaml | 1529 ++ .../templates/notification-controller.yaml | 136 + .../charts/flux2/templates/podmonitor.yaml | 32 + .../charts/flux2/templates/policies.yaml | 63 + .../pre-install-job-serviceaccount.yaml | 14 + .../flux2/templates/pre-install-job.yaml | 72 + .../templates/source-controller-service.yaml | 29 + .../source-controller-serviceaccount.yaml | 18 + .../templates/source-controller.crds.yaml | 3230 +++ .../flux2/templates/source-controller.yaml | 144 + .../system/fluxcd/charts/flux2/values.yaml | 325 + packages/system/fluxcd/values.yaml | 0 packages/system/grafana-oncall/Chart.yaml | 2 + packages/system/grafana-oncall/Makefile | 6 + .../grafana-oncall/charts/oncall/.helmignore | 26 + .../grafana-oncall/charts/oncall/Chart.lock | 27 + .../grafana-oncall/charts/oncall/Chart.yaml | 39 + .../grafana-oncall/charts/oncall/README.md | 431 + .../charts/oncall/templates/NOTES.txt | 41 + .../charts/oncall/templates/_env.tpl | 656 + .../charts/oncall/templates/_helpers.tpl | 121 + .../oncall/templates/celery/_helpers.tpl | 26 + .../oncall/templates/celery/deployment.yaml | 89 + .../charts/oncall/templates/cert-issuer.yaml | 22 + .../templates/engine/_helpers-engine.tpl | 26 + .../oncall/templates/engine/deployment.yaml | 98 + .../oncall/templates/engine/job-migrate.yaml | 102 + .../templates/engine/service-external.yaml | 24 + .../templates/engine/service-internal.yaml | 15 + .../oncall/templates/ingress-regular.yaml | 65 + .../templates/integrations/_helpers.tpl | 26 + .../templates/integrations/deployment.yaml | 99 + .../integrations/service-external.yaml | 24 + .../integrations/service-internal.yaml | 17 + .../charts/oncall/templates/secrets.yaml | 98 + .../oncall/templates/serviceaccount.yaml | 18 + .../templates/telegram-polling/_helpers.tpl | 22 + .../telegram-polling/deployment.yaml | 53 + .../charts/oncall/templates/ui/_helpers.tpl | 8 + .../oncall/templates/ui/deployment.yaml | 31 + .../grafana-oncall/charts/oncall/values.yaml | 719 + packages/system/grafana-oncall/values.yaml | 19 + packages/system/grafana-operator/Chart.yaml | 2 + packages/system/grafana-operator/Makefile | 17 + .../charts/grafana-operator/.helmignore | 23 + .../charts/grafana-operator/Chart.yaml | 24 + .../charts/grafana-operator/README.md | 61 + .../charts/grafana-operator/README.md.gotmpl | 37 + ...ana.integreatly.org_grafanadashboards.yaml | 235 + ...na.integreatly.org_grafanadatasources.yaml | 178 + ...rafana.integreatly.org_grafanafolders.yaml | 85 + .../grafana.integreatly.org_grafanas.yaml | 4007 ++++ .../grafana-operator/templates/_helpers.tpl | 62 + .../charts/grafana-operator/templates/cm.yaml | 24 + .../templates/deployment.yaml | 97 + .../grafana-operator/templates/rbac.yaml | 252 + .../grafana-operator/templates/service.yaml | 19 + .../templates/serviceaccount.yaml | 17 + .../charts/grafana-operator/values.yaml | 80 + packages/system/grafana-operator/values.yaml | 2 + packages/system/ingress-nginx/.helmignore | 2 + packages/system/ingress-nginx/Chart.yaml | 2 + packages/system/ingress-nginx/Makefile | 21 + .../charts/ingress-nginx/.helmignore | 23 + .../charts/ingress-nginx/Chart.yaml | 21 + .../ingress-nginx/charts/ingress-nginx/OWNERS | 10 + .../charts/ingress-nginx/README.md | 527 + .../charts/ingress-nginx/README.md.gotmpl | 229 + ...ler-admission-tls-cert-manager-values.yaml | 6 + .../controller-custom-ingressclass-flags.yaml | 7 + .../ci/daemonset-customconfig-values.yaml | 14 + .../ci/daemonset-customnodeport-values.yaml | 22 + .../ci/daemonset-extra-modules.yaml | 10 + .../ci/daemonset-headers-values.yaml | 14 + .../ci/daemonset-internal-lb-values.yaml | 14 + .../ci/daemonset-nodeport-values.yaml | 10 + .../ci/daemonset-podannotations-values.yaml | 17 + ...set-tcp-udp-configMapNamespace-values.yaml | 20 + ...emonset-tcp-udp-portNamePrefix-values.yaml | 18 + .../ci/daemonset-tcp-udp-values.yaml | 16 + .../ci/daemonset-tcp-values.yaml | 14 + .../ci/deamonset-default-values.yaml | 10 + .../ci/deamonset-metrics-values.yaml | 12 + .../ci/deamonset-psp-values.yaml | 13 + .../ci/deamonset-webhook-and-psp-values.yaml | 13 + .../ci/deamonset-webhook-values.yaml | 10 + ...eployment-autoscaling-behavior-values.yaml | 14 + .../ci/deployment-autoscaling-values.yaml | 11 + .../ci/deployment-customconfig-values.yaml | 12 + .../ci/deployment-customnodeport-values.yaml | 20 + .../ci/deployment-default-values.yaml | 8 + ...modules-default-container-sec-context.yaml | 12 + ...odules-specific-container-sec-context.yaml | 12 + .../ci/deployment-extra-modules.yaml | 10 + .../ci/deployment-headers-values.yaml | 13 + .../ci/deployment-internal-lb-values.yaml | 19 + .../ci/deployment-metrics-values.yaml | 11 + .../ci/deployment-nodeport-values.yaml | 9 + .../ci/deployment-podannotations-values.yaml | 16 + .../ci/deployment-psp-values.yaml | 10 + ...ent-tcp-udp-configMapNamespace-values.yaml | 19 + ...loyment-tcp-udp-portNamePrefix-values.yaml | 17 + .../ci/deployment-tcp-udp-values.yaml | 15 + .../ci/deployment-tcp-values.yaml | 11 + .../ci/deployment-webhook-and-psp-values.yaml | 12 + .../deployment-webhook-extraEnvs-values.yaml | 12 + .../deployment-webhook-resources-values.yaml | 23 + .../ci/deployment-webhook-values.yaml | 9 + .../charts/ingress-nginx/templates/NOTES.txt | 73 + .../ingress-nginx/templates/_helpers.tpl | 278 + .../ingress-nginx/templates/_params.tpl | 68 + .../admission-webhooks/cert-manager.yaml | 63 + .../job-patch/clusterrole.yaml | 33 + .../job-patch/clusterrolebinding.yaml | 23 + .../job-patch/job-createSecret.yaml | 79 + .../job-patch/job-patchWebhook.yaml | 81 + .../job-patch/networkpolicy.yaml | 26 + .../admission-webhooks/job-patch/psp.yaml | 52 + .../admission-webhooks/job-patch/role.yaml | 24 + .../job-patch/rolebinding.yaml | 24 + .../job-patch/serviceaccount.yaml | 16 + .../validating-webhook.yaml | 53 + .../ingress-nginx/templates/clusterrole.yaml | 102 + .../templates/clusterrolebinding.yaml | 19 + .../controller-configmap-addheaders.yaml | 14 + .../controller-configmap-proxyheaders.yaml | 14 + .../templates/controller-configmap-tcp.yaml | 17 + .../templates/controller-configmap-udp.yaml | 17 + .../templates/controller-configmap.yaml | 28 + .../templates/controller-daemonset.yaml | 246 + .../templates/controller-daemonset.yaml.orig | 243 + .../templates/controller-deployment.yaml | 249 + .../templates/controller-hpa.yaml | 47 + .../templates/controller-ingressclass.yaml | 21 + .../templates/controller-keda.yaml | 46 + .../templates/controller-networkpolicy.yaml | 45 + .../controller-poddisruptionbudget.yaml | 26 + .../templates/controller-prometheusrules.yaml | 23 + .../templates/controller-psp.yaml | 100 + .../templates/controller-role.yaml | 101 + .../templates/controller-rolebinding.yaml | 21 + .../templates/controller-secret.yaml | 15 + .../controller-service-internal.yaml | 82 + .../templates/controller-service-metrics.yaml | 45 + .../templates/controller-service-webhook.yaml | 40 + .../templates/controller-service.yaml | 107 + .../templates/controller-serviceaccount.yaml | 17 + .../templates/controller-servicemonitor.yaml | 50 + .../templates/default-backend-deployment.yaml | 116 + .../default-backend-extra-configmaps.yaml | 23 + .../templates/default-backend-hpa.yaml | 40 + .../default-backend-networkpolicy.yaml | 25 + .../default-backend-poddisruptionbudget.yaml | 21 + .../templates/default-backend-psp.yaml | 50 + .../templates/default-backend-role.yaml | 22 + .../default-backend-rolebinding.yaml | 21 + .../templates/default-backend-service.yaml | 41 + .../default-backend-serviceaccount.yaml | 14 + ...default-backend-extra-configmaps_test.yaml | 49 + .../charts/ingress-nginx/values.yaml | 1013 + .../ingress-nginx/patches/add-metrics2.patch | 28 + packages/system/ingress-nginx/values.yaml | 47 + packages/system/kamaji-etcd/.helmignore | 2 + packages/system/kamaji-etcd/Chart.yaml | 2 + packages/system/kamaji-etcd/Makefile | 8 + .../charts/kamaji-etcd/.helmignore | 23 + .../kamaji-etcd/charts/kamaji-etcd/Chart.yaml | 15 + .../kamaji-etcd/charts/kamaji-etcd/Makefile | 9 + .../kamaji-etcd/charts/kamaji-etcd/README.md | 133 + .../charts/kamaji-etcd/README.md.gotmpl | 59 + .../charts/kamaji-etcd/templates/_helpers.tpl | 168 + .../kamaji-etcd/templates/etcd_alerts.yaml | 22 + .../charts/kamaji-etcd/templates/etcd_cm.yaml | 98 + .../templates/etcd_cronjob_backup.yaml | 115 + .../templates/etcd_cronjob_defrag.yaml | 62 + .../kamaji-etcd/templates/etcd_datastore.yaml | 35 + .../templates/etcd_job_postdelete.yaml | 32 + .../templates/etcd_job_preinstall_1.yaml | 69 + .../templates/etcd_job_preinstall_2.yaml | 71 + .../templates/etcd_job_s3retention.yaml | 77 + .../templates/etcd_metrics_rbac.yaml | 46 + .../kamaji-etcd/templates/etcd_rbac.yaml | 60 + .../charts/kamaji-etcd/templates/etcd_sa.yaml | 15 + .../kamaji-etcd/templates/etcd_service.yaml | 18 + .../templates/etcd_service_monitor.yaml | 47 + .../kamaji-etcd/templates/etcd_sts.yaml | 117 + .../charts/kamaji-etcd/values.yaml | 223 + .../system/kamaji-etcd/patches/fix-svc.diff | 12 + .../kamaji-etcd/patches/fullnameOverride.diff | 31 + .../kamaji-etcd/templates/datastore.yaml | 33 + packages/system/kamaji/.helmignore | 2 + packages/system/kamaji/Chart.yaml | 2 + packages/system/kamaji/Makefile | 18 + .../system/kamaji/charts/kamaji/.helmignore | 23 + .../system/kamaji/charts/kamaji/Chart.yaml | 22 + packages/system/kamaji/charts/kamaji/Makefile | 9 + .../system/kamaji/charts/kamaji/README.md | 141 + .../kamaji/charts/kamaji/README.md.gotmpl | 62 + .../system/kamaji/charts/kamaji/app-readme.md | 12 + .../kamaji/charts/kamaji/crds/datastore.yaml | 239 + .../kamaji/crds/tenantcontrolplane.yaml | 7736 +++++++ .../kamaji/charts/kamaji/templates/NOTES.txt | 5 + .../charts/kamaji/templates/_helpers.tpl | 91 + .../kamaji/templates/_helpers_datastore.tpl | 94 + .../charts/kamaji/templates/_helpers_etcd.tpl | 142 + .../templates/certmanager_certificate.yaml | 16 + .../kamaji/templates/certmanager_issuer.yaml | 10 + .../charts/kamaji/templates/controller.yaml | 105 + .../charts/kamaji/templates/datastore.yaml | 28 + .../charts/kamaji/templates/etcd_cm.yaml | 98 + .../kamaji/templates/etcd_job_postdelete.yaml | 35 + .../templates/etcd_job_postinstall.yaml | 74 + .../kamaji/templates/etcd_job_preinstall.yaml | 72 + .../charts/kamaji/templates/etcd_rbac.yaml | 56 + .../charts/kamaji/templates/etcd_sa.yaml | 12 + .../charts/kamaji/templates/etcd_service.yaml | 18 + .../charts/kamaji/templates/etcd_sts.yaml | 101 + .../mutatingwebhookconfiguration.yaml | 30 + .../kamaji/charts/kamaji/templates/rbac.yaml | 240 + .../kamaji/templates/service_metrics.yaml | 16 + .../kamaji/templates/service_webhook.yaml | 16 + .../kamaji/templates/servicemonitor.yaml | 21 + .../validatingwebhookconfiguration.yaml | 70 + .../kamaji/charts/kamaji/values.sample.yaml | 2 + .../system/kamaji/charts/kamaji/values.yaml | 216 + packages/system/kamaji/values.yaml | 8 + packages/system/kubeovn/Chart.yaml | 2 + packages/system/kubeovn/Makefile | 17 + .../system/kubeovn/charts/kube-ovn/Chart.yaml | 24 + .../system/kubeovn/charts/kube-ovn/README.md | 42 + .../kubeovn/charts/kube-ovn/crds/crd.yaml | 2278 ++ .../charts/kube-ovn/templates/_helpers.tpl | 31 + .../kube-ovn/templates/central-deploy.yaml | 161 + .../kube-ovn/templates/controller-deploy.yaml | 163 + .../kube-ovn/templates/controller-svc.yaml | 16 + .../kube-ovn/templates/monitor-deploy.yaml | 139 + .../kube-ovn/templates/monitor-svc.yaml | 18 + .../charts/kube-ovn/templates/nb-svc.yaml | 19 + .../charts/kube-ovn/templates/northd-svc.yaml | 19 + .../charts/kube-ovn/templates/ovn-CR.yaml | 231 + .../charts/kube-ovn/templates/ovn-CRB.yaml | 54 + .../kube-ovn/templates/ovn-dpdk-ds.yaml | 164 + .../charts/kube-ovn/templates/ovn-sa.yaml | 34 + .../kube-ovn/templates/ovn-tls-secret.yaml | 23 + .../charts/kube-ovn/templates/ovncni-ds.yaml | 209 + .../charts/kube-ovn/templates/ovncni-svc.yaml | 16 + .../charts/kube-ovn/templates/ovsovn-ds.yaml | 224 + .../charts/kube-ovn/templates/pinger-ds.yaml | 137 + .../charts/kube-ovn/templates/pinger-svc.yaml | 16 + .../kube-ovn/templates/pre-delete-hook.yaml | 123 + .../charts/kube-ovn/templates/sb-svc.yaml | 19 + .../kube-ovn/templates/upgrade-ovs-ovn.yaml | 142 + .../kube-ovn/templates/vpc-nat-config.yaml | 10 + .../kubeovn/charts/kube-ovn/values.yaml | 177 + .../system/kubeovn/patches/cozyconfig.diff | 97 + packages/system/kubeovn/values.yaml | 25 + .../system/kubevirt-cdi-operator/Chart.yaml | 2 + .../system/kubevirt-cdi-operator/Makefile | 19 + .../templates/cdi-operator.yaml | 5091 +++++ packages/system/kubevirt-cdi/Chart.yaml | 2 + packages/system/kubevirt-cdi/Makefile | 17 + .../system/kubevirt-cdi/templates/cdi-cr.yaml | 18 + packages/system/kubevirt-csi-node/Chart.yaml | 2 + .../kubevirt-csi-node/templates/deploy.yaml | 278 + packages/system/kubevirt-operator/Chart.yaml | 2 + packages/system/kubevirt-operator/Makefile | 19 + .../templates/kubevirt-operator.yaml | 7501 +++++++ packages/system/kubevirt-operator/values.yaml | 1 + packages/system/kubevirt/Chart.yaml | 2 + packages/system/kubevirt/Makefile | 18 + .../kubevirt/templates/kubevirt-cr.yaml | 15 + packages/system/kubevirt/values.yaml | 1 + packages/system/linstor/.helmignore | 1 + packages/system/linstor/Chart.yaml | 2 + packages/system/linstor/Makefile | 11 + packages/system/linstor/examples/1.yaml | 28 + .../linstor/hack/proxmox-install-module.sh | 9 + .../system/linstor/templates/cluster.yaml | 15 + .../linstor/templates/linstor-api-tls.yaml | 27 + .../templates/linstor-internal-tls.yaml | 27 + .../system/linstor/templates/satellites.yaml | 48 + packages/system/linstor/values.yaml | 1 + packages/system/mariadb-operator/.helmignore | 3 + packages/system/mariadb-operator/Chart.yaml | 2 + packages/system/mariadb-operator/Makefile | 17 + .../charts/mariadb-operator/.helmignore | 23 + .../charts/mariadb-operator/Chart.yaml | 17 + .../charts/mariadb-operator/README.md | 93 + .../charts/mariadb-operator/README.md.gotmpl | 26 + .../charts/mariadb-operator/crds/crds.yaml | 16586 ++++++++++++++ .../mariadb-operator/templates/NOTES.txt | 4 + .../mariadb-operator/templates/_helpers.tpl | 118 + .../templates/deployment.yaml | 109 + .../mariadb-operator/templates/rbac.yaml | 434 + .../templates/serviceaccount.yaml | 15 + .../templates/servicemonitor.yaml | 36 + .../templates/webhook-certificate.yaml | 25 + .../templates/webhook-config.yaml | 269 + .../templates/webhook-deployment.yaml | 107 + .../templates/webhook-service.yaml | 13 + .../templates/webhook-serviceaccount.yaml | 13 + .../templates/webhook-servicemonitor.yaml | 36 + .../charts/mariadb-operator/values.yaml | 161 + packages/system/mariadb-operator/values.yaml | 6 + packages/system/metallb/Chart.yaml | 2 + packages/system/metallb/Makefile | 17 + .../system/metallb/charts/metallb/.helmignore | 23 + .../system/metallb/charts/metallb/Chart.lock | 6 + .../system/metallb/charts/metallb/Chart.yaml | 17 + .../system/metallb/charts/metallb/README.md | 158 + .../charts/metallb/charts/crds/.helmignore | 23 + .../charts/metallb/charts/crds/Chart.yaml | 10 + .../charts/metallb/charts/crds/README.md | 14 + .../metallb/charts/crds/templates/crds.yaml | 1233 ++ .../charts/metallb/policy/controller.rego | 16 + .../metallb/charts/metallb/policy/rbac.rego | 27 + .../charts/metallb/policy/speaker.rego | 30 + .../charts/metallb/templates/NOTES.txt | 4 + .../charts/metallb/templates/_helpers.tpl | 113 + .../charts/metallb/templates/controller.yaml | 181 + .../templates/deprecated_configInline.yaml | 3 + .../metallb/templates/exclude-l2-config.yaml | 22 + .../charts/metallb/templates/podmonitor.yaml | 106 + .../metallb/templates/prometheusrules.yaml | 84 + .../charts/metallb/templates/rbac.yaml | 206 + .../metallb/templates/service-accounts.yaml | 28 + .../metallb/templates/servicemonitor.yaml | 188 + .../charts/metallb/templates/speaker.yaml | 505 + .../charts/metallb/templates/webhooks.yaml | 168 + .../metallb/charts/metallb/values.schema.json | 427 + .../system/metallb/charts/metallb/values.yaml | 342 + packages/system/metallb/values.yaml | 6 + packages/system/monitoring/.helmignore | 1 + packages/system/monitoring/Chart.yaml | 2 + packages/system/monitoring/Makefile | 24 + .../system/monitoring/alerts/general.yaml | 57 + .../system/monitoring/alerts/kube-dns.yaml | 25 + .../monitoring/alerts/kube-state-metrics.yaml | 50 + .../system/monitoring/alerts/kubelet.yaml | 63 + .../monitoring/alerts/node-disk-usage.yaml | 357 + packages/system/monitoring/alerts/node.yaml | 36 + .../system/monitoring/alerts/pod-status.yaml | 34 + .../charts/kube-state-metrics/.helmignore | 21 + .../charts/kube-state-metrics/Chart.yaml | 26 + .../charts/kube-state-metrics/README.md | 85 + .../kube-state-metrics/templates/NOTES.txt | 23 + .../kube-state-metrics/templates/_helpers.tpl | 156 + .../templates/ciliumnetworkpolicy.yaml | 33 + .../templates/clusterrolebinding.yaml | 20 + .../templates/crs-configmap.yaml | 16 + .../templates/deployment.yaml | 290 + .../templates/extra-manifests.yaml | 4 + .../templates/kubeconfig-secret.yaml | 12 + .../templates/networkpolicy.yaml | 43 + .../kube-state-metrics/templates/pdb.yaml | 18 + .../templates/podsecuritypolicy.yaml | 39 + .../templates/psp-clusterrole.yaml | 19 + .../templates/psp-clusterrolebinding.yaml | 16 + .../templates/rbac-configmap.yaml | 22 + .../kube-state-metrics/templates/role.yaml | 212 + .../templates/rolebinding.yaml | 24 + .../kube-state-metrics/templates/service.yaml | 49 + .../templates/serviceaccount.yaml | 15 + .../templates/servicemonitor.yaml | 120 + .../templates/stsdiscovery-role.yaml | 26 + .../templates/stsdiscovery-rolebinding.yaml | 17 + .../templates/verticalpodautoscaler.yaml | 44 + .../charts/kube-state-metrics/values.yaml | 456 + .../charts/metrics-server/.helmignore | 23 + .../charts/metrics-server/Chart.yaml | 32 + .../charts/metrics-server/README.md | 90 + .../charts/metrics-server/ci/ci-values.yaml | 2 + .../charts/metrics-server/templates/NOTES.txt | 7 + .../metrics-server/templates/_helpers.tpl | 102 + .../metrics-server/templates/apiservice.yaml | 25 + .../clusterrole-aggregated-reader.yaml | 21 + .../templates/clusterrole-nanny.yaml | 13 + .../metrics-server/templates/clusterrole.yaml | 37 + .../clusterrolebinding-auth-delegator.yaml | 16 + .../templates/clusterrolebinding-nanny.yaml | 18 + .../templates/clusterrolebinding.yaml | 16 + .../templates/configmaps-nanny.yaml | 17 + .../metrics-server/templates/deployment.yaml | 146 + .../charts/metrics-server/templates/pdb.yaml | 19 + .../charts/metrics-server/templates/psp.yaml | 28 + .../metrics-server/templates/role-nanny.yaml | 27 + .../templates/rolebinding-nanny.yaml | 19 + .../metrics-server/templates/rolebinding.yaml | 17 + .../metrics-server/templates/service.yaml | 23 + .../templates/serviceaccount.yaml | 17 + .../templates/servicemonitor.yaml | 40 + .../charts/metrics-server/values.yaml | 182 + .../prometheus-node-exporter/.helmignore | 21 + .../prometheus-node-exporter/Chart.yaml | 25 + .../charts/prometheus-node-exporter/README.md | 96 + .../ci/port-values.yaml | 3 + .../templates/NOTES.txt | 29 + .../templates/_helpers.tpl | 185 + .../templates/clusterrole.yaml | 19 + .../templates/clusterrolebinding.yaml | 20 + .../templates/daemonset.yaml | 285 + .../templates/endpoints.yaml | 18 + .../templates/extra-manifests.yaml | 4 + .../templates/networkpolicy.yaml | 23 + .../templates/podmonitor.yaml | 91 + .../templates/psp-clusterrole.yaml | 14 + .../templates/psp-clusterrolebinding.yaml | 16 + .../templates/psp.yaml | 49 + .../templates/rbac-configmap.yaml | 16 + .../templates/service.yaml | 29 + .../templates/serviceaccount.yaml | 17 + .../templates/servicemonitor.yaml | 61 + .../templates/verticalpodautoscaler.yaml | 40 + .../prometheus-node-exporter/values.yaml | 480 + .../templates/additional-scrape-configs.yaml | 7 + .../templates/apiserver-scrape.yaml | 31 + .../monitoring/templates/cadvisor-scrape.yaml | 32 + .../monitoring/templates/coredns-scrape.yaml | 42 + .../monitoring/templates/etcd-scrape.yaml | 34 + .../kube-controller-manager-scrape.yaml | 49 + .../templates/kube-scheduler-scrape.yaml | 48 + .../templates/kube-state-metrics-scrape.yaml | 28 + .../monitoring/templates/kubelet-scrape.yaml | 63 + .../monitoring/templates/nginx-scrape.yaml | 54 + .../templates/node-exporter-scrape.yaml | 24 + .../monitoring/templates/vmagent-scrape.yaml | 18 + .../system/monitoring/templates/vmagent.yaml | 25 + .../templates/vmoperator-scrape.yaml | 17 + .../system/monitoring/templates/vmrules.yaml | 271 + packages/system/monitoring/values.yaml | 13 + packages/system/piraeus-operator/.helmignore | 1 + packages/system/piraeus-operator/Chart.yaml | 2 + packages/system/piraeus-operator/Makefile | 17 + .../charts/piraeus/.helmignore | 23 + .../charts/piraeus/Chart.yaml | 18 + .../piraeus-operator/charts/piraeus/README.md | 35 + .../charts/piraeus/templates/NOTES.txt | 40 + .../charts/piraeus/templates/_helpers.tpl | 74 + .../charts/piraeus/templates/config.yaml | 95 + .../charts/piraeus/templates/crds.yaml | 1426 ++ .../charts/piraeus/templates/deployment.yaml | 101 + .../piraeus/templates/metrics-service.yaml | 14 + .../charts/piraeus/templates/rbac.yaml | 461 + .../validating-webhook-configuration.yaml | 154 + .../piraeus/templates/webhook-service.yaml | 14 + .../charts/piraeus/values.yaml | 108 + .../system/piraeus-operator/examples/1.yaml | 28 + .../hack/proxmox-install-module.sh | 9 + .../templates/piraeus-tls.yaml | 8 + packages/system/piraeus-operator/values.yaml | 7 + packages/system/postgres-operator/.helmignore | 3 + packages/system/postgres-operator/Chart.yaml | 2 + packages/system/postgres-operator/Makefile | 17 + .../charts/cloudnative-pg/.helmignore | 23 + .../charts/cloudnative-pg/Chart.yaml | 17 + .../charts/cloudnative-pg/LICENSE | 202 + .../charts/cloudnative-pg/README.md | 58 + .../charts/cloudnative-pg/templates/NOTES.txt | 18 + .../cloudnative-pg/templates/_helpers.tpl | 62 + .../cloudnative-pg/templates/config.yaml | 45 + .../cloudnative-pg/templates/crds/crds.yaml | 12507 +++++++++++ .../cloudnative-pg/templates/deployment.yaml | 137 + .../templates/monitoring-configmap.yaml | 29 + .../mutatingwebhookconfiguration.yaml | 92 + .../cloudnative-pg/templates/podmonitor.yaml | 18 + .../charts/cloudnative-pg/templates/rbac.yaml | 443 + .../cloudnative-pg/templates/service.yaml | 34 + .../validatingwebhookconfiguration.yaml | 113 + .../charts/cloudnative-pg/values.schema.json | 237 + .../charts/cloudnative-pg/values.yaml | 528 + packages/system/postgres-operator/values.yaml | 3 + packages/system/rabbitmq-operator/Chart.yaml | 2 + packages/system/rabbitmq-operator/Makefile | 17 + .../templates/cluster-operator.yml | 4661 ++++ packages/system/rabbitmq-operator/values.yaml | 0 packages/system/redis-operator/Chart.yaml | 2 + packages/system/redis-operator/Makefile | 18 + .../charts/redis-operator/.helmignore | 21 + .../charts/redis-operator/Chart.yaml | 15 + ...atabases.spotahome.com_redisfailovers.yaml | 12398 +++++++++++ .../redis-operator/templates/_helpers.tpl | 85 + .../redis-operator/templates/_versions.tpl | 20 + .../redis-operator/templates/deployment.yaml | 85 + .../redis-operator/templates/monitoring.yaml | 48 + .../templates/private-registry.yaml | 19 + .../templates/service-account.yaml | 115 + .../redis-operator/templates/service.yaml | 23 + .../charts/redis-operator/values.yaml | 98 + packages/system/redis-operator/values.yaml | 3 + packages/system/telepresence/Chart.yaml | 2 + packages/system/telepresence/Makefile | 17 + .../charts/telepresence/.gitignore | 4 + .../charts/telepresence/.helmignore | 23 + .../charts/telepresence/CHANGELOG.md | 24 + .../charts/telepresence/Chart.yaml | 12 + .../charts/telepresence/README.md | 48 + .../charts/telepresence/templates/NOTES.txt | 19 + .../telepresence/templates/_helpers.tpl | 116 + .../templates/agent-configmap.yaml | 7 + .../templates/agentInjectorWebhook.yaml | 78 + .../templates/clientRbac/cluster-scope.yaml | 47 + .../templates/clientRbac/connect.yaml | 42 + .../templates/clientRbac/namespace-scope.yaml | 42 + .../telepresence/templates/deployment.yaml | 332 + .../templates/intercept-env-configmap.yaml | 12 + .../telepresence/templates/licenseSecret.yaml | 14 + .../templates/post-upgrade-hook.yaml | 85 + .../templates/pre-delete-hook.yaml | 73 + .../telepresence/templates/service.yaml | 60 + .../templates/tests/test-connection.yaml | 22 + .../templates/trafficManager-configmap.yaml | 14 + .../trafficManagerRbac/cloud-token.yaml | 39 + .../trafficManagerRbac/cluster-scope.yaml | 94 + .../trafficManagerRbac/namespace-claim.yaml | 23 + .../trafficManagerRbac/namespace-scope.yaml | 150 + .../trafficManagerRbac/service-account.yaml | 11 + .../charts/telepresence/values.yaml | 145 + packages/system/telepresence/values.yaml | 1 + .../victoria-metrics-operator/Chart.yaml | 2 + .../system/victoria-metrics-operator/Makefile | 23 + .../prometheus-operator-crds/.helmignore | 23 + .../prometheus-operator-crds/Chart.yaml | 34 + .../charts/prometheus-operator-crds/README.md | 57 + .../hack/update_crds.sh | 44 + .../templates/crd-podmonitors.yaml | 688 + .../templates/crd-probes.yaml | 730 + .../templates/crd-prometheusrules.yaml | 134 + .../templates/crd-servicemonitors.yaml | 718 + .../prometheus-operator-crds/values.yaml | 3 + .../victoria-metrics-operator/.helmignore | 22 + .../victoria-metrics-operator/CHANGELOG.md | 71 + .../victoria-metrics-operator/Chart.yaml | 40 + .../victoria-metrics-operator/README.md | 189 + .../README.md.gotmpl | 140 + .../RELEASE_NOTES.md | 10 + .../templates/NOTES.txt | 5 + .../templates/_helpers.tpl | 67 + .../templates/certmanager.yaml | 57 + .../templates/cluster_role.yaml | 499 + .../templates/clusterrole_binding.yaml | 23 + .../templates/crd.yaml | 18228 ++++++++++++++++ .../templates/deployment.yaml | 152 + .../templates/pdb.yaml | 26 + .../templates/psp.yaml | 87 + .../templates/role.yaml | 216 + .../templates/role_binding.yaml | 24 + .../templates/service.yaml | 26 + .../templates/service_account.yaml | 16 + .../templates/service_scrape.yaml | 44 + .../templates/uninstall_hook.yaml | 97 + .../templates/webhook.yaml | 233 + .../victoria-metrics-operator/values.yaml | 176 + .../victoria-metrics-operator/values.yaml | 17 + scripts/installer.sh | 48 + 1181 files changed, 381555 insertions(+) create mode 100644 .dockerignore create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 Makefile create mode 100644 README.md create mode 100644 dashboards/.gitignore create mode 100644 dashboards/cache/nginx-vts-stats.json create mode 100644 dashboards/control-plane/control-plane-status.json create mode 100644 dashboards/control-plane/deprecated-resources.json create mode 100644 dashboards/control-plane/dns-coredns.json create mode 100644 dashboards/control-plane/kube-etcd3.json create mode 100644 dashboards/db/cloudnativepg.json create mode 100644 dashboards/db/maria-db.json create mode 100644 dashboards/db/redis.json create mode 100644 dashboards/dotdc/k8s-system-coredns.json create mode 100644 dashboards/dotdc/k8s-views-global.json create mode 100644 dashboards/dotdc/k8s-views-namespaces.json create mode 100644 dashboards/dotdc/k8s-views-pods.json create mode 100644 dashboards/ingress/controller-detail.json create mode 100644 dashboards/ingress/controllers.json create mode 100644 dashboards/ingress/namespace-detail.json create mode 100644 dashboards/ingress/namespaces.json create mode 100644 dashboards/ingress/vhost-detail.json create mode 100644 dashboards/ingress/vhosts.json create mode 100644 dashboards/main/capacity-planning.json create mode 100644 dashboards/main/controller.json create mode 100644 dashboards/main/namespace.json create mode 100644 dashboards/main/namespaces.json create mode 100644 dashboards/main/node.json create mode 100644 dashboards/main/nodes.json create mode 100644 dashboards/main/ntp.json create mode 100644 dashboards/main/pod.json create mode 100644 dashboards/main/volumes.json create mode 100644 dashboards/victoria-metrics/backupmanager.json create mode 100644 dashboards/victoria-metrics/operator.json create mode 100644 dashboards/victoria-metrics/victoriametrics-cluster.json create mode 100644 dashboards/victoria-metrics/victoriametrics.json create mode 100644 dashboards/victoria-metrics/vmagent.json create mode 100644 dashboards/victoria-metrics/vmalert.json create mode 100755 hack/download-dashboards.sh create mode 100755 hack/gen_versions_map.sh create mode 100644 img/cozystack-logo.svg create mode 100644 manifests/cozystack-installer.yaml create mode 100644 packages/apps/Makefile create mode 100644 packages/apps/http-cache/.helmignore create mode 100644 packages/apps/http-cache/Chart.yaml create mode 100644 packages/apps/http-cache/Makefile create mode 100644 packages/apps/http-cache/README.md create mode 100644 packages/apps/http-cache/images/nginx-cache.json create mode 100644 packages/apps/http-cache/images/nginx-cache.tag create mode 100644 packages/apps/http-cache/images/nginx-cache/Dockerfile create mode 100755 packages/apps/http-cache/images/nginx-cache/nginx-reloader.sh create mode 100644 packages/apps/http-cache/templates/haproxy/configmap.yaml create mode 100644 packages/apps/http-cache/templates/haproxy/deployment.yaml create mode 100644 packages/apps/http-cache/templates/haproxy/service.yaml create mode 100644 packages/apps/http-cache/templates/nginx/configmap.yaml create mode 100644 packages/apps/http-cache/templates/nginx/deployment.yaml create mode 100644 packages/apps/http-cache/templates/nginx/nginx-scrape.yaml create mode 100644 packages/apps/http-cache/values.yaml create mode 100644 packages/apps/kubernetes/.helmignore create mode 100644 packages/apps/kubernetes/Chart.yaml create mode 100644 packages/apps/kubernetes/Makefile create mode 100644 packages/apps/kubernetes/README.md create mode 100644 packages/apps/kubernetes/images/ubuntu-container-disk.json create mode 100644 packages/apps/kubernetes/images/ubuntu-container-disk.tag create mode 100644 packages/apps/kubernetes/images/ubuntu-container-disk/Dockerfile create mode 100644 packages/apps/kubernetes/templates/NOTES.txt create mode 100644 packages/apps/kubernetes/templates/_helpers.tpl create mode 100644 packages/apps/kubernetes/templates/cloud-config.yaml create mode 100644 packages/apps/kubernetes/templates/cluster-autoscaler/deployment.yaml create mode 100644 packages/apps/kubernetes/templates/cluster.yaml create mode 100644 packages/apps/kubernetes/templates/csi/deploy.yaml create mode 100644 packages/apps/kubernetes/templates/csi/infra-cluster-service-account.yaml create mode 100644 packages/apps/kubernetes/templates/helmreleases/cilium.yaml create mode 100644 packages/apps/kubernetes/templates/helmreleases/csi.yaml create mode 100644 packages/apps/kubernetes/templates/helmreleases/delete.yaml create mode 100644 packages/apps/kubernetes/templates/kccm/kccm_cluster_role.yaml create mode 100644 packages/apps/kubernetes/templates/kccm/kccm_cluster_role_binding.yaml create mode 100644 packages/apps/kubernetes/templates/kccm/kccm_role.yaml create mode 100644 packages/apps/kubernetes/templates/kccm/kccm_role_binding.yaml create mode 100644 packages/apps/kubernetes/templates/kccm/manager.yaml create mode 100644 packages/apps/kubernetes/templates/kccm/service_account.yaml create mode 100644 packages/apps/kubernetes/values.schema.json create mode 100644 packages/apps/kubernetes/values.yaml create mode 100644 packages/apps/mysql/.helmignore create mode 100644 packages/apps/mysql/Chart.yaml create mode 100644 packages/apps/mysql/README.md create mode 100644 packages/apps/mysql/templates/.gitkeep create mode 100644 packages/apps/mysql/templates/backup-cronjob.yaml create mode 100644 packages/apps/mysql/templates/backup-script.yaml create mode 100644 packages/apps/mysql/templates/backup-secret.yaml create mode 100644 packages/apps/mysql/templates/config.yaml create mode 100644 packages/apps/mysql/templates/db.yaml create mode 100644 packages/apps/mysql/templates/mariadb.yaml create mode 100644 packages/apps/mysql/templates/regsecret.yaml create mode 100644 packages/apps/mysql/templates/secret.yaml create mode 100644 packages/apps/mysql/templates/user.yaml create mode 100644 packages/apps/mysql/values.yaml create mode 100644 packages/apps/postgres/.helmignore create mode 100644 packages/apps/postgres/Chart.yaml create mode 100644 packages/apps/postgres/README.md create mode 100644 packages/apps/postgres/templates/.gitkeep create mode 100644 packages/apps/postgres/templates/backup-cronjob.yaml create mode 100644 packages/apps/postgres/templates/backup-script.yaml create mode 100644 packages/apps/postgres/templates/backup-secret.yaml create mode 100644 packages/apps/postgres/templates/db.yaml create mode 100644 packages/apps/postgres/templates/external-svc.yaml create mode 100644 packages/apps/postgres/templates/init-job.yaml create mode 100644 packages/apps/postgres/templates/init-script.yaml create mode 100644 packages/apps/postgres/templates/regsecret.yaml create mode 100644 packages/apps/postgres/values.yaml create mode 100644 packages/apps/rabbitmq/.helmignore create mode 100644 packages/apps/rabbitmq/Chart.yaml create mode 100644 packages/apps/rabbitmq/README.md create mode 100644 packages/apps/rabbitmq/templates/rabbitmq.yaml create mode 100644 packages/apps/rabbitmq/values.schema.json create mode 100644 packages/apps/rabbitmq/values.yaml create mode 100644 packages/apps/redis/.helmignore create mode 100644 packages/apps/redis/Chart.yaml create mode 100644 packages/apps/redis/README.md create mode 100644 packages/apps/redis/templates/redisfailover.yaml create mode 100644 packages/apps/redis/templates/service.yaml create mode 100644 packages/apps/redis/templates/servicescrape.yaml create mode 100644 packages/apps/redis/values.schema.json create mode 100644 packages/apps/redis/values.yaml create mode 100644 packages/apps/tcp-balancer/.helmignore create mode 100644 packages/apps/tcp-balancer/Chart.yaml create mode 100644 packages/apps/tcp-balancer/README.md create mode 100644 packages/apps/tcp-balancer/templates/configmap.yaml create mode 100644 packages/apps/tcp-balancer/templates/deployment.yaml create mode 100644 packages/apps/tcp-balancer/templates/service.yaml create mode 100644 packages/apps/tcp-balancer/values.yaml create mode 100644 packages/apps/tenant/Chart.yaml create mode 100644 packages/apps/tenant/README.md create mode 100644 packages/apps/tenant/templates/_helpers.tpl create mode 100644 packages/apps/tenant/templates/etcd.yaml create mode 100644 packages/apps/tenant/templates/ingress.yaml create mode 100644 packages/apps/tenant/templates/monitoring.yaml create mode 100644 packages/apps/tenant/templates/namespace.yaml create mode 100644 packages/apps/tenant/templates/tenant.yaml create mode 100644 packages/apps/tenant/values.schema.json create mode 100644 packages/apps/tenant/values.yaml create mode 100644 packages/apps/versions_map create mode 100644 packages/apps/virtual-machine/.helmignore create mode 100644 packages/apps/virtual-machine/Chart.yaml create mode 100644 packages/apps/virtual-machine/README.md create mode 100644 packages/apps/virtual-machine/templates/_helpers.tpl create mode 100644 packages/apps/virtual-machine/templates/service.yaml create mode 100644 packages/apps/virtual-machine/templates/vm.yaml create mode 100644 packages/apps/virtual-machine/values.schema.json create mode 100644 packages/apps/virtual-machine/values.yaml create mode 100644 packages/apps/vpn/.helmignore create mode 100644 packages/apps/vpn/Chart.yaml create mode 100644 packages/apps/vpn/README.md create mode 100644 packages/apps/vpn/templates/_helpers.tpl create mode 100644 packages/apps/vpn/templates/deployment.yaml create mode 100644 packages/apps/vpn/templates/secret.yaml create mode 100644 packages/apps/vpn/templates/service.yaml create mode 100644 packages/apps/vpn/templates/tls.yaml create mode 100644 packages/apps/vpn/values.yaml create mode 100644 packages/core/Makefile create mode 100644 packages/core/installer/Chart.yaml create mode 100644 packages/core/installer/Makefile create mode 100755 packages/core/installer/hack/gen-profiles.sh create mode 100755 packages/core/installer/hack/gen-versions.sh create mode 100644 packages/core/installer/images/installer.json create mode 100644 packages/core/installer/images/installer.tag create mode 100644 packages/core/installer/images/installer/Dockerfile create mode 100644 packages/core/installer/images/matchbox.json create mode 100644 packages/core/installer/images/matchbox.tag create mode 100644 packages/core/installer/images/matchbox/Dockerfile create mode 100644 packages/core/installer/images/matchbox/groups/default.json create mode 100644 packages/core/installer/images/matchbox/profiles/default.json create mode 100644 packages/core/installer/images/talos/profiles/initramfs.yaml create mode 100644 packages/core/installer/images/talos/profiles/installer.yaml create mode 100644 packages/core/installer/images/talos/profiles/iso.yaml create mode 100644 packages/core/installer/images/talos/profiles/kernel.yaml create mode 100644 packages/core/installer/templates/cozystack.yaml create mode 100644 packages/core/platform/Chart.yaml create mode 100644 packages/core/platform/Makefile create mode 100644 packages/core/platform/templates/_helpers.tpl create mode 100644 packages/core/platform/templates/apps.yaml create mode 100644 packages/core/platform/templates/helmreleases.yaml create mode 100644 packages/core/platform/templates/helmrepos.yaml create mode 100644 packages/core/platform/templates/namespaces.yaml create mode 100644 packages/core/platform/values.yaml create mode 100644 packages/extra/Makefile create mode 100644 packages/extra/etcd/Chart.yaml create mode 100644 packages/extra/etcd/templates/check-release-name.yaml create mode 100644 packages/extra/etcd/templates/kamaji-etcd.yaml create mode 100644 packages/extra/ingress/Chart.yaml create mode 100644 packages/extra/ingress/templates/check-release-name.yaml create mode 100644 packages/extra/ingress/templates/nginx-ingress.yaml create mode 100644 packages/extra/monitoring/Chart.yaml create mode 100644 packages/extra/monitoring/dashboards.list create mode 100644 packages/extra/monitoring/patches/1.diff create mode 100644 packages/extra/monitoring/templates/check-release-name.yaml create mode 100644 packages/extra/monitoring/templates/dashboards.yaml create mode 100644 packages/extra/monitoring/templates/grafana/db.yaml create mode 100644 packages/extra/monitoring/templates/grafana/grafana.yaml create mode 100644 packages/extra/monitoring/templates/grafana/secret.yaml create mode 100644 packages/extra/monitoring/templates/oncall/oncall-db.yaml create mode 100644 packages/extra/monitoring/templates/oncall/oncall-redis.yaml create mode 100644 packages/extra/monitoring/templates/oncall/oncall-release.yaml create mode 100644 packages/extra/monitoring/templates/vm/grafana-datasource.yaml create mode 100644 packages/extra/monitoring/templates/vm/vmalert-scrape.yaml create mode 100644 packages/extra/monitoring/templates/vm/vmalert.yaml create mode 100644 packages/extra/monitoring/templates/vm/vmalertmanager.yaml create mode 100644 packages/extra/monitoring/templates/vm/vmcluster-scrape.yaml create mode 100644 packages/extra/monitoring/templates/vm/vmcluster.yaml create mode 100644 packages/extra/monitoring/values.yaml create mode 100644 packages/extra/versions_map create mode 100644 packages/system/Makefile create mode 100644 packages/system/capi-operator/.helmignore create mode 100644 packages/system/capi-operator/Chart.yaml create mode 100644 packages/system/capi-operator/Makefile create mode 100644 packages/system/capi-operator/charts/cluster-api-operator/.helmignore create mode 100644 packages/system/capi-operator/charts/cluster-api-operator/Chart.lock create mode 100644 packages/system/capi-operator/charts/cluster-api-operator/Chart.yaml create mode 100644 packages/system/capi-operator/charts/cluster-api-operator/crds/cert-manager.crds.yaml create mode 100644 packages/system/capi-operator/charts/cluster-api-operator/templates/_helpers.tpl create mode 100644 packages/system/capi-operator/charts/cluster-api-operator/templates/addon.yaml create mode 100644 packages/system/capi-operator/charts/cluster-api-operator/templates/bootstrap.yaml create mode 100644 packages/system/capi-operator/charts/cluster-api-operator/templates/cert-manager.namespace.yaml create mode 100644 packages/system/capi-operator/charts/cluster-api-operator/templates/control-plane.yaml create mode 100644 packages/system/capi-operator/charts/cluster-api-operator/templates/core-conditions.yaml create mode 100644 packages/system/capi-operator/charts/cluster-api-operator/templates/core.yaml create mode 100644 packages/system/capi-operator/charts/cluster-api-operator/templates/deployment.yaml create mode 100644 packages/system/capi-operator/charts/cluster-api-operator/templates/infra-conditions.yaml create mode 100644 packages/system/capi-operator/charts/cluster-api-operator/templates/infra.yaml create mode 100644 packages/system/capi-operator/charts/cluster-api-operator/templates/operator-components.yaml create mode 100644 packages/system/capi-operator/charts/cluster-api-operator/values.yaml create mode 100644 packages/system/capi-providers/Chart.yaml create mode 100644 packages/system/capi-providers/Makefile create mode 100644 packages/system/capi-providers/templates/providers.yaml create mode 100644 packages/system/cert-manager-issuers/.helmignore create mode 100644 packages/system/cert-manager-issuers/Chart.yaml create mode 100644 packages/system/cert-manager-issuers/Makefile create mode 100644 packages/system/cert-manager-issuers/templates/cluster-issuers.yaml create mode 100644 packages/system/cert-manager-issuers/values.yaml create mode 100644 packages/system/cert-manager/.helmignore create mode 100644 packages/system/cert-manager/Chart.yaml create mode 100644 packages/system/cert-manager/Makefile create mode 100644 packages/system/cert-manager/charts/cert-manager/Chart.yaml create mode 100644 packages/system/cert-manager/charts/cert-manager/README.md create mode 100644 packages/system/cert-manager/charts/cert-manager/templates/NOTES.txt create mode 100644 packages/system/cert-manager/charts/cert-manager/templates/_helpers.tpl create mode 100644 packages/system/cert-manager/charts/cert-manager/templates/cainjector-deployment.yaml create mode 100644 packages/system/cert-manager/charts/cert-manager/templates/cainjector-poddisruptionbudget.yaml create mode 100644 packages/system/cert-manager/charts/cert-manager/templates/cainjector-psp-clusterrole.yaml create mode 100644 packages/system/cert-manager/charts/cert-manager/templates/cainjector-psp-clusterrolebinding.yaml create mode 100644 packages/system/cert-manager/charts/cert-manager/templates/cainjector-psp.yaml create mode 100644 packages/system/cert-manager/charts/cert-manager/templates/cainjector-rbac.yaml create mode 100644 packages/system/cert-manager/charts/cert-manager/templates/cainjector-serviceaccount.yaml create mode 100644 packages/system/cert-manager/charts/cert-manager/templates/crds.yaml create mode 100644 packages/system/cert-manager/charts/cert-manager/templates/deployment.yaml create mode 100644 packages/system/cert-manager/charts/cert-manager/templates/networkpolicy-egress.yaml create mode 100644 packages/system/cert-manager/charts/cert-manager/templates/networkpolicy-webhooks.yaml create mode 100644 packages/system/cert-manager/charts/cert-manager/templates/poddisruptionbudget.yaml create mode 100644 packages/system/cert-manager/charts/cert-manager/templates/psp-clusterrole.yaml create mode 100644 packages/system/cert-manager/charts/cert-manager/templates/psp-clusterrolebinding.yaml create mode 100644 packages/system/cert-manager/charts/cert-manager/templates/psp.yaml create mode 100644 packages/system/cert-manager/charts/cert-manager/templates/rbac.yaml create mode 100644 packages/system/cert-manager/charts/cert-manager/templates/service.yaml create mode 100644 packages/system/cert-manager/charts/cert-manager/templates/serviceaccount.yaml create mode 100644 packages/system/cert-manager/charts/cert-manager/templates/servicemonitor.yaml create mode 100644 packages/system/cert-manager/charts/cert-manager/templates/startupapicheck-job.yaml create mode 100644 packages/system/cert-manager/charts/cert-manager/templates/startupapicheck-psp-clusterrole.yaml create mode 100644 packages/system/cert-manager/charts/cert-manager/templates/startupapicheck-psp-clusterrolebinding.yaml create mode 100644 packages/system/cert-manager/charts/cert-manager/templates/startupapicheck-psp.yaml create mode 100644 packages/system/cert-manager/charts/cert-manager/templates/startupapicheck-rbac.yaml create mode 100644 packages/system/cert-manager/charts/cert-manager/templates/startupapicheck-serviceaccount.yaml create mode 100644 packages/system/cert-manager/charts/cert-manager/templates/webhook-config.yaml create mode 100644 packages/system/cert-manager/charts/cert-manager/templates/webhook-deployment.yaml create mode 100644 packages/system/cert-manager/charts/cert-manager/templates/webhook-mutating-webhook.yaml create mode 100644 packages/system/cert-manager/charts/cert-manager/templates/webhook-poddisruptionbudget.yaml create mode 100644 packages/system/cert-manager/charts/cert-manager/templates/webhook-psp-clusterrole.yaml create mode 100644 packages/system/cert-manager/charts/cert-manager/templates/webhook-psp-clusterrolebinding.yaml create mode 100644 packages/system/cert-manager/charts/cert-manager/templates/webhook-psp.yaml create mode 100644 packages/system/cert-manager/charts/cert-manager/templates/webhook-rbac.yaml create mode 100644 packages/system/cert-manager/charts/cert-manager/templates/webhook-service.yaml create mode 100644 packages/system/cert-manager/charts/cert-manager/templates/webhook-serviceaccount.yaml create mode 100644 packages/system/cert-manager/charts/cert-manager/templates/webhook-validating-webhook.yaml create mode 100644 packages/system/cert-manager/charts/cert-manager/values.yaml create mode 100644 packages/system/cert-manager/values.yaml create mode 100644 packages/system/cilium/Chart.yaml create mode 100644 packages/system/cilium/Makefile create mode 100644 packages/system/cilium/charts/cilium/.helmignore create mode 100644 packages/system/cilium/charts/cilium/Chart.yaml create mode 100644 packages/system/cilium/charts/cilium/LICENSE create mode 100644 packages/system/cilium/charts/cilium/README.md create mode 100644 packages/system/cilium/charts/cilium/README.md.gotmpl create mode 100644 packages/system/cilium/charts/cilium/files/agent/poststart-eni.bash create mode 100644 packages/system/cilium/charts/cilium/files/cilium-agent/dashboards/cilium-dashboard.json create mode 100644 packages/system/cilium/charts/cilium/files/cilium-envoy/configmap/bootstrap-config.json create mode 100644 packages/system/cilium/charts/cilium/files/cilium-operator/dashboards/cilium-operator-dashboard.json create mode 100644 packages/system/cilium/charts/cilium/files/hubble/dashboards/hubble-dashboard.json create mode 100644 packages/system/cilium/charts/cilium/files/hubble/dashboards/hubble-l7-http-metrics-by-workload.json create mode 100644 packages/system/cilium/charts/cilium/files/nodeinit/prestop.bash create mode 100644 packages/system/cilium/charts/cilium/files/nodeinit/startup.bash create mode 100644 packages/system/cilium/charts/cilium/files/spire/init.bash create mode 100644 packages/system/cilium/charts/cilium/files/spire/wait-for-spire.bash create mode 100644 packages/system/cilium/charts/cilium/templates/NOTES.txt create mode 100644 packages/system/cilium/charts/cilium/templates/_helpers.tpl create mode 100644 packages/system/cilium/charts/cilium/templates/cilium-agent/clusterrole.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/cilium-agent/clusterrolebinding.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/cilium-agent/daemonset.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/cilium-agent/dashboards-configmap.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/cilium-agent/role.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/cilium-agent/rolebinding.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/cilium-agent/service.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/cilium-agent/serviceaccount.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/cilium-agent/servicemonitor.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/cilium-ca-bundle-configmap.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/cilium-ca-secret.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/cilium-configmap.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/cilium-envoy/configmap.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/cilium-envoy/daemonset.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/cilium-envoy/service.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/cilium-envoy/serviceaccount.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/cilium-envoy/servicemonitor.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/cilium-gateway-api-class.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/cilium-ingress-class.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/cilium-ingress-service.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/cilium-nodeinit/daemonset.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/cilium-nodeinit/serviceaccount.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/cilium-operator/_helpers.tpl create mode 100644 packages/system/cilium/charts/cilium/templates/cilium-operator/clusterrole.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/cilium-operator/clusterrolebinding.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/cilium-operator/dashboards-configmap.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/cilium-operator/deployment.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/cilium-operator/poddisruptionbudget.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/cilium-operator/role.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/cilium-operator/rolebinding.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/cilium-operator/secret.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/cilium-operator/service.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/cilium-operator/serviceaccount.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/cilium-operator/servicemonitor.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/cilium-preflight/clusterrole.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/cilium-preflight/clusterrolebinding.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/cilium-preflight/daemonset.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/cilium-preflight/deployment.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/cilium-preflight/poddisruptionbudget.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/cilium-preflight/serviceaccount.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/cilium-resource-quota.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/cilium-secrets-namespace.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/_helpers.tpl create mode 100644 packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/clusterrole.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/clusterrolebinding.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/deployment.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/metrics-service.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/poddisruptionbudget.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/service.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/serviceaccount.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/servicemonitor.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-certmanager/admin-secret.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-certmanager/client-secret.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-certmanager/remote-secret.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-certmanager/server-secret.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-cronjob/_job-spec.tpl create mode 100644 packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-cronjob/ca-secret.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-cronjob/cronjob.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-cronjob/job.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-cronjob/role.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-cronjob/rolebinding.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-cronjob/serviceaccount.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-helm/_helpers.tpl create mode 100644 packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-helm/admin-secret.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-helm/ca-secret.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-helm/client-secret.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-helm/remote-secret.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-helm/server-secret.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-provided/admin-secret.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-provided/ca-secret.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-provided/client-secret.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-provided/remote-secret.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-provided/server-secret.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/users-configmap.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/clustermesh-config/_helpers.tpl create mode 100644 packages/system/cilium/charts/cilium/templates/clustermesh-config/clustermesh-secret.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/clustermesh-config/kvstoremesh-secret.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/etcd-operator/cilium-etcd-operator-clusterrole.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/etcd-operator/cilium-etcd-operator-clusterrolebinding.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/etcd-operator/cilium-etcd-operator-deployment.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/etcd-operator/cilium-etcd-operator-serviceaccount.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/etcd-operator/etcd-operator-clusterrole.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/etcd-operator/etcd-operator-clusterrolebinding.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/etcd-operator/etcd-operator-serviceaccount.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/etcd-operator/poddisruptionbudget.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/hubble-relay/configmap.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/hubble-relay/deployment.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/hubble-relay/metrics-service.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/hubble-relay/poddisruptionbudget.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/hubble-relay/service.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/hubble-relay/serviceaccount.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/hubble-relay/servicemonitor.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/hubble-ui/_nginx.tpl create mode 100644 packages/system/cilium/charts/cilium/templates/hubble-ui/clusterrole.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/hubble-ui/clusterrolebinding.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/hubble-ui/configmap.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/hubble-ui/deployment.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/hubble-ui/ingress.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/hubble-ui/poddisruptionbudget.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/hubble-ui/service.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/hubble-ui/serviceaccount.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/hubble/dashboards-configmap.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/hubble/metrics-service.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/hubble/peer-service.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/hubble/servicemonitor.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/hubble/tls-certmanager/relay-client-secret.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/hubble/tls-certmanager/relay-server-secret.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/hubble/tls-certmanager/server-secret.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/hubble/tls-certmanager/ui-client-certs.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/hubble/tls-cronjob/_job-spec.tpl create mode 100644 packages/system/cilium/charts/cilium/templates/hubble/tls-cronjob/clusterrole.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/hubble/tls-cronjob/clusterrolebinding.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/hubble/tls-cronjob/cronjob.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/hubble/tls-cronjob/job.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/hubble/tls-cronjob/serviceaccount.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/hubble/tls-helm/_helpers.tpl create mode 100644 packages/system/cilium/charts/cilium/templates/hubble/tls-helm/relay-client-secret.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/hubble/tls-helm/relay-server-secret.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/hubble/tls-helm/server-secret.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/hubble/tls-helm/ui-client-certs.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/hubble/tls-provided/relay-client-secret.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/hubble/tls-provided/relay-server-secret.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/hubble/tls-provided/server-secret.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/hubble/tls-provided/ui-client-certs.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/spire/agent/clusterrole.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/spire/agent/clusterrolebinding.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/spire/agent/configmap.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/spire/agent/daemonset.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/spire/agent/serviceaccount.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/spire/bundle-configmap.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/spire/namespace.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/spire/server/clusterrole.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/spire/server/clusterrolebinding.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/spire/server/configmap.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/spire/server/role.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/spire/server/rolebinding.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/spire/server/service.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/spire/server/serviceaccount.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/spire/server/statefulset.yaml create mode 100644 packages/system/cilium/charts/cilium/templates/validate.yaml create mode 100644 packages/system/cilium/charts/cilium/values.yaml create mode 100644 packages/system/cilium/charts/cilium/values.yaml.tmpl create mode 100644 packages/system/cilium/patches/fix-cgroups.patch create mode 100644 packages/system/cilium/templates/cni.yaml create mode 100644 packages/system/cilium/values.yaml create mode 100644 packages/system/dashboard/.helmignore create mode 100644 packages/system/dashboard/Chart.yaml create mode 100644 packages/system/dashboard/Makefile create mode 100644 packages/system/dashboard/charts/kubeapps/.helmignore create mode 100644 packages/system/dashboard/charts/kubeapps/Chart.lock create mode 100644 packages/system/dashboard/charts/kubeapps/Chart.yaml create mode 100644 packages/system/dashboard/charts/kubeapps/README.md create mode 100644 packages/system/dashboard/charts/kubeapps/charts/common/.helmignore create mode 100644 packages/system/dashboard/charts/kubeapps/charts/common/Chart.yaml create mode 100644 packages/system/dashboard/charts/kubeapps/charts/common/README.md create mode 100644 packages/system/dashboard/charts/kubeapps/charts/common/templates/_affinities.tpl create mode 100644 packages/system/dashboard/charts/kubeapps/charts/common/templates/_capabilities.tpl create mode 100644 packages/system/dashboard/charts/kubeapps/charts/common/templates/_errors.tpl create mode 100644 packages/system/dashboard/charts/kubeapps/charts/common/templates/_images.tpl create mode 100644 packages/system/dashboard/charts/kubeapps/charts/common/templates/_ingress.tpl create mode 100644 packages/system/dashboard/charts/kubeapps/charts/common/templates/_labels.tpl create mode 100644 packages/system/dashboard/charts/kubeapps/charts/common/templates/_names.tpl create mode 100644 packages/system/dashboard/charts/kubeapps/charts/common/templates/_secrets.tpl create mode 100644 packages/system/dashboard/charts/kubeapps/charts/common/templates/_storage.tpl create mode 100644 packages/system/dashboard/charts/kubeapps/charts/common/templates/_tplvalues.tpl create mode 100644 packages/system/dashboard/charts/kubeapps/charts/common/templates/_utils.tpl create mode 100644 packages/system/dashboard/charts/kubeapps/charts/common/templates/_warnings.tpl create mode 100644 packages/system/dashboard/charts/kubeapps/charts/common/templates/validations/_cassandra.tpl create mode 100644 packages/system/dashboard/charts/kubeapps/charts/common/templates/validations/_mariadb.tpl create mode 100644 packages/system/dashboard/charts/kubeapps/charts/common/templates/validations/_mongodb.tpl create mode 100644 packages/system/dashboard/charts/kubeapps/charts/common/templates/validations/_mysql.tpl create mode 100644 packages/system/dashboard/charts/kubeapps/charts/common/templates/validations/_postgresql.tpl create mode 100644 packages/system/dashboard/charts/kubeapps/charts/common/templates/validations/_redis.tpl create mode 100644 packages/system/dashboard/charts/kubeapps/charts/common/templates/validations/_validations.tpl create mode 100644 packages/system/dashboard/charts/kubeapps/charts/common/values.yaml create mode 100644 packages/system/dashboard/charts/kubeapps/charts/redis/.helmignore create mode 100644 packages/system/dashboard/charts/kubeapps/charts/redis/Chart.lock create mode 100644 packages/system/dashboard/charts/kubeapps/charts/redis/Chart.yaml create mode 100644 packages/system/dashboard/charts/kubeapps/charts/redis/README.md create mode 100644 packages/system/dashboard/charts/kubeapps/charts/redis/charts/common/.helmignore create mode 100644 packages/system/dashboard/charts/kubeapps/charts/redis/charts/common/Chart.yaml create mode 100644 packages/system/dashboard/charts/kubeapps/charts/redis/charts/common/README.md create mode 100644 packages/system/dashboard/charts/kubeapps/charts/redis/charts/common/templates/_affinities.tpl create mode 100644 packages/system/dashboard/charts/kubeapps/charts/redis/charts/common/templates/_capabilities.tpl create mode 100644 packages/system/dashboard/charts/kubeapps/charts/redis/charts/common/templates/_errors.tpl create mode 100644 packages/system/dashboard/charts/kubeapps/charts/redis/charts/common/templates/_images.tpl create mode 100644 packages/system/dashboard/charts/kubeapps/charts/redis/charts/common/templates/_ingress.tpl create mode 100644 packages/system/dashboard/charts/kubeapps/charts/redis/charts/common/templates/_labels.tpl create mode 100644 packages/system/dashboard/charts/kubeapps/charts/redis/charts/common/templates/_names.tpl create mode 100644 packages/system/dashboard/charts/kubeapps/charts/redis/charts/common/templates/_secrets.tpl create mode 100644 packages/system/dashboard/charts/kubeapps/charts/redis/charts/common/templates/_storage.tpl create mode 100644 packages/system/dashboard/charts/kubeapps/charts/redis/charts/common/templates/_tplvalues.tpl create mode 100644 packages/system/dashboard/charts/kubeapps/charts/redis/charts/common/templates/_utils.tpl create mode 100644 packages/system/dashboard/charts/kubeapps/charts/redis/charts/common/templates/_warnings.tpl create mode 100644 packages/system/dashboard/charts/kubeapps/charts/redis/charts/common/templates/validations/_cassandra.tpl create mode 100644 packages/system/dashboard/charts/kubeapps/charts/redis/charts/common/templates/validations/_mariadb.tpl create mode 100644 packages/system/dashboard/charts/kubeapps/charts/redis/charts/common/templates/validations/_mongodb.tpl create mode 100644 packages/system/dashboard/charts/kubeapps/charts/redis/charts/common/templates/validations/_mysql.tpl create mode 100644 packages/system/dashboard/charts/kubeapps/charts/redis/charts/common/templates/validations/_postgresql.tpl create mode 100644 packages/system/dashboard/charts/kubeapps/charts/redis/charts/common/templates/validations/_redis.tpl create mode 100644 packages/system/dashboard/charts/kubeapps/charts/redis/charts/common/templates/validations/_validations.tpl create mode 100644 packages/system/dashboard/charts/kubeapps/charts/redis/charts/common/values.yaml create mode 100644 packages/system/dashboard/charts/kubeapps/charts/redis/img/redis-cluster-topology.png create mode 100644 packages/system/dashboard/charts/kubeapps/charts/redis/img/redis-topology.png create mode 100644 packages/system/dashboard/charts/kubeapps/charts/redis/templates/NOTES.txt create mode 100644 packages/system/dashboard/charts/kubeapps/charts/redis/templates/_helpers.tpl create mode 100644 packages/system/dashboard/charts/kubeapps/charts/redis/templates/configmap.yaml create mode 100644 packages/system/dashboard/charts/kubeapps/charts/redis/templates/extra-list.yaml create mode 100644 packages/system/dashboard/charts/kubeapps/charts/redis/templates/headless-svc.yaml create mode 100644 packages/system/dashboard/charts/kubeapps/charts/redis/templates/health-configmap.yaml create mode 100644 packages/system/dashboard/charts/kubeapps/charts/redis/templates/master/application.yaml create mode 100644 packages/system/dashboard/charts/kubeapps/charts/redis/templates/master/psp.yaml create mode 100644 packages/system/dashboard/charts/kubeapps/charts/redis/templates/master/pvc.yaml create mode 100644 packages/system/dashboard/charts/kubeapps/charts/redis/templates/master/service.yaml create mode 100644 packages/system/dashboard/charts/kubeapps/charts/redis/templates/master/serviceaccount.yaml create mode 100644 packages/system/dashboard/charts/kubeapps/charts/redis/templates/metrics-svc.yaml create mode 100644 packages/system/dashboard/charts/kubeapps/charts/redis/templates/networkpolicy.yaml create mode 100644 packages/system/dashboard/charts/kubeapps/charts/redis/templates/pdb.yaml create mode 100644 packages/system/dashboard/charts/kubeapps/charts/redis/templates/podmonitor.yaml create mode 100644 packages/system/dashboard/charts/kubeapps/charts/redis/templates/prometheusrule.yaml create mode 100644 packages/system/dashboard/charts/kubeapps/charts/redis/templates/replicas/application.yaml create mode 100644 packages/system/dashboard/charts/kubeapps/charts/redis/templates/replicas/hpa.yaml create mode 100644 packages/system/dashboard/charts/kubeapps/charts/redis/templates/replicas/service.yaml create mode 100644 packages/system/dashboard/charts/kubeapps/charts/redis/templates/replicas/serviceaccount.yaml create mode 100644 packages/system/dashboard/charts/kubeapps/charts/redis/templates/role.yaml create mode 100644 packages/system/dashboard/charts/kubeapps/charts/redis/templates/rolebinding.yaml create mode 100644 packages/system/dashboard/charts/kubeapps/charts/redis/templates/scripts-configmap.yaml create mode 100644 packages/system/dashboard/charts/kubeapps/charts/redis/templates/secret-svcbind.yaml create mode 100644 packages/system/dashboard/charts/kubeapps/charts/redis/templates/secret.yaml create mode 100644 packages/system/dashboard/charts/kubeapps/charts/redis/templates/sentinel/hpa.yaml create mode 100644 packages/system/dashboard/charts/kubeapps/charts/redis/templates/sentinel/node-services.yaml create mode 100644 packages/system/dashboard/charts/kubeapps/charts/redis/templates/sentinel/ports-configmap.yaml create mode 100644 packages/system/dashboard/charts/kubeapps/charts/redis/templates/sentinel/service.yaml create mode 100644 packages/system/dashboard/charts/kubeapps/charts/redis/templates/sentinel/statefulset.yaml create mode 100644 packages/system/dashboard/charts/kubeapps/charts/redis/templates/serviceaccount.yaml create mode 100644 packages/system/dashboard/charts/kubeapps/charts/redis/templates/servicemonitor.yaml create mode 100644 packages/system/dashboard/charts/kubeapps/charts/redis/templates/tls-secret.yaml create mode 100644 packages/system/dashboard/charts/kubeapps/charts/redis/values.schema.json create mode 100644 packages/system/dashboard/charts/kubeapps/charts/redis/values.yaml create mode 100644 packages/system/dashboard/charts/kubeapps/crds/apprepository-crd.yaml create mode 120000 packages/system/dashboard/charts/kubeapps/images create mode 100644 packages/system/dashboard/charts/kubeapps/templates/NOTES.txt create mode 100644 packages/system/dashboard/charts/kubeapps/templates/_helpers.tpl create mode 100644 packages/system/dashboard/charts/kubeapps/templates/apprepository/apprepositories-secret.yaml create mode 100644 packages/system/dashboard/charts/kubeapps/templates/apprepository/apprepositories.yaml create mode 100644 packages/system/dashboard/charts/kubeapps/templates/apprepository/deployment.yaml create mode 100644 packages/system/dashboard/charts/kubeapps/templates/apprepository/rbac.yaml create mode 100644 packages/system/dashboard/charts/kubeapps/templates/apprepository/serviceaccount.yaml create mode 100644 packages/system/dashboard/charts/kubeapps/templates/dashboard/configmap.yaml create mode 100644 packages/system/dashboard/charts/kubeapps/templates/dashboard/deployment.yaml create mode 100644 packages/system/dashboard/charts/kubeapps/templates/dashboard/service.yaml create mode 100644 packages/system/dashboard/charts/kubeapps/templates/extra-list.yaml create mode 100644 packages/system/dashboard/charts/kubeapps/templates/frontend/configmap.yaml create mode 100644 packages/system/dashboard/charts/kubeapps/templates/frontend/deployment.yaml create mode 100644 packages/system/dashboard/charts/kubeapps/templates/frontend/oauth2-secret.yaml create mode 100644 packages/system/dashboard/charts/kubeapps/templates/frontend/service.yaml create mode 100644 packages/system/dashboard/charts/kubeapps/templates/ingress-api.yaml create mode 100644 packages/system/dashboard/charts/kubeapps/templates/ingress.yaml create mode 100644 packages/system/dashboard/charts/kubeapps/templates/kubeappsapis/configmap.yaml create mode 100644 packages/system/dashboard/charts/kubeapps/templates/kubeappsapis/deployment.yaml create mode 100644 packages/system/dashboard/charts/kubeapps/templates/kubeappsapis/rbac.yaml create mode 100644 packages/system/dashboard/charts/kubeapps/templates/kubeappsapis/rbac_fluxv2.yaml create mode 100644 packages/system/dashboard/charts/kubeapps/templates/kubeappsapis/service.yaml create mode 100644 packages/system/dashboard/charts/kubeapps/templates/kubeappsapis/serviceaccount.yaml create mode 100644 packages/system/dashboard/charts/kubeapps/templates/shared/config.yaml create mode 100644 packages/system/dashboard/charts/kubeapps/templates/shared/helm-global-repos-namespace.yaml create mode 100644 packages/system/dashboard/charts/kubeapps/templates/tls-secrets.yaml create mode 100644 packages/system/dashboard/charts/kubeapps/values.schema.json create mode 100644 packages/system/dashboard/charts/kubeapps/values.yaml create mode 100644 packages/system/dashboard/images/dashboard.json create mode 100644 packages/system/dashboard/images/dashboard.tag create mode 100644 packages/system/dashboard/images/dashboard/Dockerfile create mode 100644 packages/system/dashboard/images/dashboard/apple-touch-icon.png create mode 100644 packages/system/dashboard/images/dashboard/favicon-16x16.png create mode 100644 packages/system/dashboard/images/dashboard/favicon-32x32.png create mode 100644 packages/system/dashboard/images/dashboard/favicon.ico create mode 100644 packages/system/dashboard/images/dashboard/mstile-144x144.png create mode 100644 packages/system/dashboard/images/dashboard/mstile-150x150.png create mode 100644 packages/system/dashboard/images/dashboard/mstile-310x150.png create mode 100644 packages/system/dashboard/images/dashboard/mstile-310x310.png create mode 100644 packages/system/dashboard/images/dashboard/mstile-70x70.png create mode 100644 packages/system/dashboard/images/dashboard/safari-pinned-tab.svg create mode 100644 packages/system/dashboard/images/kubeapps-apis.json create mode 100644 packages/system/dashboard/images/kubeapps-apis.tag create mode 100644 packages/system/dashboard/images/kubeapps-apis/Dockerfile create mode 100644 packages/system/dashboard/images/kubeapps-apis/dockerfile.diff create mode 100644 packages/system/dashboard/images/kubeapps-apis/fix-flux.diff create mode 100644 packages/system/dashboard/images/kubeapps-apis/labels.diff create mode 100644 packages/system/dashboard/images/kubeapps-apis/reconcile-strategy.diff create mode 100644 packages/system/dashboard/templates/_helpers.tpl create mode 100644 packages/system/dashboard/templates/allow-from-kubeapps.yaml create mode 100644 packages/system/dashboard/values.yaml create mode 100644 packages/system/fluxcd/.helmignore create mode 100644 packages/system/fluxcd/Chart.yaml create mode 100644 packages/system/fluxcd/Makefile create mode 100644 packages/system/fluxcd/charts/flux2/.helmignore create mode 100644 packages/system/fluxcd/charts/flux2/Chart.yaml create mode 100644 packages/system/fluxcd/charts/flux2/README.md create mode 100644 packages/system/fluxcd/charts/flux2/templates/_helper.tpl create mode 100644 packages/system/fluxcd/charts/flux2/templates/aggregate-clusterroles.yaml create mode 100644 packages/system/fluxcd/charts/flux2/templates/cluster-reconciler-clusterrolebinding.yaml create mode 100644 packages/system/fluxcd/charts/flux2/templates/cluster-reconciler-impersonator-clusterrole.yaml create mode 100644 packages/system/fluxcd/charts/flux2/templates/cluster-reconciler-impersonator-clusterrolebinding.yaml create mode 100644 packages/system/fluxcd/charts/flux2/templates/crd-controller-clusterrole.yaml create mode 100644 packages/system/fluxcd/charts/flux2/templates/crd-controller-clusterrolebinding.yaml create mode 100644 packages/system/fluxcd/charts/flux2/templates/extra-manifests.yaml create mode 100644 packages/system/fluxcd/charts/flux2/templates/helm-controller-sa.yaml create mode 100644 packages/system/fluxcd/charts/flux2/templates/helm-controller.crds.yaml create mode 100644 packages/system/fluxcd/charts/flux2/templates/helm-controller.yaml create mode 100644 packages/system/fluxcd/charts/flux2/templates/image-automation-controller-sa.yaml create mode 100644 packages/system/fluxcd/charts/flux2/templates/image-automation-controller.crds.yaml create mode 100644 packages/system/fluxcd/charts/flux2/templates/image-automation-controller.yaml create mode 100644 packages/system/fluxcd/charts/flux2/templates/image-reflector-controller-sa.yaml create mode 100644 packages/system/fluxcd/charts/flux2/templates/image-reflector-controller.crds.yaml create mode 100644 packages/system/fluxcd/charts/flux2/templates/image-reflector-controller.yaml create mode 100644 packages/system/fluxcd/charts/flux2/templates/kustomize-controller-sa.yaml create mode 100644 packages/system/fluxcd/charts/flux2/templates/kustomize-controller-secret.yaml create mode 100644 packages/system/fluxcd/charts/flux2/templates/kustomize-controller.crds.yaml create mode 100644 packages/system/fluxcd/charts/flux2/templates/kustomize-controller.yaml create mode 100644 packages/system/fluxcd/charts/flux2/templates/notification-controller-ingress.yaml create mode 100644 packages/system/fluxcd/charts/flux2/templates/notification-controller-sa.yaml create mode 100644 packages/system/fluxcd/charts/flux2/templates/notification-controller-service.yaml create mode 100644 packages/system/fluxcd/charts/flux2/templates/notification-controller-webhook-service.yaml create mode 100644 packages/system/fluxcd/charts/flux2/templates/notification-controller.crds.yaml create mode 100644 packages/system/fluxcd/charts/flux2/templates/notification-controller.yaml create mode 100644 packages/system/fluxcd/charts/flux2/templates/podmonitor.yaml create mode 100644 packages/system/fluxcd/charts/flux2/templates/policies.yaml create mode 100644 packages/system/fluxcd/charts/flux2/templates/pre-install-job-serviceaccount.yaml create mode 100644 packages/system/fluxcd/charts/flux2/templates/pre-install-job.yaml create mode 100644 packages/system/fluxcd/charts/flux2/templates/source-controller-service.yaml create mode 100644 packages/system/fluxcd/charts/flux2/templates/source-controller-serviceaccount.yaml create mode 100644 packages/system/fluxcd/charts/flux2/templates/source-controller.crds.yaml create mode 100644 packages/system/fluxcd/charts/flux2/templates/source-controller.yaml create mode 100644 packages/system/fluxcd/charts/flux2/values.yaml create mode 100644 packages/system/fluxcd/values.yaml create mode 100644 packages/system/grafana-oncall/Chart.yaml create mode 100644 packages/system/grafana-oncall/Makefile create mode 100644 packages/system/grafana-oncall/charts/oncall/.helmignore create mode 100644 packages/system/grafana-oncall/charts/oncall/Chart.lock create mode 100644 packages/system/grafana-oncall/charts/oncall/Chart.yaml create mode 100644 packages/system/grafana-oncall/charts/oncall/README.md create mode 100644 packages/system/grafana-oncall/charts/oncall/templates/NOTES.txt create mode 100644 packages/system/grafana-oncall/charts/oncall/templates/_env.tpl create mode 100644 packages/system/grafana-oncall/charts/oncall/templates/_helpers.tpl create mode 100644 packages/system/grafana-oncall/charts/oncall/templates/celery/_helpers.tpl create mode 100644 packages/system/grafana-oncall/charts/oncall/templates/celery/deployment.yaml create mode 100644 packages/system/grafana-oncall/charts/oncall/templates/cert-issuer.yaml create mode 100644 packages/system/grafana-oncall/charts/oncall/templates/engine/_helpers-engine.tpl create mode 100644 packages/system/grafana-oncall/charts/oncall/templates/engine/deployment.yaml create mode 100644 packages/system/grafana-oncall/charts/oncall/templates/engine/job-migrate.yaml create mode 100644 packages/system/grafana-oncall/charts/oncall/templates/engine/service-external.yaml create mode 100644 packages/system/grafana-oncall/charts/oncall/templates/engine/service-internal.yaml create mode 100644 packages/system/grafana-oncall/charts/oncall/templates/ingress-regular.yaml create mode 100644 packages/system/grafana-oncall/charts/oncall/templates/integrations/_helpers.tpl create mode 100644 packages/system/grafana-oncall/charts/oncall/templates/integrations/deployment.yaml create mode 100644 packages/system/grafana-oncall/charts/oncall/templates/integrations/service-external.yaml create mode 100644 packages/system/grafana-oncall/charts/oncall/templates/integrations/service-internal.yaml create mode 100644 packages/system/grafana-oncall/charts/oncall/templates/secrets.yaml create mode 100644 packages/system/grafana-oncall/charts/oncall/templates/serviceaccount.yaml create mode 100644 packages/system/grafana-oncall/charts/oncall/templates/telegram-polling/_helpers.tpl create mode 100644 packages/system/grafana-oncall/charts/oncall/templates/telegram-polling/deployment.yaml create mode 100644 packages/system/grafana-oncall/charts/oncall/templates/ui/_helpers.tpl create mode 100644 packages/system/grafana-oncall/charts/oncall/templates/ui/deployment.yaml create mode 100644 packages/system/grafana-oncall/charts/oncall/values.yaml create mode 100644 packages/system/grafana-oncall/values.yaml create mode 100644 packages/system/grafana-operator/Chart.yaml create mode 100644 packages/system/grafana-operator/Makefile create mode 100644 packages/system/grafana-operator/charts/grafana-operator/.helmignore create mode 100644 packages/system/grafana-operator/charts/grafana-operator/Chart.yaml create mode 100644 packages/system/grafana-operator/charts/grafana-operator/README.md create mode 100644 packages/system/grafana-operator/charts/grafana-operator/README.md.gotmpl create mode 100644 packages/system/grafana-operator/charts/grafana-operator/crds/grafana.integreatly.org_grafanadashboards.yaml create mode 100644 packages/system/grafana-operator/charts/grafana-operator/crds/grafana.integreatly.org_grafanadatasources.yaml create mode 100644 packages/system/grafana-operator/charts/grafana-operator/crds/grafana.integreatly.org_grafanafolders.yaml create mode 100644 packages/system/grafana-operator/charts/grafana-operator/crds/grafana.integreatly.org_grafanas.yaml create mode 100644 packages/system/grafana-operator/charts/grafana-operator/templates/_helpers.tpl create mode 100644 packages/system/grafana-operator/charts/grafana-operator/templates/cm.yaml create mode 100644 packages/system/grafana-operator/charts/grafana-operator/templates/deployment.yaml create mode 100644 packages/system/grafana-operator/charts/grafana-operator/templates/rbac.yaml create mode 100644 packages/system/grafana-operator/charts/grafana-operator/templates/service.yaml create mode 100644 packages/system/grafana-operator/charts/grafana-operator/templates/serviceaccount.yaml create mode 100644 packages/system/grafana-operator/charts/grafana-operator/values.yaml create mode 100644 packages/system/grafana-operator/values.yaml create mode 100644 packages/system/ingress-nginx/.helmignore create mode 100644 packages/system/ingress-nginx/Chart.yaml create mode 100644 packages/system/ingress-nginx/Makefile create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/.helmignore create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/Chart.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/OWNERS create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/README.md create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/README.md.gotmpl create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/ci/controller-admission-tls-cert-manager-values.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/ci/controller-custom-ingressclass-flags.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/ci/daemonset-customconfig-values.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/ci/daemonset-customnodeport-values.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/ci/daemonset-extra-modules.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/ci/daemonset-headers-values.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/ci/daemonset-internal-lb-values.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/ci/daemonset-nodeport-values.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/ci/daemonset-podannotations-values.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/ci/daemonset-tcp-udp-configMapNamespace-values.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/ci/daemonset-tcp-udp-portNamePrefix-values.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/ci/daemonset-tcp-udp-values.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/ci/daemonset-tcp-values.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/ci/deamonset-default-values.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/ci/deamonset-metrics-values.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/ci/deamonset-psp-values.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/ci/deamonset-webhook-and-psp-values.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/ci/deamonset-webhook-values.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-autoscaling-behavior-values.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-autoscaling-values.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-customconfig-values.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-customnodeport-values.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-default-values.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-extra-modules-default-container-sec-context.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-extra-modules-specific-container-sec-context.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-extra-modules.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-headers-values.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-internal-lb-values.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-metrics-values.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-nodeport-values.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-podannotations-values.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-psp-values.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-tcp-udp-configMapNamespace-values.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-tcp-udp-portNamePrefix-values.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-tcp-udp-values.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-tcp-values.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-webhook-and-psp-values.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-webhook-extraEnvs-values.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-webhook-resources-values.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-webhook-values.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/templates/NOTES.txt create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/templates/_helpers.tpl create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/templates/_params.tpl create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/templates/admission-webhooks/cert-manager.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/templates/admission-webhooks/job-patch/clusterrole.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/templates/admission-webhooks/job-patch/clusterrolebinding.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/templates/admission-webhooks/job-patch/job-createSecret.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/templates/admission-webhooks/job-patch/job-patchWebhook.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/templates/admission-webhooks/job-patch/networkpolicy.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/templates/admission-webhooks/job-patch/psp.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/templates/admission-webhooks/job-patch/role.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/templates/admission-webhooks/job-patch/rolebinding.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/templates/admission-webhooks/job-patch/serviceaccount.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/templates/admission-webhooks/validating-webhook.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/templates/clusterrole.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/templates/clusterrolebinding.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-configmap-addheaders.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-configmap-proxyheaders.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-configmap-tcp.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-configmap-udp.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-configmap.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-daemonset.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-daemonset.yaml.orig create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-deployment.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-hpa.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-ingressclass.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-keda.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-networkpolicy.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-poddisruptionbudget.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-prometheusrules.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-psp.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-role.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-rolebinding.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-secret.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-service-internal.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-service-metrics.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-service-webhook.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-service.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-serviceaccount.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-servicemonitor.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/templates/default-backend-deployment.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/templates/default-backend-extra-configmaps.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/templates/default-backend-hpa.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/templates/default-backend-networkpolicy.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/templates/default-backend-poddisruptionbudget.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/templates/default-backend-psp.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/templates/default-backend-role.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/templates/default-backend-rolebinding.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/templates/default-backend-service.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/templates/default-backend-serviceaccount.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/tests/default-backend-extra-configmaps_test.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/values.yaml create mode 100644 packages/system/ingress-nginx/patches/add-metrics2.patch create mode 100644 packages/system/ingress-nginx/values.yaml create mode 100644 packages/system/kamaji-etcd/.helmignore create mode 100644 packages/system/kamaji-etcd/Chart.yaml create mode 100644 packages/system/kamaji-etcd/Makefile create mode 100644 packages/system/kamaji-etcd/charts/kamaji-etcd/.helmignore create mode 100644 packages/system/kamaji-etcd/charts/kamaji-etcd/Chart.yaml create mode 100644 packages/system/kamaji-etcd/charts/kamaji-etcd/Makefile create mode 100644 packages/system/kamaji-etcd/charts/kamaji-etcd/README.md create mode 100644 packages/system/kamaji-etcd/charts/kamaji-etcd/README.md.gotmpl create mode 100644 packages/system/kamaji-etcd/charts/kamaji-etcd/templates/_helpers.tpl create mode 100644 packages/system/kamaji-etcd/charts/kamaji-etcd/templates/etcd_alerts.yaml create mode 100644 packages/system/kamaji-etcd/charts/kamaji-etcd/templates/etcd_cm.yaml create mode 100644 packages/system/kamaji-etcd/charts/kamaji-etcd/templates/etcd_cronjob_backup.yaml create mode 100644 packages/system/kamaji-etcd/charts/kamaji-etcd/templates/etcd_cronjob_defrag.yaml create mode 100644 packages/system/kamaji-etcd/charts/kamaji-etcd/templates/etcd_datastore.yaml create mode 100644 packages/system/kamaji-etcd/charts/kamaji-etcd/templates/etcd_job_postdelete.yaml create mode 100644 packages/system/kamaji-etcd/charts/kamaji-etcd/templates/etcd_job_preinstall_1.yaml create mode 100644 packages/system/kamaji-etcd/charts/kamaji-etcd/templates/etcd_job_preinstall_2.yaml create mode 100644 packages/system/kamaji-etcd/charts/kamaji-etcd/templates/etcd_job_s3retention.yaml create mode 100644 packages/system/kamaji-etcd/charts/kamaji-etcd/templates/etcd_metrics_rbac.yaml create mode 100644 packages/system/kamaji-etcd/charts/kamaji-etcd/templates/etcd_rbac.yaml create mode 100644 packages/system/kamaji-etcd/charts/kamaji-etcd/templates/etcd_sa.yaml create mode 100644 packages/system/kamaji-etcd/charts/kamaji-etcd/templates/etcd_service.yaml create mode 100644 packages/system/kamaji-etcd/charts/kamaji-etcd/templates/etcd_service_monitor.yaml create mode 100644 packages/system/kamaji-etcd/charts/kamaji-etcd/templates/etcd_sts.yaml create mode 100644 packages/system/kamaji-etcd/charts/kamaji-etcd/values.yaml create mode 100644 packages/system/kamaji-etcd/patches/fix-svc.diff create mode 100644 packages/system/kamaji-etcd/patches/fullnameOverride.diff create mode 100644 packages/system/kamaji-etcd/templates/datastore.yaml create mode 100644 packages/system/kamaji/.helmignore create mode 100644 packages/system/kamaji/Chart.yaml create mode 100644 packages/system/kamaji/Makefile create mode 100644 packages/system/kamaji/charts/kamaji/.helmignore create mode 100644 packages/system/kamaji/charts/kamaji/Chart.yaml create mode 100644 packages/system/kamaji/charts/kamaji/Makefile create mode 100644 packages/system/kamaji/charts/kamaji/README.md create mode 100644 packages/system/kamaji/charts/kamaji/README.md.gotmpl create mode 100644 packages/system/kamaji/charts/kamaji/app-readme.md create mode 100644 packages/system/kamaji/charts/kamaji/crds/datastore.yaml create mode 100644 packages/system/kamaji/charts/kamaji/crds/tenantcontrolplane.yaml create mode 100644 packages/system/kamaji/charts/kamaji/templates/NOTES.txt create mode 100644 packages/system/kamaji/charts/kamaji/templates/_helpers.tpl create mode 100644 packages/system/kamaji/charts/kamaji/templates/_helpers_datastore.tpl create mode 100644 packages/system/kamaji/charts/kamaji/templates/_helpers_etcd.tpl create mode 100644 packages/system/kamaji/charts/kamaji/templates/certmanager_certificate.yaml create mode 100644 packages/system/kamaji/charts/kamaji/templates/certmanager_issuer.yaml create mode 100644 packages/system/kamaji/charts/kamaji/templates/controller.yaml create mode 100644 packages/system/kamaji/charts/kamaji/templates/datastore.yaml create mode 100644 packages/system/kamaji/charts/kamaji/templates/etcd_cm.yaml create mode 100644 packages/system/kamaji/charts/kamaji/templates/etcd_job_postdelete.yaml create mode 100644 packages/system/kamaji/charts/kamaji/templates/etcd_job_postinstall.yaml create mode 100644 packages/system/kamaji/charts/kamaji/templates/etcd_job_preinstall.yaml create mode 100644 packages/system/kamaji/charts/kamaji/templates/etcd_rbac.yaml create mode 100644 packages/system/kamaji/charts/kamaji/templates/etcd_sa.yaml create mode 100644 packages/system/kamaji/charts/kamaji/templates/etcd_service.yaml create mode 100644 packages/system/kamaji/charts/kamaji/templates/etcd_sts.yaml create mode 100644 packages/system/kamaji/charts/kamaji/templates/mutatingwebhookconfiguration.yaml create mode 100644 packages/system/kamaji/charts/kamaji/templates/rbac.yaml create mode 100644 packages/system/kamaji/charts/kamaji/templates/service_metrics.yaml create mode 100644 packages/system/kamaji/charts/kamaji/templates/service_webhook.yaml create mode 100644 packages/system/kamaji/charts/kamaji/templates/servicemonitor.yaml create mode 100644 packages/system/kamaji/charts/kamaji/templates/validatingwebhookconfiguration.yaml create mode 100644 packages/system/kamaji/charts/kamaji/values.sample.yaml create mode 100644 packages/system/kamaji/charts/kamaji/values.yaml create mode 100644 packages/system/kamaji/values.yaml create mode 100644 packages/system/kubeovn/Chart.yaml create mode 100644 packages/system/kubeovn/Makefile create mode 100644 packages/system/kubeovn/charts/kube-ovn/Chart.yaml create mode 100644 packages/system/kubeovn/charts/kube-ovn/README.md create mode 100644 packages/system/kubeovn/charts/kube-ovn/crds/crd.yaml create mode 100644 packages/system/kubeovn/charts/kube-ovn/templates/_helpers.tpl create mode 100644 packages/system/kubeovn/charts/kube-ovn/templates/central-deploy.yaml create mode 100644 packages/system/kubeovn/charts/kube-ovn/templates/controller-deploy.yaml create mode 100644 packages/system/kubeovn/charts/kube-ovn/templates/controller-svc.yaml create mode 100644 packages/system/kubeovn/charts/kube-ovn/templates/monitor-deploy.yaml create mode 100644 packages/system/kubeovn/charts/kube-ovn/templates/monitor-svc.yaml create mode 100644 packages/system/kubeovn/charts/kube-ovn/templates/nb-svc.yaml create mode 100644 packages/system/kubeovn/charts/kube-ovn/templates/northd-svc.yaml create mode 100644 packages/system/kubeovn/charts/kube-ovn/templates/ovn-CR.yaml create mode 100644 packages/system/kubeovn/charts/kube-ovn/templates/ovn-CRB.yaml create mode 100644 packages/system/kubeovn/charts/kube-ovn/templates/ovn-dpdk-ds.yaml create mode 100644 packages/system/kubeovn/charts/kube-ovn/templates/ovn-sa.yaml create mode 100644 packages/system/kubeovn/charts/kube-ovn/templates/ovn-tls-secret.yaml create mode 100644 packages/system/kubeovn/charts/kube-ovn/templates/ovncni-ds.yaml create mode 100644 packages/system/kubeovn/charts/kube-ovn/templates/ovncni-svc.yaml create mode 100644 packages/system/kubeovn/charts/kube-ovn/templates/ovsovn-ds.yaml create mode 100644 packages/system/kubeovn/charts/kube-ovn/templates/pinger-ds.yaml create mode 100644 packages/system/kubeovn/charts/kube-ovn/templates/pinger-svc.yaml create mode 100644 packages/system/kubeovn/charts/kube-ovn/templates/pre-delete-hook.yaml create mode 100644 packages/system/kubeovn/charts/kube-ovn/templates/sb-svc.yaml create mode 100644 packages/system/kubeovn/charts/kube-ovn/templates/upgrade-ovs-ovn.yaml create mode 100755 packages/system/kubeovn/charts/kube-ovn/templates/vpc-nat-config.yaml create mode 100644 packages/system/kubeovn/charts/kube-ovn/values.yaml create mode 100644 packages/system/kubeovn/patches/cozyconfig.diff create mode 100644 packages/system/kubeovn/values.yaml create mode 100644 packages/system/kubevirt-cdi-operator/Chart.yaml create mode 100644 packages/system/kubevirt-cdi-operator/Makefile create mode 100644 packages/system/kubevirt-cdi-operator/templates/cdi-operator.yaml create mode 100644 packages/system/kubevirt-cdi/Chart.yaml create mode 100644 packages/system/kubevirt-cdi/Makefile create mode 100644 packages/system/kubevirt-cdi/templates/cdi-cr.yaml create mode 100644 packages/system/kubevirt-csi-node/Chart.yaml create mode 100644 packages/system/kubevirt-csi-node/templates/deploy.yaml create mode 100644 packages/system/kubevirt-operator/Chart.yaml create mode 100644 packages/system/kubevirt-operator/Makefile create mode 100644 packages/system/kubevirt-operator/templates/kubevirt-operator.yaml create mode 100644 packages/system/kubevirt-operator/values.yaml create mode 100644 packages/system/kubevirt/Chart.yaml create mode 100644 packages/system/kubevirt/Makefile create mode 100644 packages/system/kubevirt/templates/kubevirt-cr.yaml create mode 100644 packages/system/kubevirt/values.yaml create mode 100644 packages/system/linstor/.helmignore create mode 100644 packages/system/linstor/Chart.yaml create mode 100644 packages/system/linstor/Makefile create mode 100644 packages/system/linstor/examples/1.yaml create mode 100644 packages/system/linstor/hack/proxmox-install-module.sh create mode 100644 packages/system/linstor/templates/cluster.yaml create mode 100644 packages/system/linstor/templates/linstor-api-tls.yaml create mode 100644 packages/system/linstor/templates/linstor-internal-tls.yaml create mode 100644 packages/system/linstor/templates/satellites.yaml create mode 100644 packages/system/linstor/values.yaml create mode 100644 packages/system/mariadb-operator/.helmignore create mode 100644 packages/system/mariadb-operator/Chart.yaml create mode 100644 packages/system/mariadb-operator/Makefile create mode 100644 packages/system/mariadb-operator/charts/mariadb-operator/.helmignore create mode 100644 packages/system/mariadb-operator/charts/mariadb-operator/Chart.yaml create mode 100644 packages/system/mariadb-operator/charts/mariadb-operator/README.md create mode 100644 packages/system/mariadb-operator/charts/mariadb-operator/README.md.gotmpl create mode 100644 packages/system/mariadb-operator/charts/mariadb-operator/crds/crds.yaml create mode 100644 packages/system/mariadb-operator/charts/mariadb-operator/templates/NOTES.txt create mode 100644 packages/system/mariadb-operator/charts/mariadb-operator/templates/_helpers.tpl create mode 100644 packages/system/mariadb-operator/charts/mariadb-operator/templates/deployment.yaml create mode 100644 packages/system/mariadb-operator/charts/mariadb-operator/templates/rbac.yaml create mode 100644 packages/system/mariadb-operator/charts/mariadb-operator/templates/serviceaccount.yaml create mode 100644 packages/system/mariadb-operator/charts/mariadb-operator/templates/servicemonitor.yaml create mode 100644 packages/system/mariadb-operator/charts/mariadb-operator/templates/webhook-certificate.yaml create mode 100644 packages/system/mariadb-operator/charts/mariadb-operator/templates/webhook-config.yaml create mode 100644 packages/system/mariadb-operator/charts/mariadb-operator/templates/webhook-deployment.yaml create mode 100644 packages/system/mariadb-operator/charts/mariadb-operator/templates/webhook-service.yaml create mode 100644 packages/system/mariadb-operator/charts/mariadb-operator/templates/webhook-serviceaccount.yaml create mode 100644 packages/system/mariadb-operator/charts/mariadb-operator/templates/webhook-servicemonitor.yaml create mode 100644 packages/system/mariadb-operator/charts/mariadb-operator/values.yaml create mode 100644 packages/system/mariadb-operator/values.yaml create mode 100644 packages/system/metallb/Chart.yaml create mode 100644 packages/system/metallb/Makefile create mode 100644 packages/system/metallb/charts/metallb/.helmignore create mode 100644 packages/system/metallb/charts/metallb/Chart.lock create mode 100644 packages/system/metallb/charts/metallb/Chart.yaml create mode 100644 packages/system/metallb/charts/metallb/README.md create mode 100644 packages/system/metallb/charts/metallb/charts/crds/.helmignore create mode 100644 packages/system/metallb/charts/metallb/charts/crds/Chart.yaml create mode 100644 packages/system/metallb/charts/metallb/charts/crds/README.md create mode 100644 packages/system/metallb/charts/metallb/charts/crds/templates/crds.yaml create mode 100644 packages/system/metallb/charts/metallb/policy/controller.rego create mode 100644 packages/system/metallb/charts/metallb/policy/rbac.rego create mode 100644 packages/system/metallb/charts/metallb/policy/speaker.rego create mode 100644 packages/system/metallb/charts/metallb/templates/NOTES.txt create mode 100644 packages/system/metallb/charts/metallb/templates/_helpers.tpl create mode 100644 packages/system/metallb/charts/metallb/templates/controller.yaml create mode 100644 packages/system/metallb/charts/metallb/templates/deprecated_configInline.yaml create mode 100644 packages/system/metallb/charts/metallb/templates/exclude-l2-config.yaml create mode 100644 packages/system/metallb/charts/metallb/templates/podmonitor.yaml create mode 100644 packages/system/metallb/charts/metallb/templates/prometheusrules.yaml create mode 100644 packages/system/metallb/charts/metallb/templates/rbac.yaml create mode 100644 packages/system/metallb/charts/metallb/templates/service-accounts.yaml create mode 100644 packages/system/metallb/charts/metallb/templates/servicemonitor.yaml create mode 100644 packages/system/metallb/charts/metallb/templates/speaker.yaml create mode 100644 packages/system/metallb/charts/metallb/templates/webhooks.yaml create mode 100644 packages/system/metallb/charts/metallb/values.schema.json create mode 100644 packages/system/metallb/charts/metallb/values.yaml create mode 100644 packages/system/metallb/values.yaml create mode 100644 packages/system/monitoring/.helmignore create mode 100644 packages/system/monitoring/Chart.yaml create mode 100644 packages/system/monitoring/Makefile create mode 100644 packages/system/monitoring/alerts/general.yaml create mode 100644 packages/system/monitoring/alerts/kube-dns.yaml create mode 100644 packages/system/monitoring/alerts/kube-state-metrics.yaml create mode 100644 packages/system/monitoring/alerts/kubelet.yaml create mode 100644 packages/system/monitoring/alerts/node-disk-usage.yaml create mode 100644 packages/system/monitoring/alerts/node.yaml create mode 100644 packages/system/monitoring/alerts/pod-status.yaml create mode 100644 packages/system/monitoring/charts/kube-state-metrics/.helmignore create mode 100644 packages/system/monitoring/charts/kube-state-metrics/Chart.yaml create mode 100644 packages/system/monitoring/charts/kube-state-metrics/README.md create mode 100644 packages/system/monitoring/charts/kube-state-metrics/templates/NOTES.txt create mode 100644 packages/system/monitoring/charts/kube-state-metrics/templates/_helpers.tpl create mode 100644 packages/system/monitoring/charts/kube-state-metrics/templates/ciliumnetworkpolicy.yaml create mode 100644 packages/system/monitoring/charts/kube-state-metrics/templates/clusterrolebinding.yaml create mode 100644 packages/system/monitoring/charts/kube-state-metrics/templates/crs-configmap.yaml create mode 100644 packages/system/monitoring/charts/kube-state-metrics/templates/deployment.yaml create mode 100644 packages/system/monitoring/charts/kube-state-metrics/templates/extra-manifests.yaml create mode 100644 packages/system/monitoring/charts/kube-state-metrics/templates/kubeconfig-secret.yaml create mode 100644 packages/system/monitoring/charts/kube-state-metrics/templates/networkpolicy.yaml create mode 100644 packages/system/monitoring/charts/kube-state-metrics/templates/pdb.yaml create mode 100644 packages/system/monitoring/charts/kube-state-metrics/templates/podsecuritypolicy.yaml create mode 100644 packages/system/monitoring/charts/kube-state-metrics/templates/psp-clusterrole.yaml create mode 100644 packages/system/monitoring/charts/kube-state-metrics/templates/psp-clusterrolebinding.yaml create mode 100644 packages/system/monitoring/charts/kube-state-metrics/templates/rbac-configmap.yaml create mode 100644 packages/system/monitoring/charts/kube-state-metrics/templates/role.yaml create mode 100644 packages/system/monitoring/charts/kube-state-metrics/templates/rolebinding.yaml create mode 100644 packages/system/monitoring/charts/kube-state-metrics/templates/service.yaml create mode 100644 packages/system/monitoring/charts/kube-state-metrics/templates/serviceaccount.yaml create mode 100644 packages/system/monitoring/charts/kube-state-metrics/templates/servicemonitor.yaml create mode 100644 packages/system/monitoring/charts/kube-state-metrics/templates/stsdiscovery-role.yaml create mode 100644 packages/system/monitoring/charts/kube-state-metrics/templates/stsdiscovery-rolebinding.yaml create mode 100644 packages/system/monitoring/charts/kube-state-metrics/templates/verticalpodautoscaler.yaml create mode 100644 packages/system/monitoring/charts/kube-state-metrics/values.yaml create mode 100644 packages/system/monitoring/charts/metrics-server/.helmignore create mode 100644 packages/system/monitoring/charts/metrics-server/Chart.yaml create mode 100644 packages/system/monitoring/charts/metrics-server/README.md create mode 100644 packages/system/monitoring/charts/metrics-server/ci/ci-values.yaml create mode 100644 packages/system/monitoring/charts/metrics-server/templates/NOTES.txt create mode 100644 packages/system/monitoring/charts/metrics-server/templates/_helpers.tpl create mode 100644 packages/system/monitoring/charts/metrics-server/templates/apiservice.yaml create mode 100644 packages/system/monitoring/charts/metrics-server/templates/clusterrole-aggregated-reader.yaml create mode 100644 packages/system/monitoring/charts/metrics-server/templates/clusterrole-nanny.yaml create mode 100644 packages/system/monitoring/charts/metrics-server/templates/clusterrole.yaml create mode 100644 packages/system/monitoring/charts/metrics-server/templates/clusterrolebinding-auth-delegator.yaml create mode 100644 packages/system/monitoring/charts/metrics-server/templates/clusterrolebinding-nanny.yaml create mode 100644 packages/system/monitoring/charts/metrics-server/templates/clusterrolebinding.yaml create mode 100644 packages/system/monitoring/charts/metrics-server/templates/configmaps-nanny.yaml create mode 100644 packages/system/monitoring/charts/metrics-server/templates/deployment.yaml create mode 100644 packages/system/monitoring/charts/metrics-server/templates/pdb.yaml create mode 100644 packages/system/monitoring/charts/metrics-server/templates/psp.yaml create mode 100644 packages/system/monitoring/charts/metrics-server/templates/role-nanny.yaml create mode 100644 packages/system/monitoring/charts/metrics-server/templates/rolebinding-nanny.yaml create mode 100644 packages/system/monitoring/charts/metrics-server/templates/rolebinding.yaml create mode 100644 packages/system/monitoring/charts/metrics-server/templates/service.yaml create mode 100644 packages/system/monitoring/charts/metrics-server/templates/serviceaccount.yaml create mode 100644 packages/system/monitoring/charts/metrics-server/templates/servicemonitor.yaml create mode 100644 packages/system/monitoring/charts/metrics-server/values.yaml create mode 100644 packages/system/monitoring/charts/prometheus-node-exporter/.helmignore create mode 100644 packages/system/monitoring/charts/prometheus-node-exporter/Chart.yaml create mode 100644 packages/system/monitoring/charts/prometheus-node-exporter/README.md create mode 100644 packages/system/monitoring/charts/prometheus-node-exporter/ci/port-values.yaml create mode 100644 packages/system/monitoring/charts/prometheus-node-exporter/templates/NOTES.txt create mode 100644 packages/system/monitoring/charts/prometheus-node-exporter/templates/_helpers.tpl create mode 100644 packages/system/monitoring/charts/prometheus-node-exporter/templates/clusterrole.yaml create mode 100644 packages/system/monitoring/charts/prometheus-node-exporter/templates/clusterrolebinding.yaml create mode 100644 packages/system/monitoring/charts/prometheus-node-exporter/templates/daemonset.yaml create mode 100644 packages/system/monitoring/charts/prometheus-node-exporter/templates/endpoints.yaml create mode 100644 packages/system/monitoring/charts/prometheus-node-exporter/templates/extra-manifests.yaml create mode 100644 packages/system/monitoring/charts/prometheus-node-exporter/templates/networkpolicy.yaml create mode 100644 packages/system/monitoring/charts/prometheus-node-exporter/templates/podmonitor.yaml create mode 100644 packages/system/monitoring/charts/prometheus-node-exporter/templates/psp-clusterrole.yaml create mode 100644 packages/system/monitoring/charts/prometheus-node-exporter/templates/psp-clusterrolebinding.yaml create mode 100644 packages/system/monitoring/charts/prometheus-node-exporter/templates/psp.yaml create mode 100644 packages/system/monitoring/charts/prometheus-node-exporter/templates/rbac-configmap.yaml create mode 100644 packages/system/monitoring/charts/prometheus-node-exporter/templates/service.yaml create mode 100644 packages/system/monitoring/charts/prometheus-node-exporter/templates/serviceaccount.yaml create mode 100644 packages/system/monitoring/charts/prometheus-node-exporter/templates/servicemonitor.yaml create mode 100644 packages/system/monitoring/charts/prometheus-node-exporter/templates/verticalpodautoscaler.yaml create mode 100644 packages/system/monitoring/charts/prometheus-node-exporter/values.yaml create mode 100644 packages/system/monitoring/templates/additional-scrape-configs.yaml create mode 100644 packages/system/monitoring/templates/apiserver-scrape.yaml create mode 100644 packages/system/monitoring/templates/cadvisor-scrape.yaml create mode 100644 packages/system/monitoring/templates/coredns-scrape.yaml create mode 100644 packages/system/monitoring/templates/etcd-scrape.yaml create mode 100644 packages/system/monitoring/templates/kube-controller-manager-scrape.yaml create mode 100644 packages/system/monitoring/templates/kube-scheduler-scrape.yaml create mode 100644 packages/system/monitoring/templates/kube-state-metrics-scrape.yaml create mode 100644 packages/system/monitoring/templates/kubelet-scrape.yaml create mode 100644 packages/system/monitoring/templates/nginx-scrape.yaml create mode 100644 packages/system/monitoring/templates/node-exporter-scrape.yaml create mode 100644 packages/system/monitoring/templates/vmagent-scrape.yaml create mode 100644 packages/system/monitoring/templates/vmagent.yaml create mode 100644 packages/system/monitoring/templates/vmoperator-scrape.yaml create mode 100644 packages/system/monitoring/templates/vmrules.yaml create mode 100644 packages/system/monitoring/values.yaml create mode 100644 packages/system/piraeus-operator/.helmignore create mode 100644 packages/system/piraeus-operator/Chart.yaml create mode 100644 packages/system/piraeus-operator/Makefile create mode 100644 packages/system/piraeus-operator/charts/piraeus/.helmignore create mode 100644 packages/system/piraeus-operator/charts/piraeus/Chart.yaml create mode 100644 packages/system/piraeus-operator/charts/piraeus/README.md create mode 100644 packages/system/piraeus-operator/charts/piraeus/templates/NOTES.txt create mode 100644 packages/system/piraeus-operator/charts/piraeus/templates/_helpers.tpl create mode 100644 packages/system/piraeus-operator/charts/piraeus/templates/config.yaml create mode 100644 packages/system/piraeus-operator/charts/piraeus/templates/crds.yaml create mode 100644 packages/system/piraeus-operator/charts/piraeus/templates/deployment.yaml create mode 100644 packages/system/piraeus-operator/charts/piraeus/templates/metrics-service.yaml create mode 100644 packages/system/piraeus-operator/charts/piraeus/templates/rbac.yaml create mode 100644 packages/system/piraeus-operator/charts/piraeus/templates/validating-webhook-configuration.yaml create mode 100644 packages/system/piraeus-operator/charts/piraeus/templates/webhook-service.yaml create mode 100644 packages/system/piraeus-operator/charts/piraeus/values.yaml create mode 100644 packages/system/piraeus-operator/examples/1.yaml create mode 100644 packages/system/piraeus-operator/hack/proxmox-install-module.sh create mode 100644 packages/system/piraeus-operator/templates/piraeus-tls.yaml create mode 100644 packages/system/piraeus-operator/values.yaml create mode 100644 packages/system/postgres-operator/.helmignore create mode 100644 packages/system/postgres-operator/Chart.yaml create mode 100644 packages/system/postgres-operator/Makefile create mode 100644 packages/system/postgres-operator/charts/cloudnative-pg/.helmignore create mode 100644 packages/system/postgres-operator/charts/cloudnative-pg/Chart.yaml create mode 100644 packages/system/postgres-operator/charts/cloudnative-pg/LICENSE create mode 100644 packages/system/postgres-operator/charts/cloudnative-pg/README.md create mode 100644 packages/system/postgres-operator/charts/cloudnative-pg/templates/NOTES.txt create mode 100644 packages/system/postgres-operator/charts/cloudnative-pg/templates/_helpers.tpl create mode 100644 packages/system/postgres-operator/charts/cloudnative-pg/templates/config.yaml create mode 100644 packages/system/postgres-operator/charts/cloudnative-pg/templates/crds/crds.yaml create mode 100644 packages/system/postgres-operator/charts/cloudnative-pg/templates/deployment.yaml create mode 100644 packages/system/postgres-operator/charts/cloudnative-pg/templates/monitoring-configmap.yaml create mode 100644 packages/system/postgres-operator/charts/cloudnative-pg/templates/mutatingwebhookconfiguration.yaml create mode 100644 packages/system/postgres-operator/charts/cloudnative-pg/templates/podmonitor.yaml create mode 100644 packages/system/postgres-operator/charts/cloudnative-pg/templates/rbac.yaml create mode 100644 packages/system/postgres-operator/charts/cloudnative-pg/templates/service.yaml create mode 100644 packages/system/postgres-operator/charts/cloudnative-pg/templates/validatingwebhookconfiguration.yaml create mode 100644 packages/system/postgres-operator/charts/cloudnative-pg/values.schema.json create mode 100644 packages/system/postgres-operator/charts/cloudnative-pg/values.yaml create mode 100644 packages/system/postgres-operator/values.yaml create mode 100644 packages/system/rabbitmq-operator/Chart.yaml create mode 100644 packages/system/rabbitmq-operator/Makefile create mode 100644 packages/system/rabbitmq-operator/templates/cluster-operator.yml create mode 100644 packages/system/rabbitmq-operator/values.yaml create mode 100644 packages/system/redis-operator/Chart.yaml create mode 100644 packages/system/redis-operator/Makefile create mode 100644 packages/system/redis-operator/charts/redis-operator/.helmignore create mode 100644 packages/system/redis-operator/charts/redis-operator/Chart.yaml create mode 100644 packages/system/redis-operator/charts/redis-operator/crds/databases.spotahome.com_redisfailovers.yaml create mode 100644 packages/system/redis-operator/charts/redis-operator/templates/_helpers.tpl create mode 100644 packages/system/redis-operator/charts/redis-operator/templates/_versions.tpl create mode 100644 packages/system/redis-operator/charts/redis-operator/templates/deployment.yaml create mode 100644 packages/system/redis-operator/charts/redis-operator/templates/monitoring.yaml create mode 100644 packages/system/redis-operator/charts/redis-operator/templates/private-registry.yaml create mode 100644 packages/system/redis-operator/charts/redis-operator/templates/service-account.yaml create mode 100644 packages/system/redis-operator/charts/redis-operator/templates/service.yaml create mode 100644 packages/system/redis-operator/charts/redis-operator/values.yaml create mode 100644 packages/system/redis-operator/values.yaml create mode 100644 packages/system/telepresence/Chart.yaml create mode 100644 packages/system/telepresence/Makefile create mode 100644 packages/system/telepresence/charts/telepresence/.gitignore create mode 100644 packages/system/telepresence/charts/telepresence/.helmignore create mode 100644 packages/system/telepresence/charts/telepresence/CHANGELOG.md create mode 100644 packages/system/telepresence/charts/telepresence/Chart.yaml create mode 100644 packages/system/telepresence/charts/telepresence/README.md create mode 100644 packages/system/telepresence/charts/telepresence/templates/NOTES.txt create mode 100644 packages/system/telepresence/charts/telepresence/templates/_helpers.tpl create mode 100644 packages/system/telepresence/charts/telepresence/templates/agent-configmap.yaml create mode 100644 packages/system/telepresence/charts/telepresence/templates/agentInjectorWebhook.yaml create mode 100644 packages/system/telepresence/charts/telepresence/templates/clientRbac/cluster-scope.yaml create mode 100644 packages/system/telepresence/charts/telepresence/templates/clientRbac/connect.yaml create mode 100644 packages/system/telepresence/charts/telepresence/templates/clientRbac/namespace-scope.yaml create mode 100644 packages/system/telepresence/charts/telepresence/templates/deployment.yaml create mode 100644 packages/system/telepresence/charts/telepresence/templates/intercept-env-configmap.yaml create mode 100644 packages/system/telepresence/charts/telepresence/templates/licenseSecret.yaml create mode 100644 packages/system/telepresence/charts/telepresence/templates/post-upgrade-hook.yaml create mode 100644 packages/system/telepresence/charts/telepresence/templates/pre-delete-hook.yaml create mode 100644 packages/system/telepresence/charts/telepresence/templates/service.yaml create mode 100644 packages/system/telepresence/charts/telepresence/templates/tests/test-connection.yaml create mode 100644 packages/system/telepresence/charts/telepresence/templates/trafficManager-configmap.yaml create mode 100644 packages/system/telepresence/charts/telepresence/templates/trafficManagerRbac/cloud-token.yaml create mode 100644 packages/system/telepresence/charts/telepresence/templates/trafficManagerRbac/cluster-scope.yaml create mode 100644 packages/system/telepresence/charts/telepresence/templates/trafficManagerRbac/namespace-claim.yaml create mode 100644 packages/system/telepresence/charts/telepresence/templates/trafficManagerRbac/namespace-scope.yaml create mode 100644 packages/system/telepresence/charts/telepresence/templates/trafficManagerRbac/service-account.yaml create mode 100644 packages/system/telepresence/charts/telepresence/values.yaml create mode 100644 packages/system/telepresence/values.yaml create mode 100644 packages/system/victoria-metrics-operator/Chart.yaml create mode 100644 packages/system/victoria-metrics-operator/Makefile create mode 100644 packages/system/victoria-metrics-operator/charts/prometheus-operator-crds/.helmignore create mode 100644 packages/system/victoria-metrics-operator/charts/prometheus-operator-crds/Chart.yaml create mode 100644 packages/system/victoria-metrics-operator/charts/prometheus-operator-crds/README.md create mode 100644 packages/system/victoria-metrics-operator/charts/prometheus-operator-crds/hack/update_crds.sh create mode 100644 packages/system/victoria-metrics-operator/charts/prometheus-operator-crds/templates/crd-podmonitors.yaml create mode 100644 packages/system/victoria-metrics-operator/charts/prometheus-operator-crds/templates/crd-probes.yaml create mode 100644 packages/system/victoria-metrics-operator/charts/prometheus-operator-crds/templates/crd-prometheusrules.yaml create mode 100644 packages/system/victoria-metrics-operator/charts/prometheus-operator-crds/templates/crd-servicemonitors.yaml create mode 100644 packages/system/victoria-metrics-operator/charts/prometheus-operator-crds/values.yaml create mode 100644 packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/.helmignore create mode 100644 packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/CHANGELOG.md create mode 100644 packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/Chart.yaml create mode 100644 packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/README.md create mode 100644 packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/README.md.gotmpl create mode 100644 packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/RELEASE_NOTES.md create mode 100644 packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/templates/NOTES.txt create mode 100644 packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/templates/_helpers.tpl create mode 100644 packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/templates/certmanager.yaml create mode 100644 packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/templates/cluster_role.yaml create mode 100644 packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/templates/clusterrole_binding.yaml create mode 100644 packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/templates/crd.yaml create mode 100644 packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/templates/deployment.yaml create mode 100644 packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/templates/pdb.yaml create mode 100644 packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/templates/psp.yaml create mode 100644 packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/templates/role.yaml create mode 100644 packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/templates/role_binding.yaml create mode 100644 packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/templates/service.yaml create mode 100644 packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/templates/service_account.yaml create mode 100644 packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/templates/service_scrape.yaml create mode 100644 packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/templates/uninstall_hook.yaml create mode 100644 packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/templates/webhook.yaml create mode 100644 packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/values.yaml create mode 100644 packages/system/victoria-metrics-operator/values.yaml create mode 100755 scripts/installer.sh diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 00000000..c1d18d8a --- /dev/null +++ b/.dockerignore @@ -0,0 +1 @@ +_out diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..c1d18d8a --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +_out diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..261eeb9e --- /dev/null +++ b/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 [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..e0d3e4a4 --- /dev/null +++ b/Makefile @@ -0,0 +1,15 @@ +.PHONY: manifests repos assets + +manifests: + (cd packages/core/installer/; helm template -n cozy-installer installer .) > manifests/cozystack-installer.yaml + +repos: + rm -rf _out + make -C packages/apps check-version-map + make -C packages/extra check-version-map + make -C packages/system repo + make -C packages/apps repo + make -C packages/extra repo + +assets: + make -C packages/core/talos/ assets diff --git a/README.md b/README.md new file mode 100644 index 00000000..e6b5025b --- /dev/null +++ b/README.md @@ -0,0 +1,560 @@ +![Cozystack](img/cozystack-logo.svg) + +[![Open Source](https://img.shields.io/badge/Open-Source-brightgreen)](https://opensource.org/) +[![Apache-2.0 License](https://img.shields.io/github/license/aenix-io/cozystack)](https://opensource.org/licenses/) +[![Support](https://img.shields.io/badge/$-support-12a0df.svg?style=flat)](https://aenix.io/contact-us/#meet) +[![Active](http://img.shields.io/badge/Status-Active-green.svg)](https://aenix.io/cozystack/) +[![GitHub Release](https://img.shields.io/github/release/aenix-io/cozystack.svg?style=flat)](https://github.com/aenix-io/cozystack) +[![GitHub Commit](https://img.shields.io/github/commit-activity/y/aenix-io/cozystack)](https://github.com/aenix-io/cozystack) + +# Cozystack + +**Cozystack** is an open-source **PaaS platform** for cloud providers. + +With Cozystack, you can transform your bunch of servers into an intelligent system with a simple REST API for spawning Kubernetes clusters, Database-as-a-Service, virtual machines, load balancers, HTTP caching services, and other services with ease. + +You can use Cozystack to build your own cloud or to provide a cost-effective development environments. + +## Use-Cases + +### As a backend for a public cloud + +Cozystack positions itself as a kind of framework for building public clouds. The key word here is framework. In this case, it's important to understand that Cozystack is made for cloud providers, not for end users. + +Despite having a graphical interface, the current security model does not imply public user access to your management cluster. + +Instead, end users get access to their own Kubernetes clusters, can order LoadBalancers and additional services from it, but they have no access and know nothing about your management cluster powered by Cozystack. + +Thus, to integrate with your billing system, it's enough to teach your system to go to the management Kubernetes and place a YAML file signifying the service you're interested in. Cozystack will do the rest of the work for you. + +![](https://aenix.io/wp-content/uploads/2024/02/Wireframe-1.png) + +### As a private cloud for Infrastructure-as-Code + +One of the use cases is a self-portal for users within your company, where they can order the service they're interested in or a managed database. + +You can implement best GitOps practices, where users will launch their own Kubernetes clusters and databases for their needs with a simple commit of configuration into your infrastructure Git repository. + +Thanks to the standardization of the approach to deploying applications, you can expand the platform's capabilities using the functionality of standard Helm charts. + +### As a Kubernetes distribution for Bare Metal + +We created Cozystack primarily for our own needs, having vast experience in building reliable systems on bare metal infrastructure. This experience led to the formation of a separate boxed product, which is aimed at standardizing and providing a ready-to-use tool for managing your infrastructure. + +Currently, Cozystack already solves a huge scope of infrastructure tasks: starting from provisioning bare metal servers, having a ready monitoring system, fast and reliable storage, a network fabric with the possibility of interconnect with your infrastructure, the ability to run virtual machines, databases, and much more right out of the box. + +All this makes Cozystack a convenient platform for delivering and launching your application on Bare Metal. + +## Screenshot + +![](https://aenix.io/wp-content/uploads/2023/12/cozystack1-1.png) + +## Core values + +### Standardization and unification +All components of the platform are based on open source tools and technologies which are widely known in the industry. + +### Collaborate, not compete +If a feature being developed for the platform could be useful to a upstream project, it should be contributed to upstream project, rather than being implemented within the platform. + +### API-first +Cozystack is based on Kubernetes and involves close interaction with its API. We don't aim to completely hide the all elements behind a pretty UI or any sort of customizations; instead, we provide a standard interface and teach users how to work with basic primitives. The web interface is used solely for deploying applications and quickly diving into basic concepts of platform. + +## Quick Start + +### Preapre infrastructure + + +![](https://aenix.io/wp-content/uploads/2024/02/Wireframe-2.png) + +You need 3 physical servers or VMs with nested virtualisation: + +``` +CPU: 4 cores +CPU model: host +RAM: 8-16 GB +HDD1: 32 GB +HDD2: 100GB (raw) +``` + +And one management VM or physical server connected to the same network. +Any Linux system installed on it (eg. Ubuntu should be enough) + +**Note:** The VM should support `x86-64-v2` architecture, the most probably you can achieve this by setting cpu model to `host` + +#### Install dependicies: + +- `docker` +- `talosctl` +- `dialog` +- `nmap` +- `make` +- `yq` +- `kubectl` +- `helm` + +### Netboot server + +Start matchbox with prebuilt Talos image for Cozystack: + +```bash +sudo docker run --name=matchbox -d --net=host ghcr.io/aenix-io/cozystack/matchbox:v0.0.1 \ + -address=:8080 \ + -log-level=debug +``` + +Start DHCP-Server: +```bash +sudo docker run --name=dnsmasq -d --cap-add=NET_ADMIN --net=host quay.io/poseidon/dnsmasq \ + -d -q -p0 \ + --dhcp-range=192.168.100.3,192.168.100.254 \ + --dhcp-option=option:router,192.168.100.1 \ + --enable-tftp \ + --tftp-root=/var/lib/tftpboot \ + --dhcp-match=set:bios,option:client-arch,0 \ + --dhcp-boot=tag:bios,undionly.kpxe \ + --dhcp-match=set:efi32,option:client-arch,6 \ + --dhcp-boot=tag:efi32,ipxe.efi \ + --dhcp-match=set:efibc,option:client-arch,7 \ + --dhcp-boot=tag:efibc,ipxe.efi \ + --dhcp-match=set:efi64,option:client-arch,9 \ + --dhcp-boot=tag:efi64,ipxe.efi \ + --dhcp-userclass=set:ipxe,iPXE \ + --dhcp-boot=tag:ipxe,http://192.168.100.254:8080/boot.ipxe \ + --log-queries \ + --log-dhcp +``` + +Where: +- `192.168.100.3,192.168.100.254` range to allocate IPs from +- `192.168.100.1` your gateway +- `192.168.100.254` is address of your management server + +Check status of containers: + +``` +docker ps +``` + +example output: + +```console +CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES +22044f26f74d quay.io/poseidon/dnsmasq "/usr/sbin/dnsmasq -…" 6 seconds ago Up 5 seconds dnsmasq +231ad81ff9e0 ghcr.io/aenix-io/cozystack/matchbox:v0.0.1 "/matchbox -address=…" 58 seconds ago Up 57 seconds matchbox +``` + +### Bootstrap cluster + +Write configuration for Cozystack: + +```yaml +cat > patch.yaml <<\EOT +machine: + kubelet: + nodeIP: + validSubnets: + - 192.168.100.0/24 + kernel: + modules: + - name: openvswitch + - name: drbd + parameters: + - usermode_helper=disabled + - name: zfs + install: + image: ghcr.io/aenix-io/cozystack/talos:v1.6.4 + files: + - content: | + [plugins] + [plugins."io.containerd.grpc.v1.cri"] + device_ownership_from_security_context = true + path: /etc/cri/conf.d/20-customization.part + op: create + +cluster: + network: + cni: + name: none + podSubnets: + - 10.244.0.0/16 + serviceSubnets: + - 10.96.0.0/16 +EOT + +cat > patch-controlplane.yaml <<\EOT +cluster: + allowSchedulingOnControlPlanes: true + controllerManager: + extraArgs: + bind-address: 0.0.0.0 + scheduler: + extraArgs: + bind-address: 0.0.0.0 + apiServer: + certSANs: + - 127.0.0.1 + proxy: + disabled: true + discovery: + enabled: false + etcd: + advertisedSubnets: + - 192.168.100.0/24 +EOT +``` + +Run [talos-bootstrap](https://github.com/aenix-io/talos-bootstrap/) to deploy cluster: + +```bash +talos-bootstrap install +``` + +Save admin kubeconfig to access your Kubernetes cluster: +```bash +cp -i kubeconfig ~/.kube/config +``` + +Check connection: +```bash +kubectl get ns +``` + +example output: +```console +NAME STATUS AGE +default Active 7m56s +kube-node-lease Active 7m56s +kube-public Active 7m56s +kube-system Active 7m56s +``` + +### Install Cozystack + + +write config for cozystack: + +**Note:** please make sure that you written the same setting specified in `patch.yaml` and `patch-controlplane.yaml` files. + +```yaml +cat > cozystack-config.yaml <<\EOT +apiVersion: v1 +kind: ConfigMap +metadata: + name: cozystack + namespace: cozy-system +data: + cluster-name: "cozystack" + ipv4-pod-cidr: "10.244.0.0/16" + ipv4-pod-gateway: "10.244.0.1" + ipv4-svc-cidr: "10.96.0.0/16" + ipv4-join-cidr: "100.64.0.0/16" +EOT +``` + +Create namesapce and install Cozystack system components: + +```bash +kubectl create ns cozy-system +kubectl apply -f cozystack-config.yaml +kubectl apply -f manifests/cozystack-installer.yaml +``` + +(optional) You can track the logs of installer: +```bash +kubectl logs -n cozy-system deploy/cozystack -f +``` + +Wait for a while, then check the status of installation: +```bash +kubectl get hr -A +``` + +Wait until all releases become to `Ready` state: +```console +NAMESPACE NAME AGE READY STATUS +cozy-cert-manager cert-manager 4m1s True Release reconciliation succeeded +cozy-cert-manager cert-manager-issuers 4m1s True Release reconciliation succeeded +cozy-cilium cilium 4m1s True Release reconciliation succeeded +cozy-cluster-api capi-operator 4m1s True Release reconciliation succeeded +cozy-cluster-api capi-providers 4m1s True Release reconciliation succeeded +cozy-dashboard dashboard 4m1s True Release reconciliation succeeded +cozy-fluxcd cozy-fluxcd 4m1s True Release reconciliation succeeded +cozy-grafana-operator grafana-operator 4m1s True Release reconciliation succeeded +cozy-kamaji kamaji 4m1s True Release reconciliation succeeded +cozy-kubeovn kubeovn 4m1s True Release reconciliation succeeded +cozy-kubevirt-cdi kubevirt-cdi 4m1s True Release reconciliation succeeded +cozy-kubevirt-cdi kubevirt-cdi-operator 4m1s True Release reconciliation succeeded +cozy-kubevirt kubevirt 4m1s True Release reconciliation succeeded +cozy-kubevirt kubevirt-operator 4m1s True Release reconciliation succeeded +cozy-linstor linstor 4m1s True Release reconciliation succeeded +cozy-linstor piraeus-operator 4m1s True Release reconciliation succeeded +cozy-mariadb-operator mariadb-operator 4m1s True Release reconciliation succeeded +cozy-metallb metallb 4m1s True Release reconciliation succeeded +cozy-monitoring monitoring 4m1s True Release reconciliation succeeded +cozy-postgres-operator postgres-operator 4m1s True Release reconciliation succeeded +cozy-rabbitmq-operator rabbitmq-operator 4m1s True Release reconciliation succeeded +cozy-redis-operator redis-operator 4m1s True Release reconciliation succeeded +cozy-telepresence telepresence 4m1s True Release reconciliation succeeded +cozy-victoria-metrics-operator victoria-metrics-operator 4m1s True Release reconciliation succeeded +tenant-root tenant-root 4m1s True Release reconciliation succeeded +``` + +#### Configure Storage + +Setup alias to access LINSTOR: +```bash +alias linstor='kubectl exec -n cozy-linstor deploy/linstor-controller -- linstor' +``` + +list your nodes +```bash +linstor node list +``` + +example output: + +```console ++-------------------------------------------------------+ +| Node | NodeType | Addresses | State | +|=======================================================| +| srv1 | SATELLITE | 192.168.100.11:3367 (SSL) | Online | +| srv2 | SATELLITE | 192.168.100.12:3367 (SSL) | Online | +| srv3 | SATELLITE | 192.168.100.13:3367 (SSL) | Online | ++-------------------------------------------------------+ +``` + +list empty devices: + +```bash +linstor physical-storage list +``` + +example output: +```console ++--------------------------------------------+ +| Size | Rotational | Nodes | +|============================================| +| 107374182400 | True | srv3[/dev/sdb] | +| | | srv1[/dev/sdb] | +| | | srv2[/dev/sdb] | ++--------------------------------------------+ +``` + + +create storage pools: + +```bash +linstor ps cdp lvm srv1 /dev/sdb --pool-name data --storage-pool data +linstor ps cdp lvm srv2 /dev/sdb --pool-name data --storage-pool data +linstor ps cdp lvm srv3 /dev/sdb --pool-name data --storage-pool data +``` + +list storage pools: + +```bash +linstor sp l +``` + +example output: + +```console ++-------------------------------------------------------------------------------------------------------------------------------------+ +| StoragePool | Node | Driver | PoolName | FreeCapacity | TotalCapacity | CanSnapshots | State | SharedName | +|=====================================================================================================================================| +| DfltDisklessStorPool | srv1 | DISKLESS | | | | False | Ok | srv1;DfltDisklessStorPool | +| DfltDisklessStorPool | srv2 | DISKLESS | | | | False | Ok | srv2;DfltDisklessStorPool | +| DfltDisklessStorPool | srv3 | DISKLESS | | | | False | Ok | srv3;DfltDisklessStorPool | +| data | srv1 | LVM | data | 100.00 GiB | 100.00 GiB | False | Ok | srv1;data | +| data | srv2 | LVM | data | 100.00 GiB | 100.00 GiB | False | Ok | srv2;data | +| data | srv3 | LVM | data | 100.00 GiB | 100.00 GiB | False | Ok | srv3;data | ++-------------------------------------------------------------------------------------------------------------------------------------+ +``` + + +Create default storage classes: +```yaml +kubectl create -f- < 2m10s +data-etcd-1 Bound pvc-1579f95a-a69d-4a26-bcc2-b15ccdbede0d 10Gi RWO local 115s +data-etcd-2 Bound pvc-907009e5-88bf-4d18-91e7-b56b0dbfb97e 10Gi RWO local 91s +grafana-db-1 Bound pvc-7b3f4e23-228a-46fd-b820-d033ef4679af 10Gi RWO local 2m41s +grafana-db-2 Bound pvc-ac9b72a4-f40e-47e8-ad24-f50d843b55e4 10Gi RWO local 113s +vmselect-cachedir-vmselect-longterm-0 Bound pvc-622fa398-2104-459f-8744-565eee0a13f1 2Gi RWO local 2m21s +vmselect-cachedir-vmselect-longterm-1 Bound pvc-fc9349f5-02b2-4e25-8bef-6cbc5cc6d690 2Gi RWO local 2m21s +vmselect-cachedir-vmselect-shortterm-0 Bound pvc-7acc7ff6-6b9b-4676-bd1f-6867ea7165e2 2Gi RWO local 2m41s +vmselect-cachedir-vmselect-shortterm-1 Bound pvc-e514f12b-f1f6-40ff-9838-a6bda3580eb7 2Gi RWO local 2m40s +vmstorage-db-vmstorage-longterm-0 Bound pvc-e8ac7fc3-df0d-4692-aebf-9f66f72f9fef 10Gi RWO local 2m21s +vmstorage-db-vmstorage-longterm-1 Bound pvc-68b5ceaf-3ed1-4e5a-9568-6b95911c7c3a 10Gi RWO local 2m21s +vmstorage-db-vmstorage-shortterm-0 Bound pvc-cee3a2a4-5680-4880-bc2a-85c14dba9380 10Gi RWO local 2m41s +vmstorage-db-vmstorage-shortterm-1 Bound pvc-d55c235d-cada-4c4a-8299-e5fc3f161789 10Gi RWO local 2m41s +``` + +Check all pods are running: + + +```bash +kubectl get pod -n tenant-root +``` + +example output: +```console +NAME READY STATUS RESTARTS AGE +etcd-0 1/1 Running 0 2m1s +etcd-1 1/1 Running 0 106s +etcd-2 1/1 Running 0 82s +grafana-db-1 1/1 Running 0 119s +grafana-db-2 1/1 Running 0 13s +grafana-deployment-74b5656d6-5dcvn 1/1 Running 0 90s +grafana-deployment-74b5656d6-q5589 1/1 Running 1 (105s ago) 111s +root-ingress-controller-6ccf55bc6d-pg79l 2/2 Running 0 2m27s +root-ingress-controller-6ccf55bc6d-xbs6x 2/2 Running 0 2m29s +root-ingress-defaultbackend-686bcbbd6c-5zbvp 1/1 Running 0 2m29s +vmalert-vmalert-644986d5c-7hvwk 2/2 Running 0 2m30s +vmalertmanager-alertmanager-0 2/2 Running 0 2m32s +vmalertmanager-alertmanager-1 2/2 Running 0 2m31s +vminsert-longterm-75789465f-hc6cz 1/1 Running 0 2m10s +vminsert-longterm-75789465f-m2v4t 1/1 Running 0 2m12s +vminsert-shortterm-78456f8fd9-wlwww 1/1 Running 0 2m29s +vminsert-shortterm-78456f8fd9-xg7cw 1/1 Running 0 2m28s +vmselect-longterm-0 1/1 Running 0 2m12s +vmselect-longterm-1 1/1 Running 0 2m12s +vmselect-shortterm-0 1/1 Running 0 2m31s +vmselect-shortterm-1 1/1 Running 0 2m30s +vmstorage-longterm-0 1/1 Running 0 2m12s +vmstorage-longterm-1 1/1 Running 0 2m12s +vmstorage-shortterm-0 1/1 Running 0 2m32s +vmstorage-shortterm-1 1/1 Running 0 2m31s +``` + +Now you can get public IP of ingress controller: +``` +kubectl get svc -n tenant-root root-ingress-controller +``` + +example output: +```console +NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE +root-ingress-controller LoadBalancer 10.96.16.141 192.168.100.200 80:31632/TCP,443:30113/TCP 3m33s +``` + +Use `grafana.example.org` (under 192.168.100.200) to access system monitoring, where `example.org` is your domain specified for `tenant-root` + +- login: `admin` +- password: + +```bash +kubectl get secret -n tenant-root grafana-admin-password -o go-template='{{ printf "%s\n" (index .data "password" | base64decode) }}' +``` diff --git a/dashboards/.gitignore b/dashboards/.gitignore new file mode 100644 index 00000000..1944fd61 --- /dev/null +++ b/dashboards/.gitignore @@ -0,0 +1 @@ +*.tmp diff --git a/dashboards/cache/nginx-vts-stats.json b/dashboards/cache/nginx-vts-stats.json new file mode 100644 index 00000000..0297d72a --- /dev/null +++ b/dashboards/cache/nginx-vts-stats.json @@ -0,0 +1,3038 @@ +{ + "__inputs": [ + { + "name": "DS_VM", + "label": "vm", + "description": "", + "type": "datasource", + "pluginId": "prometheus", + "pluginName": "Prometheus" + } + ], + "__elements": {}, + "__requires": [ + { + "type": "grafana", + "id": "grafana", + "name": "Grafana", + "version": "10.1.0" + }, + { + "type": "panel", + "id": "graph", + "name": "Graph (old)", + "version": "" + }, + { + "type": "datasource", + "id": "prometheus", + "name": "Prometheus", + "version": "1.0.0" + } + ], + "annotations": { + "list": [ + { + "$$hashKey": "object:19", + "builtIn": 1, + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "description": "Show stats from nginx VTS module (direct, without exporter)", + "editable": true, + "fiscalYearStartMonth": 0, + "gnetId": 12164, + "graphTooltip": 1, + "id": null, + "links": [], + "liveNow": false, + "panels": [ + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 17, + "panels": [], + "title": "General", + "type": "row" + }, + { + "aliasColors": { + "1xx": "yellow", + "2xx": "green", + "3xx": "blue" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "description": "Requests per second grouped by response code", + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 1 + }, + "hiddenSeries": false, + "id": 3, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "10.1.0", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "editorMode": "code", + "expr": "sum(rate(nginx_vts_server_requests_total{namespace=\"$namespace\", service=~\"$service\", code!=\"total\", host=~\"$host\", pod=~\"$pod\"}[$__rate_interval])) by (code)", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "{{ code }}", + "metric": "nginx_vts_server_requests_total", + "range": true, + "refId": "A", + "step": 240 + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Requests", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:5308", + "format": "reqps", + "logBase": 10, + "min": "0", + "show": true + }, + { + "$$hashKey": "object:5309", + "format": "short", + "logBase": 1, + "show": false + } + ], + "yaxis": { + "align": false + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 1 + }, + "hiddenSeries": false, + "id": 1, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "10.1.0", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "editorMode": "code", + "expr": "sum(rate(nginx_vts_main_connections{namespace=\"$namespace\", service=~\"$service\", status=~\"active|writing|reading|waiting\", pod=~\"$pod\"}[$__rate_interval])) by (status)", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "{{status}}", + "range": true, + "refId": "B" + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Connections", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:5813", + "format": "short", + "logBase": 1, + "show": true + }, + { + "$$hashKey": "object:5814", + "format": "short", + "logBase": 1, + "show": true + } + ], + "yaxis": { + "align": false + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 8 + }, + "hiddenSeries": false, + "id": 15, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "connected", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "10.1.0", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "editorMode": "code", + "expr": "avg(nginx_vts_server_request_seconds{namespace=\"$namespace\", service=~\"$service\", host=~\"$host\", pod=~\"$pod\"} > 0) by (pod)", + "instant": false, + "interval": "", + "intervalFactor": 2, + "legendFormat": "{{ pod }} ", + "refId": "A" + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Average response time", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:434", + "format": "s", + "logBase": 1, + "show": true + }, + { + "$$hashKey": "object:435", + "format": "short", + "logBase": 1, + "show": true + } + ], + "yaxis": { + "align": false + } + }, + { + "aliasColors": { + "in": "blue", + "out": "green" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 8 + }, + "hiddenSeries": false, + "id": 2, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "10.1.0", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "editorMode": "code", + "expr": "sum(rate(nginx_vts_server_bytes_total{namespace=\"$namespace\", service=~\"$service\", host=~\"$host\", pod=~\"$pod\"}[$__rate_interval])) by (direction)", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "{{ direction }}", + "metric": "nginx_vts_server_bytes_total", + "range": true, + "refId": "A", + "step": 240 + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Throughput", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:5223", + "format": "Bps", + "logBase": 2, + "show": true + }, + { + "$$hashKey": "object:5224", + "format": "short", + "logBase": 1, + "show": true + } + ], + "yaxis": { + "align": false + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 15 + }, + "hiddenSeries": false, + "id": 11, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "10.1.0", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "editorMode": "code", + "expr": "sum(nginx_vts_main_shm_usage_bytes{namespace=\"$namespace\", service=~\"$service\", pod=~\"$pod\"}) by (shared)", + "legendFormat": "{{ shared }}", + "range": true, + "refId": "A" + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Shared memory", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:6072", + "format": "bytes", + "logBase": 10, + "show": true + }, + { + "$$hashKey": "object:6073", + "format": "short", + "logBase": 1, + "show": true + } + ], + "yaxis": { + "align": false + } + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 22 + }, + "id": 25, + "panels": [], + "title": "Filtered", + "type": "row" + }, + { + "aliasColors": { + "1xx": "yellow", + "2xx": "green", + "3xx": "blue" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "description": "Requests per second grouped by response code", + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 23 + }, + "hiddenSeries": false, + "id": 21, + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "10.1.0", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "editorMode": "code", + "expr": "sum(rate(label_replace(nginx_vts_filter_requests_total{namespace=\"$namespace\", service=~\"$service\", code!=\"total\", filter=~\"region::.*\", filter_name=~\"$host\", pod=~\"$pod\"}[$__rate_interval], \"region\", \"$1\", \"filter\", \"region::(.*)\"))) by (region)", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "{{ code }}", + "metric": "nginx_vts_server_requests_total", + "range": true, + "refId": "A", + "step": 240 + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Requests by region", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:5308", + "format": "reqps", + "logBase": 10, + "min": "0", + "show": true + }, + { + "$$hashKey": "object:5309", + "format": "short", + "logBase": 1, + "show": false + } + ], + "yaxis": { + "align": false + } + }, + { + "aliasColors": { + "in": "blue", + "out": "green" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 23 + }, + "hiddenSeries": false, + "id": 22, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "10.1.0", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "editorMode": "code", + "expr": "sum(rate(label_replace(nginx_vts_filter_bytes_total{namespace=\"$namespace\", service=~\"$service\", code!=\"total\", filter=~\"region::.*\", filter_name=~\"$host\", pod=~\"$pod\"}[$__rate_interval], \"region\", \"$1\", \"filter\", \"region::(.*)\"))) by (region)", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "{{ direction }}", + "metric": "nginx_vts_server_bytes_total", + "range": true, + "refId": "A", + "step": 240 + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Throughput by region", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:5223", + "format": "Bps", + "logBase": 2, + "show": true + }, + { + "$$hashKey": "object:5224", + "format": "short", + "logBase": 1, + "show": true + } + ], + "yaxis": { + "align": false + } + }, + { + "aliasColors": { + "1xx": "yellow", + "2xx": "green", + "3xx": "blue" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "description": "Requests per second grouped by response code", + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 30 + }, + "hiddenSeries": false, + "id": 16, + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "10.1.0", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "editorMode": "code", + "expr": "sum(rate(nginx_vts_server_requests_total{namespace=\"$namespace\", service=~\"$service\", host=~\"$host\", host!=\"*\", pod=~\"$pod\"}[$__rate_interval]) > 0) by (host)", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "{{ host }}", + "metric": "nginx_vts_server_requests_total", + "range": true, + "refId": "A", + "step": 240 + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Requests by host", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:12783", + "format": "reqps", + "logBase": 2, + "min": "0", + "show": true + }, + { + "$$hashKey": "object:12784", + "format": "short", + "logBase": 1, + "show": false + } + ], + "yaxis": { + "align": false + } + }, + { + "aliasColors": { + "1xx": "yellow", + "2xx": "green", + "3xx": "blue" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "description": "Requests per second grouped by response code", + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 30 + }, + "hiddenSeries": false, + "id": 23, + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "10.1.0", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "editorMode": "code", + "expr": "sum(rate(nginx_vts_server_bytes_total{namespace=\"$namespace\", service=~\"$service\", host=~\"$host\", pod=~\"$pod\"}[$__rate_interval])) by (host)", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "{{ host }}", + "metric": "nginx_vts_server_requests_total", + "range": true, + "refId": "A", + "step": 240 + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Throughput by host", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:12783", + "format": "reqps", + "logBase": 2, + "min": "0", + "show": true + }, + { + "$$hashKey": "object:12784", + "format": "short", + "logBase": 1, + "show": false + } + ], + "yaxis": { + "align": false + } + }, + { + "aliasColors": { + "1xx": "yellow", + "2xx": "green", + "3xx": "blue" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "description": "Requests per second grouped by response code", + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 37 + }, + "hiddenSeries": false, + "id": 32, + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "10.1.0", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "editorMode": "code", + "expr": "sum(rate(nginx_vts_filter_requests_total{namespace=\"$namespace\", service=~\"$service\", code!=\"total\", filter=~\"url::$host\", pod=~\"$pod\"}[$__rate_interval])) by (filter_name)", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "{{ host }}", + "metric": "nginx_vts_server_requests_total", + "range": true, + "refId": "A", + "step": 240 + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Requests by URL", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:12783", + "format": "reqps", + "logBase": 2, + "min": "0", + "show": true + }, + { + "$$hashKey": "object:12784", + "format": "short", + "logBase": 1, + "show": false + } + ], + "yaxis": { + "align": false + } + }, + { + "aliasColors": { + "1xx": "yellow", + "2xx": "green", + "3xx": "blue" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "description": "Requests per second grouped by response code", + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 37 + }, + "hiddenSeries": false, + "id": 33, + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "10.1.0", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "editorMode": "code", + "expr": "sum(rate(nginx_vts_filter_bytes_total{namespace=\"$namespace\", service=~\"$service\", pod=~\"$pod\", filter=~\"url::$host\"}[$__rate_interval])) by (filter_name)", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "{{ host }}", + "metric": "nginx_vts_server_requests_total", + "range": true, + "refId": "A", + "step": 240 + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Throughput by URL", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:12783", + "format": "reqps", + "logBase": 2, + "min": "0", + "show": true + }, + { + "$$hashKey": "object:12784", + "format": "short", + "logBase": 1, + "show": false + } + ], + "yaxis": { + "align": false + } + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 44 + }, + "id": 24, + "panels": [], + "title": "Upstream", + "type": "row" + }, + { + "aliasColors": { + "1xx": "yellow", + "2xx": "green", + "3xx": "blue", + "4xx": "orange", + "5xx": "red" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "description": "This one is providing aggregated error codes, but it's still possible to graph these per upstream.", + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 45 + }, + "hiddenSeries": false, + "id": 6, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "10.1.0", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "editorMode": "code", + "expr": "sum(rate(nginx_vts_upstream_requests_total{namespace=\"$namespace\", service=~\"$service\", pod=~\"$pod\", code!=\"total\"}[$__rate_interval])) by (code)", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "{{ code }}", + "metric": "nginx_vts_upstream_requests_total", + "range": true, + "refId": "A", + "step": 240 + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Upstream requests", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:6157", + "format": "reqps", + "logBase": 2, + "min": "0", + "show": true + }, + { + "$$hashKey": "object:6158", + "format": "short", + "logBase": 1, + "show": true + } + ], + "yaxis": { + "align": false + } + }, + { + "aliasColors": { + "in": "blue", + "out": "green" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 45 + }, + "hiddenSeries": false, + "id": 5, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "10.1.0", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "editorMode": "code", + "expr": "sum(rate(nginx_vts_upstream_bytes_total{namespace=\"$namespace\", service=~\"$service\", pod=~\"$pod\"}[$__rate_interval])) by (direction)", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "{{ direction }}", + "metric": "nginx_vts_upstream_bytes_total", + "range": true, + "refId": "A", + "step": 240 + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Upstream throughput", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:5900", + "format": "Bps", + "logBase": 2, + "show": true + }, + { + "$$hashKey": "object:5901", + "format": "short", + "logBase": 1, + "show": true + } + ], + "yaxis": { + "align": false + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 52 + }, + "hiddenSeries": false, + "id": 7, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "10.1.0", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "editorMode": "code", + "expr": "avg(nginx_vts_upstream_response_seconds{namespace=\"$namespace\", service=~\"$service\", pod=~\"$pod\"} > 0) by (backend)", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "{{ backend }}", + "metric": "nginx_vts_upstream_response_seconds", + "range": true, + "refId": "A", + "step": 120 + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Upstream response time", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:5985", + "format": "s", + "logBase": 1, + "show": true + }, + { + "$$hashKey": "object:5986", + "format": "short", + "logBase": 1, + "show": true + } + ], + "yaxis": { + "align": false + } + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 59 + }, + "id": 19, + "panels": [], + "title": "Cache", + "type": "row" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 60 + }, + "hiddenSeries": false, + "id": 4, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "10.1.0", + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeatDirection": "h", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "editorMode": "code", + "expr": "sum(increase(nginx_vts_server_cache_total{namespace=\"$namespace\", service=~\"$service\", pod=~\"$pod\", host=~\"$host\"}[$__rate_interval])) by (status)", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "{{ status }}", + "metric": "nginx_server_cache", + "range": true, + "refId": "A", + "step": 240 + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Cache events", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:12851", + "format": "short", + "logBase": 2, + "min": "0", + "show": true + }, + { + "$$hashKey": "object:12852", + "format": "short", + "logBase": 1, + "show": true + } + ], + "yaxis": { + "align": false + } + }, + { + "aliasColors": { + "in": "blue", + "max": "red", + "out": "yellow" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 60 + }, + "hiddenSeries": false, + "id": 13, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "10.1.0", + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeatDirection": "h", + "seriesOverrides": [ + { + "$$hashKey": "object:5553", + "alias": "in", + "yaxis": 1 + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "editorMode": "code", + "expr": "sum(rate(nginx_vts_cache_bytes_total{namespace=\"$namespace\", service=~\"$service\", pod=~\"$pod\"}[$__rate_interval])) by (direction)", + "format": "time_series", + "instant": false, + "interval": "", + "intervalFactor": 2, + "legendFormat": "{{ direction }}", + "metric": "nginx_server_cache", + "refId": "A", + "step": 240 + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Cache throughput", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:5560", + "format": "Bps", + "logBase": 10, + "show": true + }, + { + "$$hashKey": "object:5561", + "format": "short", + "logBase": 1, + "show": true + } + ], + "yaxis": { + "align": false + } + }, + { + "aliasColors": { + "max": "red" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 67 + }, + "hiddenSeries": false, + "id": 12, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "10.1.0", + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeatDirection": "h", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "editorMode": "code", + "expr": "max(sum(nginx_vts_cache_usage_bytes{namespace=\"$namespace\", service=~\"$service\", cache_size=\"max\", pod=~\"$pod\"}) by (pod))", + "format": "time_series", + "instant": false, + "interval": "", + "intervalFactor": 2, + "legendFormat": "max", + "metric": "nginx_server_cache", + "refId": "B", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "editorMode": "code", + "expr": "sum(nginx_vts_cache_usage_bytes{namespace=\"$namespace\", service=~\"$service\", cache_size=\"used\", pod=~\"$pod\"}) by (pod)", + "format": "time_series", + "hide": false, + "instant": false, + "interval": "", + "intervalFactor": 2, + "legendFormat": "{{ pod }}", + "metric": "nginx_server_cache", + "refId": "A", + "step": 240 + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Cache usage", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:5728", + "format": "decbytes", + "logBase": 10, + "show": true + }, + { + "$$hashKey": "object:5729", + "format": "short", + "logBase": 1, + "show": true + } + ], + "yaxis": { + "align": false + } + }, + { + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 74 + }, + "id": 28, + "panels": [], + "title": "Cache Fitered", + "type": "row" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 75 + }, + "hiddenSeries": false, + "id": 20, + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "10.1.0", + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeatDirection": "h", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "editorMode": "code", + "expr": "sum(increase(label_replace(nginx_vts_filter_cache_total{namespace=\"$namespace\", service=~\"$service\", code!=\"total\", filter=~\"region::.*\", filter_name=~\"$host\", pod=~\"$pod\", status=\"hit\"}[$__rate_interval], \"region\", \"$1\", \"filter\", \"region::(.*)\"))) by (region)", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "__auto", + "metric": "nginx_server_cache", + "range": true, + "refId": "A", + "step": 240 + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Cache HIT by region", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:12851", + "format": "short", + "logBase": 2, + "min": "0", + "show": true + }, + { + "$$hashKey": "object:12852", + "format": "short", + "logBase": 1, + "show": true + } + ], + "yaxis": { + "align": false + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 75 + }, + "hiddenSeries": false, + "id": 35, + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "10.1.0", + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeatDirection": "h", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "editorMode": "code", + "expr": "sum(increase(label_replace(nginx_vts_filter_cache_total{namespace=\"$namespace\", service=~\"$service\", code!=\"total\", filter=~\"region::.*\", filter_name=~\"$host\", pod=~\"$pod\", status=\"hit\"}[$__rate_interval], \"region\", \"$1\", \"filter\", \"region::(.*)\"))) by (filter_name)", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "__auto", + "metric": "nginx_server_cache", + "range": true, + "refId": "A", + "step": 240 + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Cache HIT by host", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:12851", + "format": "short", + "logBase": 2, + "min": "0", + "show": true + }, + { + "$$hashKey": "object:12852", + "format": "short", + "logBase": 1, + "show": true + } + ], + "yaxis": { + "align": false + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 82 + }, + "hiddenSeries": false, + "id": 26, + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "10.1.0", + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeatDirection": "h", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "editorMode": "code", + "expr": "sum(increase(label_replace(nginx_vts_filter_cache_total{namespace=\"$namespace\", service=~\"$service\", code!=\"total\", filter=~\"region::.*\", filter_name=~\"$host\", pod=~\"$pod\", status=\"miss\"}[$__rate_interval], \"region\", \"$1\", \"filter\", \"region::(.*)\"))) by (region)", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "__auto", + "metric": "nginx_server_cache", + "range": true, + "refId": "A", + "step": 240 + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Cache MISS by region", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:12851", + "format": "short", + "logBase": 2, + "min": "0", + "show": true + }, + { + "$$hashKey": "object:12852", + "format": "short", + "logBase": 1, + "show": true + } + ], + "yaxis": { + "align": false + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 82 + }, + "hiddenSeries": false, + "id": 36, + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "10.1.0", + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeatDirection": "h", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "editorMode": "code", + "expr": "sum(increase(label_replace(nginx_vts_filter_cache_total{namespace=\"$namespace\", service=~\"$service\", code!=\"total\", filter=~\"region::.*\", filter_name=~\"$host\", pod=~\"$pod\", status=\"miss\"}[$__rate_interval], \"region\", \"$1\", \"filter\", \"region::(.*)\"))) by (filter_name)", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "__auto", + "metric": "nginx_server_cache", + "range": true, + "refId": "A", + "step": 240 + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Cache MISS by host", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:12851", + "format": "short", + "logBase": 2, + "min": "0", + "show": true + }, + { + "$$hashKey": "object:12852", + "format": "short", + "logBase": 1, + "show": true + } + ], + "yaxis": { + "align": false + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 89 + }, + "hiddenSeries": false, + "id": 27, + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "10.1.0", + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeatDirection": "h", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "editorMode": "code", + "expr": "sum(increase(label_replace(nginx_vts_filter_cache_total{namespace=\"$namespace\", service=~\"$service\", code!=\"total\", filter=~\"region::.*\", filter_name=~\"$host\", pod=~\"$pod\", status=\"stale\"}[$__rate_interval], \"region\", \"$1\", \"filter\", \"region::(.*)\"))) by (region)", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "__auto", + "metric": "nginx_server_cache", + "range": true, + "refId": "A", + "step": 240 + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Cache STALE by region", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:12851", + "format": "short", + "logBase": 2, + "min": "0", + "show": true + }, + { + "$$hashKey": "object:12852", + "format": "short", + "logBase": 1, + "show": true + } + ], + "yaxis": { + "align": false + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 89 + }, + "hiddenSeries": false, + "id": 37, + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "10.1.0", + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeatDirection": "h", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "editorMode": "code", + "expr": "sum(increase(label_replace(nginx_vts_filter_cache_total{namespace=\"$namespace\", service=~\"$service\", code!=\"total\", filter=~\"region::.*\", filter_name=~\"$host\", pod=~\"$pod\", status=\"stale\"}[$__rate_interval], \"region\", \"$1\", \"filter\", \"region::(.*)\"))) by (filter_name)", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "__auto", + "metric": "nginx_server_cache", + "range": true, + "refId": "A", + "step": 240 + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Cache STALE by host", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:12851", + "format": "short", + "logBase": 2, + "min": "0", + "show": true + }, + { + "$$hashKey": "object:12852", + "format": "short", + "logBase": 1, + "show": true + } + ], + "yaxis": { + "align": false + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 96 + }, + "hiddenSeries": false, + "id": 34, + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "10.1.0", + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeatDirection": "h", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "editorMode": "code", + "expr": "sum(increase(nginx_vts_filter_cache_total{namespace=\"$namespace\", service=~\"$service\", pod=~\"$pod\", filter=~\"url::$host\", status=\"hit\"}[$__rate_interval])) by (filter_name)", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "__auto", + "metric": "nginx_server_cache", + "range": true, + "refId": "A", + "step": 240 + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Cache HIT by URL", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:12851", + "format": "short", + "logBase": 2, + "min": "0", + "show": true + }, + { + "$$hashKey": "object:12852", + "format": "short", + "logBase": 1, + "show": true + } + ], + "yaxis": { + "align": false + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 103 + }, + "hiddenSeries": false, + "id": 30, + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "10.1.0", + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeatDirection": "h", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "editorMode": "code", + "expr": "sum(increase(nginx_vts_filter_cache_total{namespace=\"$namespace\", service=~\"$service\", pod=~\"$pod\", filter=~\"url::$host\", status=\"miss\"}[$__rate_interval])) by (filter_name)", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "__auto", + "metric": "nginx_server_cache", + "range": true, + "refId": "A", + "step": 240 + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Cache MISS by URL", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:12851", + "format": "short", + "logBase": 2, + "min": "0", + "show": true + }, + { + "$$hashKey": "object:12852", + "format": "short", + "logBase": 1, + "show": true + } + ], + "yaxis": { + "align": false + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 110 + }, + "hiddenSeries": false, + "id": 31, + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "10.1.0", + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeatDirection": "h", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "editorMode": "code", + "expr": "sum(increase(nginx_vts_filter_cache_total{namespace=\"$namespace\", service=~\"$service\", pod=~\"$pod\", filter=~\"url::$host\", status=\"stale\"}[$__rate_interval])) by (filter_name)", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "__auto", + "metric": "nginx_server_cache", + "range": true, + "refId": "A", + "step": 240 + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Cache STALE by URL", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:12851", + "format": "short", + "logBase": 2, + "min": "0", + "show": true + }, + { + "$$hashKey": "object:12852", + "format": "short", + "logBase": 1, + "show": true + } + ], + "yaxis": { + "align": false + } + } + ], + "refresh": "", + "schemaVersion": 38, + "style": "dark", + "tags": [], + "templating": { + "list": [ + { + "current": { + "selected": false, + "text": "vm", + "value": "ef98cc92-d988-4b0c-ae21-5d13b6549140" + }, + "description": "", + "hide": 0, + "includeAll": false, + "label": "Datasource", + "multi": false, + "name": "ds_prometheus", + "options": [], + "query": "prometheus", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + }, + { + "current": {}, + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "definition": "label_values(nginx_vts_info, namespace)", + "hide": 0, + "includeAll": false, + "label": "Namespace", + "multi": false, + "name": "namespace", + "options": [], + "query": "label_values(nginx_vts_info, namespace)", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": "", + "current": {}, + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "definition": "label_values(nginx_vts_info{namespace=\"$namespace\"}, service)", + "hide": 0, + "includeAll": true, + "label": "Service", + "multi": false, + "name": "service", + "options": [], + "query": "label_values(nginx_vts_info{namespace=\"$namespace\"}, service)", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": ".{2,}", + "current": {}, + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "definition": "label_values(nginx_vts_server_requests_total{namespace=\"$namespace\", host!=\"*\"}, host)", + "hide": 0, + "includeAll": true, + "label": "HTTP Host", + "multi": false, + "name": "host", + "options": [], + "query": "label_values(nginx_vts_server_requests_total{namespace=\"$namespace\", host!=\"*\"}, host)", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": ".*", + "current": {}, + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "definition": "label_values(nginx_vts_server_requests_total{namespace=\"$namespace\"}, pod)", + "hide": 0, + "includeAll": true, + "label": "Pod", + "multi": false, + "name": "pod", + "options": [], + "query": "label_values(nginx_vts_server_requests_total{namespace=\"$namespace\"}, pod)", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + } + ] + }, + "time": { + "from": "now-3h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "browser", + "title": "Nginx VTS Stats", + "uid": "dee1bbc5-17d0-4e4f-a824-a315d251235d", + "version": 6, + "weekStart": "" +} diff --git a/dashboards/control-plane/control-plane-status.json b/dashboards/control-plane/control-plane-status.json new file mode 100644 index 00000000..8ef14d2d --- /dev/null +++ b/dashboards/control-plane/control-plane-status.json @@ -0,0 +1,2571 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "target": { + "limit": 100, + "matchAny": false, + "tags": [], + "type": "dashboard" + }, + "type": "dashboard" + } + ] + }, + "editable": false, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "iteration": 1675088603120, + "links": [], + "liveNow": false, + "panels": [ + { + "datasource": { + "uid": "$ds_prometheus" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "rgba(245, 54, 54, 0.9)", + "value": null + }, + { + "color": "rgba(237, 129, 40, 0.89)", + "value": 50 + }, + { + "color": "rgba(50, 172, 45, 0.97)", + "value": 80 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 1, + "links": [], + "maxDataPoints": 100, + "options": { + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": true, + "text": {} + }, + "pluginVersion": "8.5.13", + "targets": [ + { + "expr": "(sum(up{job=\"kube-apiserver\"} == 1) / sum(up{job=\"kube-apiserver\"})) * 100", + "format": "time_series", + "instant": true, + "intervalFactor": 1, + "refId": "A", + "step": 600 + } + ], + "title": "API Servers UP", + "type": "gauge" + }, + { + "datasource": { + "uid": "$ds_prometheus" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "rgba(245, 54, 54, 0.9)", + "value": null + }, + { + "color": "rgba(237, 129, 40, 0.89)", + "value": 50 + }, + { + "color": "rgba(50, 172, 45, 0.97)", + "value": 80 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 6, + "x": 6, + "y": 0 + }, + "id": 2, + "links": [], + "maxDataPoints": 100, + "options": { + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": true, + "text": {} + }, + "pluginVersion": "8.5.13", + "targets": [ + { + "expr": "(sum(up{job=\"kube-controller-manager\"} == 1) / sum(up{job=\"kube-controller-manager\"})) * 100", + "format": "time_series", + "instant": true, + "intervalFactor": 1, + "refId": "A", + "step": 600 + } + ], + "title": "Controller Managers UP", + "type": "gauge" + }, + { + "datasource": { + "uid": "$ds_prometheus" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "rgba(245, 54, 54, 0.9)", + "value": null + }, + { + "color": "rgba(237, 129, 40, 0.89)", + "value": 50 + }, + { + "color": "rgba(50, 172, 45, 0.97)", + "value": 80 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 6, + "x": 12, + "y": 0 + }, + "id": 3, + "links": [], + "maxDataPoints": 100, + "options": { + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": true, + "text": {} + }, + "pluginVersion": "8.5.13", + "targets": [ + { + "expr": "(sum(up{job=\"kube-scheduler\"} == 1) / sum(up{job=\"kube-scheduler\"})) * 100", + "format": "time_series", + "instant": true, + "intervalFactor": 1, + "refId": "A", + "step": 600 + } + ], + "title": "Schedulers UP", + "type": "gauge" + }, + { + "datasource": { + "uid": "$ds_prometheus" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 300 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 6, + "x": 18, + "y": 0 + }, + "id": 35, + "options": { + "displayMode": "gradient", + "minVizHeight": 10, + "minVizWidth": 0, + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showUnfilled": true, + "text": {} + }, + "pluginVersion": "8.5.13", + "targets": [ + { + "expr": "count(kube_namespace_created)", + "hide": false, + "legendFormat": "Namespaces", + "refId": "N" + }, + { + "expr": "count(kube_daemonset_created)", + "hide": false, + "legendFormat": "DaemonSets", + "refId": "C" + }, + { + "expr": "count(kube_deployment_created)", + "hide": false, + "legendFormat": "Deployments", + "refId": "D" + }, + { + "expr": "count(kube_statefulset_created)", + "hide": false, + "legendFormat": "StatefulSets", + "refId": "M" + }, + { + "expr": "count(kube_replicaset_created)", + "hide": false, + "legendFormat": "ReplicaSets", + "refId": "B" + }, + { + "expr": "count(kube_pod_created)", + "hide": false, + "legendFormat": "Pods", + "refId": "K" + }, + { + "expr": "count(kube_verticalpodautoscaler_labels)", + "hide": false, + "legendFormat": "VPA", + "refId": "O" + }, + { + "expr": "count(kube_poddisruptionbudget_created)", + "hide": false, + "legendFormat": "PDB", + "refId": "Q" + }, + { + "expr": "count(kube_persistentvolumeclaim_info)", + "hide": false, + "legendFormat": "PVC", + "refId": "J" + }, + { + "expr": "count(kube_persistentvolume_info)", + "hide": false, + "legendFormat": "PV", + "refId": "I" + }, + { + "expr": "count(kube_cronjob_created)", + "hide": false, + "legendFormat": "CronJobs", + "refId": "F" + }, + { + "expr": "count(kube_job_created)", + "hide": false, + "legendFormat": "Jobs", + "refId": "G" + }, + { + "expr": "count(kube_secret_created)", + "hide": false, + "legendFormat": "Secrets", + "refId": "P" + }, + { + "expr": "count(kube_configmap_created)", + "legendFormat": "ConfigMaps", + "refId": "A" + }, + { + "expr": "count(kube_service_created)", + "hide": false, + "legendFormat": "Services", + "refId": "L" + }, + { + "expr": "count(kube_endpoint_created)", + "hide": false, + "legendFormat": "Endpoints", + "refId": "E" + }, + { + "expr": "count(kube_node_created)", + "hide": false, + "legendFormat": "Nodes", + "refId": "H" + } + ], + "title": "Kubernetes Resources Count", + "transformations": [ + { + "id": "organize", + "options": {} + } + ], + "type": "bargauge" + }, + { + "datasource": { + "uid": "$ds_prometheus" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 7 + }, + "id": 9, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.5.13", + "targets": [ + { + "expr": "count(up{job=\"kube-apiserver\"})", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "API Servers count", + "type": "stat" + }, + { + "datasource": { + "uid": "$ds_prometheus" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 6, + "x": 6, + "y": 7 + }, + "id": 10, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.5.13", + "targets": [ + { + "expr": "count(up{job=\"kube-controller-manager\"})", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "Controller Managers count", + "type": "stat" + }, + { + "datasource": { + "uid": "$ds_prometheus" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 6, + "x": 12, + "y": 7 + }, + "id": 11, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.5.13", + "targets": [ + { + "expr": "count(up{job=\"kube-scheduler\"})", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "Schedulers count", + "type": "stat" + }, + { + "collapsed": false, + "datasource": { + "uid": "$ds_prometheus" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 10 + }, + "id": 46, + "panels": [], + "title": "Kube-apiserver", + "type": "row" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "uid": "$ds_prometheus" + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 11 + }, + "hiddenSeries": false, + "id": 31, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.5.13", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "rate(process_cpu_seconds_total{job=\"kube-apiserver\", instance=~\"$instance:.*\"}[$__rate_interval])", + "intervalFactor": 1, + "legendFormat": "{{instance}}", + "refId": "A" + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Kube-apiserver CPU Usage", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:566", + "format": "short", + "label": "CPU Usage", + "logBase": 1, + "show": true + }, + { + "$$hashKey": "object:567", + "format": "short", + "logBase": 1, + "show": true + } + ], + "yaxis": { + "align": false + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "uid": "$ds_prometheus" + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 11 + }, + "hiddenSeries": false, + "id": 33, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.5.13", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "process_resident_memory_bytes{job=\"kube-apiserver\", instance=~\"$instance:.*\"}", + "legendFormat": "{{instance}}", + "refId": "A" + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Kube-apiserver Memory Usage", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:732", + "format": "bytes", + "logBase": 1, + "show": true + }, + { + "$$hashKey": "object:733", + "format": "short", + "logBase": 1, + "show": true + } + ], + "yaxis": { + "align": false + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": { + "uid": "$ds_prometheus" + }, + "description": "", + "fieldConfig": { + "defaults": {}, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Value" + }, + "properties": [ + { + "id": "unit", + "value": "reqps" + } + ] + } + ] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 19 + }, + "hiddenSeries": false, + "id": 27, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.5.13", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": true, + "targets": [ + { + "exemplar": true, + "expr": "sum by(verb) (rate(apiserver_request_total{verb!~\"CONNECT|WATCH\", verb=~\"$verb\", instance=~\"$instance:.*\", resource=~\"$resource\"}[$__rate_interval]))", + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Kube-apiserver requests rate", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:339", + "format": "reqps", + "logBase": 1, + "show": true + }, + { + "$$hashKey": "object:340", + "format": "short", + "logBase": 1, + "show": true + } + ], + "yaxis": { + "align": false + } + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "displayMode": "auto", + "inspect": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Value" + }, + "properties": [ + { + "id": "custom.displayMode", + "value": "basic" + }, + { + "id": "displayName", + "value": "RPS" + }, + { + "id": "unit", + "value": "reqps" + }, + { + "id": "decimals", + "value": 2 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "resource" + }, + "properties": [ + { + "id": "custom.width", + "value": 291 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "verb" + }, + "properties": [ + { + "id": "custom.width", + "value": 150 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "subresource" + }, + "properties": [ + { + "id": "custom.width", + "value": 100 + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 19 + }, + "id": 47, + "options": { + "footer": { + "fields": "", + "reducer": [ + "sum" + ], + "show": false + }, + "showHeader": true, + "sortBy": [] + }, + "pluginVersion": "8.5.13", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "exemplar": true, + "expr": "sum by(verb, resource, subresource) (rate(apiserver_request_total{verb!~\"CONNECT|WATCH\", verb=~\"$verb\", instance=~\"$instance:.*\", resource=~\"$resource\"}[$__range]))", + "format": "table", + "instant": true, + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "title": "Kube-apiserver requests rate", + "transformations": [ + { + "id": "filterFieldsByName", + "options": { + "include": { + "names": [ + "resource", + "verb", + "Value", + "subresource" + ] + } + } + }, + { + "id": "sortBy", + "options": { + "fields": {}, + "sort": [ + { + "desc": true, + "field": "Value" + } + ] + } + } + ], + "type": "table" + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": { + "uid": "$ds_prometheus" + }, + "description": "", + "fieldConfig": { + "defaults": {}, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Value" + }, + "properties": [ + { + "id": "displayName", + "value": "bytes/sec" + }, + { + "id": "unit", + "value": "binBps" + } + ] + } + ] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 27 + }, + "hiddenSeries": false, + "id": 36, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.5.13", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": true, + "targets": [ + { + "exemplar": true, + "expr": "max by (verb) (rate(apiserver_response_sizes_sum{verb!~\"CONNECT|WATCH\", verb=~\"$verb\", instance=~\"$instance:.*\", resource=~\"$resource\"}[$__rate_interval])/rate(apiserver_response_sizes_count{verb!~\"CONNECT|WATCH\", verb=~\"$verb\", instance=~\"$instance:.*\", resource=~\"$resource\"}[$__rate_interval]))", + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Kube-apiserver response sizes", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:339", + "format": "binBps", + "logBase": 1, + "show": true + }, + { + "$$hashKey": "object:340", + "format": "short", + "logBase": 1, + "show": true + } + ], + "yaxis": { + "align": false + } + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "displayMode": "auto", + "inspect": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Value" + }, + "properties": [ + { + "id": "custom.displayMode", + "value": "basic" + }, + { + "id": "displayName", + "value": "bytes/s" + }, + { + "id": "unit", + "value": "binBps" + }, + { + "id": "decimals", + "value": 2 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "resource" + }, + "properties": [ + { + "id": "custom.width", + "value": 291 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "verb" + }, + "properties": [ + { + "id": "custom.width", + "value": 150 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "subresource" + }, + "properties": [ + { + "id": "custom.width", + "value": 100 + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 27 + }, + "id": 48, + "options": { + "footer": { + "fields": "", + "reducer": [ + "sum" + ], + "show": false + }, + "showHeader": true, + "sortBy": [] + }, + "pluginVersion": "8.5.13", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "exemplar": true, + "expr": "max by (verb, resource, subresource) (rate(apiserver_response_sizes_sum{verb!~\"CONNECT|WATCH\", verb=~\"$verb\", instance=~\"$instance:.*\", resource=~\"$resource\"}[$__rate_interval])/rate(apiserver_response_sizes_count{verb!~\"CONNECT|WATCH\", verb=~\"$verb\", instance=~\"$instance:.*\", resource=~\"$resource\"}[$__range]))", + "format": "table", + "instant": true, + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "title": "Kube-apiserver response sizes", + "transformations": [ + { + "id": "filterFieldsByName", + "options": { + "include": { + "names": [ + "resource", + "verb", + "Value", + "subresource" + ] + } + } + }, + { + "id": "filterByValue", + "options": { + "filters": [ + { + "config": { + "id": "regex", + "options": { + "value": "NaN" + } + }, + "fieldName": "Value" + } + ], + "match": "any", + "type": "exclude" + } + }, + { + "id": "sortBy", + "options": { + "fields": {}, + "sort": [ + { + "desc": true, + "field": "Value" + } + ] + } + } + ], + "type": "table" + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": { + "uid": "$ds_prometheus" + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 35 + }, + "hiddenSeries": false, + "id": 29, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.5.13", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "$$hashKey": "object:1066", + "alias": "/^0.[01234]/", + "color": "#56A64B" + }, + { + "$$hashKey": "object:1192", + "alias": "/^0.[56789]/", + "color": "#F2CC0C" + }, + { + "$$hashKey": "object:1208", + "alias": "/^[123456789]/", + "color": "#E02F44" + }, + { + "$$hashKey": "object:1216", + "alias": "+Inf", + "color": "#AD0317" + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": true, + "targets": [ + { + "exemplar": true, + "expr": "sum(rate(apiserver_request_duration_seconds_bucket{verb!~\"CONNECT|WATCH\", job=\"kube-apiserver\", instance=~\"$instance:6443\", verb=~\"$verb\"}[$__rate_interval])) by (le)", + "format": "heatmap", + "interval": "", + "intervalFactor": 1, + "legendFormat": "{{le}}", + "refId": "A" + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Kube-apiserver latency bucket", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:286", + "format": "ops", + "logBase": 1, + "show": true + }, + { + "$$hashKey": "object:287", + "format": "short", + "logBase": 1, + "show": false + } + ], + "yaxis": { + "align": false + } + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "displayMode": "auto", + "inspect": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Value" + }, + "properties": [ + { + "id": "custom.displayMode", + "value": "basic" + }, + { + "id": "displayName", + "value": "s" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "unit", + "value": "s" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "resource" + }, + "properties": [ + { + "id": "custom.width", + "value": 291 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "verb" + }, + "properties": [ + { + "id": "custom.width", + "value": 150 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "subresource" + }, + "properties": [ + { + "id": "custom.width", + "value": 100 + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 35 + }, + "id": 49, + "options": { + "footer": { + "fields": "", + "reducer": [ + "sum" + ], + "show": false + }, + "showHeader": true, + "sortBy": [] + }, + "pluginVersion": "8.5.13", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "exemplar": true, + "expr": "max by (verb, resource, subresource) (rate(apiserver_request_duration_seconds_sum{verb!~\"CONNECT|WATCH\", subresource!~\"exec|log\", verb=~\"$verb\", instance=~\"$instance:.*\", resource=~\"$resource\"}[$__range])/rate(apiserver_request_duration_seconds_count{verb!~\"CONNECT|WATCH\", subresource!~\"exec|log\", verb=~\"$verb\", instance=~\"$instance:.*\", resource=~\"$resource\"}[$__range]))", + "format": "table", + "instant": true, + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "title": "Kube-apiserver latency", + "transformations": [ + { + "id": "filterFieldsByName", + "options": { + "include": { + "names": [ + "resource", + "verb", + "Value", + "subresource" + ] + } + } + }, + { + "id": "filterByValue", + "options": { + "filters": [ + { + "config": { + "id": "regex", + "options": { + "value": "NaN" + } + }, + "fieldName": "Value" + } + ], + "match": "any", + "type": "exclude" + } + }, + { + "id": "sortBy", + "options": { + "fields": {}, + "sort": [ + { + "desc": true, + "field": "Value" + } + ] + } + } + ], + "type": "table" + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": { + "uid": "$ds_prometheus" + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 43 + }, + "hiddenSeries": false, + "id": 50, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.5.13", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "$$hashKey": "object:1066", + "alias": "/^0.[01234]/", + "color": "#56A64B" + }, + { + "$$hashKey": "object:1192", + "alias": "/^0.[56789]/", + "color": "#F2CC0C" + }, + { + "$$hashKey": "object:1208", + "alias": "/^[123456789]/", + "color": "#E02F44" + }, + { + "$$hashKey": "object:1216", + "alias": "+Inf", + "color": "#AD0317" + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": true, + "targets": [ + { + "exemplar": true, + "expr": "sum(rate(apiserver_request_duration_seconds_bucket{verb!~\"CONNECT|WATCH\", job=\"kube-apiserver\", instance=~\"$instance:6443\", verb=~\"$verb\"}[$__rate_interval])) by (le) / scalar(sum(rate(apiserver_request_duration_seconds_count{verb!~\"CONNECT|WATCH\", job=\"kube-apiserver\", instance=~\"$instance:6443\", verb=~\"$verb\"}[$__rate_interval])))", + "format": "heatmap", + "interval": "", + "intervalFactor": 1, + "legendFormat": "{{le}}", + "refId": "A" + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Kube-apiserver latency bucket %", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:286", + "format": "percentunit", + "logBase": 1, + "max": "1", + "min": "0", + "show": true + }, + { + "$$hashKey": "object:287", + "format": "short", + "logBase": 1, + "show": false + } + ], + "yaxis": { + "align": false + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 43 + }, + "hiddenSeries": false, + "id": 51, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.5.13", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": true, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "exemplar": true, + "expr": "histogram_quantile(0.99, sum(rate(apiserver_request_duration_seconds_bucket{verb!~\"CONNECT|WATCH\", job=\"kube-apiserver\", instance=~\"$instance:6443\", verb=~\"$verb\"}[$__rate_interval])) by (instance, le))", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Kube-apiserver latency time", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:286", + "format": "s", + "logBase": 1, + "show": true + }, + { + "$$hashKey": "object:287", + "format": "short", + "logBase": 1, + "show": false + } + ], + "yaxis": { + "align": false + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": { + "uid": "$ds_prometheus" + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 51 + }, + "hiddenSeries": false, + "id": 52, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.5.13", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "$$hashKey": "object:1066", + "alias": "/^0.00[0-9]/", + "color": "#56A64B" + }, + { + "$$hashKey": "object:1192", + "alias": "/^0.0[1-9]/", + "color": "#F2CC0C" + }, + { + "$$hashKey": "object:1208", + "alias": "/^0.[1-9]/", + "color": "#FF780A" + }, + { + "$$hashKey": "object:1216", + "alias": "/^[1-9]/", + "color": "#C4162A" + }, + { + "$$hashKey": "object:2638", + "alias": "+Inf", + "color": "#AD0317" + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": true, + "targets": [ + { + "exemplar": true, + "expr": "sum(rate(etcd_request_duration_seconds_bucket{job=\"kube-apiserver\", instance=~\"$instance:6443\", verb=~\"$verb\"}[$__rate_interval])) by (le)", + "format": "heatmap", + "interval": "", + "intervalFactor": 1, + "legendFormat": "{{le}}", + "refId": "A" + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Etcd requests latency bucket", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:286", + "format": "ops", + "logBase": 1, + "show": true + }, + { + "$$hashKey": "object:287", + "format": "short", + "logBase": 1, + "show": false + } + ], + "yaxis": { + "align": false + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "uid": "$ds_prometheus" + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 51 + }, + "hiddenSeries": false, + "id": 53, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.5.13", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": true, + "targets": [ + { + "exemplar": true, + "expr": "histogram_quantile(0.99, sum(rate(etcd_request_duration_seconds_bucket{job=\"kube-apiserver\", instance=~\"$instance:6443\"}[$__rate_interval])) by (instance, le))", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Etcd latency time", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:286", + "format": "s", + "logBase": 1, + "show": true + }, + { + "$$hashKey": "object:287", + "format": "short", + "logBase": 1, + "show": false + } + ], + "yaxis": { + "align": false + } + }, + { + "collapsed": false, + "datasource": { + "uid": "$ds_prometheus" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 59 + }, + "id": 44, + "panels": [], + "title": "Kube-scheduler", + "type": "row" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "uid": "$ds_prometheus" + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 60 + }, + "hiddenSeries": false, + "id": 37, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.5.13", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "rate(process_cpu_seconds_total{job=\"kube-scheduler\", instance=~\"$instance:.*\"}[$__rate_interval])", + "intervalFactor": 1, + "legendFormat": "{{instance}}", + "refId": "A" + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Kube-scheduler CPU Usage", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:566", + "format": "short", + "label": "CPU Usage", + "logBase": 1, + "show": true + }, + { + "$$hashKey": "object:567", + "format": "short", + "logBase": 1, + "show": true + } + ], + "yaxis": { + "align": false + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "uid": "$ds_prometheus" + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 60 + }, + "hiddenSeries": false, + "id": 38, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.5.13", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "process_resident_memory_bytes{job=\"kube-scheduler\", instance=~\"$instance:.*\"}", + "legendFormat": "{{instance}}", + "refId": "A" + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Kube-scheduler Memory Usage", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:732", + "format": "bytes", + "logBase": 1, + "show": true + }, + { + "$$hashKey": "object:733", + "format": "short", + "logBase": 1, + "show": true + } + ], + "yaxis": { + "align": false + } + }, + { + "collapsed": false, + "datasource": { + "uid": "$ds_prometheus" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 68 + }, + "id": 42, + "panels": [], + "title": "Kube-controller-manager", + "type": "row" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "uid": "$ds_prometheus" + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 69 + }, + "hiddenSeries": false, + "id": 39, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.5.13", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "rate(process_cpu_seconds_total{job=\"kube-controller-manager\", instance=~\"$instance:.*\"}[$__rate_interval])", + "intervalFactor": 1, + "legendFormat": "{{instance}}", + "refId": "A" + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Kube-controller-manager CPU Usage", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:566", + "format": "short", + "label": "CPU Usage", + "logBase": 1, + "show": true + }, + { + "$$hashKey": "object:567", + "format": "short", + "logBase": 1, + "show": true + } + ], + "yaxis": { + "align": false + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "uid": "$ds_prometheus" + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 69 + }, + "hiddenSeries": false, + "id": 40, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.5.13", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "process_resident_memory_bytes{job=\"kube-controller-manager\", instance=~\"$instance:.*\"}", + "legendFormat": "{{instance}}", + "refId": "A" + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Kube-controller-manager Memory Usage", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:732", + "format": "bytes", + "logBase": 1, + "show": true + }, + { + "$$hashKey": "object:733", + "format": "short", + "logBase": 1, + "show": true + } + ], + "yaxis": { + "align": false + } + } + ], + "refresh": "30s", + "schemaVersion": 36, + "style": "dark", + "tags": [], + "templating": { + "list": [ + { + "current": { + "selected": false, + "text": "main", + "value": "main" + }, + "hide": 0, + "includeAll": false, + "label": "Prometheus", + "multi": false, + "name": "ds_prometheus", + "options": [], + "query": "prometheus", + "queryValue": "", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + }, + { + "allValue": ".*", + "current": { + "selected": true, + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "definition": "label_values(up{job=\"kube-apiserver\"}, instance)", + "hide": 0, + "includeAll": true, + "label": "Instance", + "multi": true, + "name": "instance", + "options": [], + "query": { + "query": "label_values(up{job=\"kube-apiserver\"}, instance)", + "refId": "StandardVariableQuery" + }, + "refresh": 2, + "regex": "/(.*):.*/", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": ".*", + "current": { + "selected": true, + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "definition": "label_values(apiserver_request_total, resource)", + "hide": 0, + "includeAll": true, + "label": "Resource", + "multi": true, + "name": "resource", + "options": [], + "query": { + "query": "label_values(apiserver_request_total, resource)", + "refId": "StandardVariableQuery" + }, + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": ".*", + "current": { + "selected": true, + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "definition": "label_values(apiserver_request_total{verb!~\"CONNECT|WATCH\"}, verb)", + "hide": 0, + "includeAll": true, + "label": "VERB", + "multi": true, + "name": "verb", + "options": [], + "query": { + "query": "label_values(apiserver_request_total{verb!~\"CONNECT|WATCH\"}, verb)", + "refId": "StandardVariableQuery" + }, + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + } + ] + }, + "time": { + "from": "now-3h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "", + "title": "Control Plane Status", + "uid": "3yqtXDzia", + "version": 1, + "weekStart": "" +} diff --git a/dashboards/control-plane/deprecated-resources.json b/dashboards/control-plane/deprecated-resources.json new file mode 100644 index 00000000..4841d949 --- /dev/null +++ b/dashboards/control-plane/deprecated-resources.json @@ -0,0 +1,611 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "target": { + "limit": 100, + "matchAny": false, + "tags": [], + "type": "dashboard" + }, + "type": "dashboard" + } + ] + }, + "description": "Track whether the cluster can be upgraded to the newer Kubernetes versions", + "editable": false, + "fiscalYearStartMonth": 0, + "graphTooltip": 1, + "id": 30, + "iteration": 1656060742701, + "links": [], + "liveNow": false, + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "blue", + "mode": "fixed" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 5, + "x": 0, + "y": 0 + }, + "id": 9, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "name" + }, + "pluginVersion": "8.5.2", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "editorMode": "code", + "expr": "topk(1, sum by (git_version) (kubernetes_build_info{job=\"kube-apiserver\"}))", + "legendFormat": "{{ git_version }}", + "range": true, + "refId": "A" + } + ], + "title": "Current K8s version", + "transformations": [ + { + "id": "reduce", + "options": { + "labelsToFields": false, + "reducers": [] + } + } + ], + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "from": 1, + "result": { + "index": 0, + "text": "Cannot be upgraded" + }, + "to": 1e+18 + }, + "type": "range" + }, + { + "options": { + "match": "null+nan", + "result": { + "index": 1, + "text": "Can be upgraded" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 7, + "x": 5, + "y": 0 + }, + "id": 4, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "center", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.2", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "editorMode": "code", + "exemplar": false, + "expr": "sum(\n ceil(\n sum by(removed_release, resource, group, version) (\n sum by(removed_release, resource, group, version) \n (apiserver_requested_deprecated_apis{removed_release=\"$k8s\"}) \n *\n on(group,version,resource,subresource)\n group_right() (increase(apiserver_request_total[1h]))\n )\n )\n) or vector(0)\n+ \nsum(\n sum by (api_version, kind, helm_release_name, helm_release_namespace)\n (resource_versions_compatibility{k8s_version=~\"$k8s\"})\n) or vector(0)\n> 0", + "instant": true, + "range": false, + "refId": "A" + } + ], + "title": "Upgrade to desired version status", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "gridPos": { + "h": 5, + "w": 12, + "x": 12, + "y": 0 + }, + "id": 7, + "options": { + "content": "
\n\n#### Follow instructions to migrate from using **deprecated APIs**\n\nhttps://kubernetes.io/docs/reference/using-api/deprecation-guide/", + "mode": "markdown" + }, + "pluginVersion": "8.5.2", + "type": "text" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "displayMode": "color-background", + "filterable": false, + "inspect": false, + "minWidth": 100 + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "super-light-orange", + "value": null + }, + { + "color": "light-orange", + "value": 50 + }, + { + "color": "orange", + "value": 200 + }, + { + "color": "semi-dark-orange", + "value": 500 + }, + { + "color": "dark-orange", + "value": 1000 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Group" + }, + "properties": [ + { + "id": "custom.displayMode", + "value": "auto" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Version" + }, + "properties": [ + { + "id": "custom.displayMode", + "value": "auto" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Resource" + }, + "properties": [ + { + "id": "custom.displayMode", + "value": "auto" + } + ] + } + ] + }, + "gridPos": { + "h": 13, + "w": 12, + "x": 0, + "y": 5 + }, + "id": 2, + "options": { + "footer": { + "enablePagination": false, + "fields": "", + "reducer": [ + "sum" + ], + "show": false + }, + "showHeader": true, + "sortBy": [] + }, + "pluginVersion": "8.5.2", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "editorMode": "code", + "exemplar": false, + "expr": "ceil(\n sum by(removed_release, resource, group, version)(\n sum by(removed_release, resource, group, version) \n (apiserver_requested_deprecated_apis{removed_release=~\"$k8s\"}) \n * \n on(group,version,resource,subresource)\n group_right() (increase(apiserver_request_total[3h]))\n )\n) > 0", + "format": "table", + "instant": true, + "range": false, + "refId": "A" + } + ], + "title": "Requests to kube-apiserver (last 3 hours)", + "transformations": [ + { + "id": "filterFieldsByName", + "options": { + "include": { + "names": [ + "group", + "removed_release", + "resource", + "version", + "Value" + ] + } + } + }, + { + "id": "organize", + "options": { + "excludeByName": {}, + "indexByName": { + "Value": 4, + "group": 0, + "removed_release": 3, + "resource": 2, + "version": 1 + }, + "renameByName": { + "Value": "", + "group": "Group", + "removed_release": "Removed Release", + "resource": "Resource", + "version": "Version" + } + } + }, + { + "id": "sortBy", + "options": { + "fields": {}, + "sort": [ + { + "desc": true, + "field": "Value" + } + ] + } + } + ], + "type": "table" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "displayMode": "color-background", + "filterable": false, + "inspect": false, + "minWidth": 100 + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "super-light-orange", + "value": null + }, + { + "color": "#EAB839", + "value": 5 + }, + { + "color": "orange", + "value": 15 + }, + { + "color": "dark-orange", + "value": 50 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "API version" + }, + "properties": [ + { + "id": "custom.displayMode", + "value": "auto" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Helm release" + }, + "properties": [ + { + "id": "custom.displayMode", + "value": "auto" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Helm release namespace" + }, + "properties": [ + { + "id": "custom.displayMode", + "value": "auto" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Kind" + }, + "properties": [ + { + "id": "custom.displayMode", + "value": "auto" + } + ] + } + ] + }, + "gridPos": { + "h": 13, + "w": 12, + "x": 12, + "y": 5 + }, + "id": 5, + "options": { + "footer": { + "enablePagination": false, + "fields": "", + "reducer": [ + "sum" + ], + "show": false + }, + "showHeader": true, + "sortBy": [] + }, + "pluginVersion": "8.5.2", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "editorMode": "code", + "exemplar": false, + "expr": "sum by (api_version, kind, helm_release_name, helm_release_namespace) (resource_versions_compatibility{k8s_version=~\"$k8s\"})", + "format": "table", + "instant": true, + "legendFormat": "__auto", + "range": false, + "refId": "A" + } + ], + "title": "Helm releases", + "transformations": [ + { + "id": "organize", + "options": { + "excludeByName": { + "Time": true + }, + "indexByName": {}, + "renameByName": { + "Time": "", + "Value": "Quantity", + "api_version": "API version", + "helm_release_name": "Helm release", + "helm_release_namespace": "Helm release namespace", + "kind": "Kind" + } + } + }, + { + "id": "sortBy", + "options": { + "fields": {}, + "sort": [ + { + "desc": true, + "field": "Quantity" + } + ] + } + } + ], + "type": "table" + } + ], + "schemaVersion": 36, + "style": "dark", + "tags": [], + "templating": { + "list": [ + { + "current": { + "selected": false, + "text": "default", + "value": "default" + }, + "description": null, + "error": null, + "hide": 0, + "includeAll": false, + "label": "datasource", + "multi": false, + "name": "ds_prometheus", + "options": [], + "query": "prometheus", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "definition": "label_values(apiserver_requested_deprecated_apis, removed_release)", + "hide": 0, + "includeAll": false, + "label": "Desired K8s version", + "multi": false, + "name": "k8s", + "options": [], + "query": { + "query": "label_values(apiserver_requested_deprecated_apis, removed_release)", + "refId": "StandardVariableQuery" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + } + ] + }, + "time": { + "from": "now-3h", + "to": "now" + }, + "timepicker": { + "hidden": true, + "refresh_intervals": [ + "30s" + ] + }, + "timezone": "", + "title": "Deprecated APIs", + "uid": "B0d1Wt3nk", + "version": 2, + "weekStart": "" +} diff --git a/dashboards/control-plane/dns-coredns.json b/dashboards/control-plane/dns-coredns.json new file mode 100644 index 00000000..76e37ee7 --- /dev/null +++ b/dashboards/control-plane/dns-coredns.json @@ -0,0 +1,5638 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": "-- Grafana --", + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "description": "", + "editable": false, + "gnetId": null, + "graphTooltip": 1, + "iteration": 1562945734865, + "links": [], + "panels": [ + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 52, + "panels": [], + "title": "General", + "type": "row" + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "description": "If the graph is non-empty, it means that some CoreDNS requests resulted in panic. You can see a specific error in the container logs.", + "editable": true, + "error": false, + "fill": 1, + "grid": {}, + "gridPos": { + "h": 3, + "w": 24, + "x": 0, + "y": 1 + }, + "id": 177, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "rightSide": true, + "show": false, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 2, + "links": [], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeatDirection": "h", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(coredns_panics_total{job=\"kube-dns\", pod=~\"$pod\"}[$__rate_interval])) by (pod)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{pod}}", + "refId": "A", + "step": 40 + }, + { + "expr": "sum(rate(coredns_panics_total{job=\"kube-dns\", pod=~\"$pod\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "CoreDNS panic count", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "editable": true, + "error": false, + "fill": 1, + "grid": {}, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 4 + }, + "id": 1, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 2, + "links": [], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(coredns_dns_requests_total{job=\"kube-dns\", pod=~\"$pod\"}[$__rate_interval])) by (pod)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{pod}}", + "refId": "A", + "step": 60 + }, + { + "expr": "sum(rate(coredns_dns_requests_total{job=\"kube-dns\", pod=~\"$pod\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "B", + "step": 60 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Incoming requests count", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "reqps", + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "pps", + "logBase": 1, + "max": null, + "min": 0, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "editable": true, + "error": false, + "fill": 1, + "grid": {}, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 4 + }, + "id": 46, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(coredns_dns_request_duration_seconds_sum{job=\"kube-dns\", pod=~\"$pod\"}[$__rate_interval])) by (pod) / sum(rate(coredns_dns_requests_total{job=\"kube-dns\", pod=~\"$pod\"}[$__rate_interval])) by (pod)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{pod}}", + "refId": "A", + "step": 40 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Incoming requests duration", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "s", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "cards": { + "cardPadding": null, + "cardRound": null + }, + "color": { + "cardColor": "#b4ff00", + "colorScale": "sqrt", + "colorScheme": "interpolateMagma", + "exponent": 0.5, + "mode": "spectrum" + }, + "dataFormat": "tsbuckets", + "datasource": "$ds_prometheus", + "gridPos": { + "h": 5, + "w": 24, + "x": 0, + "y": 11 + }, + "heatmap": {}, + "hideZeroBuckets": false, + "highlightCards": true, + "id": 97, + "legend": { + "show": false + }, + "links": [], + "reverseYBuckets": false, + "targets": [ + { + "expr": "sum(rate(coredns_dns_request_duration_seconds_bucket{job=\"kube-dns\", pod=~\"$pod\"}[$__rate_interval])) by (le)", + "format": "heatmap", + "intervalFactor": 1, + "legendFormat": "{{le}}", + "refId": "A" + } + ], + "title": "Request duration", + "tooltip": { + "show": true, + "showHistogram": true + }, + "type": "heatmap", + "xAxis": { + "show": true + }, + "xBucketNumber": null, + "xBucketSize": null, + "yAxis": { + "decimals": null, + "format": "s", + "logBase": 1, + "max": null, + "min": null, + "show": true, + "splitFactor": null + }, + "yBucketBound": "auto", + "yBucketNumber": null, + "yBucketSize": null + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "editable": true, + "error": false, + "fill": 1, + "grid": {}, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 16 + }, + "id": 39, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 2, + "links": [], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "lines": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(coredns_forward_requests_total{job=\"kube-dns\", pod=~\"$pod\"}[$__rate_interval])) by (pod)", + "format": "time_series", + "instant": false, + "intervalFactor": 1, + "legendFormat": "{{pod}}", + "refId": "A", + "step": 60 + }, + { + "expr": "sum(rate(coredns_forward_requests_total{job=\"kube-dns\", pod=~\"$pod\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "B", + "step": 60 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Forwarded requests count", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "reqps", + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "pps", + "logBase": 1, + "max": null, + "min": 0, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "editable": true, + "error": false, + "fill": 1, + "grid": {}, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 16 + }, + "id": 35, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(coredns_forward_request_duration_seconds_sum{job=\"kube-dns\", pod=~\"$pod\"}[$__rate_interval])) by (pod) / sum(rate(coredns_forward_requests_total{job=\"kube-dns\", pod=~\"$pod\"}[$__rate_interval])) by (pod)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{pod}}", + "refId": "C", + "step": 40 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Forwarded requests duration", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "s", + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "cards": { + "cardPadding": null, + "cardRound": null + }, + "color": { + "cardColor": "#b4ff00", + "colorScale": "sqrt", + "colorScheme": "interpolateMagma", + "exponent": 0.5, + "mode": "spectrum" + }, + "dataFormat": "tsbuckets", + "gridPos": { + "h": 5, + "w": 24, + "x": 0, + "y": 23 + }, + "heatmap": {}, + "hideZeroBuckets": false, + "highlightCards": true, + "id": 98, + "legend": { + "show": false + }, + "links": [], + "reverseYBuckets": false, + "targets": [ + { + "expr": "sum(rate(coredns_forward_request_duration_seconds_bucket{job=\"kube-dns\", pod=~\"$pod\"}[$__rate_interval])) by (le)", + "format": "heatmap", + "intervalFactor": 1, + "legendFormat": "{{le}}", + "refId": "A" + } + ], + "title": "Forward duration", + "tooltip": { + "show": true, + "showHistogram": false + }, + "type": "heatmap", + "xAxis": { + "show": true + }, + "xBucketNumber": null, + "xBucketSize": null, + "yAxis": { + "decimals": null, + "format": "s", + "logBase": 1, + "max": null, + "min": null, + "show": true, + "splitFactor": null + }, + "yBucketBound": "auto", + "yBucketNumber": null, + "yBucketSize": null + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "description": "If the graph is non-empty, it means that some CoreDNS requests resulted in panic. You can see a specific error in the container logs.", + "editable": true, + "error": false, + "fill": 1, + "grid": {}, + "gridPos": { + "h": 3, + "w": 24, + "x": 0, + "y": 28 + }, + "id": 203, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "rightSide": true, + "show": false, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 2, + "links": [], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeatDirection": "h", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(coredns_forward_healthcheck_failures_total{job=\"kube-dns\", pod=~\"$pod\"}[$__rate_interval])) by (pod)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{pod}}", + "refId": "A", + "step": 40 + }, + { + "expr": "sum(rate(coredns_forward_healthcheck_failures_total{job=\"kube-dns\", pod=~\"$pod\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "CoreDNS Forward Healthcheck Failure Count", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "editable": true, + "error": false, + "fill": 1, + "grid": {}, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 31 + }, + "id": 16, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(coredns_cache_hits_total{job=\"kube-dns\", pod=~\"$pod\"}[$__rate_interval])) by (pod)\n/\n(\nsum(rate(coredns_cache_hits_total{job=\"kube-dns\", pod=~\"$pod\"}[$__rate_interval])) by (pod) +\nsum(rate(coredns_cache_misses_total{job=\"kube-dns\", pod=~\"$pod\"}[$__rate_interval])) by (pod) \n)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{pod}}", + "refId": "A", + "step": 40 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Cache hit rate", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "percentunit", + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "pps", + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "editable": true, + "error": false, + "fill": 1, + "grid": {}, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 31 + }, + "id": 15, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 2, + "links": [], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(max_over_time(coredns_cache_entries{job=\"kube-dns\", pod=~\"$pod\"}[$__rate_interval])) by (pod)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{pod}}", + "refId": "A", + "step": 40 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Cache size", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "logBase": 1, + "max": null, + "min": 0, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "editable": true, + "error": false, + "fill": 1, + "grid": {}, + "gridPos": { + "h": 4, + "w": 8, + "x": 0, + "y": 38 + }, + "id": 36, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "rightSide": true, + "show": false, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 2, + "links": [], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": "rcode", + "repeatDirection": "h", + "scopedVars": { + "rcode": { + "selected": false, + "text": "NXDOMAIN", + "value": "NXDOMAIN" + } + }, + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(coredns_dns_responses_total{job=\"kube-dns\", pod=~\"$pod\", rcode=~\"$rcode\"}[$__rate_interval])) by (pod)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{pod}}", + "refId": "A", + "step": 40 + }, + { + "expr": "sum(rate(coredns_dns_responses_total{job=\"kube-dns\", pod=~\"$pod\", rcode=~\"$rcode\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "$rcode", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "pps", + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "editable": true, + "error": false, + "fill": 1, + "grid": {}, + "gridPos": { + "h": 4, + "w": 8, + "x": 8, + "y": 38 + }, + "id": 206, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "rightSide": true, + "show": false, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 2, + "links": [], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "repeatDirection": "h", + "repeatIteration": 1562945734865, + "repeatPanelId": 36, + "scopedVars": { + "rcode": { + "selected": false, + "text": "SERVFAIL", + "value": "SERVFAIL" + } + }, + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(coredns_dns_responses_total{job=\"kube-dns\", pod=~\"$pod\", rcode=~\"$rcode\"}[$__rate_interval])) by (pod)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{pod}}", + "refId": "A", + "step": 40 + }, + { + "expr": "sum(rate(coredns_dns_responses_total{job=\"kube-dns\", pod=~\"$pod\", rcode=~\"$rcode\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "$rcode", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "pps", + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "editable": true, + "error": false, + "fill": 1, + "grid": {}, + "gridPos": { + "h": 4, + "w": 8, + "x": 16, + "y": 38 + }, + "id": 207, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "rightSide": true, + "show": false, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 2, + "links": [], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "repeatDirection": "h", + "repeatIteration": 1562945734865, + "repeatPanelId": 36, + "scopedVars": { + "rcode": { + "selected": false, + "text": "REFUSED", + "value": "REFUSED" + } + }, + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(coredns_dns_responses_total{job=\"kube-dns\", pod=~\"$pod\", rcode=~\"$rcode\"}[$__rate_interval])) by (pod)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{pod}}", + "refId": "A", + "step": 40 + }, + { + "expr": "sum(rate(coredns_dns_responses_total{job=\"kube-dns\", pod=~\"$pod\", rcode=~\"$rcode\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "$rcode", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "pps", + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "editable": true, + "error": false, + "fill": 1, + "grid": {}, + "gridPos": { + "h": 3, + "w": 24, + "x": 0, + "y": 42 + }, + "id": 14, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 2, + "links": [], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(coredns_dns_requests_total{job=\"kube-dns\", pod=~\"$pod\",proto=\"tcp\"}[$__rate_interval]))\n/\nsum(rate(coredns_dns_requests_total{job=\"kube-dns\", pod=~\"$pod\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "TCP", + "refId": "C", + "step": 60 + }, + { + "expr": "sum(rate(coredns_dns_requests_total{job=\"kube-dns\", pod=~\"$pod\",proto=\"udp\"}[$__rate_interval]))\n/\nsum(rate(coredns_dns_requests_total{job=\"kube-dns\", pod=~\"$pod\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "UDP", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "TCP/UDP requests ratio", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "percentunit", + "logBase": 1, + "max": "1", + "min": 0, + "show": true + }, + { + "format": "short", + "logBase": 1, + "max": null, + "min": 0, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 45 + }, + "id": 38, + "panels": [ + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "editable": true, + "error": false, + "fill": 1, + "grid": {}, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 46 + }, + "id": 12, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 2, + "links": [], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "scopedVars": { + "node": { + "selected": false, + "text": "kube-master", + "value": "kube-master" + }, + "pod": { + "selected": false, + "text": "coredns-69cf6b55b4-jzhtl", + "value": "coredns-69cf6b55b4-jzhtl" + } + }, + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(coredns_dns_requests_total{job=\"kube-dns\", pod=~\"$pod\"}[$__rate_interval])) by (type)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{type}}", + "refId": "A", + "step": 60 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Requests (by qtype)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "reqps", + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "pps", + "logBase": 1, + "max": null, + "min": 0, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "editable": true, + "error": false, + "fill": 1, + "grid": {}, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 46 + }, + "id": 5, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 2, + "links": [], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "scopedVars": { + "node": { + "selected": false, + "text": "kube-master", + "value": "kube-master" + }, + "pod": { + "selected": false, + "text": "coredns-69cf6b55b4-jzhtl", + "value": "coredns-69cf6b55b4-jzhtl" + } + }, + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(coredns_dns_responses_total{job=\"kube-dns\", pod=~\"$pod\"}[$__rate_interval])) by (rcode)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{rcode}}", + "refId": "A", + "step": 40 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Responses (by rcode)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "reqps", + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "editable": true, + "error": false, + "fill": 1, + "grid": {}, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 53 + }, + "id": 47, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 2, + "links": [], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "scopedVars": { + "node": { + "selected": false, + "text": "kube-master", + "value": "kube-master" + }, + "pod": { + "selected": false, + "text": "coredns-69cf6b55b4-jzhtl", + "value": "coredns-69cf6b55b4-jzhtl" + } + }, + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(coredns_forward_requests_total{job=\"kube-dns\", pod=~\"$pod\"}[$__rate_interval])) by (to)", + "format": "time_series", + "instant": false, + "intervalFactor": 1, + "legendFormat": "{{to}}", + "refId": "A", + "step": 60 + }, + { + "expr": "sum(rate(coredns_forward_requests_total{job=\"kube-dns\", pod=~\"$pod\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "B", + "step": 60 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Forwarded requests count (by upstream)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "reqps", + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "pps", + "logBase": 1, + "max": null, + "min": 0, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "editable": true, + "error": false, + "fill": 1, + "grid": {}, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 53 + }, + "id": 49, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 2, + "links": [], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "scopedVars": { + "node": { + "selected": false, + "text": "kube-master", + "value": "kube-master" + }, + "pod": { + "selected": false, + "text": "coredns-69cf6b55b4-jzhtl", + "value": "coredns-69cf6b55b4-jzhtl" + } + }, + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(coredns_forward_responses_total{job=\"kube-dns\", pod=~\"$pod\"}[$__rate_interval])) by (rcode)", + "format": "time_series", + "instant": false, + "intervalFactor": 1, + "legendFormat": "{{rcode}}", + "refId": "A", + "step": 60 + }, + { + "expr": "sum(rate(coredns_forward_responses_total{job=\"kube-dns\", pod=~\"$pod\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Forwarded requests count (by rcode)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "reqps", + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "pps", + "logBase": 1, + "max": null, + "min": 0, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "description": "If the graph is non-empty, it means that some CoreDNS requests resulted in panic. You can see a specific error in the container logs.", + "editable": true, + "error": false, + "fill": 1, + "grid": {}, + "gridPos": { + "h": 3, + "w": 24, + "x": 0, + "y": 60 + }, + "id": 204, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "rightSide": true, + "show": false, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 2, + "links": [], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeatDirection": "h", + "scopedVars": { + "pod": { + "selected": false, + "text": "coredns-69cf6b55b4-jzhtl", + "value": "coredns-69cf6b55b4-jzhtl" + } + }, + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(coredns_forward_healthcheck_failures_total{job=\"kube-dns\", pod=~\"$pod\"}[$__rate_interval])) by (upstream)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{pod}}", + "refId": "A", + "step": 40 + }, + { + "expr": "sum(rate(coredns_forward_healthcheck_failures_total{job=\"kube-dns\", pod=~\"$pod\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "CoreDNS Forward Healthcheck Failure Count", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "editable": true, + "error": false, + "fill": 1, + "grid": {}, + "gridPos": { + "h": 3, + "w": 24, + "x": 0, + "y": 63 + }, + "id": 135, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 2, + "links": [], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "scopedVars": { + "node": { + "selected": false, + "text": "kube-master", + "value": "kube-master" + }, + "pod": { + "selected": false, + "text": "coredns-69cf6b55b4-jzhtl", + "value": "coredns-69cf6b55b4-jzhtl" + } + }, + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(coredns_dns_requests_total{job=\"kube-dns\", pod=~\"$pod\",proto=\"tcp\"}[$__rate_interval]))\n/\nsum(rate(coredns_dns_requests_total{job=\"kube-dns\", pod=~\"$pod\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "TCP", + "refId": "C", + "step": 60 + }, + { + "expr": "sum(rate(coredns_dns_requests_total{job=\"kube-dns\", pod=~\"$pod\",proto=\"udp\"}[$__rate_interval]))\n/\nsum(rate(coredns_dns_requests_total{job=\"kube-dns\", pod=~\"$pod\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "UDP", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "TCP/UDP requests ratio", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "percentunit", + "logBase": 1, + "max": "1", + "min": 0, + "show": true + }, + { + "format": "short", + "logBase": 1, + "max": null, + "min": 0, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "editable": true, + "error": false, + "fill": 1, + "grid": {}, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 66 + }, + "id": 80, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "scopedVars": { + "node": { + "selected": false, + "text": "kube-master", + "value": "kube-master" + }, + "pod": { + "selected": false, + "text": "coredns-69cf6b55b4-jzhtl", + "value": "coredns-69cf6b55b4-jzhtl" + } + }, + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(coredns_cache_hits_total{job=\"kube-dns\", pod=~\"$pod\"}[$__rate_interval]))\n/\n(\nsum(rate(coredns_cache_hits_total{job=\"kube-dns\", pod=~\"$pod\"}[$__rate_interval])) +\nsum(rate(coredns_cache_misses_total{job=\"kube-dns\", pod=~\"$pod\"}[$__rate_interval]))\n)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A", + "step": 40 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Cache hit rate", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "percentunit", + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "pps", + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "editable": true, + "error": false, + "fill": 1, + "grid": {}, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 66 + }, + "id": 81, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 2, + "links": [], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "scopedVars": { + "node": { + "selected": false, + "text": "kube-master", + "value": "kube-master" + }, + "pod": { + "selected": false, + "text": "coredns-69cf6b55b4-jzhtl", + "value": "coredns-69cf6b55b4-jzhtl" + } + }, + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(max_over_time(coredns_cache_entries{job=\"kube-dns\", pod=~\"$pod\"}[$__rate_interval])) by (type)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{type}}", + "refId": "A", + "step": 40 + }, + { + "expr": "sum(max_over_time(coredns_cache_entries{job=\"kube-dns\", pod=~\"$pod\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Cache size", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "logBase": 1, + "max": null, + "min": 0, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "editable": true, + "error": false, + "fill": 1, + "grid": {}, + "gridPos": { + "h": 7, + "w": 24, + "x": 0, + "y": 73 + }, + "id": 2, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "scopedVars": { + "node": { + "selected": false, + "text": "kube-master", + "value": "kube-master" + }, + "pod": { + "selected": false, + "text": "coredns-69cf6b55b4-jzhtl", + "value": "coredns-69cf6b55b4-jzhtl" + } + }, + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(coredns_dns_requests_total{job=\"kube-dns\", pod=~\"$pod\"}[$__rate_interval])) by (zone)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{zone}}", + "refId": "A", + "step": 60 + }, + { + "expr": "sum(rate(coredns_dns_requests_total{job=\"kube-dns\", pod=~\"$pod\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "B", + "step": 60 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Requests (by zone)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "pps", + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "pps", + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "cards": { + "cardPadding": null, + "cardRound": null + }, + "color": { + "cardColor": "#b4ff00", + "colorScale": "sqrt", + "colorScheme": "interpolateMagma", + "exponent": 0.5, + "mode": "spectrum" + }, + "dataFormat": "tsbuckets", + "datasource": "$ds_prometheus", + "gridPos": { + "h": 7, + "w": 24, + "x": 0, + "y": 80 + }, + "heatmap": {}, + "hideZeroBuckets": false, + "highlightCards": true, + "id": 18, + "legend": { + "show": false + }, + "links": [], + "reverseYBuckets": false, + "scopedVars": { + "node": { + "selected": false, + "text": "kube-master", + "value": "kube-master" + }, + "pod": { + "selected": false, + "text": "coredns-69cf6b55b4-jzhtl", + "value": "coredns-69cf6b55b4-jzhtl" + } + }, + "targets": [ + { + "expr": "sum(rate(coredns_dns_request_duration_seconds_bucket{job=\"kube-dns\", pod=~\"$pod\"}[$__rate_interval])) by (le)", + "format": "heatmap", + "intervalFactor": 1, + "legendFormat": "{{le}}", + "refId": "A" + } + ], + "title": "Request duration", + "tooltip": { + "show": true, + "showHistogram": true + }, + "type": "heatmap", + "xAxis": { + "show": true + }, + "xBucketNumber": null, + "xBucketSize": null, + "yAxis": { + "decimals": null, + "format": "s", + "logBase": 1, + "max": null, + "min": null, + "show": true, + "splitFactor": null + }, + "yBucketBound": "auto", + "yBucketNumber": null, + "yBucketSize": null + }, + { + "cards": { + "cardPadding": null, + "cardRound": null + }, + "color": { + "cardColor": "#b4ff00", + "colorScale": "sqrt", + "colorScheme": "interpolateMagma", + "exponent": 0.5, + "mode": "spectrum" + }, + "dataFormat": "tsbuckets", + "gridPos": { + "h": 7, + "w": 24, + "x": 0, + "y": 87 + }, + "heatmap": {}, + "hideZeroBuckets": false, + "highlightCards": true, + "id": 20, + "legend": { + "show": false + }, + "links": [], + "reverseYBuckets": false, + "scopedVars": { + "node": { + "selected": false, + "text": "kube-master", + "value": "kube-master" + }, + "pod": { + "selected": false, + "text": "coredns-69cf6b55b4-jzhtl", + "value": "coredns-69cf6b55b4-jzhtl" + } + }, + "targets": [ + { + "expr": "sum(rate(coredns_forward_request_duration_seconds_bucket{job=\"kube-dns\", pod=~\"$pod\"}[$__rate_interval])) by (le)", + "format": "heatmap", + "intervalFactor": 1, + "legendFormat": "{{le}}", + "refId": "A" + } + ], + "title": "Forward duration", + "tooltip": { + "show": true, + "showHistogram": false + }, + "type": "heatmap", + "xAxis": { + "show": true + }, + "xBucketNumber": null, + "xBucketSize": null, + "yAxis": { + "decimals": null, + "format": "s", + "logBase": 1, + "max": null, + "min": null, + "show": true, + "splitFactor": null + }, + "yBucketBound": "auto", + "yBucketNumber": null, + "yBucketSize": null + } + ], + "repeat": "pod", + "scopedVars": { + "pod": { + "selected": false, + "text": "coredns-69cf6b55b4-jzhtl", + "value": "coredns-69cf6b55b4-jzhtl" + } + }, + "title": "Pod $pod", + "type": "row" + }, + { + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 46 + }, + "id": 208, + "panels": [ + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "editable": true, + "error": false, + "fill": 1, + "grid": {}, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 46 + }, + "id": 209, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 2, + "links": [], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeatIteration": 1562945734865, + "repeatPanelId": 12, + "repeatedByRow": true, + "scopedVars": { + "node": { + "selected": false, + "text": "kube-master", + "value": "kube-master" + }, + "pod": { + "selected": false, + "text": "coredns-69cf6b55b4-kf6m7", + "value": "coredns-69cf6b55b4-kf6m7" + } + }, + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(coredns_dns_requests_total{job=\"kube-dns\", pod=~\"$pod\"}[$__rate_interval])) by (type)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{type}}", + "refId": "A", + "step": 60 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Requests (by qtype)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "reqps", + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "pps", + "logBase": 1, + "max": null, + "min": 0, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "editable": true, + "error": false, + "fill": 1, + "grid": {}, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 46 + }, + "id": 210, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 2, + "links": [], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeatIteration": 1562945734865, + "repeatPanelId": 5, + "repeatedByRow": true, + "scopedVars": { + "node": { + "selected": false, + "text": "kube-master", + "value": "kube-master" + }, + "pod": { + "selected": false, + "text": "coredns-69cf6b55b4-kf6m7", + "value": "coredns-69cf6b55b4-kf6m7" + } + }, + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(coredns_dns_responses_total{job=\"kube-dns\", pod=~\"$pod\"}[$__rate_interval])) by (rcode)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{rcode}}", + "refId": "A", + "step": 40 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Responses (by rcode)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "reqps", + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "editable": true, + "error": false, + "fill": 1, + "grid": {}, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 53 + }, + "id": 211, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 2, + "links": [], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeatIteration": 1562945734865, + "repeatPanelId": 47, + "repeatedByRow": true, + "scopedVars": { + "node": { + "selected": false, + "text": "kube-master", + "value": "kube-master" + }, + "pod": { + "selected": false, + "text": "coredns-69cf6b55b4-kf6m7", + "value": "coredns-69cf6b55b4-kf6m7" + } + }, + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(coredns_forward_requests_total{job=\"kube-dns\", pod=~\"$pod\"}[$__rate_interval])) by (to)", + "format": "time_series", + "instant": false, + "intervalFactor": 1, + "legendFormat": "{{to}}", + "refId": "A", + "step": 60 + }, + { + "expr": "sum(rate(coredns_forward_requests_total{job=\"kube-dns\", pod=~\"$pod\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "B", + "step": 60 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Forwarded requests count (by upstream)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "reqps", + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "pps", + "logBase": 1, + "max": null, + "min": 0, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "editable": true, + "error": false, + "fill": 1, + "grid": {}, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 53 + }, + "id": 212, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 2, + "links": [], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeatIteration": 1562945734865, + "repeatPanelId": 49, + "repeatedByRow": true, + "scopedVars": { + "node": { + "selected": false, + "text": "kube-master", + "value": "kube-master" + }, + "pod": { + "selected": false, + "text": "coredns-69cf6b55b4-kf6m7", + "value": "coredns-69cf6b55b4-kf6m7" + } + }, + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(coredns_forward_responses_total{job=\"kube-dns\", pod=~\"$pod\"}[$__rate_interval])) by (rcode)", + "format": "time_series", + "instant": false, + "intervalFactor": 1, + "legendFormat": "{{rcode}}", + "refId": "A", + "step": 60 + }, + { + "expr": "sum(rate(coredns_forward_responses_total{job=\"kube-dns\", pod=~\"$pod\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Forwarded requests count (by rcode)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "reqps", + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "pps", + "logBase": 1, + "max": null, + "min": 0, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "description": "If the graph is non-empty, it means that some CoreDNS requests resulted in panic. You can see a specific error in the container logs.", + "editable": true, + "error": false, + "fill": 1, + "grid": {}, + "gridPos": { + "h": 3, + "w": 24, + "x": 0, + "y": 60 + }, + "id": 213, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "rightSide": true, + "show": false, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 2, + "links": [], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeatDirection": "h", + "repeatIteration": 1562945734865, + "repeatPanelId": 204, + "repeatedByRow": true, + "scopedVars": { + "pod": { + "selected": false, + "text": "coredns-69cf6b55b4-kf6m7", + "value": "coredns-69cf6b55b4-kf6m7" + } + }, + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(coredns_forward_healthcheck_failures_total{job=\"kube-dns\", pod=~\"$pod\"}[$__rate_interval])) by (upstream)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{pod}}", + "refId": "A", + "step": 40 + }, + { + "expr": "sum(rate(coredns_forward_healthcheck_failures_total{job=\"kube-dns\", pod=~\"$pod\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "CoreDNS Forward Healthcheck Failure Count", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "editable": true, + "error": false, + "fill": 1, + "grid": {}, + "gridPos": { + "h": 3, + "w": 24, + "x": 0, + "y": 63 + }, + "id": 214, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 2, + "links": [], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeatIteration": 1562945734865, + "repeatPanelId": 135, + "repeatedByRow": true, + "scopedVars": { + "node": { + "selected": false, + "text": "kube-master", + "value": "kube-master" + }, + "pod": { + "selected": false, + "text": "coredns-69cf6b55b4-kf6m7", + "value": "coredns-69cf6b55b4-kf6m7" + } + }, + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(coredns_dns_requests_total{job=\"kube-dns\", pod=~\"$pod\",proto=\"tcp\"}[$__rate_interval]))\n/\nsum(rate(coredns_dns_requests_total{job=\"kube-dns\", pod=~\"$pod\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "TCP", + "refId": "C", + "step": 60 + }, + { + "expr": "sum(rate(coredns_dns_requests_total{job=\"kube-dns\", pod=~\"$pod\",proto=\"udp\"}[$__rate_interval]))\n/\nsum(rate(coredns_dns_requests_total{job=\"kube-dns\", pod=~\"$pod\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "UDP", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "TCP/UDP requests ratio", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "percentunit", + "logBase": 1, + "max": "1", + "min": 0, + "show": true + }, + { + "format": "short", + "logBase": 1, + "max": null, + "min": 0, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "editable": true, + "error": false, + "fill": 1, + "grid": {}, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 66 + }, + "id": 215, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeatIteration": 1562945734865, + "repeatPanelId": 80, + "repeatedByRow": true, + "scopedVars": { + "node": { + "selected": false, + "text": "kube-master", + "value": "kube-master" + }, + "pod": { + "selected": false, + "text": "coredns-69cf6b55b4-kf6m7", + "value": "coredns-69cf6b55b4-kf6m7" + } + }, + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(coredns_cache_hits_total{job=\"kube-dns\", pod=~\"$pod\"}[$__rate_interval]))\n/\n(\nsum(rate(coredns_cache_hits_total{job=\"kube-dns\", pod=~\"$pod\"}[$__rate_interval])) +\nsum(rate(coredns_cache_misses_total{job=\"kube-dns\", pod=~\"$pod\"}[$__rate_interval]))\n)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A", + "step": 40 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Cache hit rate", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "percentunit", + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "pps", + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "editable": true, + "error": false, + "fill": 1, + "grid": {}, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 66 + }, + "id": 216, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 2, + "links": [], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeatIteration": 1562945734865, + "repeatPanelId": 81, + "repeatedByRow": true, + "scopedVars": { + "node": { + "selected": false, + "text": "kube-master", + "value": "kube-master" + }, + "pod": { + "selected": false, + "text": "coredns-69cf6b55b4-kf6m7", + "value": "coredns-69cf6b55b4-kf6m7" + } + }, + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(max_over_time(coredns_cache_entries{job=\"kube-dns\", pod=~\"$pod\"}[$__rate_interval])) by (type)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{type}}", + "refId": "A", + "step": 40 + }, + { + "expr": "sum(max_over_time(coredns_cache_entries{job=\"kube-dns\", pod=~\"$pod\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Cache size", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "logBase": 1, + "max": null, + "min": 0, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "editable": true, + "error": false, + "fill": 1, + "grid": {}, + "gridPos": { + "h": 7, + "w": 24, + "x": 0, + "y": 73 + }, + "id": 217, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeatIteration": 1562945734865, + "repeatPanelId": 2, + "repeatedByRow": true, + "scopedVars": { + "node": { + "selected": false, + "text": "kube-master", + "value": "kube-master" + }, + "pod": { + "selected": false, + "text": "coredns-69cf6b55b4-kf6m7", + "value": "coredns-69cf6b55b4-kf6m7" + } + }, + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(coredns_dns_requests_total{job=\"kube-dns\", pod=~\"$pod\"}[$__rate_interval])) by (zone)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{zone}}", + "refId": "A", + "step": 60 + }, + { + "expr": "sum(rate(coredns_dns_requests_total{job=\"kube-dns\", pod=~\"$pod\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "B", + "step": 60 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Requests (by zone)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "pps", + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "pps", + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "cards": { + "cardPadding": null, + "cardRound": null + }, + "color": { + "cardColor": "#b4ff00", + "colorScale": "sqrt", + "colorScheme": "interpolateMagma", + "exponent": 0.5, + "mode": "spectrum" + }, + "dataFormat": "tsbuckets", + "datasource": "$ds_prometheus", + "gridPos": { + "h": 7, + "w": 24, + "x": 0, + "y": 80 + }, + "heatmap": {}, + "hideZeroBuckets": false, + "highlightCards": true, + "id": 218, + "legend": { + "show": false + }, + "links": [], + "repeatIteration": 1562945734865, + "repeatPanelId": 18, + "repeatedByRow": true, + "reverseYBuckets": false, + "scopedVars": { + "node": { + "selected": false, + "text": "kube-master", + "value": "kube-master" + }, + "pod": { + "selected": false, + "text": "coredns-69cf6b55b4-kf6m7", + "value": "coredns-69cf6b55b4-kf6m7" + } + }, + "targets": [ + { + "expr": "sum(rate(coredns_dns_request_duration_seconds_bucket{job=\"kube-dns\", pod=~\"$pod\"}[$__rate_interval])) by (le)", + "format": "heatmap", + "intervalFactor": 1, + "legendFormat": "{{le}}", + "refId": "A" + } + ], + "title": "Request duration", + "tooltip": { + "show": true, + "showHistogram": true + }, + "type": "heatmap", + "xAxis": { + "show": true + }, + "xBucketNumber": null, + "xBucketSize": null, + "yAxis": { + "decimals": null, + "format": "s", + "logBase": 1, + "max": null, + "min": null, + "show": true, + "splitFactor": null + }, + "yBucketBound": "auto", + "yBucketNumber": null, + "yBucketSize": null + }, + { + "cards": { + "cardPadding": null, + "cardRound": null + }, + "color": { + "cardColor": "#b4ff00", + "colorScale": "sqrt", + "colorScheme": "interpolateMagma", + "exponent": 0.5, + "mode": "spectrum" + }, + "dataFormat": "tsbuckets", + "gridPos": { + "h": 7, + "w": 24, + "x": 0, + "y": 87 + }, + "heatmap": {}, + "hideZeroBuckets": false, + "highlightCards": true, + "id": 219, + "legend": { + "show": false + }, + "links": [], + "repeatIteration": 1562945734865, + "repeatPanelId": 20, + "repeatedByRow": true, + "reverseYBuckets": false, + "scopedVars": { + "node": { + "selected": false, + "text": "kube-master", + "value": "kube-master" + }, + "pod": { + "selected": false, + "text": "coredns-69cf6b55b4-kf6m7", + "value": "coredns-69cf6b55b4-kf6m7" + } + }, + "targets": [ + { + "expr": "sum(rate(coredns_forward_request_duration_seconds_bucket{job=\"kube-dns\", pod=~\"$pod\"}[$__rate_interval])) by (le)", + "format": "heatmap", + "intervalFactor": 1, + "legendFormat": "{{le}}", + "refId": "A" + } + ], + "title": "Forward duration", + "tooltip": { + "show": true, + "showHistogram": false + }, + "type": "heatmap", + "xAxis": { + "show": true + }, + "xBucketNumber": null, + "xBucketSize": null, + "yAxis": { + "decimals": null, + "format": "s", + "logBase": 1, + "max": null, + "min": null, + "show": true, + "splitFactor": null + }, + "yBucketBound": "auto", + "yBucketNumber": null, + "yBucketSize": null + } + ], + "repeat": null, + "repeatIteration": 1562945734865, + "repeatPanelId": 38, + "scopedVars": { + "pod": { + "selected": false, + "text": "coredns-69cf6b55b4-kf6m7", + "value": "coredns-69cf6b55b4-kf6m7" + } + }, + "title": "Pod $pod", + "type": "row" + }, + { + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 47 + }, + "id": 148, + "panels": [ + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "editable": true, + "error": false, + "fill": 1, + "grid": {}, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 48 + }, + "id": 149, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 2, + "links": [], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeatIteration": 1560933196142, + "repeatPanelId": 113, + "repeatedByRow": true, + "scopedVars": { + "upstream": { + "selected": false, + "text": "10.244.2.146:53", + "value": "10.244.2.146:53" + } + }, + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(coredns_forward_requests_total{job=\"kube-dns\", pod=~\"$pod\", to=~\"$upstream\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "B", + "step": 60 + }, + { + "expr": "sum(rate(coredns_forward_requests_total{job=\"kube-dns\", pod=~\"$pod\", to=~\"$upstream\"}[$__rate_interval])) by (pod)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{pod}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Forwarded requests count", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "reqps", + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "pps", + "logBase": 1, + "max": null, + "min": 0, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "editable": true, + "error": false, + "fill": 1, + "grid": {}, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 48 + }, + "id": 150, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 2, + "links": [], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeatIteration": 1560933196142, + "repeatPanelId": 114, + "repeatedByRow": true, + "scopedVars": { + "upstream": { + "selected": false, + "text": "10.244.2.146:53", + "value": "10.244.2.146:53" + } + }, + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(coredns_forward_responses_total{job=\"kube-dns\", pod=~\"$pod\", to=~\"$upstream\"}[$__rate_interval])) by (rcode)", + "format": "time_series", + "instant": false, + "intervalFactor": 1, + "legendFormat": "{{rcode}}", + "refId": "A", + "step": 60 + }, + { + "expr": "sum(rate(coredns_forward_responses_total{job=\"kube-dns\", pod=~\"$pod\", to=~\"$upstream\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Forwarded requests count (by rcode)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "reqps", + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "pps", + "logBase": 1, + "max": null, + "min": 0, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "cards": { + "cardPadding": null, + "cardRound": null + }, + "color": { + "cardColor": "#b4ff00", + "colorScale": "sqrt", + "colorScheme": "interpolateMagma", + "exponent": 0.5, + "mode": "spectrum" + }, + "dataFormat": "tsbuckets", + "gridPos": { + "h": 7, + "w": 24, + "x": 0, + "y": 55 + }, + "heatmap": {}, + "hideZeroBuckets": false, + "highlightCards": true, + "id": 151, + "legend": { + "show": false + }, + "links": [], + "repeatIteration": 1560933196142, + "repeatPanelId": 115, + "repeatedByRow": true, + "reverseYBuckets": false, + "scopedVars": { + "upstream": { + "selected": false, + "text": "10.244.2.146:53", + "value": "10.244.2.146:53" + } + }, + "targets": [ + { + "expr": "sum(rate(coredns_forward_request_duration_seconds_bucket{job=\"kube-dns\", pod=~\"$pod\", to=~\"$upstream\"}[$__rate_interval])) by (le)", + "format": "heatmap", + "intervalFactor": 1, + "legendFormat": "{{le}}", + "refId": "A" + } + ], + "title": "Forward duration", + "tooltip": { + "show": true, + "showHistogram": false + }, + "type": "heatmap", + "xAxis": { + "show": true + }, + "xBucketNumber": null, + "xBucketSize": null, + "yAxis": { + "decimals": null, + "format": "s", + "logBase": 1, + "max": null, + "min": null, + "show": true, + "splitFactor": null + }, + "yBucketBound": "auto", + "yBucketNumber": null, + "yBucketSize": null + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "description": "If the graph is non-empty, it means that some CoreDNS requests resulted in panic. You can see a specific error in the container logs.", + "editable": true, + "error": false, + "fill": 1, + "grid": {}, + "gridPos": { + "h": 3, + "w": 24, + "x": 0, + "y": 62 + }, + "id": 205, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "rightSide": true, + "show": false, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 2, + "links": [], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeatDirection": "h", + "scopedVars": { + "upstream": { + "selected": false, + "text": "10.244.2.146:53", + "value": "10.244.2.146:53" + } + }, + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(coredns_forward_healthcheck_failures_total{job=\"kube-dns\", pod=~\"$pod\", to=~\"$upstream\"}[$__rate_interval])) by (pod)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{pod}}", + "refId": "A", + "step": 40 + }, + { + "expr": "sum(rate(coredns_forward_healthcheck_failures_total{job=\"kube-dns\", pod=~\"$pod\", to=~\"$upstream\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "CoreDNS Forward Healthcheck Failure Count", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "repeat": "upstream", + "repeatIteration": 1560933196142, + "repeatPanelId": 100, + "scopedVars": { + "upstream": { + "selected": false, + "text": "10.244.2.146:53", + "value": "10.244.2.146:53" + } + }, + "title": "Upstream $upstream", + "type": "row" + }, + { + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 48 + }, + "id": 220, + "panels": [ + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "editable": true, + "error": false, + "fill": 1, + "grid": {}, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 48 + }, + "id": 221, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 2, + "links": [], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeatIteration": 1562945734865, + "repeatPanelId": 149, + "repeatedByRow": true, + "scopedVars": { + "upstream": { + "selected": false, + "text": "10.244.2.148:53", + "value": "10.244.2.148:53" + } + }, + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(coredns_forward_requests_total{job=\"kube-dns\", pod=~\"$pod\", to=~\"$upstream\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "B", + "step": 60 + }, + { + "expr": "sum(rate(coredns_forward_requests_total{job=\"kube-dns\", pod=~\"$pod\", to=~\"$upstream\"}[$__rate_interval])) by (pod)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{pod}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Forwarded requests count", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "reqps", + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "pps", + "logBase": 1, + "max": null, + "min": 0, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "editable": true, + "error": false, + "fill": 1, + "grid": {}, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 48 + }, + "id": 222, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 2, + "links": [], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeatIteration": 1562945734865, + "repeatPanelId": 150, + "repeatedByRow": true, + "scopedVars": { + "upstream": { + "selected": false, + "text": "10.244.2.148:53", + "value": "10.244.2.148:53" + } + }, + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(coredns_forward_responses_total{job=\"kube-dns\", pod=~\"$pod\", to=~\"$upstream\"}[$__rate_interval])) by (rcode)", + "format": "time_series", + "instant": false, + "intervalFactor": 1, + "legendFormat": "{{rcode}}", + "refId": "A", + "step": 60 + }, + { + "expr": "sum(rate(coredns_forward_responses_total{job=\"kube-dns\", pod=~\"$pod\", to=~\"$upstream\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Forwarded requests count (by rcode)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "reqps", + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "pps", + "logBase": 1, + "max": null, + "min": 0, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "cards": { + "cardPadding": null, + "cardRound": null + }, + "color": { + "cardColor": "#b4ff00", + "colorScale": "sqrt", + "colorScheme": "interpolateMagma", + "exponent": 0.5, + "mode": "spectrum" + }, + "dataFormat": "tsbuckets", + "gridPos": { + "h": 7, + "w": 24, + "x": 0, + "y": 55 + }, + "heatmap": {}, + "hideZeroBuckets": false, + "highlightCards": true, + "id": 223, + "legend": { + "show": false + }, + "links": [], + "repeatIteration": 1562945734865, + "repeatPanelId": 151, + "repeatedByRow": true, + "reverseYBuckets": false, + "scopedVars": { + "upstream": { + "selected": false, + "text": "10.244.2.148:53", + "value": "10.244.2.148:53" + } + }, + "targets": [ + { + "expr": "sum(rate(coredns_forward_request_duration_seconds_bucket{job=\"kube-dns\", pod=~\"$pod\", to=~\"$upstream\"}[$__rate_interval])) by (le)", + "format": "heatmap", + "intervalFactor": 1, + "legendFormat": "{{le}}", + "refId": "A" + } + ], + "title": "Forward duration", + "tooltip": { + "show": true, + "showHistogram": false + }, + "type": "heatmap", + "xAxis": { + "show": true + }, + "xBucketNumber": null, + "xBucketSize": null, + "yAxis": { + "decimals": null, + "format": "s", + "logBase": 1, + "max": null, + "min": null, + "show": true, + "splitFactor": null + }, + "yBucketBound": "auto", + "yBucketNumber": null, + "yBucketSize": null + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "description": "If the graph is non-empty, it means that some CoreDNS requests resulted in panic. You can see a specific error in the container logs.", + "editable": true, + "error": false, + "fill": 1, + "grid": {}, + "gridPos": { + "h": 3, + "w": 24, + "x": 0, + "y": 62 + }, + "id": 224, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "rightSide": true, + "show": false, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 2, + "links": [], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeatDirection": "h", + "repeatIteration": 1562945734865, + "repeatPanelId": 205, + "repeatedByRow": true, + "scopedVars": { + "upstream": { + "selected": false, + "text": "10.244.2.148:53", + "value": "10.244.2.148:53" + } + }, + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(coredns_forward_healthcheck_failures_total{job=\"kube-dns\", pod=~\"$pod\", to=~\"$upstream\"}[$__rate_interval])) by (pod)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{pod}}", + "refId": "A", + "step": 40 + }, + { + "expr": "sum(rate(coredns_forward_healthcheck_failures_total{job=\"kube-dns\", pod=~\"$pod\", to=~\"$upstream\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "CoreDNS Forward Healthcheck Failure Count", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "repeat": null, + "repeatIteration": 1562945734865, + "repeatPanelId": 148, + "scopedVars": { + "upstream": { + "selected": false, + "text": "10.244.2.148:53", + "value": "10.244.2.148:53" + } + }, + "title": "Upstream $upstream", + "type": "row" + }, + { + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 49 + }, + "id": 225, + "panels": [ + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "editable": true, + "error": false, + "fill": 1, + "grid": {}, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 48 + }, + "id": 226, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 2, + "links": [], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeatIteration": 1562945734865, + "repeatPanelId": 149, + "repeatedByRow": true, + "scopedVars": { + "upstream": { + "selected": false, + "text": "8.8.4.4:53", + "value": "8.8.4.4:53" + } + }, + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(coredns_forward_requests_total{job=\"kube-dns\", pod=~\"$pod\", to=~\"$upstream\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "B", + "step": 60 + }, + { + "expr": "sum(rate(coredns_forward_requests_total{job=\"kube-dns\", pod=~\"$pod\", to=~\"$upstream\"}[$__rate_interval])) by (pod)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{pod}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Forwarded requests count", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "reqps", + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "pps", + "logBase": 1, + "max": null, + "min": 0, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "editable": true, + "error": false, + "fill": 1, + "grid": {}, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 48 + }, + "id": 227, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 2, + "links": [], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeatIteration": 1562945734865, + "repeatPanelId": 150, + "repeatedByRow": true, + "scopedVars": { + "upstream": { + "selected": false, + "text": "8.8.4.4:53", + "value": "8.8.4.4:53" + } + }, + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(coredns_forward_responses_total{job=\"kube-dns\", pod=~\"$pod\", to=~\"$upstream\"}[$__rate_interval])) by (rcode)", + "format": "time_series", + "instant": false, + "intervalFactor": 1, + "legendFormat": "{{rcode}}", + "refId": "A", + "step": 60 + }, + { + "expr": "sum(rate(coredns_forward_responses_total{job=\"kube-dns\", pod=~\"$pod\", to=~\"$upstream\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Forwarded requests count (by rcode)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "reqps", + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "pps", + "logBase": 1, + "max": null, + "min": 0, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "cards": { + "cardPadding": null, + "cardRound": null + }, + "color": { + "cardColor": "#b4ff00", + "colorScale": "sqrt", + "colorScheme": "interpolateMagma", + "exponent": 0.5, + "mode": "spectrum" + }, + "dataFormat": "tsbuckets", + "gridPos": { + "h": 7, + "w": 24, + "x": 0, + "y": 55 + }, + "heatmap": {}, + "hideZeroBuckets": false, + "highlightCards": true, + "id": 228, + "legend": { + "show": false + }, + "links": [], + "repeatIteration": 1562945734865, + "repeatPanelId": 151, + "repeatedByRow": true, + "reverseYBuckets": false, + "scopedVars": { + "upstream": { + "selected": false, + "text": "8.8.4.4:53", + "value": "8.8.4.4:53" + } + }, + "targets": [ + { + "expr": "sum(rate(coredns_forward_request_duration_seconds_bucket{job=\"kube-dns\", pod=~\"$pod\", to=~\"$upstream\"}[$__rate_interval])) by (le)", + "format": "heatmap", + "intervalFactor": 1, + "legendFormat": "{{le}}", + "refId": "A" + } + ], + "title": "Forward duration", + "tooltip": { + "show": true, + "showHistogram": false + }, + "type": "heatmap", + "xAxis": { + "show": true + }, + "xBucketNumber": null, + "xBucketSize": null, + "yAxis": { + "decimals": null, + "format": "s", + "logBase": 1, + "max": null, + "min": null, + "show": true, + "splitFactor": null + }, + "yBucketBound": "auto", + "yBucketNumber": null, + "yBucketSize": null + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "description": "If the graph is non-empty, it means that some CoreDNS requests resulted in panic. You can see a specific error in the container logs.", + "editable": true, + "error": false, + "fill": 1, + "grid": {}, + "gridPos": { + "h": 3, + "w": 24, + "x": 0, + "y": 62 + }, + "id": 229, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "rightSide": true, + "show": false, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 2, + "links": [], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeatDirection": "h", + "repeatIteration": 1562945734865, + "repeatPanelId": 205, + "repeatedByRow": true, + "scopedVars": { + "upstream": { + "selected": false, + "text": "8.8.4.4:53", + "value": "8.8.4.4:53" + } + }, + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(coredns_forward_healthcheck_failures_total{job=\"kube-dns\", pod=~\"$pod\", to=~\"$upstream\"}[$__rate_interval])) by (pod)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{pod}}", + "refId": "A", + "step": 40 + }, + { + "expr": "sum(rate(coredns_forward_healthcheck_failures_total{job=\"kube-dns\", pod=~\"$pod\", to=~\"$upstream\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "CoreDNS Forward Healthcheck Failure Count", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "repeat": null, + "repeatIteration": 1562945734865, + "repeatPanelId": 148, + "scopedVars": { + "upstream": { + "selected": false, + "text": "8.8.4.4:53", + "value": "8.8.4.4:53" + } + }, + "title": "Upstream $upstream", + "type": "row" + }, + { + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 50 + }, + "id": 230, + "panels": [ + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "editable": true, + "error": false, + "fill": 1, + "grid": {}, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 48 + }, + "id": 231, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 2, + "links": [], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeatIteration": 1562945734865, + "repeatPanelId": 149, + "repeatedByRow": true, + "scopedVars": { + "upstream": { + "selected": false, + "text": "8.8.8.8:53", + "value": "8.8.8.8:53" + } + }, + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(coredns_forward_requests_total{job=\"kube-dns\", pod=~\"$pod\", to=~\"$upstream\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "B", + "step": 60 + }, + { + "expr": "sum(rate(coredns_forward_requests_total{job=\"kube-dns\", pod=~\"$pod\", to=~\"$upstream\"}[$__rate_interval])) by (pod)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{pod}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Forwarded requests count", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "reqps", + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "pps", + "logBase": 1, + "max": null, + "min": 0, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "editable": true, + "error": false, + "fill": 1, + "grid": {}, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 48 + }, + "id": 232, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 2, + "links": [], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeatIteration": 1562945734865, + "repeatPanelId": 150, + "repeatedByRow": true, + "scopedVars": { + "upstream": { + "selected": false, + "text": "8.8.8.8:53", + "value": "8.8.8.8:53" + } + }, + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(coredns_forward_responses_total{job=\"kube-dns\", pod=~\"$pod\", to=~\"$upstream\"}[$__rate_interval])) by (rcode)", + "format": "time_series", + "instant": false, + "intervalFactor": 1, + "legendFormat": "{{rcode}}", + "refId": "A", + "step": 60 + }, + { + "expr": "sum(rate(coredns_forward_responses_total{job=\"kube-dns\", pod=~\"$pod\", to=~\"$upstream\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Forwarded requests count (by rcode)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "reqps", + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "pps", + "logBase": 1, + "max": null, + "min": 0, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "cards": { + "cardPadding": null, + "cardRound": null + }, + "color": { + "cardColor": "#b4ff00", + "colorScale": "sqrt", + "colorScheme": "interpolateMagma", + "exponent": 0.5, + "mode": "spectrum" + }, + "dataFormat": "tsbuckets", + "gridPos": { + "h": 7, + "w": 24, + "x": 0, + "y": 55 + }, + "heatmap": {}, + "hideZeroBuckets": false, + "highlightCards": true, + "id": 233, + "legend": { + "show": false + }, + "links": [], + "repeatIteration": 1562945734865, + "repeatPanelId": 151, + "repeatedByRow": true, + "reverseYBuckets": false, + "scopedVars": { + "upstream": { + "selected": false, + "text": "8.8.8.8:53", + "value": "8.8.8.8:53" + } + }, + "targets": [ + { + "expr": "sum(rate(coredns_forward_request_duration_seconds_bucket{job=\"kube-dns\", pod=~\"$pod\", to=~\"$upstream\"}[$__rate_interval])) by (le)", + "format": "heatmap", + "intervalFactor": 1, + "legendFormat": "{{le}}", + "refId": "A" + } + ], + "title": "Forward duration", + "tooltip": { + "show": true, + "showHistogram": false + }, + "type": "heatmap", + "xAxis": { + "show": true + }, + "xBucketNumber": null, + "xBucketSize": null, + "yAxis": { + "decimals": null, + "format": "s", + "logBase": 1, + "max": null, + "min": null, + "show": true, + "splitFactor": null + }, + "yBucketBound": "auto", + "yBucketNumber": null, + "yBucketSize": null + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "description": "If the graph is non-empty, it means that some CoreDNS requests resulted in panic. You can see a specific error in the container logs.", + "editable": true, + "error": false, + "fill": 1, + "grid": {}, + "gridPos": { + "h": 3, + "w": 24, + "x": 0, + "y": 62 + }, + "id": 234, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "rightSide": true, + "show": false, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 2, + "links": [], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeatDirection": "h", + "repeatIteration": 1562945734865, + "repeatPanelId": 205, + "repeatedByRow": true, + "scopedVars": { + "upstream": { + "selected": false, + "text": "8.8.8.8:53", + "value": "8.8.8.8:53" + } + }, + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(coredns_forward_healthcheck_failures_total{job=\"kube-dns\", pod=~\"$pod\", to=~\"$upstream\"}[$__rate_interval])) by (pod)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{pod}}", + "refId": "A", + "step": 40 + }, + { + "expr": "sum(rate(coredns_forward_healthcheck_failures_total{job=\"kube-dns\", pod=~\"$pod\", to=~\"$upstream\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "CoreDNS Forward Healthcheck Failure Count", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "repeat": null, + "repeatIteration": 1562945734865, + "repeatPanelId": 148, + "scopedVars": { + "upstream": { + "selected": false, + "text": "8.8.8.8:53", + "value": "8.8.8.8:53" + } + }, + "title": "Upstream $upstream", + "type": "row" + } + ], + "refresh": "30s", + "schemaVersion": 18, + "style": "dark", + "tags": [], + "templating": { + "list": [ + { + "current": { + "text": "default", + "value": "default" + }, + "hide": 0, + "includeAll": false, + "label": "Prometheus", + "multi": false, + "name": "ds_prometheus", + "options": [], + "query": "prometheus", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + }, + { + "allValue": null, + "current": { + "text": "All", + "value": "$__all" + }, + "datasource": "$ds_prometheus", + "definition": "label_values(up{job=\"kube-dns\"}, pod)", + "hide": 0, + "includeAll": true, + "label": "Pod", + "multi": true, + "name": "pod", + "options": [], + "query": "label_values(up{job=\"kube-dns\"}, pod)", + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "current": { + "text": "All", + "value": "$__all" + }, + "datasource": "$ds_prometheus", + "definition": "label_values(coredns_dns_responses_total{rcode!=\"NOERROR\"}, rcode)", + "hide": 2, + "includeAll": true, + "label": null, + "multi": true, + "name": "rcode", + "options": [ + { + "selected": true, + "text": "All", + "value": "$__all" + }, + { + "selected": false, + "text": "NXDOMAIN", + "value": "NXDOMAIN" + }, + { + "selected": false, + "text": "SERVFAIL", + "value": "SERVFAIL" + }, + { + "selected": false, + "text": "REFUSED", + "value": "REFUSED" + } + ], + "query": "label_values(coredns_dns_responses_total{rcode!=\"NOERROR\"}, rcode)", + "refresh": 0, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "current": { + "text": "All", + "value": "$__all" + }, + "datasource": "$ds_prometheus", + "definition": "label_values(coredns_forward_request_duration_seconds_sum,to)", + "hide": 2, + "includeAll": true, + "label": null, + "multi": true, + "name": "upstream", + "options": [], + "query": "label_values(coredns_forward_request_duration_seconds_sum,to)", + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + } + ] + }, + "time": { + "from": "now-3h", + "to": "now" + }, + "timepicker": { + "now": true, + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "", + "title": "DNS (coredns)", + "uid": "KsgnV_7Zz", + "version": 4 +} diff --git a/dashboards/control-plane/kube-etcd3.json b/dashboards/control-plane/kube-etcd3.json new file mode 100644 index 00000000..862b0967 --- /dev/null +++ b/dashboards/control-plane/kube-etcd3.json @@ -0,0 +1,1602 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": "-- Grafana --", + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "target": { + "limit": 100, + "matchAny": false, + "tags": [], + "type": "dashboard" + }, + "type": "dashboard" + } + ] + }, + "description": "", + "editable": false, + "fiscalYearStartMonth": 0, + "gnetId": null, + "graphTooltip": 0, + "iteration": 1648725217596, + "links": [], + "liveNow": false, + "panels": [ + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 3, + "x": 0, + "y": 0 + }, + "id": 28, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "sum(etcd_server_has_leader{job=\"kube-etcd3\", node=~\"$node\"})", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "", + "metric": "etcd_server_has_leader", + "refId": "A", + "step": 20 + } + ], + "title": "Up", + "type": "stat" + }, + { + "columns": [ + { + "text": "Current", + "value": "current" + } + ], + "datasource": "$ds_prometheus", + "fontSize": "100%", + "gridPos": { + "h": 7, + "w": 3, + "x": 3, + "y": 0 + }, + "id": 43, + "links": [], + "pageSize": null, + "scroll": true, + "showHeader": true, + "sort": { + "col": null, + "desc": false + }, + "styles": [ + { + "alias": "Service / Node", + "align": "auto", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "pattern": "Metric", + "thresholds": [], + "type": "string", + "unit": "short" + } + ], + "targets": [ + { + "expr": "changes(etcd_server_leader_changes_seen_total{job=\"kube-etcd3\", node=~\"$node\"}[$__range])", + "format": "time_series", + "instant": true, + "intervalFactor": 1, + "legendFormat": "{{node}}", + "refId": "A" + } + ], + "title": "Total Leader Elections", + "transform": "timeseries_aggregations", + "type": "table-old" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "editable": true, + "error": false, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 10, + "x": 6, + "y": 0 + }, + "hiddenSeries": false, + "id": 23, + "isNew": true, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "sum(rate(grpc_server_started_total{job=\"kube-etcd3\", node=~\"$node\", grpc_type=\"unary\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "RPC Rate", + "metric": "grpc_server_started_total", + "refId": "A", + "step": 2 + }, + { + "expr": "sum(rate(grpc_server_handled_total{job=\"kube-etcd3\", node=~\"$node\", grpc_type=\"unary\",grpc_code!=\"OK\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "RPC Failed Rate", + "metric": "grpc_server_handled_total", + "refId": "B", + "step": 2 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "RPC Rate", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:901", + "format": "ops", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "$$hashKey": "object:902", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "editable": true, + "error": false, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 8, + "x": 16, + "y": 0 + }, + "hiddenSeries": false, + "id": 41, + "isNew": true, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": true, + "targets": [ + { + "expr": "sum(grpc_server_started_total{job=\"kube-etcd3\", node=~\"$node\", grpc_service=\"etcdserverpb.Watch\", grpc_type=\"bidi_stream\"}) - sum(grpc_server_handled_total{job=\"kube-etcd3\", node=~\"$node\", grpc_service=\"etcdserverpb.Watch\", grpc_type=\"bidi_stream\"})", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Watch Streams", + "metric": "grpc_server_handled_total", + "refId": "A", + "step": 4 + }, + { + "expr": "sum(grpc_server_started_total{job=\"kube-etcd3\", node=~\"$node\", grpc_service=\"etcdserverpb.Lease\", grpc_type=\"bidi_stream\"}) - sum(grpc_server_handled_total{job=\"kube-etcd3\", node=~\"$node\", grpc_service=\"etcdserverpb.Lease\", grpc_type=\"bidi_stream\"})", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Lease Streams", + "metric": "grpc_server_handled_total", + "refId": "B", + "step": 4 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Active Streams", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:557", + "format": "short", + "label": "", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "$$hashKey": "object:558", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": null, + "editable": true, + "error": false, + "fill": 0, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 7, + "w": 8, + "x": 0, + "y": 7 + }, + "hiddenSeries": false, + "id": 1, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "etcd_mvcc_db_total_size_in_bytes{job=\"kube-etcd3\", node=~\"$node\"}", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "{{node}} DB Size", + "metric": "", + "refId": "A", + "step": 4 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "DB Size", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "editable": true, + "error": false, + "fill": 0, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 7, + "w": 8, + "x": 8, + "y": 7 + }, + "hiddenSeries": false, + "id": 44, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 1, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "$$hashKey": "object:1385", + "alias": "/^0.000[0-9]/", + "color": "#56A64B" + }, + { + "$$hashKey": "object:1393", + "alias": "/^0.00[1-9]/", + "color": "#F2CC0C" + }, + { + "$$hashKey": "object:1401", + "alias": "/^0.0[1-9]/", + "color": "#FF780A" + }, + { + "$$hashKey": "object:1409", + "alias": "/^0.[1-9]/", + "color": "#E02F44" + }, + { + "$$hashKey": "object:1417", + "alias": "/^[1-9]/", + "color": "#C4162A" + }, + { + "$$hashKey": "object:1425", + "alias": "+Inf", + "color": "#AD0317" + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": true, + "targets": [ + { + "exemplar": true, + "expr": "sum(rate(etcd_server_apply_duration_seconds_bucket{job=\"kube-etcd3\", node=~\"$node\"}[$__rate_interval])) by (le)", + "format": "heatmap", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "{{le}}", + "metric": "etcd_disk_wal_fsync_duration_seconds_bucket", + "refId": "A", + "step": 4 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Apply duration bucket", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:231", + "format": "ops", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "$$hashKey": "object:232", + "format": "short", + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "editable": true, + "error": false, + "fill": 3, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 8, + "x": 16, + "y": 7 + }, + "hiddenSeries": false, + "id": 22, + "isNew": true, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "connected", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": true, + "targets": [ + { + "expr": "rate(etcd_network_client_grpc_received_bytes_total{job=\"kube-etcd3\", node=~\"$node\"}[$__rate_interval])", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{node}} Client Traffic In", + "metric": "etcd_network_client_grpc_received_bytes_total", + "refId": "A", + "step": 4 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Client Traffic In", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "editable": true, + "error": false, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 8, + "x": 0, + "y": 14 + }, + "hiddenSeries": false, + "id": 29, + "isNew": true, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "process_resident_memory_bytes{job=\"kube-etcd3\", node=~\"$node\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{node}} Resident Memory", + "metric": "process_resident_memory_bytes", + "refId": "A", + "step": 4 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Memory", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "editable": true, + "error": false, + "fill": 0, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 7, + "w": 8, + "x": 8, + "y": 14 + }, + "hiddenSeries": false, + "id": 3, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "connected", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 1, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "exemplar": true, + "expr": "histogram_quantile(0.99, sum(rate(etcd_disk_wal_fsync_duration_seconds_bucket{job=\"kube-etcd3\", node=~\"$node\"}[$__rate_interval])) by (node, le))", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "{{node}} WAL fsync", + "metric": "etcd_disk_wal_fsync_duration_seconds_bucket", + "refId": "A", + "step": 4 + }, + { + "expr": "histogram_quantile(0.99, sum(rate(etcd_disk_backend_commit_duration_seconds_bucket{job=\"kube-etcd3\", node=~\"$node\"}[$__rate_interval])) by (node, le))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{node}} DB fsync", + "metric": "etcd_disk_backend_commit_duration_seconds_bucket", + "refId": "B", + "step": 4 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Disk Sync Duration", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:1125", + "format": "s", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "$$hashKey": "object:1126", + "format": "short", + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "editable": true, + "error": false, + "fill": 3, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 8, + "x": 16, + "y": 14 + }, + "hiddenSeries": false, + "id": 21, + "isNew": true, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "connected", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": true, + "targets": [ + { + "expr": "rate(etcd_network_client_grpc_sent_bytes_total{job=\"kube-etcd3\", node=~\"$node\"}[$__rate_interval])", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{node}} Client Traffic Out", + "metric": "etcd_network_client_grpc_sent_bytes_total", + "refId": "A", + "step": 4 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Client Traffic Out", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "editable": true, + "error": false, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 8, + "x": 0, + "y": 21 + }, + "hiddenSeries": false, + "id": 40, + "isNew": true, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "sum(rate(etcd_server_proposals_failed_total{job=\"kube-etcd3\", node=~\"$node\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Proposal Failure Rate", + "metric": "etcd_server_proposals_failed_total", + "refId": "A", + "step": 2 + }, + { + "expr": "sum(etcd_server_proposals_pending{job=\"kube-etcd3\", node=~\"$node\"})", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Proposal Pending Total", + "metric": "etcd_server_proposals_pending", + "refId": "B", + "step": 2 + }, + { + "expr": "sum(rate(etcd_server_proposals_committed_total{job=\"kube-etcd3\", node=~\"$node\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Proposal Commit Rate", + "metric": "etcd_server_proposals_committed_total", + "refId": "C", + "step": 2 + }, + { + "expr": "sum(rate(etcd_server_proposals_applied_total{job=\"kube-etcd3\", node=~\"$node\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Proposal Apply Rate", + "refId": "D", + "step": 2 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Raft Proposals", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:117", + "format": "short", + "label": "", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "$$hashKey": "object:118", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "editable": true, + "error": false, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 8, + "x": 8, + "y": 21 + }, + "hiddenSeries": false, + "id": 20, + "isNew": true, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "sum(rate(etcd_network_peer_received_bytes_total{job=\"kube-etcd3\", node=~\"$node\"}[$__rate_interval])) by (node)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{node}} Peer Traffic In", + "metric": "etcd_network_peer_received_bytes_total", + "refId": "A", + "step": 4 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Peer Traffic In", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": null, + "editable": true, + "error": false, + "fill": 0, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 7, + "w": 8, + "x": 16, + "y": 21 + }, + "hiddenSeries": false, + "id": 16, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "sum(rate(etcd_network_peer_sent_bytes_total{job=\"kube-etcd3\", node=~\"$node\"}[$__rate_interval])) by (node)", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "{{node}} Peer Traffic Out", + "metric": "etcd_network_peer_sent_bytes_total", + "refId": "A", + "step": 4 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Peer Traffic Out", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "Bps", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "unit": "s" + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 28 + }, + "hiddenSeries": false, + "id": 46, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.5.9", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "histogram_quantile(0.99, sum(rate(grpc_server_handling_seconds_bucket{job=\"kube-etcd3\", node=~\"$node\"}[$__rate_interval])) by (node, le))", + "hide": false, + "range": true, + "intervalFactor": 1, + "legendFormat": "{{node}} RPC Request Duration", + "refId": "A", + "step": 4 + } + ], + "thresholds": [], + "timeRegions": [], + "title": "RPC Request Duration", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:387", + "format": "s", + "logBase": 1, + "show": true + }, + { + "$$hashKey": "object:388", + "format": "short", + "logBase": 1, + "show": true + } + ], + "yaxis": { + "align": false + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "description": "Peer RTT panel only relevant for multi-master configuration and will be null in single-master cluster.", + "fieldConfig": { + "defaults": { + "unit": "s" + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 28 + }, + "hiddenSeries": false, + "id": 48, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.5.9", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "histogram_quantile(0.99, sum(rate(etcd_network_peer_round_trip_time_seconds_bucket{job=\"kube-etcd3\", node=~\"$node\"}[$__rate_interval])) by (node, le))", + "hide": false, + "range": true, + "intervalFactor": 1, + "legendFormat": "{{node}} Peer RTT", + "refId": "A", + "step": 4 + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Peer RTT", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:490", + "format": "s", + "logBase": 1, + "show": true + }, + { + "$$hashKey": "object:491", + "format": "short", + "logBase": 1, + "show": true + } + ], + "yaxis": { + "align": false + } + } + ], + "refresh": "30s", + "schemaVersion": 32, + "style": "dark", + "tags": [], + "templating": { + "list": [ + { + "current": { + "selected": true, + "text": "default", + "value": "default" + }, + "description": null, + "error": null, + "hide": 0, + "includeAll": false, + "label": "Prometheus", + "multi": false, + "name": "ds_prometheus", + "options": [], + "query": "prometheus", + "queryValue": "", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + }, + { + "allValue": null, + "current": { + "selected": true, + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": "$ds_prometheus", + "definition": "label_values(up{job=\"kube-etcd3\"}, node)", + "description": null, + "error": null, + "hide": 0, + "includeAll": true, + "label": "Node", + "multi": true, + "name": "node", + "options": [], + "query": { + "query": "label_values(up{job=\"kube-etcd3\"}, node)", + "refId": "StandardVariableQuery" + }, + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + } + ] + }, + "time": { + "from": "now-3h", + "to": "now" + }, + "timepicker": { + "now": true, + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "browser", + "title": "etcd3", + "uid": "mOkHbAGmk", + "version": 1 +} diff --git a/dashboards/db/cloudnativepg.json b/dashboards/db/cloudnativepg.json new file mode 100644 index 00000000..2370ad4c --- /dev/null +++ b/dashboards/db/cloudnativepg.json @@ -0,0 +1,6320 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "target": { + "limit": 100, + "matchAny": false, + "tags": [], + "type": "dashboard" + }, + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 1, + "id": 62, + "links": [ + { + "asDropdown": false, + "icon": "external link", + "includeVars": false, + "keepTime": false, + "tags": [ + "cloudnativepg" + ], + "targetBlank": false, + "title": "Related Dashboards", + "tooltip": "", + "type": "dashboards", + "url": "" + } + ], + "liveNow": false, + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "gridPos": { + "h": 7, + "w": 3, + "x": 0, + "y": 0 + }, + "id": 334, + "options": { + "alertInstanceLabelFilter": "{namespace=~\"$namespace\",pod=~\"$cluster-[0-9]+$\"}", + "alertName": "", + "dashboardAlerts": false, + "folder": "", + "groupBy": [], + "groupMode": "default", + "maxItems": 20, + "sortOrder": 1, + "stateFilter": { + "error": true, + "firing": true, + "noData": false, + "normal": true, + "pending": true + }, + "viewMode": "list" + }, + "title": "Alerts", + "type": "alertlist" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "gridPos": { + "h": 1, + "w": 15, + "x": 3, + "y": 0 + }, + "id": 336, + "options": { + "code": { + "language": "plaintext", + "showLineNumbers": false, + "showMiniMap": false + }, + "content": "", + "mode": "markdown" + }, + "pluginVersion": "10.1.0", + "title": "Overview", + "type": "text" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "gridPos": { + "h": 1, + "w": 3, + "x": 18, + "y": 0 + }, + "id": 352, + "options": { + "code": { + "language": "plaintext", + "showLineNumbers": false, + "showMiniMap": false + }, + "content": "", + "mode": "markdown" + }, + "pluginVersion": "10.1.0", + "title": "Storage", + "type": "text" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "gridPos": { + "h": 1, + "w": 3, + "x": 21, + "y": 0 + }, + "id": 354, + "options": { + "code": { + "language": "plaintext", + "showLineNumbers": false, + "showMiniMap": false + }, + "content": "", + "mode": "markdown" + }, + "pluginVersion": "10.1.0", + "title": "Backups", + "type": "text" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "dark-blue", + "value": null + } + ] + }, + "unit": "dateTimeFromNow" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 2, + "x": 3, + "y": 1 + }, + "id": 338, + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "value" + }, + "pluginVersion": "10.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "max(cnpg_pg_postmaster_start_time{namespace=~\"$namespace\",pod=~\"$instances\"})*1000", + "format": "time_series", + "hide": false, + "instant": true, + "interval": "", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "title": "Last failover", + "transformations": [], + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 3, + "x": 5, + "y": 1 + }, + "id": 342, + "interval": "1m", + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "10.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(rate(cnpg_pg_stat_database_xact_commit{namespace=~\"$namespace\",pod=~\"$instances\"}[$__interval])) + sum(rate(cnpg_pg_stat_database_xact_rollback{namespace=~\"$namespace\",pod=~\"$instances\"}[$__interval]))", + "interval": "", + "legendFormat": "TPS", + "range": true, + "refId": "TPS" + } + ], + "title": "TPS", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "description": "CPU Utilisation from Requests", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "max": 1, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "orange", + "value": 0.8 + }, + { + "color": "red", + "value": 0.9 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 3, + "x": 8, + "y": 1 + }, + "id": 344, + "interval": "1m", + "links": [], + "options": { + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": true + }, + "pluginVersion": "10.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "editorMode": "code", + "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{ namespace=\"$namespace\"}) / sum(kube_pod_container_resource_requests{job=\"kube-state-metrics\", namespace=\"$namespace\", resource=\"cpu\"})", + "format": "time_series", + "instant": true, + "intervalFactor": 2, + "refId": "A" + } + ], + "title": "CPU Utilisation", + "type": "gauge" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "description": "Memory Utilisation from Requests", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "max": 1, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "orange", + "value": 0.8 + }, + { + "color": "red", + "value": 0.9 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 3, + "x": 11, + "y": 1 + }, + "id": 348, + "interval": "1m", + "links": [], + "options": { + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": true + }, + "pluginVersion": "10.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "editorMode": "code", + "expr": "sum(container_memory_working_set_bytes{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", namespace=\"$namespace\",container!=\"\", image!=\"\"}) / sum(max by(pod) (kube_pod_container_resource_requests{job=\"kube-state-metrics\", namespace=\"$namespace\", resource=\"memory\"}))", + "format": "time_series", + "instant": true, + "intervalFactor": 2, + "refId": "A" + } + ], + "title": "Memory Utilisation", + "type": "gauge" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "max": 30, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "yellow", + "value": 1 + }, + { + "color": "orange", + "value": 10 + }, + { + "color": "red", + "value": 20 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 2, + "x": 14, + "y": 1 + }, + "id": 465, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "10.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "editorMode": "code", + "expr": "max(cnpg_pg_replication_lag{namespace=~\"$namespace\",pod=~\"$instances\"})", + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "Replication Lag", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "yellow", + "value": 1 + }, + { + "color": "orange", + "value": 10 + }, + { + "color": "red", + "value": 20 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 2, + "x": 16, + "y": 1 + }, + "id": 467, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "10.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "editorMode": "code", + "expr": "max(cnpg_pg_stat_replication_write_lag_seconds{namespace=~\"$namespace\",pod=~\"$instances\"})", + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "Write Lag", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "max": 1, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "orange", + "value": 0.8 + }, + { + "color": "red", + "value": 0.9 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 3, + "x": 18, + "y": 1 + }, + "id": 356, + "options": { + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": true + }, + "pluginVersion": "10.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "editorMode": "code", + "expr": "max(max by(persistentvolumeclaim) (1 - kubelet_volume_stats_available_bytes{namespace=\"$namespace\", persistentvolumeclaim=~\"$instances\"} / kubelet_volume_stats_capacity_bytes{namespace=\"$namespace\", persistentvolumeclaim=~\"$instances\"}))", + "format": "time_series", + "interval": "", + "legendFormat": "DATA", + "range": true, + "refId": "DATA" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "editorMode": "code", + "expr": "max(max by(persistentvolumeclaim) (1 - kubelet_volume_stats_available_bytes{namespace=\"$namespace\", persistentvolumeclaim=~\"(${instances})-wal\"} / kubelet_volume_stats_capacity_bytes{namespace=\"$namespace\", persistentvolumeclaim=~\"(${instances})-wal\"}))", + "format": "time_series", + "interval": "", + "legendFormat": "WAL", + "range": true, + "refId": "WAL" + } + ], + "title": "Volume Space Usage", + "type": "gauge" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "description": "Elapsed time since the last successful base backup.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "from": 1, + "result": { + "color": "semi-dark-orange", + "index": 0, + "text": "Invalid date" + }, + "to": 1e+42 + }, + "type": "range" + }, + { + "options": { + "from": -2147483648, + "result": { + "color": "red", + "index": 1, + "text": "N/A" + }, + "to": -1577847600 + }, + "type": "range" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "semi-dark-red", + "value": -108000 + }, + { + "color": "semi-dark-orange", + "value": -107999 + }, + { + "color": "#EAB839", + "value": -89999 + }, + { + "color": "green", + "value": -86399 + } + ] + }, + "unit": "dtdurations" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 21, + "y": 1 + }, + "id": 360, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "10.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "editorMode": "code", + "expr": "-(time() - max(cnpg_collector_last_available_backup_timestamp{namespace=\"$namespace\",pod=~\"$instances\"}))", + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "Last Base Backup", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "color": "red", + "index": 0, + "text": "No backups" + } + }, + "type": "special" + }, + { + "options": { + "from": 0, + "result": { + "color": "text", + "index": 1, + "text": "No data" + }, + "to": 1e+22 + }, + "type": "range" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "dtdurations" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 21, + "y": 3 + }, + "id": 362, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "10.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "editorMode": "code", + "exemplar": true, + "expr": "min((1 - cnpg_pg_replication_in_recovery{namespace=~\"$namespace\",pod=~\"$instances\"} + cnpg_pg_replication_is_wal_receiver_up{namespace=~\"$namespace\",pod=~\"$instances\"}) * (time() - timestamp(cnpg_pg_stat_archiver_seconds_since_last_archival{namespace=~\"$namespace\",pod=~\"$instances\"}) -\ncnpg_pg_stat_archiver_seconds_since_last_archival{namespace=~\"$namespace\",pod=~\"$instances\"}))", + "format": "time_series", + "interval": "", + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "Last archived WAL", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "dark-blue", + "value": null + } + ] + }, + "unit": "string" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 2, + "x": 3, + "y": 4 + }, + "id": 340, + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "/^full$/", + "values": false + }, + "text": {}, + "textMode": "value" + }, + "pluginVersion": "10.1.0", + "repeatDirection": "v", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "editorMode": "builder", + "exemplar": false, + "expr": "cnpg_collector_postgres_version{namespace=~\"$namespace\",pod=~\"$instances\"}", + "format": "table", + "hide": false, + "instant": true, + "interval": "", + "intervalFactor": 1, + "legendFormat": "{{pod}}", + "range": false, + "refId": "A" + } + ], + "title": "Version", + "transformations": [], + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "yellow", + "value": 1 + }, + { + "color": "orange", + "value": 10 + }, + { + "color": "red", + "value": 20 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 2, + "x": 14, + "y": 4 + }, + "id": 466, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "10.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "editorMode": "code", + "expr": "max(cnpg_pg_stat_replication_flush_lag_seconds{namespace=~\"$namespace\",pod=~\"$cluster-[0-9]+$\"})", + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "Flush Lag", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "yellow", + "value": 1 + }, + { + "color": "orange", + "value": 10 + }, + { + "color": "red", + "value": 20 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 2, + "x": 16, + "y": 4 + }, + "id": 468, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "10.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "editorMode": "code", + "expr": "max(cnpg_pg_stat_replication_replay_lag_seconds{namespace=~\"$namespace\",pod=~\"$cluster-[0-9]+$\"})", + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "Replay Lag", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "decimals": 2, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "#EAB839", + "value": 80000000000 + }, + { + "color": "red", + "value": 90000000000 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 8, + "y": 5 + }, + "id": 346, + "links": [], + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "center", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "10.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{ namespace=\"$namespace\"})", + "hide": false, + "interval": "", + "legendFormat": "Total", + "range": true, + "refId": "B" + } + ], + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "description": "Excluding cache", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "#EAB839", + "value": 80000000000 + }, + { + "color": "red", + "value": 90000000000 + } + ] + }, + "unit": "decbytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 11, + "y": 5 + }, + "id": 350, + "links": [], + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "center", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "10.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(container_memory_working_set_bytes{pod=~\"$instances\", namespace=\"$namespace\", container!=\"\", image!=\"\"})", + "hide": false, + "interval": "", + "legendFormat": "Total", + "range": true, + "refId": "B" + } + ], + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "decimals": 2, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "#EAB839", + "value": 60000000000 + }, + { + "color": "red", + "value": 80000000000 + } + ] + }, + "unit": "decbytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 18, + "y": 5 + }, + "id": 358, + "links": [], + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "sum" + ], + "fields": "", + "values": false + }, + "textMode": "value" + }, + "pluginVersion": "10.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "cnpg_pg_database_size_bytes{namespace=\"$namespace\"}", + "format": "table", + "instant": true, + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "Database Size", + "transformations": [ + { + "id": "groupBy", + "options": { + "fields": { + "Value": { + "aggregations": [ + "max" + ], + "operation": "aggregate" + }, + "datname": { + "aggregations": [], + "operation": "groupby" + } + } + } + } + ], + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "0": { + "color": "red", + "index": 1, + "text": "N/A" + } + }, + "type": "value" + }, + { + "options": { + "match": "null", + "result": { + "color": "red", + "index": 0, + "text": "No backups" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "dateTimeAsIso" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 21, + "y": 5 + }, + "id": 364, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "10.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "editorMode": "code", + "exemplar": true, + "expr": "max(cnpg_collector_first_recoverability_point{namespace=~\"$namespace\",pod=~\"$instances\"})*1000", + "format": "time_series", + "interval": "", + "legendFormat": "{{pod}}", + "range": true, + "refId": "A" + } + ], + "title": "First Recoverability Point", + "type": "stat" + }, + { + "collapsed": false, + "datasource": { + "uid": "${ds_prometheus}" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 7 + }, + "id": 12, + "panels": [], + "targets": [ + { + "datasource": { + "uid": "${ds_prometheus}" + }, + "refId": "A" + } + ], + "title": "Server Health", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "gridPos": { + "h": 1, + "w": 3, + "x": 0, + "y": 8 + }, + "id": 191, + "options": { + "code": { + "language": "plaintext", + "showLineNumbers": false, + "showMiniMap": false + }, + "content": "", + "mode": "html" + }, + "pluginVersion": "10.1.0", + "repeatDirection": "v", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "exemplar": true, + "expr": "kube_pod_container_status_ready{container=\"postgres\",namespace=~\"$namespace\",pod=~\"$instances\"}", + "instant": true, + "interval": "", + "legendFormat": "{{pod}}", + "refId": "A" + } + ], + "title": "Instance", + "transparent": true, + "type": "text" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "gridPos": { + "h": 1, + "w": 2, + "x": 3, + "y": 8 + }, + "id": 192, + "options": { + "code": { + "language": "plaintext", + "showLineNumbers": false, + "showMiniMap": false + }, + "content": "", + "mode": "html" + }, + "pluginVersion": "10.1.0", + "repeatDirection": "v", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "exemplar": true, + "expr": "kube_pod_container_status_ready{container=\"postgres\",namespace=~\"$namespace\",pod=~\"$instances\"}", + "instant": true, + "interval": "", + "legendFormat": "{{pod}}", + "refId": "A" + } + ], + "title": "Status", + "type": "text" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "gridPos": { + "h": 1, + "w": 3, + "x": 5, + "y": 8 + }, + "id": 193, + "options": { + "code": { + "language": "plaintext", + "showLineNumbers": false, + "showMiniMap": false + }, + "content": "", + "mode": "html" + }, + "pluginVersion": "10.1.0", + "repeatDirection": "v", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "exemplar": true, + "expr": "kube_pod_container_status_ready{container=\"postgres\",namespace=~\"$namespace\",pod=~\"$instances\"}", + "instant": true, + "interval": "", + "legendFormat": "{{pod}}", + "refId": "A" + } + ], + "title": "Clustering / replicas", + "type": "text" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "gridPos": { + "h": 1, + "w": 2, + "x": 8, + "y": 8 + }, + "id": 384, + "options": { + "code": { + "language": "plaintext", + "showLineNumbers": false, + "showMiniMap": false + }, + "content": "", + "mode": "html" + }, + "pluginVersion": "10.1.0", + "repeatDirection": "v", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "exemplar": true, + "expr": "kube_pod_container_status_ready{container=\"postgres\",namespace=~\"$namespace\",pod=~\"$instances\"}", + "instant": true, + "interval": "", + "legendFormat": "{{pod}}", + "refId": "A" + } + ], + "title": "Zone", + "type": "text" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "gridPos": { + "h": 1, + "w": 4, + "x": 10, + "y": 8 + }, + "id": 195, + "options": { + "code": { + "language": "plaintext", + "showLineNumbers": false, + "showMiniMap": false + }, + "content": "", + "mode": "html" + }, + "pluginVersion": "10.1.0", + "repeatDirection": "v", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "exemplar": true, + "expr": "kube_pod_container_status_ready{container=\"postgres\",namespace=~\"$namespace\",pod=~\"$instances\"}", + "instant": true, + "interval": "", + "legendFormat": "{{pod}}", + "refId": "A" + } + ], + "title": "Connections", + "type": "text" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "gridPos": { + "h": 1, + "w": 3, + "x": 14, + "y": 8 + }, + "id": 196, + "options": { + "code": { + "language": "plaintext", + "showLineNumbers": false, + "showMiniMap": false + }, + "content": "", + "mode": "html" + }, + "pluginVersion": "10.1.0", + "repeatDirection": "v", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "exemplar": true, + "expr": "kube_pod_container_status_ready{container=\"postgres\",namespace=~\"$namespace\",pod=~\"$instances\"}", + "instant": true, + "interval": "", + "legendFormat": "{{pod}}", + "refId": "A" + } + ], + "title": "Max Connections", + "type": "text" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "description": "", + "gridPos": { + "h": 1, + "w": 3, + "x": 17, + "y": 8 + }, + "id": 197, + "options": { + "code": { + "language": "plaintext", + "showLineNumbers": false, + "showMiniMap": false + }, + "content": "", + "mode": "html" + }, + "pluginVersion": "10.1.0", + "repeatDirection": "v", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "exemplar": true, + "expr": "kube_pod_container_status_ready{container=\"postgres\",namespace=~\"$namespace\",pod=~\"$instances\"}", + "instant": true, + "interval": "", + "legendFormat": "{{pod}}", + "refId": "A" + } + ], + "title": "Wraparound", + "type": "text" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "gridPos": { + "h": 1, + "w": 2, + "x": 20, + "y": 8 + }, + "id": 313, + "options": { + "code": { + "language": "plaintext", + "showLineNumbers": false, + "showMiniMap": false + }, + "content": "", + "mode": "html" + }, + "pluginVersion": "10.1.0", + "repeatDirection": "v", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "exemplar": true, + "expr": "kube_pod_container_status_ready{container=\"postgres\",namespace=~\"$namespace\",pod=~\"$instances\"}", + "instant": true, + "interval": "", + "legendFormat": "{{pod}}", + "refId": "A" + } + ], + "title": "Started", + "type": "text" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "gridPos": { + "h": 1, + "w": 2, + "x": 22, + "y": 8 + }, + "id": 198, + "options": { + "code": { + "language": "plaintext", + "showLineNumbers": false, + "showMiniMap": false + }, + "content": "", + "mode": "html" + }, + "pluginVersion": "10.1.0", + "repeatDirection": "v", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "exemplar": true, + "expr": "kube_pod_container_status_ready{container=\"postgres\",namespace=~\"$namespace\",pod=~\"$instances\"}", + "instant": true, + "interval": "", + "legendFormat": "{{pod}}", + "refId": "A" + } + ], + "title": "Version", + "type": "text" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "gridPos": { + "h": 3, + "w": 3, + "x": 0, + "y": 9 + }, + "id": 61, + "options": { + "code": { + "language": "plaintext", + "showLineNumbers": false, + "showMiniMap": false + }, + "content": "\n \n

$instances

\n
", + "mode": "html" + }, + "pluginVersion": "10.1.0", + "repeat": "instances", + "repeatDirection": "v", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "exemplar": true, + "expr": "kube_pod_container_status_ready{container=\"postgres\",namespace=~\"$namespace\",pod=~\"$instances\"}", + "instant": true, + "interval": "", + "legendFormat": "{{pod}}", + "refId": "A" + } + ], + "type": "text" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "0": { + "index": 0, + "text": "Down" + }, + "1": { + "index": 1, + "text": "Up" + } + }, + "type": "value" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "dark-red", + "value": null + }, + { + "color": "green", + "value": 1 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 2, + "x": 3, + "y": 9 + }, + "id": 33, + "options": { + "colorMode": "background", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "value" + }, + "pluginVersion": "10.1.0", + "repeat": "instances", + "repeatDirection": "v", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "editorMode": "code", + "exemplar": true, + "expr": "min(kube_pod_container_status_ready{container=\"postgres\",namespace=~\"$namespace\",pod=~\"$instances\"})", + "instant": true, + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "0": { + "color": "red", + "index": 1, + "text": "No" + }, + "1": { + "color": "green", + "index": 0, + "text": "Yes" + } + }, + "type": "value" + } + ], + "noValue": "-", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 2, + "x": 5, + "y": 9 + }, + "id": 60, + "options": { + "colorMode": "background", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "value" + }, + "pluginVersion": "10.1.0", + "repeat": "instances", + "repeatDirection": "v", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "exemplar": true, + "expr": "1 - cnpg_pg_replication_in_recovery{namespace=~\"$namespace\",pod=~\"$instances\"} + cnpg_pg_replication_is_wal_receiver_up{namespace=~\"$namespace\",pod=~\"$instances\"}", + "instant": true, + "interval": "", + "legendFormat": "{{pod}}", + "refId": "A" + } + ], + "transformations": [], + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "noValue": "-", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 1, + "x": 7, + "y": 9 + }, + "id": 229, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "value" + }, + "pluginVersion": "10.1.0", + "repeat": "instances", + "repeatDirection": "v", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "exemplar": true, + "expr": "cnpg_pg_replication_streaming_replicas{namespace=~\"$namespace\",pod=~\"$instances\"}", + "instant": true, + "interval": "", + "legendFormat": "{{pod}}", + "refId": "A" + } + ], + "transformations": [], + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "description": "This metric depends on exporting the: `topology.kubernetes.io/zone` label through kube-state-metrics (not enabled by default). Can be added by changing its configuration with:\n\n```yaml\nmetricLabelsAllowlist:\n - nodes=[topology.kubernetes.io/zone]\n```", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "blue", + "value": null + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 2, + "x": 8, + "y": 9 + }, + "id": 386, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "/^label_topology_kubernetes_io_zone$/", + "values": false + }, + "text": { + "valueSize": 18 + }, + "textMode": "value" + }, + "pluginVersion": "10.1.0", + "repeat": "instances", + "repeatDirection": "v", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "editorMode": "code", + "exemplar": true, + "expr": "kube_pod_info{namespace=~\"$namespace\",pod=~\"$instances\"} * on(node,instance) group_left(label_topology_kubernetes_io_zone) kube_node_labels", + "format": "table", + "instant": true, + "interval": "", + "legendFormat": "{{pod}}", + "refId": "A" + } + ], + "transformations": [], + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 4, + "x": 10, + "y": 9 + }, + "id": 58, + "options": { + "legend": { + "calcs": [ + "last", + "mean" + ], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "8.2.1", + "repeat": "instances", + "repeatDirection": "v", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "exemplar": true, + "expr": "sum by (pod) (cnpg_backends_total{namespace=~\"$namespace\",pod=~\"$instances\"})", + "instant": false, + "interval": "", + "legendFormat": "-", + "refId": "A" + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "decimals": 0, + "mappings": [], + "max": 100, + "min": 0, + "noValue": "<1%", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "#EAB839", + "value": 75 + }, + { + "color": "red", + "value": 90 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 3, + "x": 14, + "y": 9 + }, + "id": 32, + "options": { + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "last" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": true, + "text": {} + }, + "pluginVersion": "10.1.0", + "repeat": "instances", + "repeatDirection": "v", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "exemplar": true, + "expr": "100 * sum by (pod) (cnpg_backends_total{namespace=~\"$namespace\",pod=~\"$instances\"}) / sum by (pod) (cnpg_pg_settings_setting{name=\"max_connections\",namespace=~\"$namespace\",pod=~\"$instances\"})", + "instant": true, + "interval": "", + "legendFormat": "{{pod}}", + "refId": "A" + } + ], + "type": "gauge" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "max": 2147483647, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "#EAB839", + "value": 200000000 + }, + { + "color": "red", + "value": 1000000000 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 3, + "x": 17, + "y": 9 + }, + "id": 8, + "options": { + "displayMode": "lcd", + "minVizHeight": 10, + "minVizWidth": 0, + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showUnfilled": true, + "text": {}, + "valueMode": "color" + }, + "pluginVersion": "10.1.0", + "repeat": "instances", + "repeatDirection": "v", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "exemplar": true, + "expr": "max by (pod) (cnpg_pg_database_xid_age{namespace=~\"$namespace\",pod=~\"$instances\"})", + "instant": true, + "interval": "", + "legendFormat": "{{pod}}", + "refId": "A" + } + ], + "type": "bargauge" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "dark-blue", + "value": null + } + ] + }, + "unit": "dateTimeFromNow" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 2, + "x": 20, + "y": 9 + }, + "id": 314, + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "value" + }, + "pluginVersion": "10.1.0", + "repeat": "instances", + "repeatDirection": "v", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "exemplar": false, + "expr": "cnpg_pg_postmaster_start_time{namespace=~\"$namespace\",pod=~\"$instances\"}*1000", + "format": "time_series", + "hide": false, + "instant": true, + "interval": "", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "transformations": [], + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "dark-blue", + "value": null + } + ] + }, + "unit": "string" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 2, + "x": 22, + "y": 9 + }, + "id": 42, + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "/^full$/", + "values": false + }, + "text": {}, + "textMode": "value" + }, + "pluginVersion": "10.1.0", + "repeat": "instances", + "repeatDirection": "v", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "cnpg_collector_postgres_version{namespace=~\"$namespace\",pod=~\"$instances\"}", + "format": "table", + "hide": false, + "instant": true, + "interval": "", + "intervalFactor": 1, + "legendFormat": "{{pod}}", + "refId": "A" + } + ], + "transformations": [], + "type": "stat" + }, + { + "collapsed": false, + "datasource": { + "uid": "${ds_prometheus}" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 12 + }, + "id": 41, + "panels": [], + "targets": [ + { + "datasource": { + "uid": "${ds_prometheus}" + }, + "refId": "A" + } + ], + "title": "Configuration", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "gridPos": { + "h": 1, + "w": 3, + "x": 0, + "y": 13 + }, + "id": 187, + "options": { + "code": { + "language": "plaintext", + "showLineNumbers": false, + "showMiniMap": false + }, + "content": "", + "mode": "html" + }, + "pluginVersion": "10.1.0", + "repeatDirection": "v", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "exemplar": true, + "expr": "kube_pod_container_status_ready{container=\"postgres\",namespace=~\"$namespace\",pod=~\"$instances\"}", + "instant": true, + "interval": "", + "legendFormat": "{{pod}}", + "refId": "A" + } + ], + "title": "Instance", + "transparent": true, + "type": "text" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "gridPos": { + "h": 1, + "w": 3, + "x": 3, + "y": 13 + }, + "id": 183, + "options": { + "code": { + "language": "plaintext", + "showLineNumbers": false, + "showMiniMap": false + }, + "content": "", + "mode": "html" + }, + "pluginVersion": "10.1.0", + "repeatDirection": "v", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "exemplar": true, + "expr": "kube_pod_container_status_ready{container=\"postgres\",namespace=~\"$namespace\",pod=~\"$instances\"}", + "instant": true, + "interval": "", + "legendFormat": "{{pod}}", + "refId": "A" + } + ], + "title": "Max Connections", + "type": "text" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "gridPos": { + "h": 1, + "w": 3, + "x": 6, + "y": 13 + }, + "id": 184, + "options": { + "code": { + "language": "plaintext", + "showLineNumbers": false, + "showMiniMap": false + }, + "content": "", + "mode": "html" + }, + "pluginVersion": "10.1.0", + "repeatDirection": "v", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "exemplar": true, + "expr": "kube_pod_container_status_ready{container=\"postgres\",namespace=~\"$namespace\",pod=~\"$instances\"}", + "instant": true, + "interval": "", + "legendFormat": "{{pod}}", + "refId": "A" + } + ], + "title": "Shared Buffers", + "type": "text" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "gridPos": { + "h": 1, + "w": 3, + "x": 9, + "y": 13 + }, + "id": 185, + "options": { + "code": { + "language": "plaintext", + "showLineNumbers": false, + "showMiniMap": false + }, + "content": "", + "mode": "html" + }, + "pluginVersion": "10.1.0", + "repeatDirection": "v", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "exemplar": true, + "expr": "kube_pod_container_status_ready{container=\"postgres\",namespace=~\"$namespace\",pod=~\"$instances\"}", + "instant": true, + "interval": "", + "legendFormat": "{{pod}}", + "refId": "A" + } + ], + "title": "Effective Cache Size", + "type": "text" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "gridPos": { + "h": 1, + "w": 3, + "x": 12, + "y": 13 + }, + "id": 186, + "options": { + "code": { + "language": "plaintext", + "showLineNumbers": false, + "showMiniMap": false + }, + "content": "", + "mode": "html" + }, + "pluginVersion": "10.1.0", + "repeatDirection": "v", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "exemplar": true, + "expr": "kube_pod_container_status_ready{container=\"postgres\",namespace=~\"$namespace\",pod=~\"$instances\"}", + "instant": true, + "interval": "", + "legendFormat": "{{pod}}", + "refId": "A" + } + ], + "title": "Work Mem", + "type": "text" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "gridPos": { + "h": 1, + "w": 3, + "x": 15, + "y": 13 + }, + "id": 188, + "options": { + "code": { + "language": "plaintext", + "showLineNumbers": false, + "showMiniMap": false + }, + "content": "", + "mode": "html" + }, + "pluginVersion": "10.1.0", + "repeatDirection": "v", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "exemplar": true, + "expr": "kube_pod_container_status_ready{container=\"postgres\",namespace=~\"$namespace\",pod=~\"$instances\"}", + "instant": true, + "interval": "", + "legendFormat": "{{pod}}", + "refId": "A" + } + ], + "title": "Maintenance Work Mem", + "type": "text" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "gridPos": { + "h": 1, + "w": 3, + "x": 18, + "y": 13 + }, + "id": 189, + "options": { + "code": { + "language": "plaintext", + "showLineNumbers": false, + "showMiniMap": false + }, + "content": "", + "mode": "html" + }, + "pluginVersion": "10.1.0", + "repeatDirection": "v", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "exemplar": true, + "expr": "kube_pod_container_status_ready{container=\"postgres\",namespace=~\"$namespace\",pod=~\"$instances\"}", + "instant": true, + "interval": "", + "legendFormat": "{{pod}}", + "refId": "A" + } + ], + "title": "Random Page Cost", + "type": "text" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "gridPos": { + "h": 1, + "w": 3, + "x": 21, + "y": 13 + }, + "id": 190, + "options": { + "code": { + "language": "plaintext", + "showLineNumbers": false, + "showMiniMap": false + }, + "content": "", + "mode": "html" + }, + "pluginVersion": "10.1.0", + "repeatDirection": "v", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "exemplar": true, + "expr": "kube_pod_container_status_ready{container=\"postgres\",namespace=~\"$namespace\",pod=~\"$instances\"}", + "instant": true, + "interval": "", + "legendFormat": "{{pod}}", + "refId": "A" + } + ], + "title": "Sequential Page Cost", + "type": "text" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "gridPos": { + "h": 3, + "w": 3, + "x": 0, + "y": 14 + }, + "id": 86, + "options": { + "code": { + "language": "plaintext", + "showLineNumbers": false, + "showMiniMap": false + }, + "content": "\n \n

$instances

\n
", + "mode": "html" + }, + "pluginVersion": "10.1.0", + "repeat": "instances", + "repeatDirection": "v", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "exemplar": true, + "expr": "kube_pod_container_status_ready{container=\"postgres\",namespace=~\"$namespace\",pod=~\"$instances\"}", + "instant": true, + "interval": "", + "legendFormat": "{{pod}}", + "refId": "A" + } + ], + "type": "text" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "dark-purple", + "value": null + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 3, + "x": 3, + "y": 14 + }, + "id": 30, + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "value" + }, + "pluginVersion": "10.1.0", + "repeat": "instances", + "repeatDirection": "v", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "exemplar": true, + "expr": "cnpg_pg_settings_setting{name=\"max_connections\",namespace=~\"$namespace\",pod=~\"$instances\"}", + "instant": true, + "interval": "", + "legendFormat": "{{pod}}", + "refId": "A" + } + ], + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "dark-purple", + "value": null + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 3, + "x": 6, + "y": 14 + }, + "id": 24, + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "value" + }, + "pluginVersion": "10.1.0", + "repeat": "instances", + "repeatDirection": "v", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "exemplar": true, + "expr": "max by (pod) (cnpg_pg_settings_setting{name=\"shared_buffers\",namespace=~\"$namespace\",pod=~\"$instances\"}) * max by (pod) (cnpg_pg_settings_setting{name=\"block_size\",namespace=~\"$namespace\",pod=~\"$instances\"})", + "instant": true, + "interval": "", + "legendFormat": "{{pod}}", + "refId": "A" + } + ], + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "dark-purple", + "value": null + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 3, + "x": 9, + "y": 14 + }, + "id": 57, + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "value" + }, + "pluginVersion": "10.1.0", + "repeat": "instances", + "repeatDirection": "v", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "exemplar": true, + "expr": "max by (pod) (cnpg_pg_settings_setting{name=\"effective_cache_size\",namespace=~\"$namespace\",pod=~\"$instances\"}) * max by (pod) (cnpg_pg_settings_setting{name=\"block_size\",namespace=~\"$namespace\",pod=~\"$instances\"})", + "instant": true, + "interval": "", + "legendFormat": "{{pod}}", + "refId": "A" + } + ], + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "dark-purple", + "value": null + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 3, + "x": 12, + "y": 14 + }, + "id": 26, + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "value" + }, + "pluginVersion": "10.1.0", + "repeat": "instances", + "repeatDirection": "v", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "exemplar": true, + "expr": "cnpg_pg_settings_setting{name=\"work_mem\",namespace=~\"$namespace\",pod=~\"$instances\"} * 1024", + "instant": true, + "interval": "", + "legendFormat": "{{pod}}", + "refId": "A" + } + ], + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "dark-purple", + "value": null + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 3, + "x": 15, + "y": 14 + }, + "id": 47, + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "value" + }, + "pluginVersion": "10.1.0", + "repeat": "instances", + "repeatDirection": "v", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "exemplar": true, + "expr": "cnpg_pg_settings_setting{name=\"maintenance_work_mem\",namespace=~\"$namespace\",pod=~\"$instances\"}", + "instant": true, + "interval": "", + "legendFormat": "{{pod}}", + "refId": "A" + } + ], + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "dark-purple", + "value": null + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 3, + "x": 18, + "y": 14 + }, + "id": 48, + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "value" + }, + "pluginVersion": "10.1.0", + "repeat": "instances", + "repeatDirection": "v", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "exemplar": true, + "expr": "cnpg_pg_settings_setting{name=\"random_page_cost\",namespace=~\"$namespace\",pod=~\"$instances\"}", + "instant": true, + "interval": "", + "legendFormat": "{{pod}}", + "refId": "A" + } + ], + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "dark-purple", + "value": null + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 3, + "x": 21, + "y": 14 + }, + "id": 56, + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "value" + }, + "pluginVersion": "10.1.0", + "repeat": "instances", + "repeatDirection": "v", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "exemplar": true, + "expr": "cnpg_pg_settings_setting{name=\"seq_page_cost\",namespace=~\"$namespace\",pod=~\"$instances\"}", + "instant": true, + "interval": "", + "legendFormat": "{{pod}}", + "refId": "A" + } + ], + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "cellOptions": { + "type": "auto" + }, + "filterable": true, + "inspect": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "dark-purple", + "value": null + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 24, + "x": 0, + "y": 17 + }, + "id": 150, + "options": { + "cellHeight": "sm", + "footer": { + "countRows": false, + "fields": "", + "reducer": [ + "sum" + ], + "show": false + }, + "showHeader": true, + "sortBy": [] + }, + "pluginVersion": "10.1.0", + "repeatDirection": "v", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "exemplar": true, + "expr": "cnpg_pg_settings_setting{namespace=~\"$namespace\",pod=~\"$instances\"}", + "format": "table", + "instant": true, + "interval": "", + "legendFormat": "{{pod}}", + "refId": "A" + } + ], + "title": "Configurations", + "transformations": [ + { + "id": "organize", + "options": { + "excludeByName": { + "Time": true, + "__name__": true, + "container": true, + "endpoint": true, + "instance": true, + "job": true, + "name": false, + "namespace": true, + "pod": false + }, + "indexByName": { + "Time": 0, + "Value": 9, + "__name__": 1, + "container": 2, + "endpoint": 3, + "instance": 4, + "job": 5, + "name": 7, + "namespace": 8, + "pod": 6 + }, + "renameByName": { + "__name__": "", + "name": "parameter" + } + } + }, + { + "id": "groupingToMatrix", + "options": { + "columnField": "pod", + "rowField": "parameter", + "valueField": "Value" + } + }, + { + "id": "organize", + "options": { + "excludeByName": {}, + "indexByName": {}, + "renameByName": { + "parameter\\pod": "parameter" + } + } + } + ], + "type": "table" + }, + { + "collapsed": true, + "datasource": { + "uid": "${ds_prometheus}" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 26 + }, + "id": 10, + "panels": [ + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 39 + }, + "hiddenSeries": false, + "id": 273, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "9.4.7", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "exemplar": true, + "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{pod=~\"$instances\", namespace=~\"$namespace\"}) by (pod)", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "{{pod}}", + "refId": "A", + "step": 10 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "exemplar": true, + "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{pod=~\"$instances\", namespace=~\"$namespace\"})", + "hide": false, + "interval": "", + "legendFormat": "total", + "refId": "B" + } + ], + "thresholds": [], + "timeRegions": [], + "title": "CPU Usage", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:189", + "format": "short", + "logBase": 1, + "min": 0, + "show": true + }, + { + "$$hashKey": "object:190", + "format": "short", + "logBase": 1, + "show": false + } + ], + "yaxis": { + "align": false + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 39 + }, + "hiddenSeries": false, + "id": 275, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "9.4.7", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "quota - requests", + "color": "#F2495C", + "dashes": true, + "fill": 0, + "hiddenSeries": true, + "hideTooltip": true, + "legend": true, + "linewidth": 2, + "stack": false + }, + { + "alias": "quota - limits", + "color": "#FF9830", + "dashes": true, + "fill": 0, + "hiddenSeries": true, + "hideTooltip": true, + "legend": true, + "linewidth": 2, + "stack": false + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "exemplar": true, + "expr": "sum(container_memory_working_set_bytes{pod=~\"$instances\", namespace=\"$namespace\", container!=\"\", image!=\"\"}) by (pod)", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "{{pod}}", + "refId": "A", + "step": 10 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "exemplar": true, + "expr": "sum(container_memory_working_set_bytes{pod=~\"$instances\", namespace=\"$namespace\", container!=\"\", image!=\"\"})", + "hide": false, + "interval": "", + "legendFormat": "total", + "refId": "B" + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Memory Usage (w/o cache)", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:246", + "format": "bytes", + "logBase": 1, + "min": 0, + "show": true + }, + { + "$$hashKey": "object:247", + "format": "short", + "logBase": 1, + "show": false + } + ], + "yaxis": { + "align": false + } + }, + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 24, + "x": 0, + "y": 46 + }, + "id": 39, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "exemplar": true, + "expr": "sum(cnpg_backends_total{namespace=~\"$namespace\",pod=~\"$instances\"}) by (pod)", + "hide": false, + "interval": "", + "legendFormat": "total ({{pod}})", + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "exemplar": true, + "expr": "sum(cnpg_backends_total{namespace=~\"$namespace\",pod=~\"$instances\"}) by (state, pod)", + "interval": "", + "legendFormat": "{{state}} ({{pod}})", + "refId": "A" + } + ], + "title": "Session States", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 54 + }, + "id": 50, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "exemplar": true, + "expr": "sum(rate(cnpg_pg_stat_database_xact_commit{namespace=~\"$namespace\",pod=~\"$instances\"}[5m])) by (pod)", + "interval": "", + "legendFormat": "committed ({{pod}})", + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "exemplar": true, + "expr": "sum(rate(cnpg_pg_stat_database_xact_rollback{namespace=~\"$namespace\",pod=~\"$instances\"}[5m])) by (pod)", + "hide": false, + "interval": "", + "legendFormat": "rolled back ({{pod}})", + "refId": "B" + } + ], + "title": "Transactions [5m]", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 54 + }, + "id": 4, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "exemplar": true, + "expr": "max by (pod) (cnpg_backends_max_tx_duration_seconds{namespace=~\"$namespace\",pod=~\"$instances\"})", + "interval": "", + "legendFormat": "{{pod}}", + "refId": "A" + } + ], + "title": "Longest Transaction", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 62 + }, + "id": 55, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "exemplar": true, + "expr": "rate(cnpg_pg_stat_database_deadlocks{datname=\"\",namespace=~\"$namespace\",pod=~\"$instances\"}[5m])", + "hide": false, + "instant": false, + "interval": "", + "legendFormat": "count ({{pod}})", + "refId": "B" + } + ], + "title": "Deadlocks [5m]", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 62 + }, + "id": 54, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "exemplar": true, + "expr": "cnpg_backends_waiting_total{namespace=~\"$namespace\",pod=~\"$instances\"}", + "interval": "", + "legendFormat": "{{pod}}", + "refId": "A" + } + ], + "title": "Blocked Queries", + "type": "timeseries" + } + ], + "targets": [ + { + "datasource": { + "uid": "${ds_prometheus}" + }, + "refId": "A" + } + ], + "title": "Operational Stats", + "type": "row" + }, + { + "collapsed": true, + "datasource": { + "uid": "${ds_prometheus}" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 27 + }, + "id": 35, + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "max": 1, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "#EAB839", + "value": 0.7 + }, + { + "color": "red", + "value": 0.8 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 48 + }, + "id": 424, + "options": { + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": true, + "text": {} + }, + "pluginVersion": "9.4.7", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "editorMode": "code", + "expr": "max by(persistentvolumeclaim) (1 - kubelet_volume_stats_available_bytes{namespace=\"$namespace\", persistentvolumeclaim=~\"$instances\"} / kubelet_volume_stats_capacity_bytes{namespace=\"$namespace\", persistentvolumeclaim=~\"$instances\"})", + "format": "time_series", + "interval": "", + "legendFormat": "{{persistentvolumeclaim}}", + "range": true, + "refId": "FREE_SPACE" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "editorMode": "code", + "expr": "max by(persistentvolumeclaim) (1 - kubelet_volume_stats_available_bytes{namespace=\"$namespace\", persistentvolumeclaim=~\"(${instances})-wal\"} / kubelet_volume_stats_capacity_bytes{namespace=\"$namespace\", persistentvolumeclaim=~\"(${instances})-wal\"})", + "format": "time_series", + "interval": "", + "legendFormat": "{{persistentvolumeclaim}}", + "range": true, + "refId": "FREE_SPACE_WAL" + } + ], + "title": "Volume Space Usage", + "transformations": [], + "type": "gauge" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "decimals": 2, + "mappings": [], + "max": 1, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "#EAB839", + "value": 0.8 + }, + { + "color": "red", + "value": 0.9 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 48 + }, + "id": 426, + "options": { + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": true + }, + "pluginVersion": "9.4.7", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "editorMode": "code", + "expr": "max by(persistentvolumeclaim) (kubelet_volume_stats_inodes_used{namespace=\"$namespace\", persistentvolumeclaim=~\"$instances\"} / kubelet_volume_stats_inodes{namespace=\"$namespace\", persistentvolumeclaim=~\"$instances\"})", + "format": "time_series", + "interval": "", + "legendFormat": "{{persistentvolumeclaim}}", + "range": true, + "refId": "FREE_INODES" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "editorMode": "code", + "expr": "max by(persistentvolumeclaim) (kubelet_volume_stats_inodes_used{namespace=\"$namespace\", persistentvolumeclaim=~\"(${instances})-wal\"} / kubelet_volume_stats_inodes{namespace=\"$namespace\", persistentvolumeclaim=~\"(${instances})-wal\"})", + "format": "time_series", + "interval": "", + "legendFormat": "{{persistentvolumeclaim}}", + "range": true, + "refId": "FREE_INODES_WAL" + } + ], + "title": "Volume Inode Usage", + "transformations": [], + "type": "gauge" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 56 + }, + "id": 44, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(rate(cnpg_pg_stat_database_tup_deleted{datname=\"\",namespace=~\"$namespace\",pod=~\"$instances\"}[5m]))", + "interval": "", + "legendFormat": "deleted", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(rate(cnpg_pg_stat_database_tup_inserted{datname=\"\",namespace=~\"$namespace\",pod=~\"$instances\"}[5m]))", + "hide": false, + "interval": "", + "legendFormat": "inserted", + "range": true, + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(rate(cnpg_pg_stat_database_tup_fetched{datname=\"\",namespace=~\"$namespace\",pod=~\"$instances\"}[5m]))", + "hide": false, + "interval": "", + "legendFormat": "fetched", + "range": true, + "refId": "C" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(rate(cnpg_pg_stat_database_tup_returned{datname=\"\",namespace=~\"$namespace\",pod=~\"$instances\"}[5m]))", + "hide": false, + "interval": "", + "legendFormat": "returned", + "range": true, + "refId": "D" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(rate(cnpg_pg_stat_database_tup_updated{datname=\"\",namespace=~\"$namespace\",pod=~\"$instances\"}[5m]))", + "hide": false, + "interval": "", + "legendFormat": "updated", + "range": true, + "refId": "E" + } + ], + "title": "Tuple I/O [5m]", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 56 + }, + "id": 46, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "editorMode": "code", + "exemplar": true, + "expr": "rate(cnpg_pg_stat_database_blks_hit{datname=\"\",namespace=~\"$namespace\",pod=~\"$instances\"}[5m])", + "interval": "", + "legendFormat": "hit ({{pod}})", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "editorMode": "code", + "exemplar": true, + "expr": "rate(cnpg_pg_stat_database_blks_read{datname=\"\",namespace=~\"$namespace\",pod=~\"$instances\"}[5m])", + "hide": false, + "interval": "", + "legendFormat": "read ({{pod}})", + "range": true, + "refId": "B" + } + ], + "title": "Block I/O [5m]", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "decbytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 64 + }, + "id": 22, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "8.0.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "editorMode": "code", + "exemplar": true, + "expr": "max by (datname) (cnpg_pg_database_size_bytes{datname!~\"template.*\",datname!=\"postgres\",namespace=~\"$namespace\",pod=~\"$instances\"})", + "interval": "", + "legendFormat": " {{pod}}: {{datname}}", + "range": true, + "refId": "A" + } + ], + "title": "Database Size", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "decbytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 64 + }, + "id": 2, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "exemplar": true, + "expr": "rate(cnpg_pg_stat_database_temp_bytes{datname=\"\",namespace=~\"$namespace\",pod=~\"$instances\"}[5m])", + "instant": false, + "interval": "", + "legendFormat": "{{pod}}", + "refId": "A" + } + ], + "title": "Temp Bytes [5m]", + "type": "timeseries" + } + ], + "targets": [ + { + "datasource": { + "uid": "${ds_prometheus}" + }, + "refId": "A" + } + ], + "title": "Storage & I/O", + "type": "row" + }, + { + "collapsed": true, + "datasource": { + "uid": "${ds_prometheus}" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 28 + }, + "id": 37, + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 0, + "y": 49 + }, + "id": 6, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "exemplar": true, + "expr": "cnpg_collector_pg_wal_archive_status{value=\"ready\",namespace=~\"$namespace\",pod=~\"$instances\"}", + "interval": "", + "legendFormat": "ready ({{pod}})", + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "exemplar": true, + "expr": "cnpg_collector_pg_wal_archive_status{value=\"done\",namespace=~\"$namespace\",pod=~\"$instances\"}", + "hide": false, + "interval": "", + "legendFormat": "done ({{pod}})", + "refId": "B" + } + ], + "title": "WAL Segment Archive Status", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 8, + "y": 49 + }, + "id": 52, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "exemplar": true, + "expr": "rate(cnpg_pg_stat_archiver_archived_count{namespace=~\"$namespace\",pod=~\"$instances\"}[5m])", + "interval": "", + "legendFormat": "archived ({{pod}})", + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "exemplar": true, + "expr": "rate(cnpg_pg_stat_archiver_failed_count{namespace=~\"$namespace\",pod=~\"$instances\"}[5m])", + "hide": false, + "interval": "", + "legendFormat": "failed ({{pod}})", + "refId": "B" + } + ], + "title": "Archiver Status [5m]", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 16, + "y": 49 + }, + "id": 53, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "exemplar": true, + "expr": "cnpg_pg_stat_archiver_seconds_since_last_archival{namespace=~\"$namespace\",pod=~\"$instances\"}", + "interval": "", + "legendFormat": "age ({{pod}})", + "refId": "A" + } + ], + "title": "Last Archive Age", + "type": "timeseries" + } + ], + "targets": [ + { + "datasource": { + "uid": "${ds_prometheus}" + }, + "refId": "A" + } + ], + "title": "Write Ahead Log", + "type": "row" + }, + { + "collapsed": true, + "datasource": { + "uid": "${ds_prometheus}" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 29 + }, + "id": 18, + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "line" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "#EAB839", + "value": 600 + }, + { + "color": "dark-red", + "value": 3600 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 6, + "x": 0, + "y": 13 + }, + "id": 16, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "exemplar": true, + "expr": "cnpg_pg_replication_lag{namespace=~\"$namespace\",pod=~\"$instances\"}", + "instant": false, + "interval": "", + "legendFormat": "{{pod}}", + "refId": "A" + } + ], + "title": "Replication Lag", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 6, + "x": 6, + "y": 13 + }, + "id": 14, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "exemplar": true, + "expr": "cnpg_pg_stat_replication_write_lag_seconds{namespace=~\"$namespace\",pod=~\"$cluster-[0-9]+$\"}", + "instant": false, + "interval": "", + "legendFormat": "{{pod}} -> {{application_name}}", + "refId": "A" + } + ], + "title": "Write Lag", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 6, + "x": 12, + "y": 13 + }, + "id": 59, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "exemplar": true, + "expr": "cnpg_pg_stat_replication_flush_lag_seconds{namespace=~\"$namespace\",pod=~\"$cluster-[0-9]+$\"}", + "instant": false, + "interval": "", + "legendFormat": "{{pod}} -> {{application_name}}", + "refId": "A" + } + ], + "title": "Flush Lag", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 6, + "x": 18, + "y": 13 + }, + "id": 20, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "exemplar": true, + "expr": "cnpg_pg_stat_replication_replay_lag_seconds{namespace=~\"$namespace\",pod=~\"$cluster-[0-9]+$\"}", + "interval": "", + "legendFormat": "{{pod}} -> {{application_name}}", + "refId": "A" + } + ], + "title": "Replay Lag", + "type": "timeseries" + } + ], + "targets": [ + { + "datasource": { + "uid": "${ds_prometheus}" + }, + "refId": "A" + } + ], + "title": "Replication", + "type": "row" + }, + { + "collapsed": true, + "datasource": { + "uid": "${ds_prometheus}" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 30 + }, + "id": 231, + "panels": [ + { + "cards": {}, + "color": { + "cardColor": "#b4ff00", + "colorScale": "sqrt", + "colorScheme": "interpolateOranges", + "exponent": 0.5, + "mode": "spectrum" + }, + "dataFormat": "timeseries", + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 51 + }, + "heatmap": {}, + "hideZeroBuckets": false, + "highlightCards": true, + "id": 233, + "legend": { + "show": false + }, + "options": { + "calculate": true, + "calculation": {}, + "cellGap": 2, + "cellValues": {}, + "color": { + "exponent": 0.5, + "fill": "#b4ff00", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "Oranges", + "steps": 128 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": false + }, + "rowsFrame": { + "layout": "auto" + }, + "showValue": "never", + "tooltip": { + "show": true, + "yHistogram": false + }, + "yAxis": { + "axisPlacement": "left", + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "9.4.7", + "reverseYBuckets": false, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "exemplar": true, + "expr": "cnpg_collector_collection_duration_seconds{namespace=~\"$namespace\",pod=~\"$instances\"}", + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "title": "Collection Duration", + "tooltip": { + "show": true, + "showHistogram": false + }, + "type": "heatmap", + "xAxis": { + "show": true + }, + "yAxis": { + "format": "s", + "logBase": 1, + "show": true + }, + "yBucketBound": "auto" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 51 + }, + "id": 235, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "exemplar": true, + "expr": "cnpg_collector_last_collection_error{namespace=~\"$namespace\",pod=~\"$instances\"}", + "interval": "", + "legendFormat": "{{pod}}", + "refId": "A" + } + ], + "title": "Errors", + "type": "timeseries" + } + ], + "targets": [ + { + "datasource": { + "uid": "${ds_prometheus}" + }, + "refId": "A" + } + ], + "title": "Collector Stats", + "type": "row" + }, + { + "collapsed": true, + "datasource": { + "uid": "${ds_prometheus}" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 31 + }, + "id": 239, + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "dateTimeAsIso" + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 8, + "x": 0, + "y": 52 + }, + "id": 237, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "exemplar": true, + "expr": "cnpg_collector_first_recoverability_point{namespace=~\"$namespace\",pod=~\"$instances\"}*1000 > 0", + "format": "time_series", + "interval": "", + "legendFormat": "{{pod}}", + "refId": "A" + } + ], + "title": "First Recoverability Point", + "type": "timeseries" + } + ], + "targets": [ + { + "datasource": { + "uid": "${ds_prometheus}" + }, + "refId": "A" + } + ], + "title": "Backups", + "type": "row" + }, + { + "collapsed": true, + "datasource": { + "uid": "${ds_prometheus}" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 32 + }, + "id": 293, + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": -1, + "drawStyle": "line", + "fillOpacity": 8, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 5, + "x": 0, + "y": 32 + }, + "id": 295, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "8.2.1", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "exemplar": true, + "expr": "cnpg_pg_stat_bgwriter_checkpoints_req{namespace=~\"$namespace\",pod=~\"$instances\"}", + "format": "time_series", + "hide": false, + "instant": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "req/{{pod}}", + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "exemplar": true, + "expr": "cnpg_pg_stat_bgwriter_checkpoints_timed{namespace=~\"$namespace\",pod=~\"$instances\"}", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "timed/{{pod}}", + "refId": "A" + } + ], + "title": "Requested/Timed", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": -1, + "drawStyle": "line", + "fillOpacity": 8, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 5, + "x": 5, + "y": 32 + }, + "id": 296, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "8.2.1", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "exemplar": true, + "expr": "cnpg_pg_stat_bgwriter_checkpoint_write_time{namespace=~\"$namespace\",pod=~\"$instances\"}", + "format": "time_series", + "hide": false, + "instant": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "write/{{pod}}", + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "exemplar": true, + "expr": "cnpg_pg_stat_bgwriter_checkpoint_sync_time{namespace=~\"$namespace\",pod=~\"$instances\"}", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "sync/{{pod}}", + "refId": "A" + } + ], + "title": "Write/Sync time", + "type": "timeseries" + } + ], + "targets": [ + { + "datasource": { + "uid": "${ds_prometheus}" + }, + "refId": "A" + } + ], + "title": "Checkpoints", + "type": "row" + } + ], + "refresh": "30s", + "revision": 1, + "schemaVersion": 38, + "style": "dark", + "tags": [ + "cloudnativepg" + ], + "templating": { + "list": [ + { + "current": { + "selected": false, + "text": "default", + "value": "default" + }, + "hide": 0, + "includeAll": false, + "label": "Datasource", + "multi": false, + "name": "ds_prometheus", + "options": [], + "query": "prometheus", + "queryValue": "", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + }, + { + "current": { + "selected": false, + "text": "db-postgres", + "value": "db-postgres" + }, + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "definition": "cnpg_collector_up", + "hide": 0, + "includeAll": false, + "multi": false, + "name": "namespace", + "options": [], + "query": { + "query": "cnpg_collector_up", + "refId": "StandardVariableQuery" + }, + "refresh": 1, + "regex": "/namespace=\"(?[^\"]+)/g", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "current": { + "selected": false, + "text": "app", + "value": "app" + }, + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "definition": "cnpg_collector_up{namespace=~\"$namespace\"}", + "hide": 0, + "includeAll": false, + "multi": false, + "name": "cluster", + "options": [], + "query": { + "query": "cnpg_collector_up{namespace=~\"$namespace\"}", + "refId": "PrometheusVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "/\\bexported_cluster\\b=\"(?[^\"]+)/g", + "skipUrlSync": false, + "sort": 1, + "type": "query" + }, + { + "current": { + "selected": false, + "text": "All", + "value": "$__all" + }, + "datasource": { + "type": "prometheus", + "uid": "${ds_prometheus}" + }, + "definition": "cnpg_collector_up{namespace=~\"$namespace\",pod=~\"$cluster-[0-9]+$\"}", + "hide": 0, + "includeAll": true, + "multi": true, + "name": "instances", + "options": [], + "query": { + "query": "cnpg_collector_up{namespace=~\"$namespace\",pod=~\"$cluster-[0-9]+$\"}", + "refId": "StandardVariableQuery" + }, + "refresh": 1, + "regex": "/pod=\"(?[^\"]+)/g", + "skipUrlSync": false, + "sort": 1, + "type": "query" + } + ] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": { + "nowDelay": "" + }, + "timezone": "", + "title": "CloudNativePG", + "uid": "cloudnative-pg", + "version": 2, + "weekStart": "" +} diff --git a/dashboards/db/maria-db.json b/dashboards/db/maria-db.json new file mode 100644 index 00000000..450dc9ca --- /dev/null +++ b/dashboards/db/maria-db.json @@ -0,0 +1,4436 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "description": "Prometheus MySQL Exporter", + "editable": true, + "fiscalYearStartMonth": 0, + "gnetId": 14057, + "graphTooltip": 1, + "id": 56, + "links": [], + "liveNow": false, + "panels": [ + { + "collapsed": false, + "datasource": { + "uid": "$datasource" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 382, + "panels": [], + "targets": [ + { + "datasource": { + "uid": "$datasource" + }, + "refId": "A" + } + ], + "type": "row" + }, + { + "datasource": { + "uid": "$datasource" + }, + "description": "**Uptime**\n\nThe amount of time since the last restart of the MySQL server process.", + "fieldConfig": { + "defaults": { + "decimals": 1, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "rgba(245, 54, 54, 0.9)", + "value": null + }, + { + "color": "rgba(237, 129, 40, 0.89)", + "value": 300 + }, + { + "color": "rgba(50, 172, 45, 0.97)", + "value": 3600 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 8, + "x": 0, + "y": 1 + }, + "id": 12, + "interval": "1m", + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "value", + "fieldOptions": { + "calcs": [ + "lastNotNull" + ] + }, + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "10.1.0", + "targets": [ + { + "calculatedInterval": "10m", + "datasource": { + "uid": "$datasource" + }, + "datasourceErrors": {}, + "errors": {}, + "expr": "mysql_global_status_uptime{job=~\"$job\", instance=~\"$instance\"}", + "format": "time_series", + "interval": "1m", + "intervalFactor": 1, + "legendFormat": "{{instance}}", + "metric": "", + "refId": "A", + "step": 300 + } + ], + "title": "Uptime", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "description": "**Current QPS**\n\nBased on the queries reported by MySQL's ``SHOW STATUS`` command, it is the number of statements executed by the server within the last second. This variable includes statements executed within stored programs, unlike the Questions variable. It does not count \n``COM_PING`` or ``COM_STATISTICS`` commands.", + "fieldConfig": { + "defaults": { + "decimals": 2, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "rgba(245, 54, 54, 0.9)", + "value": null + }, + { + "color": "rgba(237, 129, 40, 0.89)", + "value": 35 + }, + { + "color": "rgba(50, 172, 45, 0.97)", + "value": 75 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 8, + "x": 8, + "y": 1 + }, + "id": 13, + "interval": "1m", + "links": [ + { + "targetBlank": true, + "title": "MySQL Server Status Variables", + "url": "https://dev.mysql.com/doc/refman/5.7/en/server-status-variables.html#statvar_Queries" + } + ], + "maxDataPoints": 100, + "options": { + "colorMode": "value", + "fieldOptions": { + "calcs": [ + "lastNotNull" + ] + }, + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "10.1.0", + "targets": [ + { + "calculatedInterval": "10m", + "datasource": { + "uid": "$datasource" + }, + "datasourceErrors": {}, + "editorMode": "code", + "errors": {}, + "expr": "rate(mysql_global_status_queries{job=~\"$job\", instance=~\"$instance\"}[$__interval])", + "format": "time_series", + "interval": "1m", + "intervalFactor": 1, + "legendFormat": "{{instance}}", + "metric": "", + "range": true, + "refId": "A", + "step": 20 + } + ], + "title": "Current QPS", + "type": "stat" + }, + { + "datasource": { + "uid": "$datasource" + }, + "description": "**InnoDB Buffer Pool Size**\n\nInnoDB maintains a storage area called the buffer pool for caching data and indexes in memory. Knowing how the InnoDB buffer pool works, and taking advantage of it to keep frequently accessed data in memory, is one of the most important aspects of MySQL tuning. The goal is to keep the working set in memory. In most cases, this should be between 60%-90% of available memory on a dedicated database host, but depends on many factors.", + "fieldConfig": { + "defaults": { + "decimals": 0, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "rgba(50, 172, 45, 0.97)", + "value": null + }, + { + "color": "rgba(237, 129, 40, 0.89)", + "value": 90 + }, + { + "color": "rgba(245, 54, 54, 0.9)", + "value": 95 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 8, + "x": 16, + "y": 1 + }, + "id": 51, + "interval": "1m", + "links": [ + { + "targetBlank": true, + "title": "Tuning the InnoDB Buffer Pool Size", + "url": "https://www.percona.com/blog/2015/06/02/80-ram-tune-innodb_buffer_pool_size/" + } + ], + "maxDataPoints": 100, + "options": { + "colorMode": "value", + "fieldOptions": { + "calcs": [ + "lastNotNull" + ] + }, + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "10.1.0", + "targets": [ + { + "calculatedInterval": "10m", + "datasource": { + "uid": "$datasource" + }, + "datasourceErrors": {}, + "errors": {}, + "expr": "mysql_global_variables_innodb_buffer_pool_size{job=~\"$job\", instance=~\"$instance\"}", + "format": "time_series", + "interval": "1m", + "intervalFactor": 1, + "legendFormat": "{{instance}}", + "metric": "", + "refId": "A", + "step": 300 + } + ], + "title": "InnoDB Buffer Pool", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "rgb(31, 120, 193)", + "mode": "fixed" + }, + "decimals": 2, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "rgba(50, 172, 45, 0.97)", + "value": null + }, + { + "color": "rgba(237, 129, 40, 0.89)", + "value": 90 + }, + { + "color": "rgba(245, 54, 54, 0.9)", + "value": 95 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 8, + "x": 0, + "y": 5 + }, + "id": 395, + "interval": "", + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "10.1.0", + "targets": [ + { + "calculatedInterval": "10m", + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "datasourceErrors": {}, + "editorMode": "code", + "errors": {}, + "expr": "mysql_slave_status_seconds_behind_master{job=~\"$job\", instance=~\"$instance\"}", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "Seconds_Behind_Master {{instance}}", + "metric": "", + "range": true, + "refId": "A", + "step": 300 + } + ], + "title": "Slave Behind Master", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "0": { + "text": "No" + }, + "1": { + "text": "Yes" + } + }, + "type": "value" + }, + { + "options": { + "match": "null", + "result": { + "text": "No" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "rgba(245, 54, 54, 0.9)", + "value": null + }, + { + "color": "rgba(237, 129, 40, 0.89)", + "value": 0 + }, + { + "color": "rgba(50, 172, 45, 0.97)", + "value": 1 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 8, + "x": 8, + "y": 5 + }, + "id": 396, + "interval": "", + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "10.1.0", + "targets": [ + { + "calculatedInterval": "10m", + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "datasourceErrors": {}, + "editorMode": "code", + "errors": {}, + "expr": "mysql_slave_status_slave_io_running{job=~\"$job\", instance=~\"$instance\"}", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "Slave_IO_Running {{instance}}", + "metric": "", + "range": true, + "refId": "A", + "step": 300 + } + ], + "title": "Slave_IO_Running", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "0": { + "text": "No" + }, + "1": { + "text": "Yes" + } + }, + "type": "value" + }, + { + "options": { + "match": "null", + "result": { + "text": "No" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "rgba(245, 54, 54, 0.9)", + "value": null + }, + { + "color": "rgba(237, 129, 40, 0.89)", + "value": 0 + }, + { + "color": "rgba(50, 172, 45, 0.97)", + "value": 1 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 8, + "x": 16, + "y": 5 + }, + "id": 397, + "interval": "", + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "10.1.0", + "targets": [ + { + "calculatedInterval": "10m", + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "datasourceErrors": {}, + "editorMode": "code", + "errors": {}, + "expr": "mysql_slave_status_slave_sql_running{job=~\"$job\", instance=~\"$instance\"}", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "Slave_SQL_Running {{instance}}", + "metric": "", + "range": true, + "refId": "A", + "step": 300 + } + ], + "title": "Slave_SQL_Running", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 24, + "x": 0, + "y": 9 + }, + "id": 398, + "links": [], + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "10.1.0", + "targets": [ + { + "calculatedInterval": "10m", + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "datasourceErrors": {}, + "editorMode": "code", + "errors": {}, + "expr": "irate(mysql_slave_status_read_master_log_pos{job=~\"$job\", instance=~\"$instance\"}[5m])", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "read_master_log_pos", + "metric": "", + "range": true, + "refId": "A", + "step": 300 + }, + { + "calculatedInterval": "10m", + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "datasourceErrors": {}, + "editorMode": "code", + "errors": {}, + "expr": "irate(mysql_slave_status_relay_log_pos{job=~\"$job\", instance=~\"$instance\"}[5m])", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "relay_log_pos", + "metric": "", + "range": true, + "refId": "B", + "step": 300 + }, + { + "calculatedInterval": "10m", + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "datasourceErrors": {}, + "editorMode": "code", + "errors": {}, + "expr": "irate(mysql_slave_status_exec_master_log_pos{job=~\"$job\", instance=~\"$instance\"}[5m])", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "exec_master_log_pos", + "metric": "", + "range": true, + "refId": "C", + "step": 300 + } + ], + "title": "Log position", + "type": "timeseries" + }, + { + "collapsed": false, + "datasource": { + "uid": "$datasource" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 15 + }, + "id": 383, + "panels": [], + "targets": [ + { + "datasource": { + "uid": "$datasource" + }, + "refId": "A" + } + ], + "title": "Connections", + "type": "row" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "uid": "$datasource" + }, + "decimals": 0, + "description": "**Max Connections** \n\nMax Connections is the maximum permitted number of simultaneous client connections. By default, this is 151. Increasing this value increases the number of file descriptors that mysqld requires. If the required number of descriptors are not available, the server reduces the value of Max Connections.\n\nmysqld actually permits Max Connections + 1 clients to connect. The extra connection is reserved for use by accounts that have the SUPER privilege, such as root.\n\nMax Used Connections is the maximum number of connections that have been in use simultaneously since the server started.\n\nConnections is the number of connection attempts (successful or not) to the MySQL server.", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 16 + }, + "height": "250px", + "hiddenSeries": false, + "id": 92, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [ + { + "targetBlank": true, + "title": "MySQL Server System Variables", + "url": "https://dev.mysql.com/doc/refman/5.7/en/server-system-variables.html#sysvar_max_connections" + } + ], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "10.1.0", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Max Connections", + "fill": 0 + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "calculatedInterval": "2m", + "datasource": { + "uid": "$datasource" + }, + "datasourceErrors": {}, + "errors": {}, + "expr": "sum(max_over_time(mysql_global_status_threads_connected{job=~\"$job\", instance=~\"$instance\"}[$__interval]))", + "format": "time_series", + "interval": "1m", + "intervalFactor": 1, + "legendFormat": "Connections", + "metric": "", + "refId": "A", + "step": 20 + }, + { + "calculatedInterval": "2m", + "datasource": { + "uid": "$datasource" + }, + "datasourceErrors": {}, + "errors": {}, + "expr": "sum(mysql_global_status_max_used_connections{job=~\"$job\", instance=~\"$instance\"})", + "format": "time_series", + "interval": "1m", + "intervalFactor": 1, + "legendFormat": "Max Used Connections", + "metric": "", + "refId": "C", + "step": 20, + "target": "" + }, + { + "calculatedInterval": "2m", + "datasource": { + "uid": "$datasource" + }, + "datasourceErrors": {}, + "errors": {}, + "expr": "sum(mysql_global_variables_max_connections{job=~\"$job\", instance=~\"$instance\"})", + "format": "time_series", + "interval": "1m", + "intervalFactor": 1, + "legendFormat": "Max Connections", + "metric": "", + "refId": "B", + "step": 20, + "target": "" + } + ], + "thresholds": [], + "timeRegions": [], + "title": "MySQL Connections", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "", + "logBase": 1, + "min": 0, + "show": true + }, + { + "format": "short", + "label": "", + "logBase": 1, + "min": 0, + "show": true + } + ], + "yaxis": { + "align": false + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "uid": "$datasource" + }, + "decimals": 2, + "description": "**MySQL Active Threads**\n\nThreads Connected is the number of open connections, while Threads Running is the number of threads not sleeping.", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 16 + }, + "hiddenSeries": false, + "id": 10, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "10.1.0", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Peak Threads Running", + "color": "#E24D42", + "lines": false, + "pointradius": 1, + "points": true + }, + { + "alias": "Peak Threads Connected", + "color": "#1F78C1" + }, + { + "alias": "Avg Threads Running", + "color": "#EAB839" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "calculatedInterval": "2m", + "datasource": { + "uid": "$datasource" + }, + "datasourceErrors": {}, + "errors": {}, + "expr": "sum(max_over_time(mysql_global_status_threads_connected{job=~\"$job\", instance=~\"$instance\"}[$__interval]))", + "format": "time_series", + "hide": false, + "interval": "1m", + "intervalFactor": 1, + "legendFormat": "Peak Threads Connected", + "metric": "", + "refId": "A", + "step": 20 + }, + { + "calculatedInterval": "2m", + "datasource": { + "uid": "$datasource" + }, + "datasourceErrors": {}, + "errors": {}, + "expr": "sum(max_over_time(mysql_global_status_threads_running{job=~\"$job\", instance=~\"$instance\"}[$__interval]))", + "format": "time_series", + "interval": "1m", + "intervalFactor": 1, + "legendFormat": "Peak Threads Running", + "metric": "", + "refId": "B", + "step": 20 + }, + { + "datasource": { + "uid": "$datasource" + }, + "expr": "sum(avg_over_time(mysql_global_status_threads_running{job=~\"$job\", instance=~\"$instance\"}[$__interval]))", + "format": "time_series", + "interval": "1m", + "intervalFactor": 1, + "legendFormat": "Avg Threads Running", + "refId": "C", + "step": 20 + } + ], + "thresholds": [], + "timeRegions": [], + "title": "MySQL Client Thread Activity", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [ + "total" + ] + }, + "yaxes": [ + { + "format": "short", + "label": "Threads", + "logBase": 1, + "min": 0, + "show": true + }, + { + "format": "short", + "label": "", + "logBase": 1, + "min": 0, + "show": false + } + ], + "yaxis": { + "align": false + } + }, + { + "collapsed": false, + "datasource": { + "uid": "$datasource" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 23 + }, + "id": 384, + "panels": [], + "targets": [ + { + "datasource": { + "uid": "$datasource" + }, + "refId": "A" + } + ], + "title": "Table Locks", + "type": "row" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "uid": "$datasource" + }, + "decimals": 2, + "description": "**MySQL Questions**\n\nThe number of statements executed by the server. This includes only statements sent to the server by clients and not statements executed within stored programs, unlike the Queries used in the QPS calculation. \n\nThis variable does not count the following commands:\n* ``COM_PING``\n* ``COM_STATISTICS``\n* ``COM_STMT_PREPARE``\n* ``COM_STMT_CLOSE``\n* ``COM_STMT_RESET``", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 24 + }, + "hiddenSeries": false, + "id": 53, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [ + { + "targetBlank": true, + "title": "MySQL Queries and Questions", + "url": "https://www.percona.com/blog/2014/05/29/how-mysql-queries-and-questions-are-measured/" + } + ], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "10.1.0", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "calculatedInterval": "2m", + "datasource": { + "uid": "$datasource" + }, + "datasourceErrors": {}, + "errors": {}, + "expr": "rate(mysql_global_status_questions{job=~\"$job\", instance=~\"$instance\"}[$__interval])", + "format": "time_series", + "interval": "1m", + "intervalFactor": 1, + "legendFormat": "{{instance}}", + "metric": "", + "refId": "A", + "step": 20 + } + ], + "thresholds": [], + "timeRegions": [], + "title": "MySQL Questions", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "logBase": 1, + "min": 0, + "show": true + }, + { + "format": "short", + "logBase": 1, + "min": 0, + "show": true + } + ], + "yaxis": { + "align": false + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "uid": "$datasource" + }, + "decimals": 2, + "description": "**MySQL Thread Cache**\n\nThe thread_cache_size variable sets how many threads the server should cache to reuse. When a client disconnects, the client's threads are put in the cache if the cache is not full. It is autosized in MySQL 5.6.8 and above (capped to 100). Requests for threads are satisfied by reusing threads taken from the cache if possible, and only when the cache is empty is a new thread created.\n\n* *Threads_created*: The number of threads created to handle connections.\n* *Threads_cached*: The number of threads in the thread cache.", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 24 + }, + "hiddenSeries": false, + "id": 11, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [ + { + "title": "Tuning information", + "url": "https://dev.mysql.com/doc/refman/5.6/en/server-system-variables.html#sysvar_thread_cache_size" + } + ], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "10.1.0", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Threads Created", + "fill": 0 + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "calculatedInterval": "2m", + "datasource": { + "uid": "$datasource" + }, + "datasourceErrors": {}, + "errors": {}, + "expr": "sum(mysql_global_variables_thread_cache_size{job=~\"$job\", instance=~\"$instance\"})", + "format": "time_series", + "interval": "1m", + "intervalFactor": 1, + "legendFormat": "Thread Cache Size", + "metric": "", + "refId": "B", + "step": 20 + }, + { + "calculatedInterval": "2m", + "datasource": { + "uid": "$datasource" + }, + "datasourceErrors": {}, + "errors": {}, + "expr": "sum(mysql_global_status_threads_cached{job=~\"$job\", instance=~\"$instance\"})", + "format": "time_series", + "interval": "1m", + "intervalFactor": 1, + "legendFormat": "Threads Cached", + "metric": "", + "refId": "C", + "step": 20 + }, + { + "calculatedInterval": "2m", + "datasource": { + "uid": "$datasource" + }, + "datasourceErrors": {}, + "errors": {}, + "expr": "sum(rate(mysql_global_status_threads_created{job=~\"$job\", instance=~\"$instance\"}[$__interval]))", + "format": "time_series", + "interval": "1m", + "intervalFactor": 1, + "legendFormat": "Threads Created", + "metric": "", + "refId": "A", + "step": 20 + } + ], + "thresholds": [], + "timeRegions": [], + "title": "MySQL Thread Cache", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "logBase": 1, + "min": 0, + "show": true + }, + { + "format": "short", + "logBase": 1, + "min": 0, + "show": true + } + ], + "yaxis": { + "align": false + } + }, + { + "collapsed": false, + "datasource": { + "uid": "$datasource" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 31 + }, + "id": 385, + "panels": [], + "targets": [ + { + "datasource": { + "uid": "$datasource" + }, + "refId": "A" + } + ], + "title": "Temporary Objects", + "type": "row" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "uid": "$datasource" + }, + "decimals": 2, + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 32 + }, + "hiddenSeries": false, + "id": 22, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "10.1.0", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "calculatedInterval": "2m", + "datasource": { + "uid": "$datasource" + }, + "datasourceErrors": {}, + "errors": {}, + "expr": "sum(rate(mysql_global_status_created_tmp_tables{job=~\"$job\", instance=~\"$instance\"}[$__interval]))", + "interval": "1m", + "intervalFactor": 1, + "legendFormat": "Created Tmp Tables", + "metric": "", + "refId": "A", + "step": 20 + }, + { + "calculatedInterval": "2m", + "datasource": { + "uid": "$datasource" + }, + "datasourceErrors": {}, + "errors": {}, + "expr": "sum(rate(mysql_global_status_created_tmp_disk_tables{job=~\"$job\", instance=~\"$instance\"}[$__interval]))", + "interval": "1m", + "intervalFactor": 1, + "legendFormat": "Created Tmp Disk Tables", + "metric": "", + "refId": "B", + "step": 20 + }, + { + "calculatedInterval": "2m", + "datasource": { + "uid": "$datasource" + }, + "datasourceErrors": {}, + "errors": {}, + "expr": "sum(rate(mysql_global_status_created_tmp_files{job=~\"$job\", instance=~\"$instance\"}[$__interval]))", + "interval": "1m", + "intervalFactor": 1, + "legendFormat": "Created Tmp Files", + "metric": "", + "refId": "C", + "step": 20 + } + ], + "thresholds": [], + "timeRegions": [], + "title": "MySQL Temporary Objects", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "logBase": 1, + "min": 0, + "show": true + }, + { + "format": "short", + "logBase": 1, + "min": 0, + "show": true + } + ], + "yaxis": { + "align": false + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "uid": "$datasource" + }, + "decimals": 2, + "description": "**MySQL Select Types**\n\nAs with most relational databases, selecting based on indexes is more efficient than scanning an entire table's data. Here we see the counters for selects not done with indexes.\n\n* ***Select Scan*** is how many queries caused full table scans, in which all the data in the table had to be read and either discarded or returned.\n* ***Select Range*** is how many queries used a range scan, which means MySQL scanned all rows in a given range.\n* ***Select Full Join*** is the number of joins that are not joined on an index, this is usually a huge performance hit.", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 32 + }, + "height": "250px", + "hiddenSeries": false, + "id": 311, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "hideZero": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "10.1.0", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "calculatedInterval": "2m", + "datasource": { + "uid": "$datasource" + }, + "datasourceErrors": {}, + "errors": {}, + "expr": "sum(rate(mysql_global_status_select_full_join{job=~\"$job\", instance=~\"$instance\"}[$__interval]))", + "format": "time_series", + "interval": "1m", + "intervalFactor": 1, + "legendFormat": "Select Full Join", + "metric": "", + "refId": "A", + "step": 20 + }, + { + "calculatedInterval": "2m", + "datasource": { + "uid": "$datasource" + }, + "datasourceErrors": {}, + "errors": {}, + "expr": "sum(rate(mysql_global_status_select_full_range_join{job=~\"$job\", instance=~\"$instance\"}[$__interval]))", + "format": "time_series", + "interval": "1m", + "intervalFactor": 1, + "legendFormat": "Select Full Range Join", + "metric": "", + "refId": "B", + "step": 20 + }, + { + "calculatedInterval": "2m", + "datasource": { + "uid": "$datasource" + }, + "datasourceErrors": {}, + "errors": {}, + "expr": "sum(rate(mysql_global_status_select_range{job=~\"$job\", instance=~\"$instance\"}[$__interval]))", + "format": "time_series", + "interval": "1m", + "intervalFactor": 1, + "legendFormat": "Select Range", + "metric": "", + "refId": "C", + "step": 20 + }, + { + "calculatedInterval": "2m", + "datasource": { + "uid": "$datasource" + }, + "datasourceErrors": {}, + "errors": {}, + "expr": "sum(rate(mysql_global_status_select_range_check{job=~\"$job\", instance=~\"$instance\"}[$__interval]))", + "format": "time_series", + "interval": "1m", + "intervalFactor": 1, + "legendFormat": "Select Range Check", + "metric": "", + "refId": "D", + "step": 20 + }, + { + "calculatedInterval": "2m", + "datasource": { + "uid": "$datasource" + }, + "datasourceErrors": {}, + "errors": {}, + "expr": "sum(rate(mysql_global_status_select_scan{job=~\"$job\", instance=~\"$instance\"}[$__interval]))", + "format": "time_series", + "interval": "1m", + "intervalFactor": 1, + "legendFormat": "Select Scan", + "metric": "", + "refId": "E", + "step": 20 + } + ], + "thresholds": [], + "timeRegions": [], + "title": "MySQL Select Types", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "logBase": 1, + "min": 0, + "show": true + }, + { + "format": "short", + "logBase": 1, + "min": 0, + "show": true + } + ], + "yaxis": { + "align": false + } + }, + { + "collapsed": false, + "datasource": { + "uid": "$datasource" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 39 + }, + "id": 386, + "panels": [], + "targets": [ + { + "datasource": { + "uid": "$datasource" + }, + "refId": "A" + } + ], + "title": "Sorts", + "type": "row" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "uid": "$datasource" + }, + "decimals": 2, + "description": "**MySQL Sorts**\n\nDue to a query's structure, order, or other requirements, MySQL sorts the rows before returning them. For example, if a table is ordered 1 to 10 but you want the results reversed, MySQL then has to sort the rows to return 10 to 1.\n\nThis graph also shows when sorts had to scan a whole table or a given range of a table in order to return the results and which could not have been sorted via an index.", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 40 + }, + "hiddenSeries": false, + "id": 30, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "hideZero": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "10.1.0", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "calculatedInterval": "2m", + "datasource": { + "uid": "$datasource" + }, + "datasourceErrors": {}, + "errors": {}, + "expr": "sum(rate(mysql_global_status_sort_rows{job=~\"$job\", instance=~\"$instance\"}[$__interval]))", + "format": "time_series", + "interval": "1m", + "intervalFactor": 1, + "legendFormat": "Sort Rows", + "metric": "", + "refId": "A", + "step": 20 + }, + { + "calculatedInterval": "2m", + "datasource": { + "uid": "$datasource" + }, + "datasourceErrors": {}, + "errors": {}, + "expr": "sum(rate(mysql_global_status_sort_range{job=~\"$job\", instance=~\"$instance\"}[$__interval]))", + "format": "time_series", + "interval": "1m", + "intervalFactor": 1, + "legendFormat": "Sort Range", + "metric": "", + "refId": "B", + "step": 20 + }, + { + "calculatedInterval": "2m", + "datasource": { + "uid": "$datasource" + }, + "datasourceErrors": {}, + "errors": {}, + "expr": "sum(rate(mysql_global_status_sort_merge_passes{job=~\"$job\", instance=~\"$instance\"}[$__interval]))", + "format": "time_series", + "interval": "1m", + "intervalFactor": 1, + "legendFormat": "Sort Merge Passes", + "metric": "", + "refId": "C", + "step": 20 + }, + { + "calculatedInterval": "2m", + "datasource": { + "uid": "$datasource" + }, + "datasourceErrors": {}, + "errors": {}, + "expr": "sum(rate(mysql_global_status_sort_scan{job=~\"$job\", instance=~\"$instance\"}[$__interval]))", + "format": "time_series", + "interval": "1m", + "intervalFactor": 1, + "legendFormat": "Sort Scan", + "metric": "", + "refId": "D", + "step": 20 + } + ], + "thresholds": [], + "timeRegions": [], + "title": "MySQL Sorts", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "logBase": 1, + "min": 0, + "show": true + }, + { + "format": "short", + "logBase": 1, + "min": 0, + "show": true + } + ], + "yaxis": { + "align": false + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "uid": "$datasource" + }, + "decimals": 2, + "description": "**MySQL Slow Queries**\n\nSlow queries are defined as queries being slower than the long_query_time setting. For example, if you have long_query_time set to 3, all queries that take longer than 3 seconds to complete will show on this graph.", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 40 + }, + "hiddenSeries": false, + "id": 48, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "10.1.0", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "calculatedInterval": "2m", + "datasource": { + "uid": "$datasource" + }, + "datasourceErrors": {}, + "errors": {}, + "expr": "sum(rate(mysql_global_status_slow_queries{job=~\"$job\", instance=~\"$instance\"}[$__interval]))", + "format": "time_series", + "interval": "1m", + "intervalFactor": 1, + "legendFormat": "Slow Queries", + "metric": "", + "refId": "A", + "step": 20 + } + ], + "thresholds": [], + "timeRegions": [], + "title": "MySQL Slow Queries", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "", + "logBase": 1, + "min": 0, + "show": true + }, + { + "format": "short", + "label": "", + "logBase": 1, + "min": 0, + "show": true + } + ], + "yaxis": { + "align": false + } + }, + { + "collapsed": false, + "datasource": { + "uid": "$datasource" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 47 + }, + "id": 387, + "panels": [], + "targets": [ + { + "datasource": { + "uid": "$datasource" + }, + "refId": "A" + } + ], + "title": "Aborted", + "type": "row" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "uid": "$datasource" + }, + "decimals": 2, + "description": "**Aborted Connections**\n\nWhen a given host connects to MySQL and the connection is interrupted in the middle (for example due to bad credentials), MySQL keeps that info in a system table (since 5.6 this table is exposed in performance_schema).\n\nIf the amount of failed requests without a successful connection reaches the value of max_connect_errors, mysqld assumes that something is wrong and blocks the host from further connection.\n\nTo allow connections from that host again, you need to issue the ``FLUSH HOSTS`` statement.", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 48 + }, + "hiddenSeries": false, + "id": 47, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "10.1.0", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "calculatedInterval": "2m", + "datasource": { + "uid": "$datasource" + }, + "datasourceErrors": {}, + "errors": {}, + "expr": "sum(rate(mysql_global_status_aborted_connects{job=~\"$job\", instance=~\"$instance\"}[$__interval]))", + "format": "time_series", + "interval": "1m", + "intervalFactor": 1, + "legendFormat": "Aborted Connects (attempts)", + "metric": "", + "refId": "A", + "step": 20 + }, + { + "calculatedInterval": "2m", + "datasource": { + "uid": "$datasource" + }, + "datasourceErrors": {}, + "errors": {}, + "expr": "sum(rate(mysql_global_status_aborted_clients{job=~\"$job\", instance=~\"$instance\"}[$__interval]))", + "format": "time_series", + "interval": "1m", + "intervalFactor": 1, + "legendFormat": "Aborted Clients (timeout)", + "metric": "", + "refId": "B", + "step": 20, + "target": "" + } + ], + "thresholds": [], + "timeRegions": [], + "title": "MySQL Aborted Connections", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "", + "logBase": 1, + "min": 0, + "show": true + }, + { + "format": "short", + "label": "", + "logBase": 1, + "min": 0, + "show": true + } + ], + "yaxis": { + "align": false + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "uid": "$datasource" + }, + "decimals": 2, + "description": "**Table Locks**\n\nMySQL takes a number of different locks for varying reasons. In this graph we see how many Table level locks MySQL has requested from the storage engine. In the case of InnoDB, many times the locks could actually be row locks as it only takes table level locks in a few specific cases.\n\nIt is most useful to compare Locks Immediate and Locks Waited. If Locks waited is rising, it means you have lock contention. Otherwise, Locks Immediate rising and falling is normal activity.", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 48 + }, + "hiddenSeries": false, + "id": 32, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "10.1.0", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "calculatedInterval": "2m", + "datasource": { + "uid": "$datasource" + }, + "datasourceErrors": {}, + "errors": {}, + "expr": "sum(rate(mysql_global_status_table_locks_immediate{job=~\"$job\", instance=~\"$instance\"}[$__interval]))", + "format": "time_series", + "interval": "1m", + "intervalFactor": 1, + "legendFormat": "Table Locks Immediate", + "metric": "", + "refId": "A", + "step": 20 + }, + { + "calculatedInterval": "2m", + "datasource": { + "uid": "$datasource" + }, + "datasourceErrors": {}, + "errors": {}, + "expr": "sum(rate(mysql_global_status_table_locks_waited{job=~\"$job\", instance=~\"$instance\"}[$__interval]))", + "format": "time_series", + "interval": "1m", + "intervalFactor": 1, + "legendFormat": "Table Locks Waited", + "metric": "", + "refId": "B", + "step": 20 + } + ], + "thresholds": [], + "timeRegions": [], + "title": "MySQL Table Locks", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "logBase": 1, + "min": 0, + "show": true + }, + { + "format": "short", + "logBase": 1, + "min": 0, + "show": true + } + ], + "yaxis": { + "align": false + } + }, + { + "collapsed": false, + "datasource": { + "uid": "$datasource" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 55 + }, + "id": 388, + "panels": [], + "targets": [ + { + "datasource": { + "uid": "$datasource" + }, + "refId": "A" + } + ], + "title": "Network", + "type": "row" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "uid": "$datasource" + }, + "decimals": 2, + "description": "**MySQL Network Traffic**\n\nHere we can see how much network traffic is generated by MySQL. Outbound is network traffic sent from MySQL and Inbound is network traffic MySQL has received.", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 6, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 7, + "w": 24, + "x": 0, + "y": 56 + }, + "hiddenSeries": false, + "id": 9, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "10.1.0", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "calculatedInterval": "2m", + "datasource": { + "uid": "$datasource" + }, + "datasourceErrors": {}, + "errors": {}, + "expr": "sum(rate(mysql_global_status_bytes_received{job=~\"$job\", instance=~\"$instance\"}[$__interval]))", + "format": "time_series", + "interval": "1m", + "intervalFactor": 1, + "legendFormat": "Inbound", + "metric": "", + "refId": "A", + "step": 20 + }, + { + "calculatedInterval": "2m", + "datasource": { + "uid": "$datasource" + }, + "datasourceErrors": {}, + "errors": {}, + "expr": "sum(rate(mysql_global_status_bytes_sent{job=~\"$job\", instance=~\"$instance\"}[$__interval]))", + "format": "time_series", + "interval": "1m", + "intervalFactor": 1, + "legendFormat": "Outbound", + "metric": "", + "refId": "B", + "step": 20 + } + ], + "thresholds": [], + "timeRegions": [], + "title": "MySQL Network Traffic", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "Bps", + "logBase": 1, + "min": 0, + "show": true + }, + { + "format": "none", + "logBase": 1, + "min": 0, + "show": true + } + ], + "yaxis": { + "align": false + } + }, + { + "collapsed": false, + "datasource": { + "uid": "$datasource" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 63 + }, + "id": 389, + "panels": [], + "targets": [ + { + "datasource": { + "uid": "$datasource" + }, + "refId": "A" + } + ], + "title": "Memory", + "type": "row" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "uid": "$datasource" + }, + "decimals": 0, + "description": "***System Memory***: Total Memory for the system.\\\n***InnoDB Buffer Pool Data***: InnoDB maintains a storage area called the buffer pool for caching data and indexes in memory.\\\n***TokuDB Cache Size***: Similar in function to the InnoDB Buffer Pool, TokuDB will allocate 50% of the installed RAM for its own cache.\\\n***Key Buffer Size***: Index blocks for MYISAM tables are buffered and are shared by all threads. key_buffer_size is the size of the buffer used for index blocks.\\\n***Adaptive Hash Index Size***: When InnoDB notices that some index values are being accessed very frequently, it builds a hash index for them in memory on top of B-Tree indexes.\\\n ***Query Cache Size***: The query cache stores the text of a SELECT statement together with the corresponding result that was sent to the client. The query cache has huge scalability problems in that only one thread can do an operation in the query cache at the same time.\\\n***InnoDB Dictionary Size***: The data dictionary is InnoDB ‘s internal catalog of tables. InnoDB stores the data dictionary on disk, and loads entries into memory while the server is running.\\\n***InnoDB Log Buffer Size***: The MySQL InnoDB log buffer allows transactions to run without having to write the log to disk before the transactions commit.", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 6, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 7, + "w": 24, + "x": 0, + "y": 64 + }, + "hiddenSeries": false, + "id": 50, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": true, + "min": true, + "rightSide": true, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [ + { + "title": "Detailed descriptions about metrics", + "url": "https://www.percona.com/doc/percona-monitoring-and-management/dashboard.mysql-overview.html#mysql-internal-memory-overview" + } + ], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "10.1.0", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "System Memory", + "fill": 0, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "datasource": { + "uid": "$datasource" + }, + "expr": "sum(mysql_global_status_innodb_page_size{job=~\"$job\", instance=~\"$instance\"} * on (instance) mysql_global_status_buffer_pool_pages{job=~\"$job\", instance=~\"$instance\", state=\"data\"})", + "format": "time_series", + "hide": false, + "interval": "1m", + "intervalFactor": 1, + "legendFormat": "InnoDB Buffer Pool Data", + "refId": "A", + "step": 20 + }, + { + "datasource": { + "uid": "$datasource" + }, + "expr": "sum(mysql_global_variables_innodb_log_buffer_size{job=~\"$job\", instance=~\"$instance\"})", + "format": "time_series", + "interval": "1m", + "intervalFactor": 1, + "legendFormat": "InnoDB Log Buffer Size", + "refId": "D", + "step": 20 + }, + { + "datasource": { + "uid": "$datasource" + }, + "expr": "sum(mysql_global_variables_innodb_additional_mem_pool_size{job=~\"$job\", instance=~\"$instance\"})", + "format": "time_series", + "interval": "1m", + "intervalFactor": 2, + "legendFormat": "InnoDB Additional Memory Pool Size", + "refId": "H", + "step": 40 + }, + { + "datasource": { + "uid": "$datasource" + }, + "expr": "sum(mysql_global_status_innodb_mem_dictionary{job=~\"$job\", instance=~\"$instance\"})", + "format": "time_series", + "interval": "1m", + "intervalFactor": 1, + "legendFormat": "InnoDB Dictionary Size", + "refId": "F", + "step": 20 + }, + { + "datasource": { + "uid": "$datasource" + }, + "expr": "sum(mysql_global_variables_key_buffer_size{job=~\"$job\", instance=~\"$instance\"})", + "format": "time_series", + "interval": "1m", + "intervalFactor": 1, + "legendFormat": "Key Buffer Size", + "refId": "B", + "step": 20 + }, + { + "datasource": { + "uid": "$datasource" + }, + "expr": "sum(mysql_global_variables_query_cache_size{job=~\"$job\", instance=~\"$instance\"})", + "format": "time_series", + "interval": "1m", + "intervalFactor": 1, + "legendFormat": "Query Cache Size", + "refId": "C", + "step": 20 + }, + { + "datasource": { + "uid": "$datasource" + }, + "expr": "sum(mysql_global_status_innodb_mem_adaptive_hash{job=~\"$job\", instance=~\"$instance\"})", + "format": "time_series", + "interval": "1m", + "intervalFactor": 1, + "legendFormat": "Adaptive Hash Index Size", + "refId": "E", + "step": 20 + }, + { + "datasource": { + "uid": "$datasource" + }, + "expr": "sum(mysql_global_variables_tokudb_cache_size{job=~\"$job\", instance=~\"$instance\"})", + "format": "time_series", + "interval": "1m", + "intervalFactor": 1, + "legendFormat": "TokuDB Cache Size", + "refId": "I", + "step": 20 + } + ], + "thresholds": [], + "timeRegions": [], + "title": "MySQL Internal Memory Overview", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": "", + "logBase": 1, + "min": 0, + "show": true + }, + { + "format": "short", + "logBase": 1, + "show": true + } + ], + "yaxis": { + "align": false + } + }, + { + "collapsed": false, + "datasource": { + "uid": "$datasource" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 71 + }, + "id": 390, + "panels": [], + "targets": [ + { + "datasource": { + "uid": "$datasource" + }, + "refId": "A" + } + ], + "title": "Command, Handlers, Processes", + "type": "row" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "uid": "$datasource" + }, + "decimals": 2, + "description": "**Top Command Counters**\n\nThe Com_{{xxx}} statement counter variables indicate the number of times each xxx statement has been executed. There is one status variable for each type of statement. For example, Com_delete and Com_update count [``DELETE``](https://dev.mysql.com/doc/refman/5.7/en/delete.html) and [``UPDATE``](https://dev.mysql.com/doc/refman/5.7/en/update.html) statements, respectively. Com_delete_multi and Com_update_multi are similar but apply to [``DELETE``](https://dev.mysql.com/doc/refman/5.7/en/delete.html) and [``UPDATE``](https://dev.mysql.com/doc/refman/5.7/en/update.html) statements that use multiple-table syntax.", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 7, + "w": 24, + "x": 0, + "y": 72 + }, + "hiddenSeries": false, + "id": 14, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": true, + "min": true, + "rightSide": true, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [ + { + "title": "Server Status Variables (Com_xxx)", + "url": "https://dev.mysql.com/doc/refman/5.7/en/server-status-variables.html#statvar_Com_xxx" + } + ], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "10.1.0", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "calculatedInterval": "2m", + "datasource": { + "uid": "$datasource" + }, + "datasourceErrors": {}, + "errors": {}, + "expr": "topk(5, rate(mysql_global_status_commands_total{job=~\"$job\", instance=~\"$instance\"}[$__interval])>0)", + "format": "time_series", + "hide": false, + "interval": "1m", + "intervalFactor": 1, + "legendFormat": "Com_{{ command }}", + "metric": "", + "refId": "B", + "step": 20 + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Top Command Counters", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "logBase": 1, + "min": 0, + "show": true + }, + { + "format": "short", + "logBase": 1, + "min": 0, + "show": true + } + ], + "yaxis": { + "align": false + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "uid": "$datasource" + }, + "decimals": 2, + "description": "**MySQL Handlers**\n\nHandler statistics are internal statistics on how MySQL is selecting, updating, inserting, and modifying rows, tables, and indexes.\n\nThis is in fact the layer between the Storage Engine and MySQL.\n\n* `read_rnd_next` is incremented when the server performs a full table scan and this is a counter you don't really want to see with a high value.\n* `read_key` is incremented when a read is done with an index.\n* `read_next` is incremented when the storage engine is asked to 'read the next index entry'. A high value means a lot of index scans are being done.", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 7, + "w": 24, + "x": 0, + "y": 79 + }, + "hiddenSeries": false, + "id": 8, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "hideZero": true, + "max": true, + "min": true, + "rightSide": true, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "10.1.0", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "calculatedInterval": "2m", + "datasource": { + "uid": "$datasource" + }, + "datasourceErrors": {}, + "errors": {}, + "expr": "rate(mysql_global_status_handlers_total{instance=~\"$host\", handler!~\"commit|rollback|savepoint.*|prepare\"}[$__interval]) or irate(mysql_global_status_handlers_total{instance=~\"$host\", handler!~\"commit|rollback|savepoint.*|prepare\"}[5m])", + "format": "time_series", + "interval": "1m", + "intervalFactor": 1, + "legendFormat": "{{ handler }}", + "metric": "", + "refId": "J", + "step": 20 + } + ], + "thresholds": [], + "timeRegions": [], + "title": "MySQL Handlers", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "logBase": 1, + "min": 0, + "show": true + }, + { + "format": "short", + "logBase": 1, + "min": 0, + "show": true + } + ], + "yaxis": { + "align": false + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "uid": "$datasource" + }, + "decimals": 2, + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 7, + "w": 24, + "x": 0, + "y": 86 + }, + "hiddenSeries": false, + "id": 28, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "hideZero": true, + "max": true, + "min": true, + "rightSide": true, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "10.1.0", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "calculatedInterval": "2m", + "datasource": { + "uid": "$datasource" + }, + "datasourceErrors": {}, + "errors": {}, + "expr": "rate(mysql_global_status_handlers_total{instance=~\"$host\", handler=~\"commit|rollback|savepoint.*|prepare\"}[$__interval]) or irate(mysql_global_status_handlers_total{instance=~\"$host\", handler=~\"commit|rollback|savepoint.*|prepare\"}[5m])", + "interval": "1m", + "intervalFactor": 1, + "legendFormat": "{{ handler }}", + "metric": "", + "refId": "A", + "step": 20 + } + ], + "thresholds": [], + "timeRegions": [], + "title": "MySQL Transaction Handlers", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "logBase": 1, + "min": 0, + "show": true + }, + { + "format": "short", + "logBase": 1, + "min": 0, + "show": true + } + ], + "yaxis": { + "align": false + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "uid": "$datasource" + }, + "decimals": 2, + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 7, + "w": 24, + "x": 0, + "y": 93 + }, + "hiddenSeries": false, + "id": 40, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "hideZero": true, + "max": true, + "min": false, + "rightSide": true, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "10.1.0", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "calculatedInterval": "2m", + "datasource": { + "uid": "$datasource" + }, + "datasourceErrors": {}, + "errors": {}, + "expr": "mysql_info_schema_threads{job=~\"$job\", instance=~\"$instance\"}", + "format": "time_series", + "interval": "1m", + "intervalFactor": 1, + "legendFormat": "{{ state }}", + "metric": "", + "refId": "A", + "step": 20 + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Process States", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "logBase": 1, + "min": 0, + "show": true + }, + { + "format": "short", + "logBase": 1, + "min": 0, + "show": true + } + ], + "yaxis": { + "align": false + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": { + "uid": "$datasource" + }, + "decimals": 2, + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 6, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 7, + "w": 24, + "x": 0, + "y": 100 + }, + "hiddenSeries": false, + "id": 49, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "hideZero": true, + "max": true, + "min": false, + "rightSide": true, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 2, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "10.1.0", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "calculatedInterval": "2m", + "datasource": { + "uid": "$datasource" + }, + "datasourceErrors": {}, + "errors": {}, + "expr": "topk(5, avg_over_time(mysql_info_schema_threads{job=~\"$job\", instance=~\"$instance\"}[1h]))", + "interval": "1m", + "intervalFactor": 1, + "legendFormat": "{{ state }}", + "metric": "", + "refId": "A", + "step": 3600 + } + ], + "thresholds": [], + "timeFrom": "24h", + "timeRegions": [], + "title": "Top Process States Hourly", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "logBase": 1, + "min": 0, + "show": true + }, + { + "format": "short", + "logBase": 1, + "min": 0, + "show": true + } + ], + "yaxis": { + "align": false + } + }, + { + "collapsed": false, + "datasource": { + "uid": "$datasource" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 107 + }, + "id": 391, + "panels": [], + "targets": [ + { + "datasource": { + "uid": "$datasource" + }, + "refId": "A" + } + ], + "title": "Query Cache", + "type": "row" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "uid": "$datasource" + }, + "decimals": 2, + "description": "**MySQL Query Cache Memory**\n\nThe query cache has huge scalability problems in that only one thread can do an operation in the query cache at the same time. This serialization is true not only for SELECTs, but also for INSERT/UPDATE/DELETE.\n\nThis also means that the larger the `query_cache_size` is set to, the slower those operations become. In concurrent environments, the MySQL Query Cache quickly becomes a contention point, decreasing performance. MariaDB and AWS Aurora have done work to try and eliminate the query cache contention in their flavors of MySQL, while MySQL 8.0 has eliminated the query cache feature.\n\nThe recommended settings for most environments is to set:\n ``query_cache_type=0``\n ``query_cache_size=0``\n\nNote that while you can dynamically change these values, to completely remove the contention point you have to restart the database.", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 108 + }, + "hiddenSeries": false, + "id": 46, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "10.1.0", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "calculatedInterval": "2m", + "datasource": { + "uid": "$datasource" + }, + "datasourceErrors": {}, + "errors": {}, + "expr": "mysql_global_status_qcache_free_memory{job=~\"$job\", instance=~\"$instance\"}", + "format": "time_series", + "interval": "1m", + "intervalFactor": 1, + "legendFormat": "Free Memory", + "metric": "", + "refId": "F", + "step": 20 + }, + { + "calculatedInterval": "2m", + "datasource": { + "uid": "$datasource" + }, + "datasourceErrors": {}, + "errors": {}, + "expr": "mysql_global_variables_query_cache_size{job=~\"$job\", instance=~\"$instance\"}", + "format": "time_series", + "interval": "1m", + "intervalFactor": 1, + "legendFormat": "Query Cache Size", + "metric": "", + "refId": "E", + "step": 20 + } + ], + "thresholds": [], + "timeRegions": [], + "title": "MySQL Query Cache Memory", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "logBase": 1, + "min": 0, + "show": true + }, + { + "format": "short", + "logBase": 1, + "min": 0, + "show": true + } + ], + "yaxis": { + "align": false + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "uid": "$datasource" + }, + "decimals": 2, + "description": "**MySQL Query Cache Activity**\n\nThe query cache has huge scalability problems in that only one thread can do an operation in the query cache at the same time. This serialization is true not only for SELECTs, but also for INSERT/UPDATE/DELETE.\n\nThis also means that the larger the `query_cache_size` is set to, the slower those operations become. In concurrent environments, the MySQL Query Cache quickly becomes a contention point, decreasing performance. MariaDB and AWS Aurora have done work to try and eliminate the query cache contention in their flavors of MySQL, while MySQL 8.0 has eliminated the query cache feature.\n\nThe recommended settings for most environments is to set:\n``query_cache_type=0``\n``query_cache_size=0``\n\nNote that while you can dynamically change these values, to completely remove the contention point you have to restart the database.", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 108 + }, + "height": "", + "hiddenSeries": false, + "id": 45, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "10.1.0", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "calculatedInterval": "2m", + "datasource": { + "uid": "$datasource" + }, + "datasourceErrors": {}, + "errors": {}, + "expr": "rate(mysql_global_status_qcache_hits{job=~\"$job\", instance=~\"$instance\"}[$__interval]) or irate(mysql_global_status_qcache_hits{job=~\"$job\", instance=~\"$instance\"}[5m])", + "format": "time_series", + "interval": "1m", + "intervalFactor": 1, + "legendFormat": "Hits", + "metric": "", + "refId": "B", + "step": 20 + }, + { + "calculatedInterval": "2m", + "datasource": { + "uid": "$datasource" + }, + "datasourceErrors": {}, + "errors": {}, + "expr": "rate(mysql_global_status_qcache_inserts{job=~\"$job\", instance=~\"$instance\"}[$__interval]) or irate(mysql_global_status_qcache_inserts{job=~\"$job\", instance=~\"$instance\"}[5m])", + "format": "time_series", + "interval": "1m", + "intervalFactor": 1, + "legendFormat": "Inserts", + "metric": "", + "refId": "C", + "step": 20 + }, + { + "calculatedInterval": "2m", + "datasource": { + "uid": "$datasource" + }, + "datasourceErrors": {}, + "errors": {}, + "expr": "rate(mysql_global_status_qcache_not_cached{job=~\"$job\", instance=~\"$instance\"}[$__interval]) or irate(mysql_global_status_qcache_not_cached{job=~\"$job\", instance=~\"$instance\"}[5m])", + "format": "time_series", + "interval": "1m", + "intervalFactor": 1, + "legendFormat": "Not Cached", + "metric": "", + "refId": "D", + "step": 20 + }, + { + "calculatedInterval": "2m", + "datasource": { + "uid": "$datasource" + }, + "datasourceErrors": {}, + "errors": {}, + "expr": "rate(mysql_global_status_qcache_lowmem_prunes{job=~\"$job\", instance=~\"$instance\"}[$__interval]) or irate(mysql_global_status_qcache_lowmem_prunes{job=~\"$job\", instance=~\"$instance\"}[5m])", + "format": "time_series", + "interval": "1m", + "intervalFactor": 1, + "legendFormat": "Prunes", + "metric": "", + "refId": "F", + "step": 20 + }, + { + "calculatedInterval": "2m", + "datasource": { + "uid": "$datasource" + }, + "datasourceErrors": {}, + "errors": {}, + "expr": "mysql_global_status_qcache_queries_in_cache{job=~\"$job\", instance=~\"$instance\"}", + "format": "time_series", + "interval": "1m", + "intervalFactor": 1, + "legendFormat": "Queries in Cache", + "metric": "", + "refId": "E", + "step": 20 + } + ], + "thresholds": [], + "timeRegions": [], + "title": "MySQL Query Cache Activity", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "logBase": 1, + "min": 0, + "show": true + }, + { + "format": "short", + "logBase": 1, + "min": 0, + "show": true + } + ], + "yaxis": { + "align": false + } + }, + { + "collapsed": false, + "datasource": { + "uid": "$datasource" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 115 + }, + "id": 392, + "panels": [], + "targets": [ + { + "datasource": { + "uid": "$datasource" + }, + "refId": "A" + } + ], + "title": "Files and Tables", + "type": "row" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "uid": "$datasource" + }, + "decimals": 2, + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 116 + }, + "hiddenSeries": false, + "id": 43, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "10.1.0", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "calculatedInterval": "2m", + "datasource": { + "uid": "$datasource" + }, + "datasourceErrors": {}, + "errors": {}, + "expr": "rate(mysql_global_status_opened_files{job=~\"$job\", instance=~\"$instance\"}[$__interval]) or irate(mysql_global_status_opened_files{job=~\"$job\", instance=~\"$instance\"}[5m])", + "interval": "1m", + "intervalFactor": 1, + "legendFormat": "Openings", + "metric": "", + "refId": "A", + "step": 20 + } + ], + "thresholds": [], + "timeRegions": [], + "title": "MySQL File Openings", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "logBase": 1, + "min": 0, + "show": true + }, + { + "format": "short", + "logBase": 1, + "min": 0, + "show": true + } + ], + "yaxis": { + "align": false + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "uid": "$datasource" + }, + "decimals": 2, + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 116 + }, + "hiddenSeries": false, + "id": 41, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "10.1.0", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "calculatedInterval": "2m", + "datasource": { + "uid": "$datasource" + }, + "datasourceErrors": {}, + "errors": {}, + "expr": "mysql_global_status_open_files{job=~\"$job\", instance=~\"$instance\"}", + "interval": "1m", + "intervalFactor": 1, + "legendFormat": "Open Files", + "metric": "", + "refId": "A", + "step": 20 + }, + { + "calculatedInterval": "2m", + "datasource": { + "uid": "$datasource" + }, + "datasourceErrors": {}, + "errors": {}, + "expr": "mysql_global_variables_open_files_limit{job=~\"$job\", instance=~\"$instance\"}", + "interval": "1m", + "intervalFactor": 1, + "legendFormat": "Open Files Limit", + "metric": "", + "refId": "D", + "step": 20 + }, + { + "datasource": { + "uid": "$datasource" + }, + "expr": "mysql_global_status_innodb_num_open_files{job=~\"$job\", instance=~\"$instance\"}", + "interval": "1m", + "intervalFactor": 1, + "legendFormat": "InnoDB Open Files", + "refId": "B", + "step": 20 + } + ], + "thresholds": [], + "timeRegions": [], + "title": "MySQL Open Files", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "logBase": 1, + "min": 0, + "show": true + }, + { + "format": "short", + "logBase": 1, + "min": 0, + "show": true + } + ], + "yaxis": { + "align": false + } + }, + { + "collapsed": false, + "datasource": { + "uid": "$datasource" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 123 + }, + "id": 393, + "panels": [], + "targets": [ + { + "datasource": { + "uid": "$datasource" + }, + "refId": "A" + } + ], + "title": "Table Openings", + "type": "row" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "uid": "$datasource" + }, + "decimals": 2, + "description": "**MySQL Table Open Cache Status**\n\nThe recommendation is to set the `table_open_cache_instances` to a loose correlation to virtual CPUs, keeping in mind that more instances means the cache is split more times. If you have a cache set to 500 but it has 10 instances, each cache will only have 50 cached.\n\nThe `table_definition_cache` and `table_open_cache` can be left as default as they are auto-sized MySQL 5.6 and above (ie: do not set them to any value).", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 124 + }, + "hiddenSeries": false, + "id": 44, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [ + { + "title": "Server Status Variables (table_open_cache)", + "url": "http://dev.mysql.com/doc/refman/5.6/en/server-system-variables.html#sysvar_table_open_cache" + } + ], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "10.1.0", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Table Open Cache Hit Ratio", + "yaxis": 2 + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "calculatedInterval": "2m", + "datasource": { + "uid": "$datasource" + }, + "datasourceErrors": {}, + "errors": {}, + "expr": "rate(mysql_global_status_opened_tables{job=~\"$job\", instance=~\"$instance\"}[$__interval]) or irate(mysql_global_status_opened_tables{job=~\"$job\", instance=~\"$instance\"}[5m])", + "format": "time_series", + "interval": "1m", + "intervalFactor": 1, + "legendFormat": "Openings", + "metric": "", + "refId": "A", + "step": 20 + }, + { + "datasource": { + "uid": "$datasource" + }, + "expr": "rate(mysql_global_status_table_open_cache_hits{job=~\"$job\", instance=~\"$instance\"}[$__interval]) or irate(mysql_global_status_table_open_cache_hits{job=~\"$job\", instance=~\"$instance\"}[5m])", + "format": "time_series", + "interval": "1m", + "intervalFactor": 1, + "legendFormat": "Hits", + "refId": "B", + "step": 20 + }, + { + "datasource": { + "uid": "$datasource" + }, + "expr": "rate(mysql_global_status_table_open_cache_misses{job=~\"$job\", instance=~\"$instance\"}[$__interval]) or irate(mysql_global_status_table_open_cache_misses{job=~\"$job\", instance=~\"$instance\"}[5m])", + "format": "time_series", + "interval": "1m", + "intervalFactor": 1, + "legendFormat": "Misses", + "refId": "C", + "step": 20 + }, + { + "datasource": { + "uid": "$datasource" + }, + "expr": "rate(mysql_global_status_table_open_cache_overflows{job=~\"$job\", instance=~\"$instance\"}[$__interval]) or irate(mysql_global_status_table_open_cache_overflows{job=~\"$job\", instance=~\"$instance\"}[5m])", + "format": "time_series", + "interval": "1m", + "intervalFactor": 1, + "legendFormat": "Misses due to Overflows", + "refId": "D", + "step": 20 + }, + { + "datasource": { + "uid": "$datasource" + }, + "expr": "(rate(mysql_global_status_table_open_cache_hits{job=~\"$job\", instance=~\"$instance\"}[$__interval]) or irate(mysql_global_status_table_open_cache_hits{job=~\"$job\", instance=~\"$instance\"}[5m]))/((rate(mysql_global_status_table_open_cache_hits{job=~\"$job\", instance=~\"$instance\"}[$__interval]) or irate(mysql_global_status_table_open_cache_hits{job=~\"$job\", instance=~\"$instance\"}[5m]))+(rate(mysql_global_status_table_open_cache_misses{job=~\"$job\", instance=~\"$instance\"}[$__interval]) or irate(mysql_global_status_table_open_cache_misses{job=~\"$job\", instance=~\"$instance\"}[5m])))", + "format": "time_series", + "interval": "1m", + "intervalFactor": 1, + "legendFormat": "Table Open Cache Hit Ratio", + "refId": "E", + "step": 20 + } + ], + "thresholds": [], + "timeRegions": [], + "title": "MySQL Table Open Cache Status", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "logBase": 1, + "min": 0, + "show": true + }, + { + "format": "percentunit", + "logBase": 1, + "min": 0, + "show": true + } + ], + "yaxis": { + "align": false + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "uid": "$datasource" + }, + "decimals": 2, + "description": "**MySQL Open Tables**\n\nThe recommendation is to set the `table_open_cache_instances` to a loose correlation to virtual CPUs, keeping in mind that more instances means the cache is split more times. If you have a cache set to 500 but it has 10 instances, each cache will only have 50 cached.\n\nThe `table_definition_cache` and `table_open_cache` can be left as default as they are auto-sized MySQL 5.6 and above (ie: do not set them to any value).", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 124 + }, + "hiddenSeries": false, + "id": 42, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [ + { + "title": "Server Status Variables (table_open_cache)", + "url": "http://dev.mysql.com/doc/refman/5.6/en/server-system-variables.html#sysvar_table_open_cache" + } + ], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "10.1.0", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "calculatedInterval": "2m", + "datasource": { + "uid": "$datasource" + }, + "datasourceErrors": {}, + "errors": {}, + "expr": "mysql_global_status_open_tables{job=~\"$job\", instance=~\"$instance\"}", + "format": "time_series", + "interval": "1m", + "intervalFactor": 1, + "legendFormat": "Open Tables", + "metric": "", + "refId": "B", + "step": 20 + }, + { + "calculatedInterval": "2m", + "datasource": { + "uid": "$datasource" + }, + "datasourceErrors": {}, + "errors": {}, + "expr": "mysql_global_variables_table_open_cache{job=~\"$job\", instance=~\"$instance\"}", + "format": "time_series", + "interval": "1m", + "intervalFactor": 1, + "legendFormat": "Table Open Cache", + "metric": "", + "refId": "C", + "step": 20 + } + ], + "thresholds": [], + "timeRegions": [], + "title": "MySQL Open Tables", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "logBase": 1, + "min": 0, + "show": true + }, + { + "format": "short", + "logBase": 1, + "min": 0, + "show": true + } + ], + "yaxis": { + "align": false + } + }, + { + "collapsed": false, + "datasource": { + "uid": "$datasource" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 131 + }, + "id": 394, + "panels": [], + "targets": [ + { + "datasource": { + "uid": "$datasource" + }, + "refId": "A" + } + ], + "title": "MySQL Table Definition Cache", + "type": "row" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "uid": "$datasource" + }, + "decimals": 2, + "description": "**MySQL Table Definition Cache**\n\nThe recommendation is to set the `table_open_cache_instances` to a loose correlation to virtual CPUs, keeping in mind that more instances means the cache is split more times. If you have a cache set to 500 but it has 10 instances, each cache will only have 50 cached.\n\nThe `table_definition_cache` and `table_open_cache` can be left as default as they are auto-sized MySQL 5.6 and above (ie: do not set them to any value).", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 7, + "w": 24, + "x": 0, + "y": 132 + }, + "hiddenSeries": false, + "id": 54, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [ + { + "title": "Server Status Variables (table_open_cache)", + "url": "http://dev.mysql.com/doc/refman/5.6/en/server-system-variables.html#sysvar_table_open_cache" + } + ], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "10.1.0", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Opened Table Definitions", + "yaxis": 2 + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "calculatedInterval": "2m", + "datasource": { + "uid": "$datasource" + }, + "datasourceErrors": {}, + "errors": {}, + "expr": "mysql_global_status_open_table_definitions{job=~\"$job\", instance=~\"$instance\"}", + "format": "time_series", + "interval": "1m", + "intervalFactor": 1, + "legendFormat": "Open Table Definitions", + "metric": "", + "refId": "B", + "step": 20 + }, + { + "calculatedInterval": "2m", + "datasource": { + "uid": "$datasource" + }, + "datasourceErrors": {}, + "errors": {}, + "expr": "mysql_global_variables_table_definition_cache{job=~\"$job\", instance=~\"$instance\"}", + "format": "time_series", + "interval": "1m", + "intervalFactor": 1, + "legendFormat": "Table Definitions Cache Size", + "metric": "", + "refId": "C", + "step": 20 + }, + { + "datasource": { + "uid": "$datasource" + }, + "expr": "rate(mysql_global_status_opened_table_definitions{job=~\"$job\", instance=~\"$instance\"}[$__interval]) or irate(mysql_global_status_opened_table_definitions{job=~\"$job\", instance=~\"$instance\"}[5m])", + "format": "time_series", + "interval": "1m", + "intervalFactor": 1, + "legendFormat": "Opened Table Definitions", + "refId": "A", + "step": 20 + } + ], + "thresholds": [], + "timeRegions": [], + "title": "MySQL Table Definition Cache", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "logBase": 1, + "min": 0, + "show": true + }, + { + "format": "short", + "logBase": 1, + "min": 0, + "show": true + } + ], + "yaxis": { + "align": false + } + } + ], + "refresh": "10s", + "schemaVersion": 38, + "style": "dark", + "tags": [ + "MariaDB" + ], + "templating": { + "list": [ + { + "current": { + "selected": false, + "text": "vm", + "value": "${datasource}" + }, + "hide": 0, + "includeAll": false, + "multi": false, + "name": "datasource", + "options": [], + "query": "prometheus", + "queryValue": "", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + }, + { + "current": { + "selected": true, + "text": [ + "app" + ], + "value": [ + "app" + ] + }, + "datasource": { + "uid": "$datasource" + }, + "definition": "label_values(mysql_up, job)", + "hide": 0, + "includeAll": true, + "multi": true, + "name": "job", + "options": [], + "query": "label_values(mysql_up, job)", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "current": { + "selected": true, + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "uid": "$datasource" + }, + "definition": "label_values(mysql_up{job=\"$job\"},instance)", + "hide": 0, + "includeAll": true, + "multi": true, + "name": "instance", + "options": [], + "query": { + "query": "label_values(mysql_up{job=\"$job\"},instance)", + "refId": "PrometheusVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + } + ] + }, + "time": { + "from": "now-30m", + "to": "now" + }, + "timepicker": { + "collapse": false, + "enable": true, + "hidden": false, + "notice": false, + "now": true, + "refresh_intervals": [ + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "status": "Stable", + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ], + "type": "timepicker" + }, + "timezone": "", + "title": "MySQL Exporter", + "uid": "549c2bf8936f7767ea6ac47c47b00f2a", + "version": 6, + "weekStart": "" +} diff --git a/dashboards/db/redis.json b/dashboards/db/redis.json new file mode 100644 index 00000000..dee4c9ed --- /dev/null +++ b/dashboards/db/redis.json @@ -0,0 +1,1659 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "target": { + "limit": 100, + "matchAny": false, + "tags": [], + "type": "dashboard" + }, + "type": "dashboard" + } + ] + }, + "description": "Redis Dashboard for Prometheus Redis Exporter 1.x", + "editable": true, + "fiscalYearStartMonth": 0, + "gnetId": 763, + "graphTooltip": 1, + "id": 66, + "links": [], + "liveNow": false, + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "${Datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "rgb(31, 120, 193)", + "mode": "fixed" + }, + "decimals": 0, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 3, + "x": 0, + "y": 0 + }, + "id": 9, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "10.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${Datasource}" + }, + "editorMode": "code", + "expr": "max(max_over_time(redis_uptime_in_seconds{service=~\"$cluster\", pod=~\"$instance\"}[$__interval]))", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "", + "metric": "", + "range": true, + "refId": "A", + "step": 1800 + } + ], + "title": "Max Uptime", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${Datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "rgb(31, 120, 193)", + "mode": "fixed" + }, + "decimals": 0, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 2, + "x": 3, + "y": 0 + }, + "hideTimeOverride": true, + "id": 12, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "10.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${Datasource}" + }, + "editorMode": "code", + "expr": "sum(redis_connected_clients{service=~\"$cluster\", pod=~\"$instance\"})", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "", + "metric": "", + "range": true, + "refId": "A", + "step": 2 + } + ], + "timeFrom": "1m", + "title": "Clients", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${Datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "decimals": 0, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "rgba(50, 172, 45, 0.97)", + "value": null + }, + { + "color": "rgba(237, 129, 40, 0.89)", + "value": 80 + }, + { + "color": "rgba(245, 54, 54, 0.9)", + "value": 95 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 3, + "x": 5, + "y": 0 + }, + "hideTimeOverride": true, + "id": 11, + "links": [], + "maxDataPoints": 100, + "options": { + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": true, + "text": {} + }, + "pluginVersion": "10.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${Datasource}" + }, + "editorMode": "code", + "expr": "sum(100 * (redis_memory_used_bytes{service=~\"$cluster\", pod=~\"$instance\"} / redis_memory_max_bytes{service=~\"$cluster\", pod=~\"$instance\"}))", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "", + "metric": "", + "range": true, + "refId": "A", + "step": 2 + } + ], + "timeFrom": "1m", + "title": "Memory Usage", + "type": "gauge" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${Datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 80, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 8, + "x": 8, + "y": 0 + }, + "id": 18, + "links": [], + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "10.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${Datasource}" + }, + "editorMode": "code", + "expr": "sum(rate(redis_commands_total{service=~\"$cluster\", pod=~\"$instance\"} [1m])) by (cmd)", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "{{ cmd }}", + "metric": "redis_command_calls_total", + "range": true, + "refId": "A", + "step": 240 + } + ], + "title": "Total Commands / sec", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${Datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 2, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 8, + "x": 16, + "y": 0 + }, + "id": 1, + "links": [], + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "10.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${Datasource}" + }, + "editorMode": "code", + "expr": "irate(redis_keyspace_hits_total{service=~\"$cluster\", pod=~\"$instance\"}[5m])", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 2, + "legendFormat": "hits, {{ instance }}", + "metric": "", + "range": true, + "refId": "A", + "step": 240, + "target": "" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${Datasource}" + }, + "editorMode": "code", + "expr": "irate(redis_keyspace_misses_total{service=~\"$cluster\", pod=~\"$instance\"}[5m])", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 2, + "legendFormat": "misses, {{ instance }}", + "metric": "", + "range": true, + "refId": "B", + "step": 240, + "target": "" + } + ], + "title": "Hits / Misses per Sec", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${Datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 2, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "max" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#BF1B00", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 7 + }, + "id": 7, + "links": [], + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "10.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${Datasource}" + }, + "editorMode": "code", + "expr": "redis_memory_used_bytes{service=~\"$cluster\", pod=~\"$instance\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "used, {{ instance }}", + "metric": "", + "range": true, + "refId": "A", + "step": 240, + "target": "" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${Datasource}" + }, + "editorMode": "code", + "expr": "redis_memory_max_bytes{service=~\"$cluster\", pod=~\"$instance\"}", + "format": "time_series", + "hide": false, + "intervalFactor": 2, + "legendFormat": "max, {{ instance }}", + "range": true, + "refId": "B", + "step": 240 + } + ], + "title": "Total Memory Usage", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${Datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 2, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 7 + }, + "id": 10, + "links": [], + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "10.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${Datasource}" + }, + "editorMode": "code", + "expr": "sum(rate(redis_net_input_bytes_total{service=~\"$cluster\", pod=~\"$instance\"}[5m]))", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "input", + "range": true, + "refId": "A", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${Datasource}" + }, + "editorMode": "code", + "expr": "sum(rate(redis_net_output_bytes_total{service=~\"$cluster\", pod=~\"$instance\"}[5m]))", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "output", + "range": true, + "refId": "B", + "step": 240 + } + ], + "title": "Network I/O", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${Datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 70, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 2, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [ + { + "matcher": { + "id": "byValue", + "options": { + "op": "gte", + "reducer": "allIsZero", + "value": 0 + } + }, + "properties": [ + { + "id": "custom.hideFrom", + "value": { + "legend": true, + "tooltip": true, + "viz": false + } + } + ] + } + ] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 14 + }, + "id": 5, + "links": [], + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "10.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${Datasource}" + }, + "editorMode": "code", + "expr": "sum (redis_db_keys{service=~\"$cluster\", pod=~\"$instance\"}) by (db, pod)", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "{{ db }}, {{ pod }}", + "range": true, + "refId": "A", + "step": 240, + "target": "" + } + ], + "title": "Total Items per DB", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${Datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 70, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 2, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 14 + }, + "id": 13, + "links": [], + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "10.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${Datasource}" + }, + "editorMode": "code", + "expr": "sum (redis_db_keys{service=~\"$cluster\", pod=~\"$instance\"}) by (pod) - sum (redis_db_keys_expiring{service=~\"$cluster\", pod=~\"$instance\"}) by (pod)", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "not expiring, {{ pod }}", + "range": true, + "refId": "A", + "step": 240, + "target": "" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${Datasource}" + }, + "editorMode": "code", + "expr": "sum (redis_db_keys_expiring{service=~\"$cluster\", pod=~\"$instance\"}) by (pod)", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "expiring, {{ pod }}", + "metric": "", + "range": true, + "refId": "B", + "step": 240 + } + ], + "title": "Expiring vs Not-Expiring Keys", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${Datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 2, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "evicts" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#890F02", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "memcached_items_evicted_total{instance=\"172.17.0.1:9150\",job=\"prometheus\"}" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#890F02", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "reclaims" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#3F6833", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 21 + }, + "id": 8, + "links": [], + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "10.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${Datasource}" + }, + "editorMode": "code", + "expr": "sum(rate(redis_expired_keys_total{service=~\"$cluster\", pod=~\"$instance\"}[5m])) by (pod)", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 2, + "legendFormat": "expired, {{ pod }}", + "metric": "", + "range": true, + "refId": "A", + "step": 240, + "target": "" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${Datasource}" + }, + "editorMode": "code", + "expr": "sum(rate(redis_evicted_keys_total{service=~\"$cluster\", pod=~\"$instance\"}[5m])) by (pod)", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "evicted, {{ pod }}", + "range": true, + "refId": "B", + "step": 240 + } + ], + "title": "Expired/Evicted Keys", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${Datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 21 + }, + "id": 16, + "links": [], + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "10.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${Datasource}" + }, + "editorMode": "code", + "expr": "sum(redis_connected_clients{service=~\"$cluster\", pod=~\"$instance\"})", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "connected", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${Datasource}" + }, + "editorMode": "code", + "expr": "sum(redis_blocked_clients{service=~\"$cluster\", pod=~\"$instance\"})", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "blocked", + "range": true, + "refId": "B" + } + ], + "title": "Connected/Blocked Clients", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${Datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "s" + }, + "overrides": [ + { + "matcher": { + "id": "byValue", + "options": { + "op": "gte", + "reducer": "allIsZero", + "value": 0 + } + }, + "properties": [ + { + "id": "custom.hideFrom", + "value": { + "legend": true, + "tooltip": true, + "viz": false + } + } + ] + }, + { + "__systemRef": "hideSeriesFrom", + "matcher": { + "id": "byNames", + "options": { + "mode": "exclude", + "names": [ + "mget" + ], + "prefix": "All except:", + "readOnly": true + } + }, + "properties": [ + { + "id": "custom.hideFrom", + "value": { + "legend": false, + "tooltip": false, + "viz": true + } + } + ] + } + ] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 28 + }, + "id": 20, + "links": [], + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "10.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${Datasource}" + }, + "editorMode": "code", + "expr": "sum(irate(redis_commands_duration_seconds_total{service=~\"$cluster\", pod=~\"$instance\"}[1m])) by (cmd)\n /\nsum(irate(redis_commands_total{service=~\"$cluster\", pod=~\"$instance\"}[1m])) by (cmd)\n", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "{{ cmd }}", + "metric": "redis_command_calls_total", + "range": true, + "refId": "A", + "step": 240 + } + ], + "title": "Average Time Spent by Command / sec", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${Datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 80, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 28 + }, + "id": 14, + "links": [], + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "10.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${Datasource}" + }, + "editorMode": "code", + "expr": "sum(irate(redis_commands_duration_seconds_total{service=~\"$cluster\", pod=~\"$instance\"}[1m])) by (cmd) != 0", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "{{ cmd }}", + "metric": "redis_command_calls_total", + "range": true, + "refId": "A", + "step": 240 + } + ], + "title": "Total Time Spent by Command / sec", + "type": "timeseries" + } + ], + "refresh": "", + "revision": 1, + "schemaVersion": 38, + "style": "dark", + "tags": [ + "prometheus", + "redis" + ], + "templating": { + "list": [ + { + "current": { + "selected": false, + "text": "vm", + "value": "7de66667-64e8-4685-b5b4-2c3d573910bc" + }, + "hide": 0, + "includeAll": false, + "multi": false, + "name": "Datasource", + "options": [], + "query": "prometheus", + "queryValue": "", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + }, + { + "current": { + "selected": true, + "text": "app", + "value": "app" + }, + "definition": "label_values(redis_up,service)", + "hide": 0, + "includeAll": false, + "multi": false, + "name": "cluster", + "options": [], + "query": { + "query": "label_values(redis_up,service)", + "refId": "PrometheusVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "current": { + "selected": true, + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "prometheus", + "uid": "${Datasource}" + }, + "definition": "label_values(redis_up{service=~\"$cluster\"},pod)", + "hide": 0, + "includeAll": true, + "multi": true, + "name": "instance", + "options": [], + "query": { + "query": "label_values(redis_up{service=~\"$cluster\"},pod)", + "refId": "PrometheusVariableQueryEditor-VariableQuery" + }, + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + } + ] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "browser", + "title": "Redis", + "uid": "4GFbkOsZkss", + "version": 2, + "weekStart": "" +} diff --git a/dashboards/dotdc/k8s-system-coredns.json b/dashboards/dotdc/k8s-system-coredns.json new file mode 100644 index 00000000..3d8dbc53 --- /dev/null +++ b/dashboards/dotdc/k8s-system-coredns.json @@ -0,0 +1,1558 @@ +{ + "__inputs": [ + { + "name": "DS_PROMETHEUS", + "label": "Prometheus", + "description": "", + "type": "datasource", + "pluginId": "prometheus", + "pluginName": "Prometheus" + } + ], + "__elements": [], + "__requires": [ + { + "type": "grafana", + "id": "grafana", + "name": "Grafana", + "version": "8.4.4" + }, + { + "type": "datasource", + "id": "prometheus", + "name": "Prometheus", + "version": "5.0.0" + }, + { + "type": "panel", + "id": "timeseries", + "name": "Time series", + "version": "" + }, + { + "type": "panel", + "id": "stat", + "name": "Stat", + "version": "" + } + ], + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "target": { + "limit": 100, + "matchAny": false, + "tags": [], + "type": "dashboard" + }, + "type": "dashboard" + } + ] + }, + "description": "This is a modern CoreDNS dashboard for your Kubernetes cluster(s). Made for kube-prometheus-stack and take advantage of the latest Grafana features. GitHub repository: https://github.com/dotdc/grafana-dashboards-kubernetes", + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 1, + "links": [], + "liveNow": false, + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "mappings": [ + { + "options": { + "0": { + "text": "DOWN" + }, + "1": { + "text": "UP" + } + }, + "type": "value" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "red", + "value": null + }, + { + "color": "green", + "value": 1 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 25, + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "vertical", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "value_and_name" + }, + "pluginVersion": "10.0.1", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "exemplar": true, + "expr": "up{job=\"coredns\", instance=~\"$instance\"}", + "interval": "", + "legendFormat": "{{ instance }}", + "refId": "A" + } + ], + "title": "CoreDNS - Health Status", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 25, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "smooth", + "lineWidth": 2, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 2, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 3 + }, + "id": 19, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "8.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "exemplar": true, + "expr": "rate(process_cpu_seconds_total{job=\"coredns\", instance=~\"$instance\"}[$__rate_interval])", + "interval": "$resolution", + "legendFormat": "{{ instance }}", + "refId": "A" + } + ], + "title": "CoreDNS - CPU Usage by instance", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 25, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "smooth", + "lineWidth": 2, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 3 + }, + "id": 21, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "8.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "exemplar": true, + "expr": "process_resident_memory_bytes{job=\"coredns\", instance=~\"$instance\"}", + "interval": "", + "legendFormat": "{{ instance }}", + "refId": "A" + } + ], + "title": "CoreDNS - Memory Usage by instance", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 25, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "smooth", + "lineWidth": 2, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 11 + }, + "id": 9, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "8.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "exemplar": true, + "expr": "sum(rate(coredns_dns_requests_total{instance=~\"$instance\",proto=\"$protocol\"}[$__rate_interval]))", + "interval": "$resolution", + "legendFormat": "total $protocol requests", + "refId": "A" + } + ], + "title": "CoreDNS - Total DNS Requests ($protocol)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 25, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "smooth", + "lineWidth": 2, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 11 + }, + "id": 7, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "8.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "exemplar": true, + "expr": "sum(rate(coredns_dns_request_size_bytes_sum{instance=~\"$instance\",proto=\"$protocol\"}[$__rate_interval])) by (proto) / sum(rate(coredns_dns_request_size_bytes_count{instance=~\"$instance\",proto=\"$protocol\"}[$__rate_interval])) by (proto)", + "interval": "$resolution", + "legendFormat": "average $protocol packet size", + "refId": "A" + } + ], + "title": "CoreDNS - Average Packet Size ($protocol)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 25, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "smooth", + "lineWidth": 2, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 19 + }, + "id": 2, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "8.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "exemplar": true, + "expr": "sum(rate(coredns_dns_requests_total{instance=~\"$instance\"}[$__rate_interval])) by (type)", + "interval": "$resolution", + "legendFormat": "{{ type }}", + "refId": "A" + } + ], + "title": "CoreDNS - Requests by type", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 25, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "smooth", + "lineWidth": 2, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 19 + }, + "id": 4, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "8.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "exemplar": true, + "expr": "sum(rate(coredns_dns_responses_total{instance=~\"$instance\"}[$__rate_interval])) by (rcode)", + "interval": "$resolution", + "legendFormat": "{{ rcode }}", + "refId": "A" + } + ], + "title": "CoreDNS - Requests by return code", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 25, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "smooth", + "lineWidth": 2, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 27 + }, + "id": 23, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "8.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "exemplar": true, + "expr": "sum(rate(coredns_forward_requests_total[$__rate_interval]))", + "interval": "$resolution", + "legendFormat": "total forward requests", + "refId": "A" + } + ], + "title": "CoreDNS - Total Forward Requests", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 25, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "smooth", + "lineWidth": 2, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 27 + }, + "id": 13, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "8.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "exemplar": true, + "expr": "sum(rate(coredns_forward_responses_total{rcode=~\"SERVFAIL|REFUSED\"}[$__rate_interval])) by (rcode)", + "interval": "$resolution", + "legendFormat": "{{ rcode }}", + "refId": "A" + } + ], + "title": "CoreDNS - DNS Errors", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 25, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "smooth", + "lineWidth": 2, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 35 + }, + "id": 17, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "8.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "exemplar": true, + "expr": "sum(rate(coredns_cache_hits_total{instance=~\"$instance\"}[$__rate_interval])) by (type)", + "interval": "$resolution", + "legendFormat": "{{ type }}", + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "exemplar": true, + "expr": "sum(rate(coredns_cache_misses_total{instance=~\"$instance\"}[$__rate_interval])) by (type)", + "interval": "$resolution", + "legendFormat": "misses", + "refId": "B" + } + ], + "title": "CoreDNS - Cache Hits / Misses", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 25, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "smooth", + "lineWidth": 2, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 35 + }, + "id": 15, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "8.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "exemplar": true, + "expr": "sum(coredns_cache_entries) by (type)", + "interval": "", + "legendFormat": "{{ type }}", + "refId": "A" + } + ], + "title": "CoreDNS - Cache Size", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 43 + }, + "id": 27, + "options": { + "calculate": false, + "cellGap": 1, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdYlBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "show": true, + "yHistogram": false + }, + "yAxis": { + "axisPlacement": "left", + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "10.0.1", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "sum(increase(coredns_dns_request_duration_seconds_bucket{instance=~\"$instance\"}[$__rate_interval])) by (le)", + "format": "heatmap", + "legendFormat": "{{le}}", + "range": true, + "refId": "A" + } + ], + "title": "CoreDNS - DNS request duration", + "type": "heatmap" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 43 + }, + "id": 30, + "options": { + "calculate": false, + "cellGap": 1, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdYlBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "show": true, + "yHistogram": false + }, + "yAxis": { + "axisPlacement": "left", + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "10.0.1", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "sum(increase(coredns_forward_request_duration_seconds_bucket{instance=~\"$instance\"}[$__rate_interval])) by (le)", + "format": "heatmap", + "legendFormat": "{{le}}", + "range": true, + "refId": "A" + } + ], + "title": "CoreDNS - Forward request duration", + "type": "heatmap" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 53 + }, + "id": 28, + "options": { + "calculate": false, + "cellGap": 1, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdYlBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "show": true, + "yHistogram": false + }, + "yAxis": { + "axisPlacement": "left", + "reverse": false, + "unit": "decbytes" + } + }, + "pluginVersion": "10.0.1", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "sum(increase(coredns_dns_request_size_bytes_bucket{instance=~\"$instance\", le!=\"0\"}[$__rate_interval])) by (le)", + "format": "heatmap", + "legendFormat": "{{le}}", + "range": true, + "refId": "A" + } + ], + "title": "CoreDNS - DNS request size", + "type": "heatmap" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 53 + }, + "id": 29, + "options": { + "calculate": false, + "cellGap": 1, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdYlBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "show": true, + "yHistogram": false + }, + "yAxis": { + "axisPlacement": "left", + "reverse": false, + "unit": "decbytes" + } + }, + "pluginVersion": "10.0.1", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "sum(increase(coredns_dns_response_size_bytes_bucket{instance=~\"$instance\", le!=\"0\"}[$__rate_interval])) by (le)", + "format": "heatmap", + "legendFormat": "{{le}}", + "range": true, + "refId": "A" + } + ], + "title": "CoreDNS - DNS response size", + "type": "heatmap" + } + ], + "refresh": "30s", + "schemaVersion": 38, + "style": "dark", + "tags": [ + "Kubernetes", + "Prometheus" + ], + "templating": { + "list": [ + { + "current": { + "selected": false, + "text": "Prometheus", + "value": "Prometheus" + }, + "hide": 0, + "includeAll": false, + "multi": false, + "name": "datasource", + "options": [], + "query": "prometheus", + "queryValue": "", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + }, + { + "current": { + "selected": false, + "text": "All", + "value": "$__all" + }, + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "definition": "label_values(up{job=\"coredns\"}, instance)", + "hide": 0, + "includeAll": true, + "label": "", + "multi": false, + "name": "instance", + "options": [], + "query": { + "query": "label_values(up{job=\"coredns\"}, instance)", + "refId": "StandardVariableQuery" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": "udp,tcp", + "current": { + "selected": false, + "text": "udp", + "value": "udp" + }, + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "definition": "label_values(coredns_dns_requests_total, proto)", + "hide": 0, + "includeAll": false, + "label": "", + "multi": false, + "name": "protocol", + "options": [], + "query": { + "query": "label_values(coredns_dns_requests_total, proto)", + "refId": "StandardVariableQuery" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "current": { + "selected": true, + "text": "30s", + "value": "30s" + }, + "hide": 0, + "includeAll": false, + "multi": false, + "name": "resolution", + "options": [ + { + "selected": false, + "text": "1s", + "value": "1s" + }, + { + "selected": false, + "text": "15s", + "value": "15s" + }, + { + "selected": true, + "text": "30s", + "value": "30s" + }, + { + "selected": false, + "text": "1m", + "value": "1m" + }, + { + "selected": false, + "text": "3m", + "value": "3m" + }, + { + "selected": false, + "text": "5m", + "value": "5m" + } + ], + "query": "1s, 15s, 30s, 1m, 3m, 5m", + "queryValue": "", + "skipUrlSync": false, + "type": "custom" + } + ] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "Kubernetes / System / CoreDNS", + "uid": "k8s_system_coredns", + "version": 13, + "weekStart": "" +} diff --git a/dashboards/dotdc/k8s-views-global.json b/dashboards/dotdc/k8s-views-global.json new file mode 100644 index 00000000..d0ec2980 --- /dev/null +++ b/dashboards/dotdc/k8s-views-global.json @@ -0,0 +1,2943 @@ +{ + "__inputs": [ + { + "name": "DS_PROMETHEUS", + "label": "Prometheus", + "description": "", + "type": "datasource", + "pluginId": "prometheus", + "pluginName": "Prometheus" + } + ], + "__elements": [], + "__requires": [ + { + "type": "grafana", + "id": "grafana", + "name": "Grafana", + "version": "8.3.4" + }, + { + "type": "datasource", + "id": "prometheus", + "name": "Prometheus", + "version": "5.0.0" + }, + { + "type": "panel", + "id": "timeseries", + "name": "Time series", + "version": "" + }, + { + "type": "panel", + "id": "stat", + "name": "Stat", + "version": "" + }, + { + "type": "panel", + "id": "gauge", + "name": "Gauge", + "version": "" + } + ], + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "target": { + "limit": 100, + "matchAny": false, + "tags": [], + "type": "dashboard" + }, + "type": "dashboard" + } + ] + }, + "description": "This is a modern 'Global View' dashboard for your Kubernetes cluster(s). Made for kube-prometheus-stack and take advantage of the latest Grafana features. GitHub repository: https://github.com/dotdc/grafana-dashboards-kubernetes", + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 1, + "links": [], + "liveNow": false, + "panels": [ + { + "collapsed": false, + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 67, + "panels": [], + "title": "Overview", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "continuous-GrYlRd" + }, + "mappings": [], + "max": 1, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 6, + "x": 0, + "y": 1 + }, + "id": 77, + "options": { + "displayMode": "lcd", + "minVizHeight": 10, + "minVizWidth": 0, + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showUnfilled": true, + "valueMode": "color" + }, + "pluginVersion": "10.0.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "exemplar": true, + "expr": "avg(1-rate(node_cpu_seconds_total{mode=\"idle\"}[$__rate_interval]))", + "interval": "", + "legendFormat": "Real", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "sum(kube_pod_container_resource_requests{resource=\"cpu\"}) / sum(machine_cpu_cores)", + "hide": false, + "legendFormat": "Requests", + "range": true, + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "sum(kube_pod_container_resource_limits{resource=\"cpu\"}) / sum(machine_cpu_cores)", + "hide": false, + "legendFormat": "Limits", + "range": true, + "refId": "C" + } + ], + "title": "Global CPU Usage", + "type": "bargauge" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "continuous-GrYlRd" + }, + "decimals": 2, + "mappings": [], + "max": 1, + "min": 0, + "thresholds": { + "mode": "percentage", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 6, + "x": 6, + "y": 1 + }, + "id": 78, + "options": { + "displayMode": "lcd", + "minVizHeight": 10, + "minVizWidth": 0, + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showUnfilled": true, + "text": {}, + "valueMode": "color" + }, + "pluginVersion": "10.0.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(node_memory_MemTotal_bytes - node_memory_MemAvailable_bytes) / sum(node_memory_MemTotal_bytes)", + "interval": "", + "legendFormat": "Real", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "sum(kube_pod_container_resource_requests{resource=\"memory\"}) / sum(machine_memory_bytes)", + "hide": false, + "legendFormat": "Requests", + "range": true, + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "sum(kube_pod_container_resource_limits{resource=\"memory\"}) / sum(machine_memory_bytes)", + "hide": false, + "legendFormat": "Limits", + "range": true, + "refId": "C" + } + ], + "title": "Global RAM Usage", + "type": "bargauge" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "mappings": [], + "noValue": "0", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "blue", + "value": null + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 2, + "x": 12, + "y": 1 + }, + "id": 63, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "last" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "value" + }, + "pluginVersion": "10.0.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "exemplar": true, + "expr": "count(count by (node) (kube_node_info))", + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "title": "Nodes", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 25, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "smooth", + "lineWidth": 2, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 12, + "w": 10, + "x": 14, + "y": 1 + }, + "id": 52, + "options": { + "legend": { + "calcs": [ + "min", + "max", + "mean" + ], + "displayMode": "table", + "placement": "right", + "showLegend": true, + "sortBy": "Max", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "8.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "exemplar": true, + "expr": "sum(kube_namespace_labels)", + "interval": "", + "legendFormat": "Namespaces", + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "sum(kube_pod_container_status_running)", + "interval": "", + "legendFormat": "Running Containers", + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "sum(kube_pod_status_phase{phase=\"Running\"})", + "interval": "", + "legendFormat": "Running Pods", + "refId": "O" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "sum(kube_service_info)", + "interval": "", + "legendFormat": "Services", + "refId": "C" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "sum(kube_endpoint_info)", + "interval": "", + "legendFormat": "Endpoints", + "refId": "D" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "sum(kube_ingress_info)", + "interval": "", + "legendFormat": "Ingresses", + "refId": "E" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "sum(kube_deployment_labels)", + "interval": "", + "legendFormat": "Deployments", + "refId": "F" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "sum(kube_statefulset_labels)", + "interval": "", + "legendFormat": "Statefulsets", + "refId": "G" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "sum(kube_daemonset_labels)", + "interval": "", + "legendFormat": "Daemonsets", + "refId": "H" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "sum(kube_persistentvolumeclaim_info)", + "interval": "", + "legendFormat": "Persistent Volume Claims", + "refId": "I" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "sum(kube_hpa_labels)", + "interval": "", + "legendFormat": "Horizontal Pod Autoscalers", + "refId": "J" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "sum(kube_configmap_info)", + "interval": "", + "legendFormat": "Configmaps", + "refId": "K" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "sum(kube_secret_info)", + "interval": "", + "legendFormat": "Secrets", + "refId": "L" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "sum(kube_networkpolicy_labels)", + "interval": "", + "legendFormat": "Network Policies", + "refId": "M" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "exemplar": true, + "expr": "count(count by (node) (kube_node_info))", + "hide": false, + "interval": "", + "legendFormat": "Nodes", + "refId": "N" + } + ], + "title": "Kubernetes Resource Count", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "mappings": [], + "noValue": "0", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "blue", + "value": null + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 2, + "x": 12, + "y": 5 + }, + "id": 59, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "last" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "value" + }, + "pluginVersion": "10.0.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "count(kube_namespace_created)", + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "title": "Namespaces", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "mappings": [], + "noValue": "0", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "rgb(255, 255, 255)", + "value": null + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 6, + "x": 0, + "y": 9 + }, + "id": 37, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "center", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "10.0.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(1-rate(node_cpu_seconds_total{mode=\"idle\"}[$__rate_interval]))", + "interval": "", + "legendFormat": "Real", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "sum(kube_pod_container_resource_requests{resource=\"cpu\"})", + "hide": false, + "legendFormat": "Requests", + "range": true, + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "sum(kube_pod_container_resource_limits{resource=\"cpu\"})", + "hide": false, + "legendFormat": "Limits", + "range": true, + "refId": "C" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "sum(machine_cpu_cores)", + "hide": false, + "legendFormat": "Total", + "range": true, + "refId": "D" + } + ], + "title": "CPU Usage", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "mappings": [], + "noValue": "0", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "rgb(255, 255, 255)", + "value": null + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 6, + "x": 6, + "y": 9 + }, + "id": 39, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "10.0.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(node_memory_MemTotal_bytes - node_memory_MemAvailable_bytes)", + "interval": "", + "legendFormat": "Real", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "sum(kube_pod_container_resource_requests{resource=\"memory\"})", + "hide": false, + "legendFormat": "Requests", + "range": true, + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "sum(kube_pod_container_resource_limits{resource=\"memory\"})", + "hide": false, + "legendFormat": "Limits", + "range": true, + "refId": "C" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "sum(machine_memory_bytes)", + "hide": false, + "legendFormat": "Total", + "range": true, + "refId": "D" + } + ], + "title": "RAM Usage", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "mappings": [], + "noValue": "0", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "blue", + "value": null + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 2, + "x": 12, + "y": 9 + }, + "id": 62, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "last" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "value" + }, + "pluginVersion": "10.0.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "sum(kube_pod_status_phase{phase=\"Running\"})", + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "title": "Running Pods", + "type": "stat" + }, + { + "collapsed": false, + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 13 + }, + "id": 71, + "panels": [], + "title": "Resources", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "continuous-GrYlRd", + "seriesBy": "last" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "CPU %", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "scheme", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "smooth", + "lineStyle": { + "fill": "solid" + }, + "lineWidth": 2, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 2, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "yellow", + "value": 0.5 + }, + { + "color": "red", + "value": 0.7 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 14 + }, + "id": 72, + "options": { + "legend": { + "calcs": [], + "displayMode": "hidden", + "placement": "right", + "showLegend": false + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "8.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "exemplar": true, + "expr": "avg(1-rate(node_cpu_seconds_total{mode=\"idle\"}[$__rate_interval]))", + "interval": "$resolution", + "legendFormat": "CPU usage in %", + "refId": "A" + } + ], + "title": "Cluster CPU Utilization", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "continuous-GrYlRd" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "MEMORY", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "scheme", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "smooth", + "lineWidth": 2, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "#EAB839", + "value": 0.5 + }, + { + "color": "red", + "value": 0.7 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 14 + }, + "id": 55, + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "hidden", + "placement": "right", + "showLegend": false + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "8.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(node_memory_MemTotal_bytes - node_memory_MemAvailable_bytes) / sum(node_memory_MemTotal_bytes)", + "interval": "$resolution", + "legendFormat": "Memory usage in %", + "range": true, + "refId": "A" + } + ], + "title": "Cluster Memory Utilization", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "CPU CORES", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 25, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "smooth", + "lineStyle": { + "fill": "solid" + }, + "lineWidth": 2, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 2, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 22 + }, + "id": 46, + "options": { + "legend": { + "calcs": [ + "min", + "max", + "mean" + ], + "displayMode": "table", + "placement": "right", + "showLegend": true, + "sortBy": "Max", + "sortDesc": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "8.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "exemplar": true, + "expr": "sum(rate(container_cpu_usage_seconds_total{image!=\"\"}[$__rate_interval])) by (namespace)", + "interval": "$resolution", + "legendFormat": "{{ namespace }}", + "refId": "A" + } + ], + "title": "CPU Utilization by namespace", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 25, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "smooth", + "lineWidth": 2, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 22 + }, + "id": 50, + "options": { + "legend": { + "calcs": [ + "min", + "max", + "mean" + ], + "displayMode": "table", + "placement": "right", + "showLegend": true, + "sortBy": "Max", + "sortDesc": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "8.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "exemplar": true, + "expr": "sum(container_memory_working_set_bytes{image!=\"\"}) by (namespace)", + "interval": "$resolution", + "legendFormat": "{{ namespace }}", + "refId": "A" + } + ], + "title": "Memory Utilization by namespace", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "CPU %", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 25, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "smooth", + "lineWidth": 2, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 2, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 30 + }, + "id": 54, + "options": { + "legend": { + "calcs": [ + "min", + "max", + "mean" + ], + "displayMode": "table", + "placement": "right", + "showLegend": true, + "sortBy": "Max", + "sortDesc": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "8.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "exemplar": true, + "expr": "avg(1-rate(node_cpu_seconds_total{mode=\"idle\"}[$__rate_interval])) by (instance)", + "interval": "$resolution", + "legendFormat": "{{ node }}", + "refId": "A" + } + ], + "title": "CPU Utilization by instance", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "MEMORY", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 25, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "smooth", + "lineWidth": 2, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 30 + }, + "id": 73, + "options": { + "legend": { + "calcs": [ + "min", + "max", + "mean" + ], + "displayMode": "table", + "placement": "right", + "showLegend": true, + "sortBy": "Max", + "sortDesc": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "8.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(node_memory_MemTotal_bytes - node_memory_MemAvailable_bytes) by (instance)", + "interval": "$resolution", + "legendFormat": "{{ node}}", + "range": true, + "refId": "A" + } + ], + "title": "Memory Utilization by instance", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "No data is generally a good thing here.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "SECONDS", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 25, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "smooth", + "lineStyle": { + "fill": "solid" + }, + "lineWidth": 2, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 2, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 38 + }, + "id": 82, + "options": { + "legend": { + "calcs": [ + "min", + "max", + "mean" + ], + "displayMode": "table", + "placement": "right", + "showLegend": true, + "sortBy": "Max", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "8.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(rate(container_cpu_cfs_throttled_seconds_total{image!=\"\"}[$__rate_interval])) by (namespace) > 0", + "interval": "$resolution", + "legendFormat": "{{ namespace }}", + "range": true, + "refId": "A" + } + ], + "title": "CPU Throttled seconds by namespace", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "No data is generally a good thing here.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "NB", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 25, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "smooth", + "lineStyle": { + "fill": "solid" + }, + "lineWidth": 2, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 2, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 38 + }, + "id": 83, + "options": { + "legend": { + "calcs": [ + "min", + "max", + "mean" + ], + "displayMode": "table", + "placement": "right", + "showLegend": true, + "sortBy": "Max", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "8.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(rate(node_cpu_core_throttles_total[$__rate_interval])) by (instance)", + "interval": "$resolution", + "legendFormat": "{{ instance }}", + "range": true, + "refId": "A" + } + ], + "title": "CPU Core Throttled by instance", + "type": "timeseries" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 46 + }, + "id": 86, + "panels": [], + "title": "Kubernetes", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 25, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "smooth", + "lineWidth": 2, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 47 + }, + "id": 84, + "options": { + "legend": { + "calcs": [ + "min", + "max", + "mean" + ], + "displayMode": "table", + "placement": "right", + "showLegend": true, + "sortBy": "Max", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "8.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(kube_pod_status_qos_class) by (qos_class)", + "interval": "", + "legendFormat": "{{ qos_class }} pods", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "sum(kube_pod_info)", + "hide": false, + "legendFormat": "Total pods", + "range": true, + "refId": "B" + } + ], + "title": "Kubernetes Pods QoS classes", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 25, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "smooth", + "lineWidth": 2, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 47 + }, + "id": 85, + "options": { + "legend": { + "calcs": [ + "min", + "max", + "mean" + ], + "displayMode": "table", + "placement": "right", + "showLegend": true, + "sortBy": "Max", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "8.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(kube_pod_status_reason) by (reason)", + "interval": "", + "legendFormat": "{{ reason }}", + "range": true, + "refId": "A" + } + ], + "title": "Kubernetes Pods Status Reason", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "No data is generally a good thing here.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "points", + "fillOpacity": 25, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "smooth", + "lineWidth": 2, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 56 + }, + "id": 87, + "options": { + "legend": { + "calcs": [ + "min", + "max", + "mean" + ], + "displayMode": "table", + "placement": "right", + "showLegend": true, + "sortBy": "Max", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "8.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(increase(container_oom_events_total[$__rate_interval])) by (namespace) > 0", + "interval": "", + "legendFormat": "{{ namespace }}", + "range": true, + "refId": "A" + } + ], + "title": "OOM Events by namespace", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "No data is generally a good thing here.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "points", + "fillOpacity": 25, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "smooth", + "lineWidth": 2, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 56 + }, + "id": 88, + "options": { + "legend": { + "calcs": [ + "min", + "max", + "mean" + ], + "displayMode": "table", + "placement": "right", + "showLegend": true, + "sortBy": "Max", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "8.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(increase(kube_pod_container_status_restarts_total[$__rate_interval])) by (namespace) > 0", + "interval": "", + "legendFormat": "{{ namespace }}", + "range": true, + "refId": "A" + } + ], + "title": "Container Restarts by namespace", + "type": "timeseries" + }, + { + "collapsed": false, + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 65 + }, + "id": 69, + "panels": [], + "title": "Network", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "Dropped noisy virtual devices for readability.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "BANDWIDTH", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 25, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "smooth", + "lineWidth": 2, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 66 + }, + "id": 44, + "options": { + "legend": { + "calcs": [], + "displayMode": "hidden", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "8.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(rate(node_network_receive_bytes_total{device!~\"lxc.*|veth.*\"}[$__rate_interval])) by (device)", + "interval": "$resolution", + "legendFormat": "Received : {{ device }}", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "exemplar": true, + "expr": "- sum(rate(node_network_transmit_bytes_total{device!~\"lxc.*|veth.*\"}[$__rate_interval])) by (device)", + "interval": "$resolution", + "legendFormat": "Transmitted : {{ device }}", + "range": true, + "refId": "B" + } + ], + "title": "Global Network Utilization by device", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "DROPPED PACKETS", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 25, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "smooth", + "lineWidth": 2, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 66 + }, + "id": 53, + "options": { + "legend": { + "calcs": [], + "displayMode": "hidden", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "8.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(rate(node_network_receive_drop_total[$__rate_interval]))", + "interval": "$resolution", + "legendFormat": "Packets dropped (receive)", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "exemplar": true, + "expr": "- sum(rate(node_network_transmit_drop_total[$__rate_interval]))", + "interval": "$resolution", + "legendFormat": "Packets dropped (transmit)", + "range": true, + "refId": "B" + } + ], + "title": "Network Saturation - Packets dropped", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "BANDWIDTH", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 25, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "smooth", + "lineWidth": 2, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 74 + }, + "id": 79, + "options": { + "legend": { + "calcs": [], + "displayMode": "hidden", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "8.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(rate(container_network_receive_bytes_total[$__rate_interval])) by (namespace)", + "interval": "$resolution", + "legendFormat": "Received : {{ namespace }}", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "- sum(rate(container_network_transmit_bytes_total[$__rate_interval])) by (namespace)", + "hide": false, + "interval": "$resolution", + "legendFormat": "Transmitted : {{ namespace }}", + "range": true, + "refId": "B" + } + ], + "title": "Network Received by namespace", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "BANDWIDTH", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 25, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "smooth", + "lineWidth": 2, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 74 + }, + "id": 80, + "options": { + "legend": { + "calcs": [], + "displayMode": "hidden", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "8.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(rate(node_network_receive_bytes_total[$__rate_interval])) by (instance)", + "interval": "$resolution", + "legendFormat": "Received bytes in {{ instance }}", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "- sum(rate(node_network_transmit_bytes_total[$__rate_interval])) by (instance)", + "hide": false, + "interval": "$resolution", + "legendFormat": "Transmitted bytes in {{ instance }}", + "range": true, + "refId": "B" + } + ], + "title": "Total Network Received (with all virtual devices) by instance", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "Dropped noisy virtual devices for readability.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "BANDWIDTH", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 25, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "smooth", + "lineWidth": 2, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 82 + }, + "id": 56, + "options": { + "legend": { + "calcs": [], + "displayMode": "hidden", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "8.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(rate(node_network_receive_bytes_total{device!~\"lxc.*|veth.*|lo\"}[$__rate_interval])) by (instance)", + "interval": "$resolution", + "legendFormat": "Received bytes in {{ instance }}", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "- sum(rate(node_network_transmit_bytes_total{device!~\"lxc.*|veth.*|lo\"}[$__rate_interval])) by (instance)", + "hide": false, + "interval": "$resolution", + "legendFormat": "Transmitted bytes in {{ instance }}", + "range": true, + "refId": "B" + } + ], + "title": "Network Received (without loopback) by instance", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "Dropped noisy virtual devices for readability.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "BANDWIDTH", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 25, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "smooth", + "lineWidth": 2, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 82 + }, + "id": 81, + "options": { + "legend": { + "calcs": [], + "displayMode": "hidden", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "8.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(rate(node_network_receive_bytes_total{device=\"lo\"}[$__rate_interval])) by (instance)", + "interval": "$resolution", + "legendFormat": "Received bytes in {{ instance }}", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "- sum(rate(node_network_transmit_bytes_total{device=\"lo\"}[$__rate_interval])) by (instance)", + "hide": false, + "interval": "$resolution", + "legendFormat": "Transmitted bytes in {{ instance }}", + "range": true, + "refId": "B" + } + ], + "title": "Network Received (loopback only) by instance", + "type": "timeseries" + } + ], + "refresh": "30s", + "schemaVersion": 38, + "style": "dark", + "tags": [ + "Kubernetes", + "Prometheus" + ], + "templating": { + "list": [ + { + "current": { + "selected": false, + "text": "Prometheus", + "value": "Prometheus" + }, + "hide": 0, + "includeAll": false, + "multi": false, + "name": "datasource", + "options": [], + "query": "prometheus", + "queryValue": "", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + }, + { + "current": { + "selected": true, + "text": "30s", + "value": "30s" + }, + "hide": 0, + "includeAll": false, + "multi": false, + "name": "resolution", + "options": [ + { + "selected": false, + "text": "1s", + "value": "1s" + }, + { + "selected": false, + "text": "15s", + "value": "15s" + }, + { + "selected": true, + "text": "30s", + "value": "30s" + }, + { + "selected": false, + "text": "1m", + "value": "1m" + }, + { + "selected": false, + "text": "3m", + "value": "3m" + }, + { + "selected": false, + "text": "5m", + "value": "5m" + } + ], + "query": "1s, 15s, 30s, 1m, 3m, 5m", + "queryValue": "", + "skipUrlSync": false, + "type": "custom" + } + ] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "Kubernetes / Views / Global", + "uid": "k8s_views_global", + "version": 31, + "weekStart": "" +} diff --git a/dashboards/dotdc/k8s-views-namespaces.json b/dashboards/dotdc/k8s-views-namespaces.json new file mode 100644 index 00000000..06ff0b9a --- /dev/null +++ b/dashboards/dotdc/k8s-views-namespaces.json @@ -0,0 +1,2260 @@ +{ + "__inputs": [ + { + "name": "DS_PROMETHEUS", + "label": "Prometheus", + "description": "", + "type": "datasource", + "pluginId": "prometheus", + "pluginName": "Prometheus" + } + ], + "__elements": [], + "__requires": [ + { + "type": "grafana", + "id": "grafana", + "name": "Grafana", + "version": "8.3.4" + }, + { + "type": "datasource", + "id": "prometheus", + "name": "Prometheus", + "version": "5.0.0" + }, + { + "type": "panel", + "id": "timeseries", + "name": "Time series", + "version": "" + }, + { + "type": "panel", + "id": "stat", + "name": "Stat", + "version": "" + } + ], + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "target": { + "limit": 100, + "matchAny": false, + "tags": [], + "type": "dashboard" + }, + "type": "dashboard" + } + ] + }, + "description": "This is a modern 'Namespaces View' dashboard for your Kubernetes cluster(s). Made for kube-prometheus-stack and take advantage of the latest Grafana features. GitHub repository: https://github.com/dotdc/grafana-dashboards-kubernetes", + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 1, + "links": [], + "liveNow": false, + "panels": [ + { + "collapsed": false, + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 38, + "panels": [], + "title": "Overview", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "decimals": 2, + "mappings": [], + "max": 1, + "min": 0, + "thresholds": { + "mode": "percentage", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "orange", + "value": 50 + }, + { + "color": "red", + "value": 70 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 6, + "x": 0, + "y": 1 + }, + "id": 46, + "options": { + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": true, + "text": {} + }, + "pluginVersion": "10.0.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "sum(rate(container_cpu_usage_seconds_total{namespace=~\"$namespace\", image!=\"\"}[$__rate_interval])) / sum(machine_cpu_cores)", + "instant": true, + "interval": "", + "legendFormat": "", + "range": false, + "refId": "A" + } + ], + "title": "Namespace(s) usage on total cluster CPU in %", + "type": "gauge" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "decimals": 2, + "mappings": [], + "max": 1, + "min": 0, + "thresholds": { + "mode": "percentage", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "orange", + "value": 50 + }, + { + "color": "red", + "value": 70 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 6, + "x": 6, + "y": 1 + }, + "id": 48, + "options": { + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": true, + "text": {} + }, + "pluginVersion": "10.0.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "exemplar": true, + "expr": "sum(container_memory_working_set_bytes{namespace=~\"$namespace\", image!=\"\"}) / sum(machine_memory_bytes)", + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "title": "Namespace(s) usage on total cluster RAM in %", + "type": "gauge" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 25, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "smooth", + "lineWidth": 2, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 11, + "w": 12, + "x": 12, + "y": 1 + }, + "id": 32, + "options": { + "legend": { + "calcs": [ + "min", + "max", + "mean" + ], + "displayMode": "table", + "placement": "right", + "showLegend": true, + "sortBy": "Max", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "8.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "sum(kube_pod_container_status_running{namespace=~\"$namespace\"})", + "interval": "", + "legendFormat": "Running Pods", + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "sum(kube_service_info{namespace=~\"$namespace\"})", + "interval": "", + "legendFormat": "Services", + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "sum(kube_ingress_info{namespace=~\"$namespace\"})", + "interval": "", + "legendFormat": "Ingresses", + "refId": "C" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "sum(kube_deployment_labels{namespace=~\"$namespace\"})", + "interval": "", + "legendFormat": "Deployments", + "refId": "D" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "sum(kube_statefulset_labels{namespace=~\"$namespace\"})", + "interval": "", + "legendFormat": "Statefulsets", + "refId": "E" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "sum(kube_daemonset_labels{namespace=~\"$namespace\"})", + "interval": "", + "legendFormat": "Daemonsets", + "refId": "F" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "sum(kube_persistentvolumeclaim_info{namespace=~\"$namespace\"})", + "interval": "", + "legendFormat": "Persistent Volume Claims", + "refId": "G" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "sum(kube_hpa_labels{namespace=~\"$namespace\"})", + "interval": "", + "legendFormat": "Horizontal Pod Autoscalers", + "refId": "H" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "sum(kube_configmap_info{namespace=~\"$namespace\"})", + "interval": "", + "legendFormat": "Configmaps", + "refId": "I" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "sum(kube_secret_info{namespace=~\"$namespace\"})", + "interval": "", + "legendFormat": "Secrets", + "refId": "J" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "sum(kube_networkpolicy_labels{namespace=~\"$namespace\"})", + "interval": "", + "legendFormat": "Network Policies", + "refId": "K" + } + ], + "title": "Kubernetes Resource Count", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "mappings": [], + "noValue": "0", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "rgb(255, 255, 255)", + "value": null + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 6, + "x": 0, + "y": 8 + }, + "id": 62, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "center", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "10.0.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(rate(container_cpu_usage_seconds_total{namespace=~\"$namespace\", image!=\"\"}[$__rate_interval]))", + "interval": "", + "legendFormat": "Real", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "sum(kube_pod_container_resource_requests{namespace=~\"$namespace\", resource=\"cpu\"})", + "hide": false, + "legendFormat": "Requests", + "range": true, + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "sum(kube_pod_container_resource_limits{namespace=~\"$namespace\", resource=\"cpu\"})", + "hide": false, + "legendFormat": "Limits", + "range": true, + "refId": "C" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "sum(machine_cpu_cores)", + "hide": false, + "legendFormat": "Cluster Total", + "range": true, + "refId": "D" + } + ], + "title": "Namespace(s) CPU Usage in cores", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "mappings": [], + "noValue": "0", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "rgb(255, 255, 255)", + "value": null + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 6, + "x": 6, + "y": 8 + }, + "id": 64, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "10.0.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(container_memory_working_set_bytes{namespace=~\"$namespace\", image!=\"\"})", + "interval": "", + "legendFormat": "Real", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "sum(kube_pod_container_resource_requests{namespace=~\"$namespace\", resource=\"memory\"})", + "hide": false, + "legendFormat": "Requests", + "range": true, + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "sum(kube_pod_container_resource_limits{namespace=~\"$namespace\", resource=\"memory\"})", + "hide": false, + "legendFormat": "Limits", + "range": true, + "refId": "C" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "sum(machine_memory_bytes)", + "hide": false, + "legendFormat": "Cluster Total", + "range": true, + "refId": "D" + } + ], + "title": "Namespace(s) RAM Usage in bytes", + "type": "stat" + }, + { + "collapsed": false, + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 12 + }, + "id": 40, + "panels": [], + "title": "Resources", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "CPU CORES", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 25, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "smooth", + "lineWidth": 2, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 13 + }, + "id": 29, + "options": { + "legend": { + "calcs": [], + "displayMode": "table", + "placement": "right", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "8.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(rate(container_cpu_usage_seconds_total{namespace=~\"$namespace\", image!=\"\", pod=~\"${created_by}.*\"}[$__rate_interval])) by (pod)", + "interval": "$resolution", + "legendFormat": "{{ pod }}", + "range": true, + "refId": "A" + } + ], + "title": "CPU usage by Pod", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 25, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "smooth", + "lineWidth": 2, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 13 + }, + "id": 30, + "options": { + "legend": { + "calcs": [], + "displayMode": "table", + "placement": "right", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "8.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(container_memory_working_set_bytes{namespace=~\"$namespace\", image!=\"\", pod=~\"${created_by}.*\"}) by (pod)", + "interval": "$resolution", + "legendFormat": "{{ pod }}", + "range": true, + "refId": "A" + } + ], + "title": "Memory usage by Pod", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "SECONDS", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 25, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "smooth", + "lineStyle": { + "fill": "solid" + }, + "lineWidth": 2, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 2, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 21 + }, + "id": 68, + "options": { + "legend": { + "calcs": [ + "min", + "max", + "mean" + ], + "displayMode": "table", + "placement": "right", + "showLegend": true, + "sortBy": "Max", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "8.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(rate(container_cpu_cfs_throttled_seconds_total{namespace=~\"$namespace\", image!=\"\", pod=~\"${created_by}.*\"}[$__rate_interval])) by (pod) > 0", + "interval": "$resolution", + "legendFormat": "{{ pod }}", + "range": true, + "refId": "A" + } + ], + "title": "CPU Throttled seconds by pod", + "type": "timeseries" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 29 + }, + "id": 73, + "panels": [], + "title": "Kubernetes", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 25, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "smooth", + "lineWidth": 2, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 30 + }, + "id": 70, + "options": { + "legend": { + "calcs": [ + "min", + "max", + "mean" + ], + "displayMode": "table", + "placement": "right", + "showLegend": true, + "sortBy": "Max", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "8.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(kube_pod_status_qos_class{namespace=~\"$namespace\"}) by (qos_class)", + "interval": "", + "legendFormat": "{{ qos_class }} pods", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "sum(kube_pod_info{namespace=~\"$namespace\"})", + "hide": false, + "legendFormat": "Total pods", + "range": true, + "refId": "B" + } + ], + "title": "Kubernetes Pods QoS classes", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 25, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "smooth", + "lineWidth": 2, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 30 + }, + "id": 72, + "options": { + "legend": { + "calcs": [ + "min", + "max", + "mean" + ], + "displayMode": "table", + "placement": "right", + "showLegend": true, + "sortBy": "Max", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "8.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(kube_pod_status_reason) by (reason)", + "interval": "", + "legendFormat": "{{ reason }}", + "range": true, + "refId": "A" + } + ], + "title": "Kubernetes Pods Status Reason", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "No data is generally a good thing here.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "points", + "fillOpacity": 25, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "smooth", + "lineWidth": 2, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 39 + }, + "id": 74, + "options": { + "legend": { + "calcs": [ + "min", + "max", + "mean" + ], + "displayMode": "table", + "placement": "right", + "showLegend": true, + "sortBy": "Max", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "8.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(increase(container_oom_events_total{namespace=~\"${namespace}\"}[$__rate_interval])) by (namespace, pod) > 0", + "interval": "", + "legendFormat": "namespace: {{ namespace }} - pod: {{ pod }}", + "range": true, + "refId": "A" + } + ], + "title": "OOM Events by namespace, pod", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "No data is generally a good thing here.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "points", + "fillOpacity": 25, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "smooth", + "lineWidth": 2, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 39 + }, + "id": 75, + "options": { + "legend": { + "calcs": [ + "min", + "max", + "mean" + ], + "displayMode": "table", + "placement": "right", + "showLegend": true, + "sortBy": "Max", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "8.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(increase(kube_pod_container_status_restarts_total{namespace=~\"${namespace}\"}[$__rate_interval])) by (namespace, pod) > 0", + "interval": "", + "legendFormat": "namespace: {{ namespace }} - pod: {{ pod }}", + "range": true, + "refId": "A" + } + ], + "title": "Container Restarts by namespace, pod", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 25, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "smooth", + "lineWidth": 2, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 0, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 48 + }, + "id": 5, + "options": { + "legend": { + "calcs": [], + "displayMode": "table", + "placement": "right", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "8.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "sum(kube_pod_container_status_ready{namespace=~\"$namespace\", pod=~\"${created_by}.*\"})", + "interval": "", + "legendFormat": "Ready", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "sum(kube_pod_container_status_running{namespace=~\"$namespace\", pod=~\"${created_by}.*\"})", + "interval": "", + "legendFormat": "Running", + "range": true, + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "sum(kube_pod_container_status_waiting{namespace=~\"$namespace\"})", + "interval": "", + "legendFormat": "Waiting", + "refId": "C" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "sum(kube_pod_container_status_restarts_total{namespace=~\"$namespace\"})", + "interval": "", + "legendFormat": "Restarts Total", + "refId": "D" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "sum(kube_pod_container_status_terminated{namespace=~\"$namespace\"})", + "interval": "", + "legendFormat": "Terminated", + "refId": "E" + } + ], + "title": "Nb of pods by state", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 25, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "smooth", + "lineWidth": 2, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 0, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 48 + }, + "id": 2, + "options": { + "legend": { + "calcs": [], + "displayMode": "hidden", + "placement": "right", + "showLegend": false + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "8.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "sum(kube_pod_container_info{namespace=~\"$namespace\", pod=~\"${created_by}.*\"}) by (pod)", + "interval": "", + "legendFormat": "{{ pod }}", + "range": true, + "refId": "A" + } + ], + "title": "Nb of containers by pod", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 25, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "smooth", + "lineWidth": 2, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 56 + }, + "id": 7, + "options": { + "legend": { + "calcs": [], + "displayMode": "table", + "placement": "right", + "showLegend": false + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "8.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(kube_deployment_status_replicas_available{namespace=~\"$namespace\"}) by (deployment)", + "interval": "", + "legendFormat": "{{ deployment }}", + "range": true, + "refId": "A" + } + ], + "title": "Replicas available by deployment", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 25, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "smooth", + "lineWidth": 2, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 56 + }, + "id": 8, + "options": { + "legend": { + "calcs": [], + "displayMode": "table", + "placement": "right", + "showLegend": false + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "8.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "sum(kube_deployment_status_replicas_unavailable{namespace=~\"$namespace\", pod=~\"${created_by}.*\"}) by (deployment)", + "interval": "", + "legendFormat": "{{ deployment }}", + "range": true, + "refId": "A" + } + ], + "title": "Replicas unavailable by deployment", + "type": "timeseries" + }, + { + "collapsed": false, + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 64 + }, + "id": 42, + "panels": [], + "title": "Kubernetes Storage", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 25, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "smooth", + "lineWidth": 2, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 2, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 65 + }, + "id": 65, + "options": { + "legend": { + "calcs": [], + "displayMode": "table", + "placement": "right", + "showLegend": false + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "8.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "exemplar": true, + "expr": "sum(kubelet_volume_stats_used_bytes{namespace=~\"$namespace\"}) by (persistentvolumeclaim) / sum(kubelet_volume_stats_capacity_bytes{namespace=~\"$namespace\"}) by (persistentvolumeclaim)", + "interval": "", + "legendFormat": "{{ persistentvolumeclaim }}", + "refId": "A" + } + ], + "title": "Persistent Volumes - Capacity and usage in %", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 25, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "smooth", + "lineWidth": 2, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 2, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 65 + }, + "id": 66, + "options": { + "legend": { + "calcs": [], + "displayMode": "table", + "placement": "right", + "showLegend": false + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "8.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "exemplar": true, + "expr": "sum(kubelet_volume_stats_used_bytes{namespace=~\"$namespace\"}) by (persistentvolumeclaim)", + "interval": "", + "legendFormat": "{{ persistentvolumeclaim }} - Used", + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "exemplar": true, + "expr": "sum(kubelet_volume_stats_capacity_bytes{namespace=~\"$namespace\"}) by (persistentvolumeclaim)", + "hide": false, + "interval": "", + "legendFormat": "{{ persistentvolumeclaim }} - Capacity", + "refId": "B" + } + ], + "title": "Persistent Volumes - Capacity and usage in bytes", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 25, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "smooth", + "lineWidth": 2, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 2, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 73 + }, + "id": 27, + "options": { + "legend": { + "calcs": [], + "displayMode": "table", + "placement": "right", + "showLegend": false + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "8.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "exemplar": true, + "expr": "1 - sum(kubelet_volume_stats_inodes_used{namespace=~\"$namespace\"}) by (persistentvolumeclaim) / sum(kubelet_volume_stats_inodes{namespace=~\"$namespace\"}) by (persistentvolumeclaim)", + "interval": "", + "legendFormat": "{{ persistentvolumeclaim }}", + "refId": "A" + } + ], + "title": "Persistent Volumes - Inodes", + "type": "timeseries" + } + ], + "refresh": "30s", + "schemaVersion": 38, + "style": "dark", + "tags": [ + "Kubernetes", + "Prometheus" + ], + "templating": { + "list": [ + { + "current": { + "selected": false, + "text": "Prometheus", + "value": "Prometheus" + }, + "hide": 0, + "includeAll": false, + "multi": false, + "name": "datasource", + "options": [], + "query": "prometheus", + "queryValue": "", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + }, + { + "current": { + "selected": true, + "text": [ + "monitoring" + ], + "value": [ + "monitoring" + ] + }, + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "definition": "label_values(kube_pod_info, namespace)", + "hide": 0, + "includeAll": true, + "multi": true, + "name": "namespace", + "options": [], + "query": { + "query": "label_values(kube_pod_info, namespace)", + "refId": "StandardVariableQuery" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "current": { + "selected": true, + "text": "30s", + "value": "30s" + }, + "hide": 0, + "includeAll": false, + "multi": false, + "name": "resolution", + "options": [ + { + "selected": false, + "text": "1s", + "value": "1s" + }, + { + "selected": false, + "text": "15s", + "value": "15s" + }, + { + "selected": true, + "text": "30s", + "value": "30s" + }, + { + "selected": false, + "text": "1m", + "value": "1m" + }, + { + "selected": false, + "text": "3m", + "value": "3m" + }, + { + "selected": false, + "text": "5m", + "value": "5m" + } + ], + "query": "1s, 15s, 30s, 1m, 3m, 5m", + "queryValue": "", + "skipUrlSync": false, + "type": "custom" + }, + { + "current": { + "selected": false, + "text": "All", + "value": "$__all" + }, + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "definition": "label_values(kube_pod_info{namespace=~\"$namespace\", container!=\"\"},created_by_name)", + "description": "Can be used to filter on a specific deployment, statefulset or deamonset (only relevant panels).", + "hide": 0, + "includeAll": true, + "multi": true, + "name": "created_by", + "options": [], + "query": { + "query": "label_values(kube_pod_info{namespace=~\"$namespace\", container!=\"\"},created_by_name)", + "refId": "PrometheusVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "type": "query" + } + ] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "Kubernetes / Views / Namespaces", + "uid": "k8s_views_ns", + "version": 27, + "weekStart": "" +} diff --git a/dashboards/dotdc/k8s-views-pods.json b/dashboards/dotdc/k8s-views-pods.json new file mode 100644 index 00000000..c441f49d --- /dev/null +++ b/dashboards/dotdc/k8s-views-pods.json @@ -0,0 +1,2594 @@ +{ + "__inputs": [ + { + "name": "DS_PROMETHEUS", + "label": "Prometheus", + "description": "", + "type": "datasource", + "pluginId": "prometheus", + "pluginName": "Prometheus" + } + ], + "__elements": [], + "__requires": [ + { + "type": "grafana", + "id": "grafana", + "name": "Grafana", + "version": "8.3.4" + }, + { + "type": "datasource", + "id": "prometheus", + "name": "Prometheus", + "version": "5.0.0" + }, + { + "type": "panel", + "id": "timeseries", + "name": "Time series", + "version": "" + }, + { + "type": "panel", + "id": "stat", + "name": "Stat", + "version": "" + }, + { + "type": "panel", + "id": "gauge", + "name": "Gauge", + "version": "" + }, + { + "type": "panel", + "id": "table", + "name": "Table", + "version": "" + } + ], + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "target": { + "limit": 100, + "matchAny": false, + "tags": [], + "type": "dashboard" + }, + "type": "dashboard" + } + ] + }, + "description": "This is a modern 'Pods View' dashboard for your Kubernetes cluster(s). Made for kube-prometheus-stack and take advantage of the latest Grafana features. GitHub repository: https://github.com/dotdc/grafana-dashboards-kubernetes", + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 1, + "links": [], + "liveNow": false, + "panels": [ + { + "collapsed": false, + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 43, + "panels": [], + "targets": [ + { + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "refId": "A" + } + ], + "title": "Information", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "rgb(255, 255, 255)", + "value": null + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 12, + "x": 0, + "y": 1 + }, + "id": 2, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "textMode": "name" + }, + "pluginVersion": "10.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "exemplar": false, + "expr": "kube_pod_info{namespace=\"$namespace\", pod=\"$pod\"}", + "instant": true, + "interval": "", + "legendFormat": "{{ created_by_kind }}: {{ created_by_name }}", + "refId": "A" + } + ], + "title": "Created by", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "links": [ + { + "title": "", + "url": "/d/k8s_views_nodes/kubernetes-views-nodes?var-datasource=${datasource}&var-node=${__data.fields.node}" + } + ], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "rgb(255, 255, 255)", + "value": null + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 6, + "x": 12, + "y": 1 + }, + "id": 33, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "textMode": "name" + }, + "pluginVersion": "10.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "exemplar": false, + "expr": "kube_pod_info{namespace=\"$namespace\", pod=\"$pod\"}", + "instant": true, + "interval": "", + "legendFormat": "{{ node }}", + "refId": "A" + } + ], + "title": "Running on", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "rgb(255, 255, 255)", + "value": null + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 6, + "x": 18, + "y": 1 + }, + "id": 41, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "textMode": "name" + }, + "pluginVersion": "10.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "exemplar": false, + "expr": "kube_pod_info{namespace=\"$namespace\", pod=\"$pod\"}", + "instant": true, + "interval": "", + "legendFormat": "{{ pod_ip }}", + "refId": "A" + } + ], + "title": "Pod IP", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "rgb(255, 255, 255)", + "value": null + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 5, + "x": 0, + "y": 3 + }, + "id": 52, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "textMode": "name" + }, + "pluginVersion": "10.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "kube_pod_info{namespace=\"$namespace\", pod=\"$pod\", priority_class!=\"\"}", + "format": "time_series", + "instant": true, + "interval": "", + "legendFormat": "{{ priority_class }}", + "range": false, + "refId": "A" + } + ], + "title": "Priority Class", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "none" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Burstable" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "red", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "BestEffort" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "orange", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 2, + "w": 7, + "x": 5, + "y": 3 + }, + "id": 53, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [], + "fields": "", + "values": false + }, + "textMode": "name" + }, + "pluginVersion": "10.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "kube_pod_status_qos_class{namespace=\"$namespace\", pod=\"$pod\"} > 0", + "instant": true, + "interval": "", + "legendFormat": "{{ qos_class }}", + "refId": "A" + } + ], + "title": "QOS Class", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "text", + "value": null + }, + { + "color": "red", + "value": 1 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 6, + "x": 12, + "y": 3 + }, + "id": 56, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [], + "fields": "", + "values": false + }, + "textMode": "name" + }, + "pluginVersion": "10.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "kube_pod_container_status_last_terminated_reason{namespace=\"$namespace\", pod=\"$pod\"}", + "instant": true, + "interval": "", + "legendFormat": "{{ reason }}", + "refId": "A" + } + ], + "title": "Last Terminated Reason", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "text", + "value": null + }, + { + "color": "red", + "value": 1 + }, + { + "color": "#EAB839", + "value": 2 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 6, + "x": 18, + "y": 3 + }, + "id": 57, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [], + "fields": "", + "values": true + }, + "textMode": "value" + }, + "pluginVersion": "10.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "kube_pod_container_status_last_terminated_exitcode{namespace=\"$namespace\", pod=\"$pod\"}", + "instant": true, + "interval": "", + "legendFormat": "__auto", + "range": false, + "refId": "A" + } + ], + "title": "Last Terminated Exit Code", + "type": "stat" + }, + { + "collapsed": false, + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 5 + }, + "id": 47, + "panels": [], + "targets": [ + { + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "refId": "A" + } + ], + "title": "Resources", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "blue", + "mode": "fixed" + }, + "decimals": 2, + "mappings": [], + "max": 1, + "min": 0, + "thresholds": { + "mode": "percentage", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "#EAB839", + "value": 60 + }, + { + "color": "red", + "value": 75 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 3, + "x": 0, + "y": 6 + }, + "id": 39, + "options": { + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "last" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": true + }, + "pluginVersion": "10.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "sum(rate(container_cpu_usage_seconds_total{namespace=\"$namespace\", pod=\"$pod\", image!=\"\"}[$__rate_interval])) / sum(kube_pod_container_resource_requests{namespace=\"$namespace\", pod=\"$pod\", resource=\"cpu\"})", + "instant": true, + "interval": "$resolution", + "legendFormat": "Requests", + "refId": "A" + } + ], + "title": "Total pod CPU Requests usage", + "type": "gauge" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "decimals": 2, + "mappings": [], + "max": 1, + "min": 0, + "thresholds": { + "mode": "percentage", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "#EAB839", + "value": 60 + }, + { + "color": "red", + "value": 75 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 3, + "x": 3, + "y": 6 + }, + "id": 48, + "options": { + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "last" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": true + }, + "pluginVersion": "10.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "sum(rate(container_cpu_usage_seconds_total{namespace=\"$namespace\", pod=\"$pod\", image!=\"\"}[$__rate_interval])) / sum(kube_pod_container_resource_limits{namespace=\"$namespace\", pod=\"$pod\", resource=\"cpu\"})", + "instant": true, + "interval": "$resolution", + "legendFormat": "Limits", + "refId": "A" + } + ], + "title": "Total pod CPU Limits usage", + "type": "gauge" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "blue", + "mode": "fixed" + }, + "decimals": 2, + "mappings": [], + "max": 1, + "min": 0, + "thresholds": { + "mode": "percentage", + "steps": [ + { + "color": "blue", + "value": null + }, + { + "color": "#EAB839", + "value": 80 + }, + { + "color": "red", + "value": 99 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 3, + "x": 6, + "y": 6 + }, + "id": 40, + "options": { + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "last" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": true + }, + "pluginVersion": "10.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "exemplar": false, + "expr": "sum(container_memory_working_set_bytes{namespace=\"$namespace\", pod=\"$pod\", image!=\"\"}) / sum(kube_pod_container_resource_requests{namespace=\"$namespace\", pod=\"$pod\", resource=\"memory\"})", + "instant": true, + "interval": "$resolution", + "legendFormat": "Requests", + "refId": "A" + } + ], + "title": "Total pod RAM Requests usage", + "type": "gauge" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "decimals": 2, + "mappings": [], + "max": 1, + "min": 0, + "thresholds": { + "mode": "percentage", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "#EAB839", + "value": 60 + }, + { + "color": "red", + "value": 75 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 3, + "x": 9, + "y": 6 + }, + "id": 49, + "options": { + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "last" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": true + }, + "pluginVersion": "10.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "exemplar": false, + "expr": "sum(container_memory_working_set_bytes{namespace=\"$namespace\", pod=\"$pod\", image!=\"\"}) / sum(kube_pod_container_resource_limits{namespace=\"$namespace\", pod=\"$pod\", resource=\"memory\"}) ", + "instant": true, + "interval": "$resolution", + "legendFormat": "Limits", + "refId": "B" + } + ], + "title": "Total pod RAM Limits usage", + "type": "gauge" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "custom": { + "align": "auto", + "cellOptions": { + "type": "auto" + }, + "filterable": false, + "inspect": false, + "minWidth": 100 + }, + "decimals": 4, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "blue", + "value": null + } + ] + }, + "unit": "none" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Memory Requests" + }, + "properties": [ + { + "id": "unit", + "value": "bytes" + }, + { + "id": "decimals", + "value": 2 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Memory Limits" + }, + "properties": [ + { + "id": "unit", + "value": "bytes" + }, + { + "id": "decimals", + "value": 2 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Memory Used" + }, + "properties": [ + { + "id": "unit", + "value": "bytes" + }, + { + "id": "decimals", + "value": 2 + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 6 + }, + "id": 38, + "options": { + "cellHeight": "sm", + "footer": { + "countRows": false, + "fields": "", + "reducer": [ + "sum" + ], + "show": false + }, + "showHeader": true, + "sortBy": [] + }, + "pluginVersion": "10.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "sum(kube_pod_container_resource_requests{namespace=\"$namespace\", pod=\"$pod\", resource=\"cpu\"}) by (container)", + "format": "table", + "instant": true, + "interval": "", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "sum(kube_pod_container_resource_limits{namespace=\"$namespace\", pod=\"$pod\", resource=\"cpu\"}) by (container)", + "format": "table", + "instant": true, + "interval": "", + "intervalFactor": 1, + "legendFormat": "", + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "sum(kube_pod_container_resource_requests{namespace=\"$namespace\", pod=\"$pod\", resource=\"memory\"}) by (container)", + "format": "table", + "instant": true, + "interval": "", + "legendFormat": "", + "refId": "C" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "sum(kube_pod_container_resource_limits{namespace=\"$namespace\", pod=\"$pod\", resource=\"memory\"}) by (container)", + "format": "table", + "instant": true, + "interval": "", + "legendFormat": "", + "refId": "D" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "sum(rate(container_cpu_usage_seconds_total{namespace=\"$namespace\", pod=\"$pod\", image!=\"\", container!=\"\"}[$__rate_interval])) by (container)", + "format": "table", + "hide": false, + "instant": true, + "legendFormat": "__auto", + "range": false, + "refId": "E" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "sum(container_memory_working_set_bytes{namespace=\"$namespace\", pod=\"$pod\", image!=\"\", container!=\"\"}) by (container)", + "format": "table", + "hide": false, + "instant": true, + "range": false, + "refId": "F" + } + ], + "title": "Resources by container", + "transformations": [ + { + "id": "seriesToColumns", + "options": { + "byField": "container" + } + }, + { + "id": "organize", + "options": { + "excludeByName": { + "Time": true, + "Time 1": true, + "Time 2": true, + "Time 4": true, + "__name__": true, + "__name__ 1": true, + "__name__ 2": true, + "__name__ 3": true, + "__name__ 4": true, + "container": false, + "endpoint": true, + "endpoint 2": true, + "endpoint 3": true, + "endpoint 4": true, + "instance": true, + "instance 2": true, + "instance 3": true, + "instance 4": true, + "job": true, + "job 2": true, + "job 3": true, + "job 4": true, + "namespace": true, + "namespace 2": true, + "namespace 3": true, + "namespace 4": true, + "node": true, + "node 2": true, + "node 3": true, + "node 4": true, + "pod": true, + "pod 2": true, + "pod 3": true, + "pod 4": true, + "resource 1": true, + "resource 2": true, + "resource 3": true, + "resource 4": true, + "service": true, + "service 2": true, + "service 3": true, + "service 4": true, + "uid 1": true, + "uid 2": true, + "uid 3": true, + "uid 4": true, + "unit 1": true, + "unit 2": true, + "unit 3": true, + "unit 4": true + }, + "indexByName": { + "Time 1": 7, + "Time 2": 8, + "Time 3": 9, + "Time 4": 10, + "Time 5": 11, + "Time 6": 12, + "Value #A": 2, + "Value #B": 3, + "Value #C": 5, + "Value #D": 6, + "Value #E": 1, + "Value #F": 4, + "container": 0 + }, + "renameByName": { + "Value #A": "CPU Requests", + "Value #B": "CPU Limits", + "Value #C": "Memory Requests", + "Value #D": "Memory Limits", + "Value #E": "CPU Used", + "Value #F": "Memory Used", + "container": "Container" + } + } + } + ], + "type": "table" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "Percent", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 25, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "smooth", + "lineWidth": 2, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "area" + } + }, + "mappings": [], + "max": 1, + "min": 0, + "thresholds": { + "mode": "percentage", + "steps": [ + { + "color": "red", + "value": null + }, + { + "color": "yellow", + "value": 20 + }, + { + "color": "green", + "value": 30 + }, + { + "color": "yellow", + "value": 70 + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 14 + }, + "id": 50, + "options": { + "legend": { + "calcs": [], + "displayMode": "table", + "placement": "right", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "8.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(rate(container_cpu_usage_seconds_total{namespace=\"$namespace\", pod=\"$pod\", image!=\"\"}[$__rate_interval])) by (container) / sum(kube_pod_container_resource_requests{namespace=\"$namespace\", pod=\"$pod\", resource=\"cpu\"}) by (container)", + "interval": "$resolution", + "legendFormat": "{{ container }} REQUESTS", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "sum(rate(container_cpu_usage_seconds_total{namespace=\"$namespace\", pod=\"$pod\", image!=\"\"}[$__rate_interval])) by (container) / sum(kube_pod_container_resource_limits{namespace=\"$namespace\", pod=\"$pod\", resource=\"cpu\"}) by (container)", + "hide": false, + "legendFormat": "{{ container }} LIMITS", + "range": true, + "refId": "B" + } + ], + "title": "CPU Usage / Requests & Limits by container", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "blue", + "mode": "thresholds" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "Percent", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 25, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "smooth", + "lineStyle": { + "fill": "solid" + }, + "lineWidth": 2, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "area" + } + }, + "mappings": [], + "max": 1, + "min": 0, + "thresholds": { + "mode": "percentage", + "steps": [ + { + "color": "red", + "value": null + }, + { + "color": "yellow", + "value": 20 + }, + { + "color": "green", + "value": 30 + }, + { + "color": "#EAB839", + "value": 70 + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 14 + }, + "id": 30, + "options": { + "legend": { + "calcs": [], + "displayMode": "table", + "placement": "right", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "8.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(container_memory_working_set_bytes{namespace=\"$namespace\", pod=\"$pod\", image!=\"\"}) by (container) / sum(kube_pod_container_resource_requests{namespace=\"$namespace\", pod=\"$pod\", resource=\"memory\"}) by (container)", + "interval": "", + "legendFormat": "{{ container }} REQUESTS", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "sum(container_memory_working_set_bytes{namespace=\"$namespace\", pod=\"$pod\", image!=\"\"}) by (container) / sum(kube_pod_container_resource_limits{namespace=\"$namespace\", pod=\"$pod\", resource=\"memory\"}) by (container)", + "hide": false, + "legendFormat": "{{ container }} LIMITS", + "range": true, + "refId": "B" + } + ], + "title": "Memory Usage / Requests & Limits by container", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "CPU Cores", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 25, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "smooth", + "lineWidth": 2, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 4, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "limit" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#F2495C", + "mode": "fixed" + } + }, + { + "id": "custom.fillOpacity", + "value": 0 + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 22 + }, + "id": 29, + "options": { + "legend": { + "calcs": [ + "min", + "max", + "mean" + ], + "displayMode": "table", + "placement": "right", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "8.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(rate(container_cpu_usage_seconds_total{namespace=\"$namespace\", pod=\"$pod\", image!=\"\", container!=\"\"}[$__rate_interval])) by (container)", + "interval": "$resolution", + "legendFormat": "{{ container }}", + "range": true, + "refId": "A" + } + ], + "title": "CPU Usage by container", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "Bytes", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 25, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "smooth", + "lineStyle": { + "fill": "solid" + }, + "lineWidth": 2, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 2, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 22 + }, + "id": 51, + "options": { + "legend": { + "calcs": [ + "min", + "max", + "mean" + ], + "displayMode": "table", + "placement": "right", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "8.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(container_memory_working_set_bytes{namespace=\"$namespace\", pod=\"$pod\", image!=\"\", container!=\"\"}) by (container)", + "interval": "", + "legendFormat": "{{ container }}", + "range": true, + "refId": "A" + } + ], + "title": "Memory Usage by container", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "SECONDS", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 25, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "smooth", + "lineStyle": { + "fill": "solid" + }, + "lineWidth": 2, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 2, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 30 + }, + "id": 59, + "options": { + "legend": { + "calcs": [ + "min", + "max", + "mean" + ], + "displayMode": "table", + "placement": "right", + "showLegend": true, + "sortBy": "Max", + "sortDesc": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "8.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(rate(container_cpu_cfs_throttled_seconds_total{namespace=~\"$namespace\", pod=\"$pod\", image!=\"\", container!=\"\"}[$__rate_interval])) by (container)", + "interval": "$resolution", + "legendFormat": "{{ container }}", + "range": true, + "refId": "A" + } + ], + "title": "CPU Throttled seconds by container", + "type": "timeseries" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 38 + }, + "id": 62, + "panels": [], + "title": "Kubernetes", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "blue", + "mode": "thresholds" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "Percent", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 25, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "smooth", + "lineStyle": { + "fill": "solid" + }, + "lineWidth": 2, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "area" + } + }, + "mappings": [], + "max": 1, + "min": 0, + "thresholds": { + "mode": "percentage", + "steps": [ + { + "color": "red", + "value": null + }, + { + "color": "yellow", + "value": 20 + }, + { + "color": "green", + "value": 30 + }, + { + "color": "#EAB839", + "value": 70 + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 39 + }, + "id": 60, + "options": { + "legend": { + "calcs": [], + "displayMode": "table", + "placement": "right", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "8.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(increase(container_oom_events_total{namespace=\"${namespace}\", pod=\"${pod}\", container!=\"\"}[$__rate_interval])) by (container)", + "interval": "", + "legendFormat": "{{ container }}", + "range": true, + "refId": "A" + } + ], + "title": "OOM Events by container", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "blue", + "mode": "thresholds" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "Percent", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 25, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "smooth", + "lineStyle": { + "fill": "solid" + }, + "lineWidth": 2, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "area" + } + }, + "mappings": [], + "max": 1, + "min": 0, + "thresholds": { + "mode": "percentage", + "steps": [ + { + "color": "red", + "value": null + }, + { + "color": "yellow", + "value": 20 + }, + { + "color": "green", + "value": 30 + }, + { + "color": "#EAB839", + "value": 70 + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 39 + }, + "id": 61, + "options": { + "legend": { + "calcs": [], + "displayMode": "table", + "placement": "right", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "8.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(increase(kube_pod_container_status_restarts_total{namespace=~\"${namespace}\", pod=\"${pod}\", container!=\"\"}[$__rate_interval])) by (container)", + "interval": "", + "legendFormat": "{{ container }}", + "range": true, + "refId": "A" + } + ], + "title": "Container Restarts by container", + "type": "timeseries" + }, + { + "collapsed": false, + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 47 + }, + "id": 45, + "panels": [], + "targets": [ + { + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "refId": "A" + } + ], + "title": "Network", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 25, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "smooth", + "lineWidth": 2, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 48 + }, + "id": 31, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "8.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "exemplar": true, + "expr": "sum(rate(container_network_receive_bytes_total{namespace=\"$namespace\", pod=\"$pod\"}[$__rate_interval]))", + "interval": "$resolution", + "legendFormat": "Received", + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "exemplar": true, + "expr": "- sum(rate(container_network_transmit_bytes_total{namespace=\"$namespace\", pod=\"$pod\"}[$__rate_interval]))", + "interval": "$resolution", + "legendFormat": "Transmitted", + "refId": "B" + } + ], + "title": "Network - Bandwidth", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 25, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "smooth", + "lineWidth": 2, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "pps" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 48 + }, + "id": 34, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "8.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "exemplar": true, + "expr": "sum(rate(container_network_receive_packets_total{namespace=\"$namespace\", pod=\"$pod\"}[$__rate_interval]))", + "interval": "$resolution", + "legendFormat": "Received", + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "exemplar": true, + "expr": "- sum(rate(container_network_transmit_packets_total{namespace=\"$namespace\", pod=\"$pod\"}[$__rate_interval]))", + "interval": "$resolution", + "legendFormat": "Transmitted", + "refId": "B" + } + ], + "title": "Network - Packets Rate", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 25, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "smooth", + "lineWidth": 2, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "pps" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 56 + }, + "id": 36, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "8.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "exemplar": true, + "expr": "sum(rate(container_network_receive_packets_dropped_total{namespace=\"$namespace\", pod=\"$pod\"}[$__rate_interval]))", + "interval": "$resolution", + "legendFormat": "Received", + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "exemplar": true, + "expr": "- sum(rate(container_network_transmit_packets_dropped_total{namespace=\"$namespace\", pod=\"$pod\"}[$__rate_interval]))", + "interval": "$resolution", + "legendFormat": "Transmitted", + "refId": "B" + } + ], + "title": "Network - Packets Dropped", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 25, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "smooth", + "lineWidth": 2, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "pps" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 56 + }, + "id": 37, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "8.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "exemplar": true, + "expr": "sum(rate(container_network_receive_errors_total{namespace=\"$namespace\", pod=\"$pod\"}[$__rate_interval]))", + "interval": "$resolution", + "legendFormat": "Received", + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "exemplar": true, + "expr": "- sum(rate(container_network_transmit_errors_total{namespace=\"$namespace\", pod=\"$pod\"}[$__rate_interval]))", + "interval": "$resolution", + "legendFormat": "Transmitted", + "refId": "B" + } + ], + "title": "Network - Errors", + "type": "timeseries" + } + ], + "refresh": "30s", + "schemaVersion": 38, + "style": "dark", + "tags": [ + "Kubernetes", + "Prometheus" + ], + "templating": { + "list": [ + { + "current": { + "selected": false, + "text": "Prometheus", + "value": "Prometheus" + }, + "hide": 0, + "includeAll": false, + "multi": false, + "name": "datasource", + "options": [], + "query": "prometheus", + "queryValue": "", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + }, + { + "current": { + "selected": false, + "text": "monitoring", + "value": "monitoring" + }, + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "definition": "label_values(kube_pod_info, namespace)", + "hide": 0, + "includeAll": false, + "multi": false, + "name": "namespace", + "options": [], + "query": { + "query": "label_values(kube_pod_info, namespace)", + "refId": "Prometheus-namespace-Variable-Query" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "current": { + "selected": false, + "text": "", + "value": "" + }, + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "definition": "label_values(kube_pod_info{namespace=\"$namespace\"}, pod)", + "hide": 0, + "includeAll": false, + "multi": false, + "name": "pod", + "options": [], + "query": { + "query": "label_values(kube_pod_info{namespace=\"$namespace\"}, pod)", + "refId": "Prometheus-pod-Variable-Query" + }, + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "current": { + "selected": true, + "text": "30s", + "value": "30s" + }, + "hide": 0, + "includeAll": false, + "multi": false, + "name": "resolution", + "options": [ + { + "selected": false, + "text": "1s", + "value": "1s" + }, + { + "selected": false, + "text": "15s", + "value": "15s" + }, + { + "selected": true, + "text": "30s", + "value": "30s" + }, + { + "selected": false, + "text": "1m", + "value": "1m" + }, + { + "selected": false, + "text": "3m", + "value": "3m" + }, + { + "selected": false, + "text": "5m", + "value": "5m" + } + ], + "query": "1s, 15s, 30s, 1m, 3m, 5m", + "queryValue": "", + "skipUrlSync": false, + "type": "custom" + } + ] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "Kubernetes / Views / Pods", + "uid": "k8s_views_pods", + "version": 22, + "weekStart": "" +} diff --git a/dashboards/ingress/controller-detail.json b/dashboards/ingress/controller-detail.json new file mode 100644 index 00000000..1f8cb2cf --- /dev/null +++ b/dashboards/ingress/controller-detail.json @@ -0,0 +1,10221 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": "-- Grafana --", + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "limit": 100, + "name": "Annotations & Alerts", + "showIn": 0, + "target": { + "limit": 100, + "matchAny": false, + "tags": [], + "type": "dashboard" + }, + "type": "dashboard" + } + ] + }, + "editable": false, + "fiscalYearStartMonth": 0, + "gnetId": null, + "graphTooltip": 1, + "iteration": 1643277965811, + "links": [], + "liveNow": false, + "panels": [ + { + "collapsed": true, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 219, + "panels": [ + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 12, + "x": 0, + "y": 1 + }, + "hiddenSeries": false, + "id": 225, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "rightSide": true, + "show": false, + "sort": null, + "sortDesc": null, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "lines": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": true, + "targets": [ + { + "expr": "sum(rate(container_cpu_usage_seconds_total{pod=~\"controller-$controller.*\", node=~\"$node\", namespace=\"d8-ingress-nginx\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A", + "step": 10 + }, + { + "expr": "sum(rate(container_cpu_usage_seconds_total{pod=~\"controller-$controller.*\", node=~\"$node\", namespace=\"d8-ingress-nginx\"}[$__rate_interval])\n) $cadvisor_by", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$cadvisor_legend_format", + "refId": "B", + "step": 10 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "CPU", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "cores", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 12, + "x": 12, + "y": 1 + }, + "hiddenSeries": false, + "id": 229, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "rightSide": true, + "show": false, + "sort": null, + "sortDesc": null, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "lines": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": true, + "targets": [ + { + "expr": "sum(\n rate(container_network_receive_bytes_total{pod=~\"controller-.*\", node=~\"$node\", namespace=\"d8-ingress-nginx\"}[$__rate_interval])\n) * 8", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A", + "step": 10 + }, + { + "expr": "sum(\n rate(container_network_receive_bytes_total{pod=~\"controller-$controller.*\", node=~\"$node\", namespace=\"d8-ingress-nginx\"}[$__rate_interval])\n) $cadvisor_by * 8", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$cadvisor_legend_format", + "refId": "B", + "step": 10 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Received Traffic", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bps", + "label": "bits / second", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 12, + "x": 0, + "y": 7 + }, + "hiddenSeries": false, + "id": 227, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "rightSide": true, + "show": false, + "sort": null, + "sortDesc": null, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "lines": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": true, + "targets": [ + { + "expr": "sum(\n container_memory_usage_bytes{pod=~\"controller-.*\", node=~\"$node\", namespace=\"d8-ingress-nginx\"}\n)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A", + "step": 10 + }, + { + "expr": "sum(\n container_memory_usage_bytes{pod=~\"controller-$controller.*\", node=~\"$node\", namespace=\"d8-ingress-nginx\"}\n) $cadvisor_by", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$cadvisor_legend_format", + "refId": "B", + "step": 10 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Memory", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "decbytes", + "label": "bytes", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 12, + "x": 12, + "y": 7 + }, + "hiddenSeries": false, + "id": 231, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "rightSide": true, + "show": false, + "sort": null, + "sortDesc": null, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "lines": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": true, + "targets": [ + { + "expr": "sum(\n rate(container_network_transmit_bytes_total{pod=~\"controller-.*\", node=~\"$node\", namespace=\"d8-ingress-nginx\"}[$__rate_interval])\n) * 8", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A", + "step": 10 + }, + { + "expr": "sum(\n rate(container_network_transmit_bytes_total{pod=~\"controller-.*\", node=~\"$node\", namespace=\"d8-ingress-nginx\"}[$__rate_interval])\n) $cadvisor_by * 8", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$cadvisor_legend_format", + "refId": "B", + "step": 10 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Transmit Traffic", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bps", + "label": "bits / second", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "title": "Container Resources (Content Kind filter is ignored)", + "type": "row" + }, + { + "collapsed": true, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 1 + }, + "id": 217, + "panels": [ + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "fill": 5, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 12, + "x": 0, + "y": 2 + }, + "height": "150", + "hiddenSeries": false, + "id": 221, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": true, + "show": false, + "sideWidth": 500, + "sort": null, + "sortDesc": null, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": true, + "targets": [ + { + "expr": "sum(nginx_ingress_controller_nginx_process_connections{state=\"active\", controller=~\"$controller-failover\", node=~\"$node\", job=\"nginx-ingress-controller\"})", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "B", + "step": 10 + }, + { + "expr": "sum(nginx_ingress_controller_nginx_process_connections{state=\"active\", controller=~\"$controller-failover\", node=~\"$node\", job=\"nginx-ingress-controller\"}) $protobuf_by", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$protobuf_legend_format", + "refId": "A", + "step": 10 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Active Connections", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "fill": 5, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 12, + "x": 12, + "y": 2 + }, + "height": "150", + "hiddenSeries": false, + "id": 223, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": true, + "show": false, + "sideWidth": 500, + "sort": null, + "sortDesc": null, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": true, + "targets": [ + { + "expr": "sum(rate(nginx_ingress_controller_nginx_process_connections_total{state=\"accepted\", controller=~\"$controller-failover\", node=~\"$node\", job=\"nginx-ingress-controller\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "B", + "step": 10 + }, + { + "expr": "sum(rate(nginx_ingress_controller_nginx_process_connections_total{state=\"accepted\", controller=~\"$controller-failover\", node=~\"$node\", job=\"nginx-ingress-controller\"}[$__rate_interval])) $protobuf_by", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$protobuf_legend_format", + "refId": "A", + "step": 10 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Accepted Connections", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "cps", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "title": "Direct Fallback (Content Kind filter is ignored)", + "type": "row" + }, + { + "collapsed": false, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 2 + }, + "id": 237, + "panels": [], + "title": "Controller (Content Kind filter is ignored)", + "type": "row" + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "fill": 5, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 16, + "x": 0, + "y": 3 + }, + "height": "150", + "hiddenSeries": false, + "id": 213, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": true, + "show": false, + "sideWidth": 500, + "sort": null, + "sortDesc": null, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": true, + "targets": [ + { + "expr": "sum(nginx_ingress_controller_nginx_process_connections{job=\"nginx-ingress-controller\", state=\"active\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\"})", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "B", + "step": 10 + }, + { + "expr": "sum(nginx_ingress_controller_nginx_process_connections{job=\"nginx-ingress-controller\", state=\"active\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\"}) $protobuf_by", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$protobuf_legend_format", + "refId": "A", + "step": 10 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Active Connections", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "fill": 5, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 8, + "x": 16, + "y": 3 + }, + "height": "150", + "hiddenSeries": false, + "id": 215, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": true, + "show": false, + "sideWidth": 500, + "sort": null, + "sortDesc": null, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": true, + "targets": [ + { + "expr": "", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "B", + "step": 10 + }, + { + "expr": "sum(nginx_ingress_controller_nginx_process_connections{job=\"nginx-ingress-controller\", state=\"active\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\"}) $protobuf_by\n/ scalar(sum(nginx_ingress_controller_nginx_process_connections{job=\"nginx-ingress-controller\", state=\"active\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\"}))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$protobuf_legend_format", + "refId": "A", + "step": 10 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Active Connections %", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "percentunit", + "label": "", + "logBase": 1, + "max": "1", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "fill": 5, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 16, + "x": 0, + "y": 8 + }, + "height": "150", + "hiddenSeries": false, + "id": 306, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": true, + "show": false, + "sideWidth": 500, + "sort": null, + "sortDesc": null, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "$$hashKey": "object:950", + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": true, + "targets": [ + { + "exemplar": true, + "expr": "sum(rate(ingress_nginx_detail_requests_total{job=\"nginx-ingress-controller\", controller=~\".*\", app=~\".*\", node=~\".*\", vhost=~\"_\"}[$__rate_interval]))", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "B", + "step": 10 + }, + { + "exemplar": true, + "expr": "sum(rate(ingress_nginx_detail_requests_total{job=\"nginx-ingress-controller\", controller=~\".*\", app=~\".*\", node=~\".*\", vhost=~\"_\"}[$__rate_interval])) by (controller)", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "A", + "step": 10 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Requests to Default Server", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:959", + "format": "short", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "$$hashKey": "object:960", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "fill": 5, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 8, + "x": 16, + "y": 8 + }, + "height": "150", + "hiddenSeries": false, + "id": 263, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": true, + "show": false, + "sideWidth": 500, + "sort": null, + "sortDesc": null, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "$$hashKey": "object:1211", + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": true, + "targets": [ + { + "expr": "", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "B", + "step": 10 + }, + { + "exemplar": true, + "expr": "sum(rate(ingress_nginx_detail_requests_total{job=\"nginx-ingress-controller\", controller=~\".*\", app=~\".*\", node=~\".*\", vhost=~\"_\"}[$__rate_interval])) by (controller)\n/ scalar(sum(rate(ingress_nginx_detail_requests_total{job=\"nginx-ingress-controller\", controller=~\".*\", app=~\".*\", node=~\".*\", vhost=~\"_\"}[$__rate_interval])))", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "A", + "step": 10 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Requests to Default Server %", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:1220", + "format": "percentunit", + "label": "", + "logBase": 1, + "max": "1", + "min": "0", + "show": true + }, + { + "$$hashKey": "object:1221", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "semi-dark-yellow", + "mode": "fixed" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "bars", + "fillOpacity": 100, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "stepAfter", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 16, + "x": 0, + "y": 13 + }, + "id": 233, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "hidden", + "placement": "right" + }, + "tooltip": { + "mode": "single" + } + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "exemplar": true, + "expr": "sum by (controller, node) (rate(nginx_ingress_controller_nginx_process_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\".*\", node=~\".*\"}[$__rate_interval])) / sum by (controller, node) (rate(nginx_ingress_controller_nginx_process_connections_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\".*\", node=~\".*\", state=\"handled\"}[$__rate_interval]))", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "{{ controller }} / {{ node }}", + "refId": "B", + "step": 10 + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Requests Handled by Nginx", + "type": "timeseries" + }, + { + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "yellow", + "mode": "fixed" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": -1, + "drawStyle": "bars", + "fillOpacity": 100, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 8, + "x": 16, + "y": 13 + }, + "id": 281, + "links": [], + "options": { + "legend": { + "calcs": [ + "lastNotNull", + "max", + "min" + ], + "displayMode": "hidden", + "placement": "bottom" + }, + "tooltip": { + "mode": "multi" + } + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "exemplar": true, + "expr": "sum by (controller, node) (increase(nginx_ingress_controller_success{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\"}[$__rate_interval]))", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "{{ controller }} / {{ node }}", + "refId": "A", + "step": 10 + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Config Reload Operations", + "type": "timeseries" + }, + { + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 11, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 12, + "x": 0, + "y": 18 + }, + "id": 235, + "links": [], + "options": { + "legend": { + "calcs": [ + "lastNotNull", + "max", + "min" + ], + "displayMode": "hidden", + "placement": "bottom" + }, + "tooltip": { + "mode": "none" + } + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "exemplar": true, + "expr": "rate(nginx_ingress_controller_nginx_process_cpu_seconds_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\"}[$__rate_interval])", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "{{ controller }} / {{ node }}", + "refId": "A", + "step": 10 + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Total CPU (Nginx Process)", + "type": "timeseries" + }, + { + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 11, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "decbytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 12, + "x": 12, + "y": 18 + }, + "id": 307, + "links": [], + "options": { + "legend": { + "calcs": [ + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "right" + }, + "tooltip": { + "mode": "multi" + } + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "exemplar": true, + "expr": "sum(nginx_ingress_controller_nginx_process_resident_memory_bytes{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\"})", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "resident", + "refId": "A", + "step": 10 + }, + { + "exemplar": true, + "expr": "sum(nginx_ingress_controller_nginx_process_virtual_memory_bytes{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\"})", + "hide": false, + "interval": "", + "legendFormat": "virtual", + "refId": "B" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Total Memory (Nginx Process)", + "type": "timeseries" + }, + { + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 11, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 12, + "x": 0, + "y": 23 + }, + "id": 308, + "links": [], + "options": { + "legend": { + "calcs": [ + "lastNotNull", + "max", + "min" + ], + "displayMode": "hidden", + "placement": "bottom" + }, + "tooltip": { + "mode": "multi" + } + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "exemplar": true, + "expr": "rate(process_cpu_seconds_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", scrape_source=\"controller\"}[$__rate_interval])", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "{{ controller }} / {{ node }}", + "refId": "A", + "step": 10 + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Total CPU (Go Ingress Controller)", + "type": "timeseries" + }, + { + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 11, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "decbytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 12, + "x": 12, + "y": 23 + }, + "id": 280, + "links": [], + "options": { + "legend": { + "calcs": [ + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "right" + }, + "tooltip": { + "mode": "single" + } + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "exemplar": true, + "expr": "sum(process_resident_memory_bytes{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\"})", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "resident", + "refId": "A", + "step": 10 + }, + { + "exemplar": true, + "expr": "sum(process_virtual_memory_bytes{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\"})", + "hide": false, + "interval": "", + "legendFormat": "virtual", + "refId": "B" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Total Memory (Go Ingress Controller)", + "type": "timeseries" + }, + { + "collapsed": false, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 28 + }, + "id": 126, + "panels": [], + "title": "Main", + "type": "row" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "rgb(31, 120, 193)", + "mode": "fixed" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 0, + "y": 29 + }, + "id": 26, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]))", + "format": "time_series", + "instant": true, + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "Requests", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "rgb(31, 120, 193)", + "mode": "fixed" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 3, + "y": 29 + }, + "id": 111, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "sum(increase(ingress_nginx_${metric}_upstream_retries_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]))\n / sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]))\nor vector(0)", + "format": "time_series", + "instant": true, + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "Retried Requests", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "rgb(31, 120, 193)", + "mode": "fixed" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 6, + "y": 29 + }, + "id": 47, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "sum(increase(ingress_nginx_${metric}_received_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]))", + "format": "time_series", + "instant": true, + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "In Traffic", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "rgb(31, 120, 193)", + "mode": "fixed" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 9, + "y": 29 + }, + "id": 48, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "sum(increase(ingress_nginx_${metric}_sent_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]))", + "format": "time_series", + "instant": true, + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "Out Traffic", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "rgb(31, 120, 193)", + "mode": "fixed" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ops" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 12, + "y": 29 + }, + "id": 109, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]))", + "format": "time_series", + "instant": true, + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "Avg RPS", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 15, + "y": 29 + }, + "id": 65, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_request_seconds_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]))\n / sum(rate(ingress_nginx_${metric}_request_seconds_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]))\n * 1000", + "format": "time_series", + "instant": true, + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "Avg Req Time", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 18, + "y": 29 + }, + "id": 69, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "sum(increase(ingress_nginx_${metric}_upstream_response_seconds_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]))\n / sum(increase(ingress_nginx_${metric}_upstream_response_seconds_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]))\n * 1000", + "format": "time_series", + "instant": true, + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "Avg Upstr Time", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "rgb(31, 120, 193)", + "mode": "fixed" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 21, + "y": 29 + }, + "id": 110, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", scheme=\"https\"}[$__rate_interval]))\n / (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) > 0)", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "HTTPS", + "type": "stat" + }, + { + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": null, + "displayMode": "auto", + "minWidth": 64 + }, + "decimals": 2, + "displayName": "", + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Time" + }, + "properties": [ + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #A" + }, + "properties": [ + { + "id": "displayName", + "value": "RPS" + }, + { + "id": "unit", + "value": "ops" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 85 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #B" + }, + "properties": [ + { + "id": "displayName", + "value": "Retried Req" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 85 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #C" + }, + "properties": [ + { + "id": "displayName", + "value": "Req Time" + }, + { + "id": "unit", + "value": "s" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 85 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #D" + }, + "properties": [ + { + "id": "displayName", + "value": "Upstr Time" + }, + { + "id": "unit", + "value": "s" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 85 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #E" + }, + "properties": [ + { + "id": "displayName", + "value": "In Traffic" + }, + { + "id": "unit", + "value": "bps" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 85 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #F" + }, + "properties": [ + { + "id": "displayName", + "value": "Out Traffic" + }, + { + "id": "unit", + "value": "bps" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 85 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #G" + }, + "properties": [ + { + "id": "displayName", + "value": "Req Size" + }, + { + "id": "unit", + "value": "bytes" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 85 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #H" + }, + "properties": [ + { + "id": "displayName", + "value": "Resp Size" + }, + { + "id": "unit", + "value": "bytes" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 85 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #I" + }, + "properties": [ + { + "id": "displayName", + "value": "1xx" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 62 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #J" + }, + "properties": [ + { + "id": "displayName", + "value": "2xx" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 62 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #K" + }, + "properties": [ + { + "id": "displayName", + "value": "3xx" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 62 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #L" + }, + "properties": [ + { + "id": "displayName", + "value": "4xx" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 62 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #M" + }, + "properties": [ + { + "id": "displayName", + "value": "5xx" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 62 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #N" + }, + "properties": [ + { + "id": "displayName", + "value": "HTTPS" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 62 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #O" + }, + "properties": [ + { + "id": "displayName", + "value": "GET" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 62 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #P" + }, + "properties": [ + { + "id": "displayName", + "value": "POST" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 65 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #Q" + }, + "properties": [ + { + "id": "displayName", + "value": "HEAD" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 62 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #R" + }, + "properties": [ + { + "id": "displayName", + "value": "PUT" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 62 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #S" + }, + "properties": [ + { + "id": "displayName", + "value": "DELETE" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 62 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #T" + }, + "properties": [ + { + "id": "displayName", + "value": "OPTIONS" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 62 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #U" + }, + "properties": [ + { + "id": "displayName", + "value": "PATCH" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 62 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "app" + }, + "properties": [ + { + "id": "displayName", + "value": "App" + }, + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 120 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "node" + }, + "properties": [ + { + "id": "displayName", + "value": "Node" + }, + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 140 + } + ] + } + ] + }, + "gridPos": { + "h": 6, + "w": 24, + "x": 0, + "y": 31 + }, + "id": 28, + "links": [], + "options": { + "showHeader": true + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "(sum(rate(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "A" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_upstream_retries_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by\n / (sum(rate(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "legendFormat": "", + "refId": "B" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_request_seconds_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by\n / (sum(increase(ingress_nginx_${metric}_request_seconds_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "legendFormat": "", + "refId": "C" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_upstream_response_seconds_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by\n / (sum(increase(ingress_nginx_${metric}_upstream_response_seconds_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "legendFormat": "", + "refId": "D" + }, + { + "expr": "(sum(rate(ingress_nginx_${metric}_received_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by * 8 > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "legendFormat": "", + "refId": "E" + }, + { + "expr": "(sum(rate(ingress_nginx_${metric}_sent_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by * 8 > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "F" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_received_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by\n / (sum(increase(ingress_nginx_${metric}_received_bytes_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "G" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_sent_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by\n / (sum(increase(ingress_nginx_${metric}_sent_bytes_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "H" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"1..\"}[$__range])) $by\n/ (sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "I" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"2..\"}[$__range])) $by\n/ (sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "J" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"3..\"}[$__range])) $by\n/ (sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "K" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"4..\"}[$__range])) $by\n/ (sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "L" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"5..\"}[$__range])) $by\n/ (sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "M" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", scheme=\"https\"}[$__range])) $by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "N" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"GET\"}[$__range])) $by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "O" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"POST\"}[$__range])) $by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "P" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"HEAD\"}[$__range])) $by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "Q" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"PUT\"}[$__range])) $by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "R" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"DELETE\"}[$__range])) $by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "S" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"OPTIONS\"}[$__range])) $by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "T" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"PATCH\"}[$__range])) $by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "U" + } + ], + "title": "Average", + "transformations": [ + { + "id": "merge", + "options": { + "reducers": [] + } + }, + { + "id": "filterFieldsByName", + "options": { + "include": { + "names": [ + "app", + "node", + "Value #A", + "Value #B", + "Value #C", + "Value #D", + "Value #E", + "Value #F", + "Value #G", + "Value #H", + "Value #I", + "Value #J", + "Value #K", + "Value #L", + "Value #M", + "Value #N", + "Value #O", + "Value #P", + "Value #Q", + "Value #R", + "Value #S", + "Value #T", + "Value #U" + ] + } + } + } + ], + "type": "table" + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 16, + "x": 0, + "y": 37 + }, + "hiddenSeries": false, + "id": 1, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sort": "total", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A", + "step": 20 + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $by > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Requests", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 8, + "x": 16, + "y": 37 + }, + "hiddenSeries": false, + "id": 80, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sort": "total", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $by\n / scalar(sum(rate(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))) > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Requests %", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "percentunit", + "label": "", + "logBase": 1, + "max": "1", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "3xx": "#6ED0E0", + "4xx": "#EAB839", + "5xx": "#BF1B00" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 16, + "x": 0, + "y": 42 + }, + "hiddenSeries": false, + "id": 238, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": true, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + }, + { + "alias": "2xx", + "color": "#73BF69" + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A" + }, + { + "expr": "sum(label_replace(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]), \"status_group\", \"${1}xx\", \"status\", \"([0-9])..\")) by (status_group) > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{ status_group }}", + "refId": "B", + "step": 40 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Responses", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "3xx": "#6ED0E0", + "4xx": "#EAB839", + "5xx": "#BF1B00" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 8, + "x": 16, + "y": 42 + }, + "hiddenSeries": false, + "id": 239, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": true, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(label_replace(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]), \"status_group\", \"${1}xx\", \"status\", \"([0-9])..\")) by (status_group)\n / scalar(sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))) > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{ status_group }}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Responses %", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "percentunit", + "label": "", + "logBase": 1, + "max": "1", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 8, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 16, + "x": 0, + "y": 47 + }, + "hiddenSeries": false, + "hideTimeOverride": false, + "id": 4, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sideWidth": null, + "sort": null, + "sortDesc": null, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 0, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "0.005", + "color": "#76B576" + }, + { + "alias": "0.01", + "color": "#83BC6D" + }, + { + "alias": "0.02", + "color": "#91C364" + }, + { + "alias": "0.03", + "color": "#9FCB5B" + }, + { + "alias": "0.04", + "color": "#ACD252" + }, + { + "alias": "0.05", + "color": "#BADA49" + }, + { + "alias": "0.075", + "color": "#C8E140" + }, + { + "alias": "0.1", + "color": "#D5E837" + }, + { + "alias": "0.2", + "color": "#E3F02E" + }, + { + "alias": "0.3", + "color": "#F1F725" + }, + { + "alias": "0.4", + "color": "#FFFF1C" + }, + { + "alias": "0.5", + "color": "#FAE519" + }, + { + "alias": "0.75", + "color": "#F6CC16" + }, + { + "alias": "1", + "color": "#F2B213" + }, + { + "alias": "1.5", + "color": "#EE9910" + }, + { + "alias": "2", + "color": "#EA7F0E" + }, + { + "alias": "3", + "color": "#E6660B" + }, + { + "alias": "4", + "color": "#E24C08" + }, + { + "alias": "5", + "color": "#DE3205" + }, + { + "alias": "10", + "color": "#DA1902" + }, + { + "alias": "+Inf", + "color": "#D60000" + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_lowres_upstream_response_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)", + "format": "heatmap", + "intervalFactor": 1, + "legendFormat": "{{le}}", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Upstream Response Time", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + "total" + ] + }, + "yaxes": [ + { + "decimals": null, + "format": "ops", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 8, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 8, + "x": 16, + "y": 47 + }, + "hiddenSeries": false, + "hideTimeOverride": false, + "id": 81, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sideWidth": null, + "sort": null, + "sortDesc": null, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 0, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "0.005", + "color": "#76B576" + }, + { + "alias": "0.01", + "color": "#83BC6D" + }, + { + "alias": "0.02", + "color": "#91C364" + }, + { + "alias": "0.03", + "color": "#9FCB5B" + }, + { + "alias": "0.04", + "color": "#ACD252" + }, + { + "alias": "0.05", + "color": "#BADA49" + }, + { + "alias": "0.075", + "color": "#C8E140" + }, + { + "alias": "0.1", + "color": "#D5E837" + }, + { + "alias": "0.2", + "color": "#E3F02E" + }, + { + "alias": "0.3", + "color": "#F1F725" + }, + { + "alias": "0.4", + "color": "#FFFF1C" + }, + { + "alias": "0.5", + "color": "#FAE519" + }, + { + "alias": "0.75", + "color": "#F6CC16" + }, + { + "alias": "1", + "color": "#F2B213" + }, + { + "alias": "1.5", + "color": "#EE9910" + }, + { + "alias": "2", + "color": "#EA7F0E" + }, + { + "alias": "3", + "color": "#E6660B" + }, + { + "alias": "4", + "color": "#E24C08" + }, + { + "alias": "5", + "color": "#DE3205" + }, + { + "alias": "10", + "color": "#DA1902" + }, + { + "alias": "+Inf", + "color": "#D60000" + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_lowres_upstream_response_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)\n / scalar(sum(rate(ingress_nginx_${metric}_lowres_upstream_response_seconds_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])))", + "format": "heatmap", + "intervalFactor": 1, + "legendFormat": "{{le}}", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Upstream Response Time %", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + "total" + ] + }, + "yaxes": [ + { + "format": "percentunit", + "label": null, + "logBase": 1, + "max": "1", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 8, + "x": 0, + "y": 53 + }, + "hiddenSeries": false, + "hideTimeOverride": false, + "id": 62, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sideWidth": null, + "sort": null, + "sortDesc": null, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": true, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_upstream_retries_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_upstream_retries_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $by > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Retried Requests", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + "total" + ] + }, + "yaxes": [ + { + "format": "ops", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 8, + "x": 8, + "y": 53 + }, + "hiddenSeries": false, + "hideTimeOverride": false, + "id": 112, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sideWidth": null, + "sort": null, + "sortDesc": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_upstream_retries_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $by\n/ sum(rate(ingress_nginx_${metric}_upstream_retries_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $by\n> 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Retries (per Retried Request)", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + "total" + ] + }, + "yaxes": [ + { + "format": "ops", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "3xx": "#6ED0E0", + "4xx": "#EAB839", + "5xx": "#BF1B00" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 8, + "x": 16, + "y": 53 + }, + "hiddenSeries": false, + "id": 196, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": true, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"1..\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"1..\"}[$__rate_interval])) $by > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "B", + "step": 40 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "1xx", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "3xx": "#6ED0E0", + "4xx": "#EAB839", + "5xx": "#BF1B00" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 8, + "x": 16, + "y": 57 + }, + "hiddenSeries": false, + "id": 87, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": true, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"2..\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"2..\"}[$__rate_interval])) $by > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "B", + "step": 40 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "2xx", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": null, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 8, + "x": 0, + "y": 58 + }, + "hiddenSeries": false, + "hideTimeOverride": false, + "id": 49, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sideWidth": null, + "sort": null, + "sortDesc": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_request_seconds_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $by\n / sum(rate(ingress_nginx_${metric}_request_seconds_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $by > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Avg Request Time", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + "total" + ] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": null, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 8, + "x": 8, + "y": 58 + }, + "hiddenSeries": false, + "hideTimeOverride": false, + "id": 63, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sideWidth": null, + "sort": null, + "sortDesc": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_upstream_response_seconds_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $by\n / sum(rate(ingress_nginx_${metric}_upstream_response_seconds_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $by > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Avg Upstream Response Time", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + "total" + ] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "3xx": "#6ED0E0", + "4xx": "#EAB839", + "5xx": "#BF1B00" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 8, + "x": 16, + "y": 61 + }, + "hiddenSeries": false, + "id": 10, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": true, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"3..\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"3..\"}[$__rate_interval])) $by > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "B", + "step": 40 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "3xx", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": null, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 8, + "x": 0, + "y": 63 + }, + "hiddenSeries": false, + "hideTimeOverride": false, + "id": 58, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sideWidth": null, + "sort": null, + "sortDesc": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_received_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $by\n / sum(rate(ingress_nginx_${metric}_received_bytes_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $by > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Avg Request Size", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + "total" + ] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": null, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 8, + "x": 8, + "y": 63 + }, + "hiddenSeries": false, + "hideTimeOverride": false, + "id": 73, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sideWidth": null, + "sort": null, + "sortDesc": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_sent_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $by\n / sum(rate(ingress_nginx_${metric}_sent_bytes_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $by > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Avg Response Size", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + "total" + ] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "3xx": "#6ED0E0", + "4xx": "#EAB839", + "5xx": "#BF1B00" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 8, + "x": 16, + "y": 65 + }, + "hiddenSeries": false, + "id": 18, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": true, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"4..\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"4..\"}[$__rate_interval])) $by > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "B", + "step": 40 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "4xx", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 8, + "x": 0, + "y": 68 + }, + "hiddenSeries": false, + "id": 12, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_received_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) * 8", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A", + "step": 20 + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_received_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $by * 8 > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "B", + "step": 20 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Incoming Traffic", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bps", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 8, + "x": 8, + "y": 68 + }, + "hiddenSeries": false, + "id": 9, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sort": "max", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_sent_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) * 8", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A", + "step": 20 + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_sent_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $by * 8 > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Outgoing Traffic", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bps", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "3xx": "#6ED0E0", + "4xx": "#EAB839", + "5xx": "#BF1B00" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 8, + "x": 16, + "y": 69 + }, + "hiddenSeries": false, + "id": 17, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": true, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"5..\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"5..\"}[$__rate_interval])) $by > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "B", + "step": 40 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "5xx", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "collapsed": false, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 73 + }, + "id": 195, + "panels": [], + "title": "Status Codes", + "type": "row" + }, + { + "aliasColors": { + "3xx": "#6ED0E0", + "4xx": "#EAB839", + "5xx": "#BF1B00" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 8, + "x": 0, + "y": 74 + }, + "hiddenSeries": false, + "id": 189, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": true, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": true, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"1..\"}[$__rate_interval])) by (status)\n / scalar(sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"1..\"}[$__rate_interval])))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{status}}", + "refId": "B", + "step": 40 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "1xx", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "percentunit", + "label": "", + "logBase": 1, + "max": "100", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "3xx": "#6ED0E0", + "4xx": "#EAB839", + "5xx": "#BF1B00" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 8, + "x": 8, + "y": 74 + }, + "hiddenSeries": false, + "id": 190, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": true, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": true, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"2..\"}[$__rate_interval])) by (status)\n / scalar(sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"2..\"}[$__rate_interval])))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{status}}", + "refId": "B", + "step": 40 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "2xx", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "percentunit", + "label": "", + "logBase": 1, + "max": "100", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "3xx": "#6ED0E0", + "4xx": "#EAB839", + "5xx": "#BF1B00" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 8, + "x": 16, + "y": 74 + }, + "hiddenSeries": false, + "id": 191, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": true, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": true, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"3..\"}[$__rate_interval])) by (status)\n / scalar(sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"3..\"}[$__rate_interval])))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{status}}", + "refId": "B", + "step": 40 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "3xx", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "percentunit", + "label": "", + "logBase": 1, + "max": "100", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "3xx": "#6ED0E0", + "4xx": "#EAB839", + "5xx": "#BF1B00" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 12, + "x": 0, + "y": 78 + }, + "hiddenSeries": false, + "id": 192, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": true, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": true, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"4..\"}[$__rate_interval])) by (status)\n / scalar(sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"4..\"}[$__rate_interval])))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{status}}", + "refId": "B", + "step": 40 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "4xx", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "percentunit", + "label": "", + "logBase": 1, + "max": "100", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "3xx": "#6ED0E0", + "4xx": "#EAB839", + "5xx": "#BF1B00" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 12, + "x": 12, + "y": 78 + }, + "hiddenSeries": false, + "id": 193, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": true, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": true, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"5..\"}[$__rate_interval])) by (status)\n / scalar(sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"5..\"}[$__rate_interval])))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{status}}", + "refId": "B", + "step": 40 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "5xx", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "percentunit", + "label": "", + "logBase": 1, + "max": "100", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "3xx": "#6ED0E0", + "4xx": "#EAB839", + "5xx": "#BF1B00" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 6, + "x": 0, + "y": 83 + }, + "hiddenSeries": false, + "id": 86, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": true, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "maxPerRow": 4, + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": "status", + "repeatDirection": "h", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=\"$status\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=\"$status\"}[$__rate_interval])) $by > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "B", + "step": 40 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "$status", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "collapsed": false, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 103 + }, + "id": 150, + "panels": [], + "title": "Request Time and Upstream Response Time", + "type": "row" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 0, + "y": 104 + }, + "id": 130, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_request_seconds_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))\n / sum(rate(ingress_nginx_${metric}_request_seconds_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))\n * 1000", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "Avg Req Time", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 3, + "y": 104 + }, + "id": 132, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "histogram_quantile(0.5, sum(rate(ingress_nginx_${metric}_request_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)) * 1000", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "50th Req Time", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 6, + "y": 104 + }, + "id": 134, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "histogram_quantile(0.9, sum(rate(ingress_nginx_${metric}_request_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)) * 1000", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "90th Req Time", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 9, + "y": 104 + }, + "id": 174, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "histogram_quantile(0.99, sum(rate(ingress_nginx_${metric}_request_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)) * 1000", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "99th Req Time", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 12, + "y": 104 + }, + "id": 140, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_upstream_response_seconds_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))\n / sum(rate(ingress_nginx_${metric}_upstream_response_seconds_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))\n * 1000", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "Avg Upstr Time", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 15, + "y": 104 + }, + "id": 142, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "histogram_quantile(0.5, sum(rate(ingress_nginx_${metric}_upstream_response_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)) * 1000", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "50th Upstr Time", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 18, + "y": 104 + }, + "id": 144, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "histogram_quantile(0.9, sum(rate(ingress_nginx_${metric}_upstream_response_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)) * 1000", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "90th Upstr Time", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 21, + "y": 104 + }, + "id": 146, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "histogram_quantile(0.99, sum(rate(ingress_nginx_${metric}_upstream_response_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)) * 1000", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "99th Upstr Time", + "type": "stat" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": null, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 12, + "x": 0, + "y": 106 + }, + "hiddenSeries": false, + "hideTimeOverride": false, + "id": 136, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sideWidth": null, + "sort": null, + "sortDesc": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Avg", + "fill": 2, + "linewidth": 0 + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "histogram_quantile(0.99, sum(rate(ingress_nginx_${metric}_request_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)) * 1000", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "99th", + "refId": "A" + }, + { + "expr": "histogram_quantile(0.9, sum(rate(ingress_nginx_${metric}_request_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)) * 1000", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "90th", + "refId": "B" + }, + { + "expr": "histogram_quantile(0.5, sum(rate(ingress_nginx_${metric}_request_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)) * 1000", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "50th", + "refId": "C" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_request_seconds_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))\n / sum(rate(ingress_nginx_${metric}_request_seconds_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))\n * 1000", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Avg", + "refId": "D" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Request Time", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + "total" + ] + }, + "yaxes": [ + { + "format": "ms", + "label": null, + "logBase": 10, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": null, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 12, + "x": 12, + "y": 106 + }, + "hiddenSeries": false, + "hideTimeOverride": false, + "id": 148, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sideWidth": null, + "sort": null, + "sortDesc": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Avg", + "fill": 2, + "linewidth": 0 + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "histogram_quantile(0.99, sum(rate(ingress_nginx_${metric}_upstream_response_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)) * 1000", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "99th", + "refId": "A" + }, + { + "expr": "histogram_quantile(0.9, sum(rate(ingress_nginx_${metric}_upstream_response_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)) * 1000", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "90th", + "refId": "B" + }, + { + "expr": "histogram_quantile(0.5, sum(rate(ingress_nginx_${metric}_upstream_response_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)) * 1000", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "50th", + "refId": "C" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_upstream_response_seconds_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))\n / sum(rate(ingress_nginx_${metric}_upstream_response_seconds_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))\n * 1000", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Avg", + "refId": "D" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Upstream Response Time", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + "total" + ] + }, + "yaxes": [ + { + "format": "ms", + "label": null, + "logBase": 10, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "collapsed": false, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 111 + }, + "id": 211, + "panels": [], + "title": "Request Time Heatmap and Upstream Response Time Heatmap", + "type": "row" + }, + { + "cards": { + "cardPadding": 0, + "cardRound": 0 + }, + "color": { + "cardColor": "#b4ff00", + "colorScale": "sqrt", + "colorScheme": "interpolateYlGnBu", + "exponent": 0.5, + "max": null, + "min": 0, + "mode": "spectrum" + }, + "dataFormat": "tsbuckets", + "datasource": null, + "gridPos": { + "h": 21, + "w": 12, + "x": 0, + "y": 112 + }, + "heatmap": {}, + "hideZeroBuckets": false, + "highlightCards": true, + "id": 152, + "legend": { + "show": true + }, + "links": [], + "reverseYBuckets": false, + "targets": [ + { + "expr": "sum(increase(ingress_nginx_${metric}_request_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le) > 0", + "format": "heatmap", + "intervalFactor": 1, + "legendFormat": "{{le}}", + "refId": "A" + } + ], + "title": "Request Time", + "tooltip": { + "show": true, + "showHistogram": true + }, + "type": "heatmap", + "xAxis": { + "show": true + }, + "xBucketNumber": null, + "xBucketSize": null, + "yAxis": { + "decimals": 1, + "format": "s", + "logBase": 1, + "max": null, + "min": null, + "show": true, + "splitFactor": null + }, + "yBucketBound": "auto", + "yBucketNumber": null, + "yBucketSize": null + }, + { + "cards": { + "cardPadding": 0, + "cardRound": 0 + }, + "color": { + "cardColor": "#b4ff00", + "colorScale": "sqrt", + "colorScheme": "interpolateYlGnBu", + "exponent": 0.5, + "max": null, + "min": 0, + "mode": "spectrum" + }, + "dataFormat": "tsbuckets", + "datasource": null, + "gridPos": { + "h": 21, + "w": 12, + "x": 12, + "y": 112 + }, + "heatmap": {}, + "hideZeroBuckets": false, + "highlightCards": true, + "id": 153, + "legend": { + "show": true + }, + "links": [], + "reverseYBuckets": false, + "targets": [ + { + "expr": "sum(increase(ingress_nginx_${metric}_upstream_response_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le) > 0", + "format": "heatmap", + "intervalFactor": 1, + "legendFormat": "{{le}}", + "refId": "A" + } + ], + "title": "Upstream Response Time", + "tooltip": { + "show": true, + "showHistogram": true + }, + "type": "heatmap", + "xAxis": { + "show": true + }, + "xBucketNumber": null, + "xBucketSize": null, + "yAxis": { + "decimals": 1, + "format": "s", + "logBase": 1, + "max": null, + "min": null, + "show": true, + "splitFactor": null + }, + "yBucketBound": "auto", + "yBucketNumber": null, + "yBucketSize": null + }, + { + "collapsed": false, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 133 + }, + "id": 160, + "panels": [], + "title": "Request Size and Response Size", + "type": "row" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 0, + "y": 134 + }, + "id": 171, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_received_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))\n / sum(rate(ingress_nginx_${metric}_received_bytes_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "Avg Req Size", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 3, + "y": 134 + }, + "id": 172, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "histogram_quantile(0.5, sum(rate(ingress_nginx_${metric}_received_bytes_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le))", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "50th Req Size", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 6, + "y": 134 + }, + "id": 173, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "histogram_quantile(0.9, sum(rate(ingress_nginx_${metric}_received_bytes_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le))", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "90th Req Size", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 9, + "y": 134 + }, + "id": 128, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "histogram_quantile(0.99, sum(rate(ingress_nginx_${metric}_received_bytes_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le))", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "99th Req Size", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 12, + "y": 134 + }, + "id": 175, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_sent_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))\n / sum(rate(ingress_nginx_${metric}_sent_bytes_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "Avg Resp Size", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 15, + "y": 134 + }, + "id": 176, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "histogram_quantile(0.5, sum(rate(ingress_nginx_${metric}_sent_bytes_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le))", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "50th Resp Size", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 18, + "y": 134 + }, + "id": 177, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "histogram_quantile(0.9, sum(rate(ingress_nginx_${metric}_sent_bytes_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le))", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "90th Resp Size", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 21, + "y": 134 + }, + "id": 178, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "histogram_quantile(0.99, sum(rate(ingress_nginx_${metric}_sent_bytes_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le))", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "99th Resp Size", + "type": "stat" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": null, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 12, + "x": 0, + "y": 136 + }, + "hiddenSeries": false, + "hideTimeOverride": false, + "id": 155, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sideWidth": null, + "sort": null, + "sortDesc": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Avg", + "fill": 2, + "linewidth": 0 + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "histogram_quantile(0.99, sum(rate(ingress_nginx_${metric}_received_bytes_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "99th", + "refId": "A" + }, + { + "expr": "histogram_quantile(0.9, sum(rate(ingress_nginx_${metric}_received_bytes_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "90th", + "refId": "B" + }, + { + "expr": "histogram_quantile(0.5, sum(rate(ingress_nginx_${metric}_received_bytes_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "50th", + "refId": "C" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_received_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))\n / sum(rate(ingress_nginx_${metric}_received_bytes_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Avg", + "refId": "D" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Request Size", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + "total" + ] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 2, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": null, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 12, + "x": 12, + "y": 136 + }, + "hiddenSeries": false, + "hideTimeOverride": false, + "id": 157, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sideWidth": null, + "sort": null, + "sortDesc": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Avg", + "fill": 2, + "linewidth": 0 + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "histogram_quantile(0.99, sum(rate(ingress_nginx_${metric}_sent_bytes_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "99th", + "refId": "A" + }, + { + "expr": "histogram_quantile(0.9, sum(rate(ingress_nginx_${metric}_sent_bytes_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "90th", + "refId": "B" + }, + { + "expr": "histogram_quantile(0.5, sum(rate(ingress_nginx_${metric}_sent_bytes_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "50th", + "refId": "C" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_sent_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))\n / sum(rate(ingress_nginx_${metric}_sent_bytes_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Avg", + "refId": "D" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Response Size", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + "total" + ] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 2, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "collapsed": false, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 140 + }, + "id": 209, + "panels": [], + "title": "Request Size Heatmap and Response Size Heatmap", + "type": "row" + }, + { + "cards": { + "cardPadding": 0, + "cardRound": 0 + }, + "color": { + "cardColor": "#b4ff00", + "colorScale": "sqrt", + "colorScheme": "interpolateYlGnBu", + "exponent": 0.5, + "max": null, + "min": 0, + "mode": "spectrum" + }, + "dataFormat": "tsbuckets", + "datasource": null, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 141 + }, + "heatmap": {}, + "hideZeroBuckets": false, + "highlightCards": true, + "id": 158, + "legend": { + "show": true + }, + "links": [], + "reverseYBuckets": false, + "targets": [ + { + "expr": "sum(increase(ingress_nginx_${metric}_received_bytes_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)", + "format": "heatmap", + "intervalFactor": 1, + "legendFormat": "{{le}}", + "refId": "A" + } + ], + "title": "Request Size", + "tooltip": { + "show": true, + "showHistogram": true + }, + "type": "heatmap", + "xAxis": { + "show": true + }, + "xBucketNumber": null, + "xBucketSize": null, + "yAxis": { + "decimals": 0, + "format": "bytes", + "logBase": 1, + "max": null, + "min": null, + "show": true, + "splitFactor": null + }, + "yBucketBound": "auto", + "yBucketNumber": null, + "yBucketSize": null + }, + { + "cards": { + "cardPadding": 0, + "cardRound": 0 + }, + "color": { + "cardColor": "#b4ff00", + "colorScale": "sqrt", + "colorScheme": "interpolateYlGnBu", + "exponent": 0.5, + "max": null, + "min": 0, + "mode": "spectrum" + }, + "dataFormat": "tsbuckets", + "datasource": null, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 141 + }, + "heatmap": {}, + "hideZeroBuckets": false, + "highlightCards": true, + "id": 161, + "legend": { + "show": true + }, + "links": [], + "reverseYBuckets": false, + "targets": [ + { + "expr": "sum(increase(ingress_nginx_${metric}_sent_bytes_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)", + "format": "heatmap", + "intervalFactor": 1, + "legendFormat": "{{le}}", + "refId": "A" + } + ], + "title": "Response Size", + "tooltip": { + "show": true, + "showHistogram": true + }, + "type": "heatmap", + "xAxis": { + "show": true + }, + "xBucketNumber": null, + "xBucketSize": null, + "yAxis": { + "decimals": 0, + "format": "bytes", + "logBase": 1, + "max": null, + "min": null, + "show": true, + "splitFactor": null + }, + "yBucketBound": "auto", + "yBucketNumber": null, + "yBucketSize": null + }, + { + "collapsed": false, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 151 + }, + "id": 89, + "panels": [], + "title": "Request Method and Content Kind", + "type": "row" + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 12, + "x": 0, + "y": 152 + }, + "hiddenSeries": false, + "id": 61, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sort": "total", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (method)\n / scalar(sum(rate(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{method}}", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Method %", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "percentunit", + "label": "", + "logBase": 1, + "max": "1", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 12, + "x": 12, + "y": 152 + }, + "hiddenSeries": false, + "id": 60, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sort": "total", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\"}[$__rate_interval])) by (content_kind)\n/ scalar(sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\"}[$__rate_interval])))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{content_kind}}", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Content Kind %", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "percentunit", + "label": "", + "logBase": 1, + "max": "1", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 12, + "x": 0, + "y": 158 + }, + "hiddenSeries": false, + "id": 90, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sort": "total", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": "method", + "repeatDirection": "v", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"$method\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"$method\"}[$__rate_interval])) $by > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "$method", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 12, + "x": 12, + "y": 158 + }, + "hiddenSeries": false, + "id": 97, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sort": "total", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": "content_kind", + "repeatDirection": "v", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=\"$content_kind\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=\"$content_kind\"}[$__rate_interval])) $by > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "$content_kind", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "collapsed": false, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 178 + }, + "id": 46, + "panels": [], + "title": "By $alt_name", + "type": "row" + }, + { + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": null, + "displayMode": "auto", + "minWidth": 64 + }, + "decimals": 2, + "displayName": "", + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Time" + }, + "properties": [ + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #A" + }, + "properties": [ + { + "id": "displayName", + "value": "RPS" + }, + { + "id": "unit", + "value": "ops" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 85 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #B" + }, + "properties": [ + { + "id": "displayName", + "value": "Retried Req" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #C" + }, + "properties": [ + { + "id": "displayName", + "value": "Req Time" + }, + { + "id": "unit", + "value": "s" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 85 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #D" + }, + "properties": [ + { + "id": "displayName", + "value": "Resp Time" + }, + { + "id": "unit", + "value": "s" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 85 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #E" + }, + "properties": [ + { + "id": "displayName", + "value": "In Traffic" + }, + { + "id": "unit", + "value": "bps" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 85 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #F" + }, + "properties": [ + { + "id": "displayName", + "value": "Out Traffic" + }, + { + "id": "unit", + "value": "bps" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 85 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #G" + }, + "properties": [ + { + "id": "displayName", + "value": "Req Size" + }, + { + "id": "unit", + "value": "bytes" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 85 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #H" + }, + "properties": [ + { + "id": "displayName", + "value": "Resp Size" + }, + { + "id": "unit", + "value": "bytes" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 85 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #I" + }, + "properties": [ + { + "id": "displayName", + "value": "1xx" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #J" + }, + "properties": [ + { + "id": "displayName", + "value": "2xx" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #K" + }, + "properties": [ + { + "id": "displayName", + "value": "3xx" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #L" + }, + "properties": [ + { + "id": "displayName", + "value": "4xx" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #M" + }, + "properties": [ + { + "id": "displayName", + "value": "5xx" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #N" + }, + "properties": [ + { + "id": "displayName", + "value": "HTTPS" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #O" + }, + "properties": [ + { + "id": "displayName", + "value": "GET" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #P" + }, + "properties": [ + { + "id": "displayName", + "value": "POST" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #Q" + }, + "properties": [ + { + "id": "displayName", + "value": "HEAD" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #R" + }, + "properties": [ + { + "id": "displayName", + "value": "PUT" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #S" + }, + "properties": [ + { + "id": "displayName", + "value": "DELETE" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #T" + }, + "properties": [ + { + "id": "displayName", + "value": "OPTIONS" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #U" + }, + "properties": [ + { + "id": "displayName", + "value": "PATCH" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "namespace" + }, + "properties": [ + { + "id": "displayName", + "value": "Namespace" + }, + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "links", + "value": [ + { + "targetBlank": false, + "title": "Open Namespace", + "url": "/d/Z-phNqGmz/namespaces?var-namespace=${__value.raw}&${__url_time_range}\n" + } + ] + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 120 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "ingress" + }, + "properties": [ + { + "id": "displayName", + "value": "Ingress" + }, + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "links", + "value": [ + { + "targetBlank": false, + "title": "Open Namespace Detail", + "url": "/d/oipwXCMik/namespace-detail?var-namespace=${__data.fields[Namespace]}&var-ingress=${__value.raw}&${__url_time_range}\n" + } + ] + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 120 + } + ] + } + ] + }, + "gridPos": { + "h": 6, + "w": 24, + "x": 0, + "y": 179 + }, + "id": 42, + "links": [], + "options": { + "showHeader": true + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "(sum(rate(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "instant": true, + "intervalFactor": 1, + "refId": "A" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_upstream_retries_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by\n / (sum(rate(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "legendFormat": "", + "refId": "B" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_request_seconds_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by\n / (sum(increase(ingress_nginx_${metric}_request_seconds_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "legendFormat": "", + "refId": "C" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_upstream_response_seconds_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by\n / (sum(increase(ingress_nginx_${metric}_upstream_response_seconds_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "legendFormat": "", + "refId": "D" + }, + { + "expr": "(sum(rate(ingress_nginx_${metric}_received_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by * 8 > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "legendFormat": "", + "refId": "E" + }, + { + "expr": "(sum(rate(ingress_nginx_${metric}_sent_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by * 8 > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "F" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_received_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by\n / (sum(increase(ingress_nginx_${metric}_received_bytes_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "G" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_sent_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by\n / (sum(increase(ingress_nginx_${metric}_sent_bytes_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "H" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"1..\"}[$__range])) $alt_by\n/ (sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "I" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"2..\"}[$__range])) $alt_by\n/ (sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "J" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"3..\"}[$__range])) $alt_by\n/ (sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "K" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"4..\"}[$__range])) $alt_by\n/ (sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "L" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"5..\"}[$__range])) $alt_by\n/ (sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "M" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", scheme=\"https\"}[$__range])) $alt_by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "N" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"GET\"}[$__range])) $alt_by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "O" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"POST\"}[$__range])) $alt_by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "P" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"HEAD\"}[$__range])) $alt_by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "Q" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"PUT\"}[$__range])) $alt_by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "R" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"DELETE\"}[$__range])) $alt_by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "S" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"OPTIONS\"}[$__range])) $alt_by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "T" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"PATCH\"}[$__range])) $alt_by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "U" + } + ], + "title": "Average", + "transformations": [ + { + "id": "merge", + "options": { + "reducers": [] + } + }, + { + "id": "filterFieldsByName", + "options": { + "include": { + "names": [ + "ingress", + "namespace", + "Value #A", + "Value #B", + "Value #C", + "Value #D", + "Value #E", + "Value #F", + "Value #G", + "Value #H", + "Value #I", + "Value #J", + "Value #K", + "Value #L", + "Value #M", + "Value #N", + "Value #O", + "Value #P", + "Value #Q", + "Value #R", + "Value #S", + "Value #T", + "Value #U" + ] + } + } + } + ], + "type": "table" + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 8, + "x": 0, + "y": 185 + }, + "hiddenSeries": false, + "id": 39, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sort": "total", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": true, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $alt_by > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$alt_legend_format", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Requests per $alt_name", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": "", + "logBase": 1, + "max": "100", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 1, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 8, + "x": 8, + "y": 185 + }, + "hiddenSeries": false, + "id": 41, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": true, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_received_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $alt_by * 8 > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$alt_legend_format", + "refId": "B", + "step": 20 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Incoming Traffic per $alt_name", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bps", + "label": null, + "logBase": 1, + "max": "100", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 1, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 8, + "x": 16, + "y": 185 + }, + "hiddenSeries": false, + "id": 40, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sort": "max", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": true, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_sent_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $alt_by * 8 > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$alt_legend_format", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Outgoing Traffic per $alt_name", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bps", + "label": null, + "logBase": 1, + "max": "100", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "refresh": "30s", + "schemaVersion": 32, + "style": "dark", + "tags": [ + "ingress" + ], + "templating": { + "list": [ + { + "current": { + "selected": false, + "text": "default", + "value": "default" + }, + "description": null, + "error": null, + "hide": 0, + "includeAll": false, + "label": "Prometheus", + "multi": false, + "name": "ds_prometheus", + "options": [], + "query": "prometheus", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + }, + { + "description": null, + "error": null, + "hide": 2, + "label": null, + "name": "metric", + "query": "detail", + "skipUrlSync": false, + "type": "constant" + }, + { + "description": null, + "error": null, + "hide": 2, + "label": null, + "name": "by", + "query": "by (node, app)", + "skipUrlSync": false, + "type": "constant" + }, + { + "description": null, + "error": null, + "hide": 2, + "label": null, + "name": "legend_format", + "query": "{{node}} ({{app}})", + "skipUrlSync": false, + "type": "constant" + }, + { + "description": null, + "error": null, + "hide": 2, + "label": null, + "name": "alt_name", + "query": "Namespace and Ingress", + "skipUrlSync": false, + "type": "constant" + }, + { + "description": null, + "error": null, + "hide": 2, + "label": null, + "name": "alt_by", + "query": "by (namespace, ingress)", + "skipUrlSync": false, + "type": "constant" + }, + { + "description": null, + "error": null, + "hide": 2, + "label": null, + "name": "alt_legend_format", + "query": "{{namespace}}/{{ingress}}", + "skipUrlSync": false, + "type": "constant" + }, + { + "hide": 2, + "name": "protobuf_legend_format", + "query": "{{node}} ({{controller_pod}})", + "skipUrlSync": false, + "type": "constant" + }, + { + "hide": 2, + "name": "protobuf_by", + "query": "by (node, controller_pod)", + "skipUrlSync": false, + "type": "constant" + }, + { + "hide": 2, + "name": "cadvisor_legend_format", + "query": "{{node}} ({{pod}})", + "skipUrlSync": false, + "type": "constant" + }, + { + "hide": 2, + "name": "cadvisor_by", + "query": "by (node, pod)", + "skipUrlSync": false, + "type": "constant" + }, + { + "allValue": ".*", + "current": { + "selected": false, + "text": "main", + "value": "main" + }, + "datasource": "$ds_prometheus", + "definition": "", + "description": null, + "error": null, + "hide": 0, + "includeAll": false, + "label": "Controller", + "multi": false, + "name": "controller", + "options": [], + "query": { + "query": "label_values(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\"}, controller)", + "refId": "main-controller-Variable-Query" + }, + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "description": null, + "error": null, + "hide": 2, + "label": "App", + "name": "app", + "query": ".*", + "skipUrlSync": false, + "type": "constant" + }, + { + "allValue": ".*", + "current": { + "selected": true, + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": "$ds_prometheus", + "definition": "", + "description": null, + "error": null, + "hide": 0, + "includeAll": true, + "label": "Node", + "multi": true, + "name": "node", + "options": [], + "query": { + "query": "label_values(kube_pod_info{namespace=\"d8-ingress-nginx\", pod=~\"controller-.*\"}, node)", + "refId": "main-node-Variable-Query" + }, + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 5, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "description": null, + "error": null, + "hide": 2, + "label": "Namespace", + "name": "namespace", + "query": ".*", + "skipUrlSync": false, + "type": "constant" + }, + { + "description": null, + "error": null, + "hide": 2, + "label": "Ingress", + "name": "ingress", + "query": ".*", + "skipUrlSync": false, + "type": "constant" + }, + { + "description": null, + "error": null, + "hide": 2, + "label": "Service", + "name": "service", + "query": ".*", + "skipUrlSync": false, + "type": "constant" + }, + { + "description": null, + "error": null, + "hide": 2, + "label": "Service Port", + "name": "service_port", + "query": ".*", + "skipUrlSync": false, + "type": "constant" + }, + { + "description": null, + "error": null, + "hide": 2, + "label": "VHost", + "name": "vhost", + "query": ".*", + "skipUrlSync": false, + "type": "constant" + }, + { + "description": null, + "error": null, + "hide": 2, + "label": "Location", + "name": "location", + "query": ".*", + "skipUrlSync": false, + "type": "constant" + }, + { + "allValue": ".*", + "current": { + "selected": true, + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": "$ds_prometheus", + "definition": "", + "description": null, + "error": null, + "hide": 0, + "includeAll": true, + "label": "Content Kind", + "multi": true, + "name": "content_kind", + "options": [], + "query": { + "query": "label_values(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\"}, content_kind)", + "refId": "main-content_kind-Variable-Query" + }, + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": ".*", + "current": { + "selected": true, + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": "$ds_prometheus", + "definition": "", + "description": null, + "error": null, + "hide": 2, + "includeAll": true, + "label": "Method", + "multi": true, + "name": "method", + "options": [], + "query": { + "query": "label_values(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}, method)", + "refId": "main-method-Variable-Query" + }, + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": ".*", + "current": { + "selected": true, + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": "$ds_prometheus", + "definition": "", + "description": null, + "error": null, + "hide": 2, + "includeAll": true, + "label": "Method", + "multi": true, + "name": "status", + "options": [], + "query": { + "query": "label_values(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}, status)", + "refId": "main-status-Variable-Query" + }, + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + } + ] + }, + "time": { + "from": "now-3h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "", + "title": "Ingress Nginx Controller Detail", + "uid": "kZxJEeMmz", + "version": 1 +} diff --git a/dashboards/ingress/controllers.json b/dashboards/ingress/controllers.json new file mode 100644 index 00000000..c8682ee5 --- /dev/null +++ b/dashboards/ingress/controllers.json @@ -0,0 +1,9524 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": "-- Grafana --", + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "limit": 100, + "name": "Annotations & Alerts", + "showIn": 0, + "target": { + "limit": 100, + "matchAny": false, + "tags": [], + "type": "dashboard" + }, + "type": "dashboard" + } + ] + }, + "editable": false, + "fiscalYearStartMonth": 0, + "gnetId": null, + "graphTooltip": 1, + "iteration": 1640792770501, + "links": [], + "liveNow": false, + "panels": [ + { + "collapsed": true, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 219, + "panels": [ + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 12, + "x": 0, + "y": 1 + }, + "hiddenSeries": false, + "id": 217, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "rightSide": true, + "show": false, + "sort": null, + "sortDesc": null, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "lines": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": true, + "targets": [ + { + "expr": "sum(\n rate(container_cpu_usage_seconds_total{pod=~\"controller-.*\", node=~\"$node\", namespace=\"d8-ingress-nginx\"}[$__rate_interval])\n)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A", + "step": 10 + }, + { + "expr": "sum(\n rate(container_cpu_usage_seconds_total{pod=~\"controller-$controller.*\", node=~\"$node\", namespace=\"d8-ingress-nginx\"}[$__rate_interval])\n) $cadvisor_by", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$cadvisor_legend_format", + "refId": "B", + "step": 10 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "CPU", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "cores", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 12, + "x": 12, + "y": 1 + }, + "hiddenSeries": false, + "id": 226, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "rightSide": true, + "show": false, + "sort": null, + "sortDesc": null, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "lines": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": true, + "targets": [ + { + "expr": "sum(\n rate(container_network_receive_bytes_total{pod=~\"controller-.*\", node=~\"$node\", namespace=\"d8-ingress-nginx\"}[$__rate_interval])\n) * 8", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A", + "step": 10 + }, + { + "expr": "sum(\n rate(container_network_receive_bytes_total{pod=~\"controller-$controller.*\", node=~\"$node\", namespace=\"d8-ingress-nginx\"}[$__rate_interval])\n) $cadvisor_by * 8", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$cadvisor_legend_format", + "refId": "B", + "step": 10 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Received Traffic", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bps", + "label": "bits / second", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 12, + "x": 0, + "y": 7 + }, + "hiddenSeries": false, + "id": 215, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "rightSide": true, + "show": false, + "sort": null, + "sortDesc": null, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "lines": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": true, + "targets": [ + { + "expr": "sum(\n container_memory_usage_bytes{pod=~\"controller-.*\", node=~\"$node\", namespace=\"d8-ingress-nginx\"}\n)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A", + "step": 10 + }, + { + "expr": "sum(\n container_memory_usage_bytes{pod=~\"controller-$controller.*\", node=~\"$node\", namespace=\"d8-ingress-nginx\"}\n) $cadvisor_by", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$cadvisor_legend_format", + "refId": "B", + "step": 10 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Memory", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "decbytes", + "label": "bytes", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 12, + "x": 12, + "y": 7 + }, + "hiddenSeries": false, + "id": 227, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "rightSide": true, + "show": false, + "sort": null, + "sortDesc": null, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "lines": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": true, + "targets": [ + { + "expr": "sum(\n rate(container_network_transmit_bytes_total{pod=~\"controller-.*\", node=~\"$node\", namespace=\"d8-ingress-nginx\"}[$__rate_interval])\n) * 8", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A", + "step": 10 + }, + { + "expr": "sum(\n rate(container_network_transmit_bytes_total{pod=~\"controller-.*\", node=~\"$node\", namespace=\"d8-ingress-nginx\"}[$__rate_interval])\n) $cadvisor_by * 8", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$cadvisor_legend_format", + "refId": "B", + "step": 10 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Transmit Traffic", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bps", + "label": "bits / second", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "title": "Containers Resources (Content Kind filter is ignored)", + "type": "row" + }, + { + "collapsed": true, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 1 + }, + "id": 225, + "panels": [ + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "description": "Content Kind is ignored!!!", + "fill": 5, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 12, + "x": 0, + "y": 2 + }, + "height": "150", + "hiddenSeries": false, + "id": 221, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": true, + "show": false, + "sideWidth": 500, + "sort": null, + "sortDesc": null, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": true, + "targets": [ + { + "expr": "sum(nginx_ingress_controller_nginx_process_connections{state=\"active\", controller=~\"$controller-failover\", node=~\"$node\", job=\"nginx-ingress-controller\"})", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "B", + "step": 10 + }, + { + "expr": "sum(nginx_ingress_controller_nginx_process_connections{state=\"active\", controller=~\"$controller-failover\", node=~\"$node\", job=\"nginx-ingress-controller\"}) $by", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "A", + "step": 10 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Active Connections", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "fill": 5, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 12, + "x": 12, + "y": 2 + }, + "height": "150", + "hiddenSeries": false, + "id": 223, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": true, + "show": false, + "sideWidth": 500, + "sort": null, + "sortDesc": null, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": true, + "targets": [ + { + "expr": "sum(rate(nginx_ingress_controller_nginx_process_connections_total{state=\"accepted\", controller=~\"$controller-failover\", node=~\"$node\", job=\"nginx-ingress-controller\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "B", + "step": 10 + }, + { + "expr": "sum(rate(nginx_ingress_controller_nginx_process_connections_total{state=\"accepted\", controller=~\"$controller-failover\", node=~\"$node\", job=\"nginx-ingress-controller\"}[$__rate_interval])) $by", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "A", + "step": 10 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Accepted Connections", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "cps", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "title": "Direct Fallback (Content Kind filter is ignored)", + "type": "row" + }, + { + "collapsed": false, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 2 + }, + "id": 234, + "panels": [], + "title": "Controller (Content Kind filter is ignored)", + "type": "row" + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "fill": 5, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 16, + "x": 0, + "y": 3 + }, + "height": "150", + "hiddenSeries": false, + "id": 213, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": true, + "show": false, + "sideWidth": 500, + "sort": null, + "sortDesc": null, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": true, + "targets": [ + { + "expr": "sum(nginx_ingress_controller_nginx_process_connections{state=\"active\", controller=~\"$controller\", controller!~\".*-failover\", node=~\"$node\", job=\"nginx-ingress-controller\"})", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "B", + "step": 10 + }, + { + "expr": "sum(nginx_ingress_controller_nginx_process_connections{state=\"active\", controller=~\"$controller\", controller!~\".*-failover\", node=~\"$node\", job=\"nginx-ingress-controller\"}) $by", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "A", + "step": 10 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Active Connections", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "fill": 5, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 8, + "x": 16, + "y": 3 + }, + "height": "150", + "hiddenSeries": false, + "id": 230, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": true, + "show": false, + "sideWidth": 500, + "sort": null, + "sortDesc": null, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": true, + "targets": [ + { + "expr": "sum(nginx_ingress_controller_nginx_process_connections{state=\"active\", controller=~\"$controller\", controller!~\".*-failover\", node=~\"$node\", job=\"nginx-ingress-controller\"}) $by / scalar(sum(nginx_ingress_controller_nginx_process_connections{state=\"active\", controller!~\".*-failover\", node=~\"$node\", job=\"nginx-ingress-controller\"}))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "A", + "step": 10 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Active Connections %", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "percentunit", + "label": "", + "logBase": 1, + "max": "1", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "fill": 5, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 16, + "x": 0, + "y": 8 + }, + "height": "150", + "hiddenSeries": false, + "id": 231, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": true, + "show": false, + "sideWidth": 500, + "sort": null, + "sortDesc": null, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": true, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_detail_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", vhost=~\"_\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "B", + "step": 10 + }, + { + "expr": "sum(rate(ingress_nginx_detail_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", vhost=~\"_\"}[$__rate_interval])) $by", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "A", + "step": 10 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Requests to Default Server", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "fill": 5, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 8, + "x": 16, + "y": 8 + }, + "height": "150", + "hiddenSeries": false, + "id": 232, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": true, + "show": false, + "sideWidth": 500, + "sort": null, + "sortDesc": null, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": true, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_detail_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", vhost=~\"_\"}[$__rate_interval])) $by\n/ scalar(sum(rate(ingress_nginx_detail_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", vhost=~\"_\"}[$__rate_interval])))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "A", + "step": 10 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Requests to Default Server %", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "percentunit", + "label": "", + "logBase": 1, + "max": "1", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "collapsed": false, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 13 + }, + "id": 126, + "panels": [], + "title": "Main", + "type": "row" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "rgb(31, 120, 193)", + "mode": "fixed" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 0, + "y": 14 + }, + "id": 26, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]))", + "format": "time_series", + "instant": true, + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "Requests", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "rgb(31, 120, 193)", + "mode": "fixed" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 3, + "y": 14 + }, + "id": 111, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "sum(increase(ingress_nginx_${metric}_upstream_retries_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]))\n / sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]))\nor vector(0)", + "format": "time_series", + "instant": true, + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "Retried Requests", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "rgb(31, 120, 193)", + "mode": "fixed" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 6, + "y": 14 + }, + "id": 47, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "sum(increase(ingress_nginx_${metric}_received_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]))", + "format": "time_series", + "instant": true, + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "In Traffic", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "rgb(31, 120, 193)", + "mode": "fixed" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 9, + "y": 14 + }, + "id": 48, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "sum(increase(ingress_nginx_${metric}_sent_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]))", + "format": "time_series", + "instant": true, + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "Out Traffic", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "rgb(31, 120, 193)", + "mode": "fixed" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ops" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 12, + "y": 14 + }, + "id": 109, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]))", + "format": "time_series", + "instant": true, + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "Avg RPS", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 15, + "y": 14 + }, + "id": 65, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_request_seconds_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]))\n / sum(rate(ingress_nginx_${metric}_request_seconds_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]))\n * 1000", + "format": "time_series", + "instant": true, + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "Avg Req Time", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 18, + "y": 14 + }, + "id": 69, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "sum(increase(ingress_nginx_${metric}_upstream_response_seconds_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]))\n / sum(increase(ingress_nginx_${metric}_upstream_response_seconds_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]))\n * 1000", + "format": "time_series", + "instant": true, + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "Avg Upstr Time", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "rgb(31, 120, 193)", + "mode": "fixed" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 21, + "y": 14 + }, + "id": 110, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", scheme=\"https\"}[$__rate_interval]))\n / (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) > 0)", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "HTTPS", + "type": "stat" + }, + { + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": null, + "displayMode": "auto", + "minWidth": 64 + }, + "decimals": 2, + "displayName": "", + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Time" + }, + "properties": [ + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #A" + }, + "properties": [ + { + "id": "displayName", + "value": "RPS" + }, + { + "id": "unit", + "value": "ops" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 85 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #B" + }, + "properties": [ + { + "id": "displayName", + "value": "Retried Req" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 85 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #C" + }, + "properties": [ + { + "id": "displayName", + "value": "Req Time" + }, + { + "id": "unit", + "value": "s" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 85 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #D" + }, + "properties": [ + { + "id": "displayName", + "value": "Upstr Time" + }, + { + "id": "unit", + "value": "s" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 85 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #E" + }, + "properties": [ + { + "id": "displayName", + "value": "In Traffic" + }, + { + "id": "unit", + "value": "bps" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 85 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #F" + }, + "properties": [ + { + "id": "displayName", + "value": "Out Traffic" + }, + { + "id": "unit", + "value": "bps" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 85 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #G" + }, + "properties": [ + { + "id": "displayName", + "value": "Req Size" + }, + { + "id": "unit", + "value": "bytes" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 85 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #H" + }, + "properties": [ + { + "id": "displayName", + "value": "Resp Size" + }, + { + "id": "unit", + "value": "bytes" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 85 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #I" + }, + "properties": [ + { + "id": "displayName", + "value": "1xx" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #J" + }, + "properties": [ + { + "id": "displayName", + "value": "2xx" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #K" + }, + "properties": [ + { + "id": "displayName", + "value": "3xx" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #L" + }, + "properties": [ + { + "id": "displayName", + "value": "4xx" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #M" + }, + "properties": [ + { + "id": "displayName", + "value": "5xx" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #N" + }, + "properties": [ + { + "id": "displayName", + "value": "HTTPS" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #O" + }, + "properties": [ + { + "id": "displayName", + "value": "GET" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #P" + }, + "properties": [ + { + "id": "displayName", + "value": "POST" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #Q" + }, + "properties": [ + { + "id": "displayName", + "value": "HEAD" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #R" + }, + "properties": [ + { + "id": "displayName", + "value": "PUT" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #S" + }, + "properties": [ + { + "id": "displayName", + "value": "DELETE" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #T" + }, + "properties": [ + { + "id": "displayName", + "value": "OPTIONS" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #U" + }, + "properties": [ + { + "id": "displayName", + "value": "PATCH" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "controller" + }, + "properties": [ + { + "id": "displayName", + "value": "Controller" + }, + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "links", + "value": [ + { + "targetBlank": false, + "title": "Open Controller Detail", + "url": "/d/kZxJEeMmz/controller-detail?var-controller=${__value.raw}&${__url_time_range}" + } + ] + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 100 + } + ] + } + ] + }, + "gridPos": { + "h": 6, + "w": 24, + "x": 0, + "y": 16 + }, + "id": 28, + "links": [], + "options": { + "showHeader": true + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "(sum(rate(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "A" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_upstream_retries_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by\n / (sum(rate(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "legendFormat": "", + "refId": "B" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_request_seconds_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by\n / (sum(increase(ingress_nginx_${metric}_request_seconds_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "legendFormat": "", + "refId": "C" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_upstream_response_seconds_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by\n / (sum(increase(ingress_nginx_${metric}_upstream_response_seconds_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "legendFormat": "", + "refId": "D" + }, + { + "expr": "(sum(rate(ingress_nginx_${metric}_received_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by * 8 > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "legendFormat": "", + "refId": "E" + }, + { + "expr": "(sum(rate(ingress_nginx_${metric}_sent_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by * 8 > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "F" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_received_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by\n / (sum(increase(ingress_nginx_${metric}_received_bytes_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "G" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_sent_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by\n / (sum(increase(ingress_nginx_${metric}_sent_bytes_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "H" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"1..\"}[$__range])) $by\n/ (sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "I" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"2..\"}[$__range])) $by\n/ (sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "J" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"3..\"}[$__range])) $by\n/ (sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "K" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"4..\"}[$__range])) $by\n/ (sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "L" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"5..\"}[$__range])) $by\n/ (sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "M" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", scheme=\"https\"}[$__range])) $by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "N" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"GET\"}[$__range])) $by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "O" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"POST\"}[$__range])) $by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "P" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"HEAD\"}[$__range])) $by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "Q" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"PUT\"}[$__range])) $by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "R" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"DELETE\"}[$__range])) $by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "S" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"OPTIONS\"}[$__range])) $by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "T" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"PATCH\"}[$__range])) $by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "U" + } + ], + "title": "Average", + "transformations": [ + { + "id": "merge", + "options": { + "reducers": [] + } + }, + { + "id": "filterFieldsByName", + "options": { + "include": { + "names": [ + "controller", + "Value #A", + "Value #B", + "Value #C", + "Value #D", + "Value #E", + "Value #F", + "Value #G", + "Value #H", + "Value #I", + "Value #J", + "Value #K", + "Value #L", + "Value #M", + "Value #N", + "Value #O", + "Value #P", + "Value #Q", + "Value #R", + "Value #S", + "Value #T", + "Value #U" + ] + } + } + } + ], + "type": "table" + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 16, + "x": 0, + "y": 22 + }, + "hiddenSeries": false, + "id": 1, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sort": "total", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A", + "step": 20 + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $by > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Requests", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 8, + "x": 16, + "y": 22 + }, + "hiddenSeries": false, + "id": 80, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sort": "total", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $by\n / scalar(sum(rate(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))) > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Requests %", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "percentunit", + "label": "", + "logBase": 1, + "max": "1", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "3xx": "#6ED0E0", + "4xx": "#EAB839", + "5xx": "#BF1B00" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 16, + "x": 0, + "y": 27 + }, + "hiddenSeries": false, + "id": 235, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": true, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + }, + { + "alias": "2xx", + "color": "#73BF69" + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A" + }, + { + "expr": "sum(label_replace(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]), \"status_group\", \"${1}xx\", \"status\", \"([0-9])..\")) by (status_group) > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{ status_group }}", + "refId": "B", + "step": 40 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Responses", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "3xx": "#6ED0E0", + "4xx": "#EAB839", + "5xx": "#BF1B00" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 8, + "x": 16, + "y": 27 + }, + "hiddenSeries": false, + "id": 236, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": true, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(label_replace(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]), \"status_group\", \"${1}xx\", \"status\", \"([0-9])..\")) by (status_group)\n / scalar(sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))) > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{ status_group }}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Responses %", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "percentunit", + "label": "", + "logBase": 1, + "max": "1", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 8, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 16, + "x": 0, + "y": 32 + }, + "hiddenSeries": false, + "hideTimeOverride": false, + "id": 4, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sideWidth": null, + "sort": null, + "sortDesc": null, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 0, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "0.005", + "color": "#76B576" + }, + { + "alias": "0.01", + "color": "#83BC6D" + }, + { + "alias": "0.02", + "color": "#91C364" + }, + { + "alias": "0.03", + "color": "#9FCB5B" + }, + { + "alias": "0.04", + "color": "#ACD252" + }, + { + "alias": "0.05", + "color": "#BADA49" + }, + { + "alias": "0.075", + "color": "#C8E140" + }, + { + "alias": "0.1", + "color": "#D5E837" + }, + { + "alias": "0.2", + "color": "#E3F02E" + }, + { + "alias": "0.3", + "color": "#F1F725" + }, + { + "alias": "0.4", + "color": "#FFFF1C" + }, + { + "alias": "0.5", + "color": "#FAE519" + }, + { + "alias": "0.75", + "color": "#F6CC16" + }, + { + "alias": "1", + "color": "#F2B213" + }, + { + "alias": "1.5", + "color": "#EE9910" + }, + { + "alias": "2", + "color": "#EA7F0E" + }, + { + "alias": "3", + "color": "#E6660B" + }, + { + "alias": "4", + "color": "#E24C08" + }, + { + "alias": "5", + "color": "#DE3205" + }, + { + "alias": "10", + "color": "#DA1902" + }, + { + "alias": "+Inf", + "color": "#D60000" + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_lowres_upstream_response_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)", + "format": "heatmap", + "intervalFactor": 1, + "legendFormat": "{{le}}", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Upstream Response Time", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + "total" + ] + }, + "yaxes": [ + { + "decimals": null, + "format": "ops", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 8, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 8, + "x": 16, + "y": 32 + }, + "hiddenSeries": false, + "hideTimeOverride": false, + "id": 81, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sideWidth": null, + "sort": null, + "sortDesc": null, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 0, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "0.005", + "color": "#76B576" + }, + { + "alias": "0.01", + "color": "#83BC6D" + }, + { + "alias": "0.02", + "color": "#91C364" + }, + { + "alias": "0.03", + "color": "#9FCB5B" + }, + { + "alias": "0.04", + "color": "#ACD252" + }, + { + "alias": "0.05", + "color": "#BADA49" + }, + { + "alias": "0.075", + "color": "#C8E140" + }, + { + "alias": "0.1", + "color": "#D5E837" + }, + { + "alias": "0.2", + "color": "#E3F02E" + }, + { + "alias": "0.3", + "color": "#F1F725" + }, + { + "alias": "0.4", + "color": "#FFFF1C" + }, + { + "alias": "0.5", + "color": "#FAE519" + }, + { + "alias": "0.75", + "color": "#F6CC16" + }, + { + "alias": "1", + "color": "#F2B213" + }, + { + "alias": "1.5", + "color": "#EE9910" + }, + { + "alias": "2", + "color": "#EA7F0E" + }, + { + "alias": "3", + "color": "#E6660B" + }, + { + "alias": "4", + "color": "#E24C08" + }, + { + "alias": "5", + "color": "#DE3205" + }, + { + "alias": "10", + "color": "#DA1902" + }, + { + "alias": "+Inf", + "color": "#D60000" + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_lowres_upstream_response_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)\n / scalar(sum(rate(ingress_nginx_${metric}_lowres_upstream_response_seconds_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])))", + "format": "heatmap", + "intervalFactor": 1, + "legendFormat": "{{le}}", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Upstream Response Time %", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + "total" + ] + }, + "yaxes": [ + { + "format": "percentunit", + "label": null, + "logBase": 1, + "max": "1", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 8, + "x": 0, + "y": 38 + }, + "hiddenSeries": false, + "hideTimeOverride": false, + "id": 62, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sideWidth": null, + "sort": null, + "sortDesc": null, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": true, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_upstream_retries_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_upstream_retries_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $by > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Retried Requests", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + "total" + ] + }, + "yaxes": [ + { + "format": "ops", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 8, + "x": 8, + "y": 38 + }, + "hiddenSeries": false, + "hideTimeOverride": false, + "id": 112, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sideWidth": null, + "sort": null, + "sortDesc": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_upstream_retries_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $by\n/ sum(rate(ingress_nginx_${metric}_upstream_retries_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $by\n> 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Retries (per Retried Request)", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + "total" + ] + }, + "yaxes": [ + { + "format": "ops", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "3xx": "#6ED0E0", + "4xx": "#EAB839", + "5xx": "#BF1B00" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 8, + "x": 16, + "y": 38 + }, + "hiddenSeries": false, + "id": 196, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": true, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"1..\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"1..\"}[$__rate_interval])) $by > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "B", + "step": 40 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "1xx", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "3xx": "#6ED0E0", + "4xx": "#EAB839", + "5xx": "#BF1B00" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 8, + "x": 16, + "y": 42 + }, + "hiddenSeries": false, + "id": 87, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": true, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"2..\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"2..\"}[$__rate_interval])) $by > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "B", + "step": 40 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "2xx", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": null, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 8, + "x": 0, + "y": 43 + }, + "hiddenSeries": false, + "hideTimeOverride": false, + "id": 49, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sideWidth": null, + "sort": null, + "sortDesc": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_request_seconds_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $by\n / sum(rate(ingress_nginx_${metric}_request_seconds_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $by > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Avg Request Time", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + "total" + ] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": null, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 8, + "x": 8, + "y": 43 + }, + "hiddenSeries": false, + "hideTimeOverride": false, + "id": 63, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sideWidth": null, + "sort": null, + "sortDesc": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_upstream_response_seconds_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $by\n / sum(rate(ingress_nginx_${metric}_upstream_response_seconds_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $by > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Avg Upstream Response Time", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + "total" + ] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "3xx": "#6ED0E0", + "4xx": "#EAB839", + "5xx": "#BF1B00" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 8, + "x": 16, + "y": 46 + }, + "hiddenSeries": false, + "id": 10, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": true, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"3..\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"3..\"}[$__rate_interval])) $by > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "B", + "step": 40 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "3xx", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": null, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 8, + "x": 0, + "y": 48 + }, + "hiddenSeries": false, + "hideTimeOverride": false, + "id": 58, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sideWidth": null, + "sort": null, + "sortDesc": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_received_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $by\n / sum(rate(ingress_nginx_${metric}_received_bytes_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $by > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Avg Request Size", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + "total" + ] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": null, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 8, + "x": 8, + "y": 48 + }, + "hiddenSeries": false, + "hideTimeOverride": false, + "id": 73, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sideWidth": null, + "sort": null, + "sortDesc": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_sent_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $by\n / sum(rate(ingress_nginx_${metric}_sent_bytes_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $by > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Avg Response Size", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + "total" + ] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "3xx": "#6ED0E0", + "4xx": "#EAB839", + "5xx": "#BF1B00" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 8, + "x": 16, + "y": 50 + }, + "hiddenSeries": false, + "id": 18, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": true, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"4..\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"4..\"}[$__rate_interval])) $by > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "B", + "step": 40 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "4xx", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 8, + "x": 0, + "y": 53 + }, + "hiddenSeries": false, + "id": 12, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_received_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) * 8", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A", + "step": 20 + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_received_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $by * 8 > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "B", + "step": 20 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Incoming Traffic", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bps", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 8, + "x": 8, + "y": 53 + }, + "hiddenSeries": false, + "id": 9, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sort": "max", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_sent_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) * 8", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A", + "step": 20 + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_sent_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $by * 8 > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Outgoing Traffic", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bps", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "3xx": "#6ED0E0", + "4xx": "#EAB839", + "5xx": "#BF1B00" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 8, + "x": 16, + "y": 54 + }, + "hiddenSeries": false, + "id": 17, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": true, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"5..\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"5..\"}[$__rate_interval])) $by > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "B", + "step": 40 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "5xx", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "collapsed": false, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 58 + }, + "id": 195, + "panels": [], + "title": "Status Codes", + "type": "row" + }, + { + "aliasColors": { + "3xx": "#6ED0E0", + "4xx": "#EAB839", + "5xx": "#BF1B00" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 8, + "x": 0, + "y": 59 + }, + "hiddenSeries": false, + "id": 189, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": true, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": true, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"1..\"}[$__rate_interval])) by (status)\n / scalar(sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"1..\"}[$__rate_interval])))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{status}}", + "refId": "B", + "step": 40 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "1xx", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "percentunit", + "label": "", + "logBase": 1, + "max": "100", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "3xx": "#6ED0E0", + "4xx": "#EAB839", + "5xx": "#BF1B00" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 8, + "x": 8, + "y": 59 + }, + "hiddenSeries": false, + "id": 190, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": true, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": true, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"2..\"}[$__rate_interval])) by (status)\n / scalar(sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"2..\"}[$__rate_interval])))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{status}}", + "refId": "B", + "step": 40 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "2xx", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "percentunit", + "label": "", + "logBase": 1, + "max": "100", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "3xx": "#6ED0E0", + "4xx": "#EAB839", + "5xx": "#BF1B00" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 8, + "x": 16, + "y": 59 + }, + "hiddenSeries": false, + "id": 191, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": true, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": true, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"3..\"}[$__rate_interval])) by (status)\n / scalar(sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"3..\"}[$__rate_interval])))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{status}}", + "refId": "B", + "step": 40 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "3xx", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "percentunit", + "label": "", + "logBase": 1, + "max": "100", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "3xx": "#6ED0E0", + "4xx": "#EAB839", + "5xx": "#BF1B00" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 12, + "x": 0, + "y": 63 + }, + "hiddenSeries": false, + "id": 192, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": true, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": true, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"4..\"}[$__rate_interval])) by (status)\n / scalar(sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"4..\"}[$__rate_interval])))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{status}}", + "refId": "B", + "step": 40 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "4xx", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "percentunit", + "label": "", + "logBase": 1, + "max": "100", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "3xx": "#6ED0E0", + "4xx": "#EAB839", + "5xx": "#BF1B00" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 12, + "x": 12, + "y": 63 + }, + "hiddenSeries": false, + "id": 193, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": true, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": true, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"5..\"}[$__rate_interval])) by (status)\n / scalar(sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"5..\"}[$__rate_interval])))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{status}}", + "refId": "B", + "step": 40 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "5xx", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "percentunit", + "label": "", + "logBase": 1, + "max": "100", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "3xx": "#6ED0E0", + "4xx": "#EAB839", + "5xx": "#BF1B00" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 8, + "x": 0, + "y": 68 + }, + "hiddenSeries": false, + "id": 86, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": true, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "maxPerRow": 4, + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": "status", + "repeatDirection": "h", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=\"$status\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=\"$status\"}[$__rate_interval])) $by > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "B", + "step": 40 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "$status", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "collapsed": true, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 72 + }, + "id": 150, + "panels": [ + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 0, + "y": 60 + }, + "id": 130, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_request_seconds_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))\n / sum(rate(ingress_nginx_${metric}_request_seconds_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))\n * 1000", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "Avg Req Time", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 3, + "y": 60 + }, + "id": 132, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "histogram_quantile(0.5, sum(rate(ingress_nginx_${metric}_request_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)) * 1000", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "50th Req Time", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 6, + "y": 60 + }, + "id": 134, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "histogram_quantile(0.9, sum(rate(ingress_nginx_${metric}_request_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)) * 1000", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "90th Req Time", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 9, + "y": 60 + }, + "id": 174, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "histogram_quantile(0.99, sum(rate(ingress_nginx_${metric}_request_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)) * 1000", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "99th Req Time", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 12, + "y": 60 + }, + "id": 140, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_upstream_response_seconds_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))\n / sum(rate(ingress_nginx_${metric}_upstream_response_seconds_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))\n * 1000", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "Avg Upstr Time", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 15, + "y": 60 + }, + "id": 142, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "histogram_quantile(0.5, sum(rate(ingress_nginx_${metric}_upstream_response_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)) * 1000", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "50th Upstr Time", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 18, + "y": 60 + }, + "id": 144, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "histogram_quantile(0.9, sum(rate(ingress_nginx_${metric}_upstream_response_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)) * 1000", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "90th Upstr Time", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 21, + "y": 60 + }, + "id": 146, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "histogram_quantile(0.99, sum(rate(ingress_nginx_${metric}_upstream_response_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)) * 1000", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "99th Upstr Time", + "type": "stat" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": null, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 12, + "x": 0, + "y": 62 + }, + "hiddenSeries": false, + "hideTimeOverride": false, + "id": 136, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sideWidth": null, + "sort": null, + "sortDesc": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Avg", + "fill": 2, + "linewidth": 0 + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "histogram_quantile(0.99, sum(rate(ingress_nginx_${metric}_request_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)) * 1000", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "99th", + "refId": "A" + }, + { + "expr": "histogram_quantile(0.9, sum(rate(ingress_nginx_${metric}_request_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)) * 1000", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "90th", + "refId": "B" + }, + { + "expr": "histogram_quantile(0.5, sum(rate(ingress_nginx_${metric}_request_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)) * 1000", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "50th", + "refId": "C" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_request_seconds_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))\n / sum(rate(ingress_nginx_${metric}_request_seconds_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))\n * 1000", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Avg", + "refId": "D" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Request Time", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + "total" + ] + }, + "yaxes": [ + { + "format": "ms", + "label": null, + "logBase": 10, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": null, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 12, + "x": 12, + "y": 62 + }, + "hiddenSeries": false, + "hideTimeOverride": false, + "id": 148, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sideWidth": null, + "sort": null, + "sortDesc": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Avg", + "fill": 2, + "linewidth": 0 + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "histogram_quantile(0.99, sum(rate(ingress_nginx_${metric}_upstream_response_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)) * 1000", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "99th", + "refId": "A" + }, + { + "expr": "histogram_quantile(0.9, sum(rate(ingress_nginx_${metric}_upstream_response_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)) * 1000", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "90th", + "refId": "B" + }, + { + "expr": "histogram_quantile(0.5, sum(rate(ingress_nginx_${metric}_upstream_response_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)) * 1000", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "50th", + "refId": "C" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_upstream_response_seconds_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))\n / sum(rate(ingress_nginx_${metric}_upstream_response_seconds_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))\n * 1000", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Avg", + "refId": "D" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Upstream Response Time", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + "total" + ] + }, + "yaxes": [ + { + "format": "ms", + "label": null, + "logBase": 10, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "title": "Request Time and Upstream Response Time", + "type": "row" + }, + { + "collapsed": true, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 73 + }, + "id": 211, + "panels": [ + { + "cards": { + "cardPadding": 0, + "cardRound": 0 + }, + "color": { + "cardColor": "#b4ff00", + "colorScale": "sqrt", + "colorScheme": "interpolateYlGnBu", + "exponent": 0.5, + "max": null, + "min": 0, + "mode": "spectrum" + }, + "dataFormat": "tsbuckets", + "datasource": null, + "gridPos": { + "h": 21, + "w": 12, + "x": 0, + "y": 61 + }, + "heatmap": {}, + "hideZeroBuckets": false, + "highlightCards": true, + "id": 152, + "legend": { + "show": true + }, + "links": [], + "reverseYBuckets": false, + "targets": [ + { + "expr": "sum(increase(ingress_nginx_${metric}_request_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le) > 0", + "format": "heatmap", + "intervalFactor": 1, + "legendFormat": "{{le}}", + "refId": "A" + } + ], + "title": "Request Time", + "tooltip": { + "show": true, + "showHistogram": true + }, + "type": "heatmap", + "xAxis": { + "show": true + }, + "xBucketNumber": null, + "xBucketSize": null, + "yAxis": { + "decimals": 1, + "format": "s", + "logBase": 1, + "max": null, + "min": null, + "show": true, + "splitFactor": null + }, + "yBucketBound": "auto", + "yBucketNumber": null, + "yBucketSize": null + }, + { + "cards": { + "cardPadding": 0, + "cardRound": 0 + }, + "color": { + "cardColor": "#b4ff00", + "colorScale": "sqrt", + "colorScheme": "interpolateYlGnBu", + "exponent": 0.5, + "max": null, + "min": 0, + "mode": "spectrum" + }, + "dataFormat": "tsbuckets", + "datasource": null, + "gridPos": { + "h": 21, + "w": 12, + "x": 12, + "y": 61 + }, + "heatmap": {}, + "hideZeroBuckets": false, + "highlightCards": true, + "id": 153, + "legend": { + "show": true + }, + "links": [], + "reverseYBuckets": false, + "targets": [ + { + "expr": "sum(increase(ingress_nginx_${metric}_upstream_response_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le) > 0", + "format": "heatmap", + "intervalFactor": 1, + "legendFormat": "{{le}}", + "refId": "A" + } + ], + "title": "Upstream Response Time", + "tooltip": { + "show": true, + "showHistogram": true + }, + "type": "heatmap", + "xAxis": { + "show": true + }, + "xBucketNumber": null, + "xBucketSize": null, + "yAxis": { + "decimals": 1, + "format": "s", + "logBase": 1, + "max": null, + "min": null, + "show": true, + "splitFactor": null + }, + "yBucketBound": "auto", + "yBucketNumber": null, + "yBucketSize": null + } + ], + "title": "Request Time Heatmap and Upstream Response Time Heatmap", + "type": "row" + }, + { + "collapsed": true, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 74 + }, + "id": 160, + "panels": [ + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 0, + "y": 62 + }, + "id": 171, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_received_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))\n / sum(rate(ingress_nginx_${metric}_received_bytes_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "Avg Req Size", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 3, + "y": 62 + }, + "id": 172, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "histogram_quantile(0.5, sum(rate(ingress_nginx_${metric}_received_bytes_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le))", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "50th Req Size", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 6, + "y": 62 + }, + "id": 173, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "histogram_quantile(0.9, sum(rate(ingress_nginx_${metric}_received_bytes_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le))", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "90th Req Size", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 9, + "y": 62 + }, + "id": 128, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "histogram_quantile(0.99, sum(rate(ingress_nginx_${metric}_received_bytes_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le))", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "99th Req Size", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 12, + "y": 62 + }, + "id": 175, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_sent_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))\n / sum(rate(ingress_nginx_${metric}_sent_bytes_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "Avg Resp Size", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 15, + "y": 62 + }, + "id": 176, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "histogram_quantile(0.5, sum(rate(ingress_nginx_${metric}_sent_bytes_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le))", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "50th Resp Size", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 18, + "y": 62 + }, + "id": 177, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "histogram_quantile(0.9, sum(rate(ingress_nginx_${metric}_sent_bytes_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le))", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "90th Resp Size", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 21, + "y": 62 + }, + "id": 178, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "histogram_quantile(0.99, sum(rate(ingress_nginx_${metric}_sent_bytes_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le))", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "99th Resp Size", + "type": "stat" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": null, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 12, + "x": 0, + "y": 64 + }, + "hiddenSeries": false, + "hideTimeOverride": false, + "id": 155, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sideWidth": null, + "sort": null, + "sortDesc": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Avg", + "fill": 2, + "linewidth": 0 + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "histogram_quantile(0.99, sum(rate(ingress_nginx_${metric}_received_bytes_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "99th", + "refId": "A" + }, + { + "expr": "histogram_quantile(0.9, sum(rate(ingress_nginx_${metric}_received_bytes_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "90th", + "refId": "B" + }, + { + "expr": "histogram_quantile(0.5, sum(rate(ingress_nginx_${metric}_received_bytes_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "50th", + "refId": "C" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_received_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))\n / sum(rate(ingress_nginx_${metric}_received_bytes_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Avg", + "refId": "D" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Request Size", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + "total" + ] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 2, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": null, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 12, + "x": 12, + "y": 64 + }, + "hiddenSeries": false, + "hideTimeOverride": false, + "id": 157, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sideWidth": null, + "sort": null, + "sortDesc": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Avg", + "fill": 2, + "linewidth": 0 + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "histogram_quantile(0.99, sum(rate(ingress_nginx_${metric}_sent_bytes_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "99th", + "refId": "A" + }, + { + "expr": "histogram_quantile(0.9, sum(rate(ingress_nginx_${metric}_sent_bytes_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "90th", + "refId": "B" + }, + { + "expr": "histogram_quantile(0.5, sum(rate(ingress_nginx_${metric}_sent_bytes_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "50th", + "refId": "C" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_sent_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))\n / sum(rate(ingress_nginx_${metric}_sent_bytes_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Avg", + "refId": "D" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Response Size", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + "total" + ] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 2, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "title": "Request Size and Response Size", + "type": "row" + }, + { + "collapsed": true, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 75 + }, + "id": 209, + "panels": [ + { + "cards": { + "cardPadding": 0, + "cardRound": 0 + }, + "color": { + "cardColor": "#b4ff00", + "colorScale": "sqrt", + "colorScheme": "interpolateYlGnBu", + "exponent": 0.5, + "max": null, + "min": 0, + "mode": "spectrum" + }, + "dataFormat": "tsbuckets", + "datasource": null, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 63 + }, + "heatmap": {}, + "hideZeroBuckets": false, + "highlightCards": true, + "id": 158, + "legend": { + "show": true + }, + "links": [], + "reverseYBuckets": false, + "targets": [ + { + "expr": "sum(increase(ingress_nginx_${metric}_received_bytes_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)", + "format": "heatmap", + "intervalFactor": 1, + "legendFormat": "{{le}}", + "refId": "A" + } + ], + "title": "Request Size", + "tooltip": { + "show": true, + "showHistogram": true + }, + "type": "heatmap", + "xAxis": { + "show": true + }, + "xBucketNumber": null, + "xBucketSize": null, + "yAxis": { + "decimals": 0, + "format": "bytes", + "logBase": 1, + "max": null, + "min": null, + "show": true, + "splitFactor": null + }, + "yBucketBound": "auto", + "yBucketNumber": null, + "yBucketSize": null + }, + { + "cards": { + "cardPadding": 0, + "cardRound": 0 + }, + "color": { + "cardColor": "#b4ff00", + "colorScale": "sqrt", + "colorScheme": "interpolateYlGnBu", + "exponent": 0.5, + "max": null, + "min": 0, + "mode": "spectrum" + }, + "dataFormat": "tsbuckets", + "datasource": null, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 63 + }, + "heatmap": {}, + "hideZeroBuckets": false, + "highlightCards": true, + "id": 161, + "legend": { + "show": true + }, + "links": [], + "reverseYBuckets": false, + "targets": [ + { + "expr": "sum(increase(ingress_nginx_${metric}_sent_bytes_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)", + "format": "heatmap", + "intervalFactor": 1, + "legendFormat": "{{le}}", + "refId": "A" + } + ], + "title": "Response Size", + "tooltip": { + "show": true, + "showHistogram": true + }, + "type": "heatmap", + "xAxis": { + "show": true + }, + "xBucketNumber": null, + "xBucketSize": null, + "yAxis": { + "decimals": 0, + "format": "bytes", + "logBase": 1, + "max": null, + "min": null, + "show": true, + "splitFactor": null + }, + "yBucketBound": "auto", + "yBucketNumber": null, + "yBucketSize": null + } + ], + "title": "Request Size Heatmap and Response Size Heatmap", + "type": "row" + }, + { + "collapsed": true, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 76 + }, + "id": 89, + "panels": [ + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 12, + "x": 0, + "y": 64 + }, + "hiddenSeries": false, + "id": 61, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sort": "total", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (method)\n / scalar(sum(rate(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{method}}", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Method %", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "percentunit", + "label": "", + "logBase": 1, + "max": "1", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 12, + "x": 12, + "y": 64 + }, + "hiddenSeries": false, + "id": 60, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sort": "total", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\"}[$__rate_interval])) by (content_kind)\n/ scalar(sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\"}[$__rate_interval])))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{content_kind}}", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Content Kind %", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "percentunit", + "label": "", + "logBase": 1, + "max": "1", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 12, + "x": 0, + "y": 70 + }, + "hiddenSeries": false, + "id": 90, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sort": "total", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": "method", + "repeatDirection": "v", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"$method\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"$method\"}[$__rate_interval])) $by > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "$method", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 12, + "x": 12, + "y": 70 + }, + "hiddenSeries": false, + "id": 97, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sort": "total", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": "content_kind", + "repeatDirection": "v", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=\"$content_kind\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=\"$content_kind\"}[$__rate_interval])) $by > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "$content_kind", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "title": "Request Method and Content Kind", + "type": "row" + }, + { + "collapsed": true, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 77 + }, + "id": 79, + "panels": [ + { + "circleMaxSize": "10", + "circleMinSize": 2, + "colors": [ + "#890f02", + "#890f02" + ], + "datasource": "$ds_prometheus", + "decimals": 0, + "esGeoPoint": "geohash", + "esLocationName": "place", + "esMetric": "Value", + "gridPos": { + "h": 18, + "w": 24, + "x": 0, + "y": 65 + }, + "hideEmpty": false, + "hideZero": false, + "id": 75, + "initialZoom": "3", + "links": [], + "locationData": "geohash", + "mapCenter": "Europe", + "mapCenterLatitude": 46, + "mapCenterLongitude": 14, + "maxDataPoints": 1, + "mouseWheelZoom": false, + "showLegend": false, + "stickyLabels": false, + "tableQueryOptions": { + "geohashField": "geohash", + "latitudeField": "latitude", + "longitudeField": "longitude", + "metricField": "metric", + "queryType": "geohash" + }, + "targets": [ + { + "expr": "sum(increase(ingress_nginx_${metric}_geohash_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) by (geohash, place) > 0", + "format": "table", + "instant": true, + "intervalFactor": 1, + "refId": "A" + } + ], + "thresholds": "", + "title": "Requests", + "type": "grafana-worldmap-panel", + "unitPlural": "", + "unitSingle": "", + "valueName": "total" + } + ], + "title": "Map", + "type": "row" + }, + { + "collapsed": true, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 78 + }, + "id": 46, + "panels": [ + { + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": null, + "displayMode": "auto", + "minWidth": 64 + }, + "decimals": 2, + "displayName": "", + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Time" + }, + "properties": [ + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #A" + }, + "properties": [ + { + "id": "displayName", + "value": "RPS" + }, + { + "id": "unit", + "value": "ops" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 85 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #B" + }, + "properties": [ + { + "id": "displayName", + "value": "Retried Req" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #C" + }, + "properties": [ + { + "id": "displayName", + "value": "Req Time" + }, + { + "id": "unit", + "value": "s" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 85 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #D" + }, + "properties": [ + { + "id": "displayName", + "value": "Resp Time" + }, + { + "id": "unit", + "value": "s" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 85 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #E" + }, + "properties": [ + { + "id": "displayName", + "value": "In Traffic" + }, + { + "id": "unit", + "value": "bps" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 85 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #F" + }, + "properties": [ + { + "id": "displayName", + "value": "Out Traffic" + }, + { + "id": "unit", + "value": "bps" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #G" + }, + "properties": [ + { + "id": "displayName", + "value": "Req Size" + }, + { + "id": "unit", + "value": "bytes" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #H" + }, + "properties": [ + { + "id": "displayName", + "value": "Resp Size" + }, + { + "id": "unit", + "value": "bytes" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #I" + }, + "properties": [ + { + "id": "displayName", + "value": "1xx" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #J" + }, + "properties": [ + { + "id": "displayName", + "value": "2xx" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #K" + }, + "properties": [ + { + "id": "displayName", + "value": "3xx" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #L" + }, + "properties": [ + { + "id": "displayName", + "value": "4xx" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #M" + }, + "properties": [ + { + "id": "displayName", + "value": "5xx" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #N" + }, + "properties": [ + { + "id": "displayName", + "value": "HTTPS" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #O" + }, + "properties": [ + { + "id": "displayName", + "value": "GET" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #P" + }, + "properties": [ + { + "id": "displayName", + "value": "POST" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #Q" + }, + "properties": [ + { + "id": "displayName", + "value": "HEAD" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #R" + }, + "properties": [ + { + "id": "displayName", + "value": "PUT" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #S" + }, + "properties": [ + { + "id": "displayName", + "value": "DELETE" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #T" + }, + "properties": [ + { + "id": "displayName", + "value": "OPTIONS" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #U" + }, + "properties": [ + { + "id": "displayName", + "value": "PATCH" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "namespace" + }, + "properties": [ + { + "id": "displayName", + "value": "Namespace" + }, + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "links", + "value": [ + { + "targetBlank": false, + "title": "Open Namespace", + "url": "/d/Z-phNqGmz/namespaces?var-namespace=${__value.raw}&${__url_time_range}" + } + ] + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 120 + } + ] + } + ] + }, + "gridPos": { + "h": 6, + "w": 24, + "x": 0, + "y": 79 + }, + "id": 42, + "links": [], + "options": { + "showHeader": true + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "(sum(rate(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "instant": true, + "intervalFactor": 1, + "refId": "A" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_upstream_retries_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by\n / (sum(rate(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "legendFormat": "", + "refId": "B" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_request_seconds_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by\n / (sum(increase(ingress_nginx_${metric}_request_seconds_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "legendFormat": "", + "refId": "C" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_upstream_response_seconds_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by\n / (sum(increase(ingress_nginx_${metric}_upstream_response_seconds_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "legendFormat": "", + "refId": "D" + }, + { + "expr": "(sum(rate(ingress_nginx_${metric}_received_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by * 8 > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "legendFormat": "", + "refId": "E" + }, + { + "expr": "(sum(rate(ingress_nginx_${metric}_sent_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by * 8 > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "F" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_received_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by\n / (sum(increase(ingress_nginx_${metric}_received_bytes_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "G" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_sent_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by\n / (sum(increase(ingress_nginx_${metric}_sent_bytes_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "H" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"1..\"}[$__range])) $alt_by\n/ (sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "I" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"2..\"}[$__range])) $alt_by\n/ (sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "J" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"3..\"}[$__range])) $alt_by\n/ (sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "K" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"4..\"}[$__range])) $alt_by\n/ (sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "L" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"5..\"}[$__range])) $alt_by\n/ (sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "M" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", scheme=\"https\"}[$__range])) $alt_by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "N" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"GET\"}[$__range])) $alt_by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "O" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"POST\"}[$__range])) $alt_by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "P" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"HEAD\"}[$__range])) $alt_by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "Q" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"PUT\"}[$__range])) $alt_by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "R" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"DELETE\"}[$__range])) $alt_by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "S" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"OPTIONS\"}[$__range])) $alt_by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "T" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"PATCH\"}[$__range])) $alt_by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "U" + } + ], + "title": "Average", + "transformations": [ + { + "id": "merge", + "options": { + "reducers": [] + } + }, + { + "id": "filterFieldsByName", + "options": { + "include": { + "names": [ + "namespace", + "Value #A", + "Value #B", + "Value #C", + "Value #D", + "Value #E", + "Value #F", + "Value #G", + "Value #H", + "Value #I", + "Value #J", + "Value #K", + "Value #L", + "Value #M", + "Value #N", + "Value #O", + "Value #P", + "Value #Q", + "Value #R", + "Value #S", + "Value #T", + "Value #U" + ] + } + } + } + ], + "type": "table" + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 8, + "x": 0, + "y": 85 + }, + "hiddenSeries": false, + "id": 39, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sort": "total", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": true, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $alt_by > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$alt_legend_format", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Requests per $alt_name", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": "", + "logBase": 1, + "max": "100", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 1, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 8, + "x": 8, + "y": 85 + }, + "hiddenSeries": false, + "id": 41, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": true, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_received_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $alt_by * 8 > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$alt_legend_format", + "refId": "B", + "step": 20 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Incoming Traffic per $alt_name", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bps", + "label": null, + "logBase": 1, + "max": "100", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 1, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 8, + "x": 16, + "y": 85 + }, + "hiddenSeries": false, + "id": 40, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sort": "max", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": true, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_sent_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $alt_by * 8 > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$alt_legend_format", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Outgoing Traffic per $alt_name", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bps", + "label": null, + "logBase": 1, + "max": "100", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "title": "By $alt_name", + "type": "row" + } + ], + "refresh": "30s", + "schemaVersion": 32, + "style": "dark", + "tags": [ + "ingress" + ], + "templating": { + "list": [ + { + "current": { + "selected": false, + "text": "default", + "value": "default" + }, + "description": null, + "error": null, + "hide": 0, + "includeAll": false, + "label": "Prometheus", + "multi": false, + "name": "ds_prometheus", + "options": [], + "query": "prometheus", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + }, + { + "description": null, + "error": null, + "hide": 2, + "label": null, + "name": "metric", + "query": "overall", + "skipUrlSync": false, + "type": "constant" + }, + { + "description": null, + "error": null, + "hide": 2, + "label": null, + "name": "by", + "query": "by (controller)", + "skipUrlSync": false, + "type": "constant" + }, + { + "description": null, + "error": null, + "hide": 2, + "label": null, + "name": "legend_format", + "query": "{{controller}}", + "skipUrlSync": false, + "type": "constant" + }, + { + "hide": 2, + "name": "cadvisor_legend_format", + "query": "{{node}} ({{pod}})", + "skipUrlSync": false, + "type": "constant" + }, + { + "hide": 2, + "name": "cadvisor_by", + "query": "by (node, pod)", + "skipUrlSync": false, + "type": "constant" + }, + { + "description": null, + "error": null, + "hide": 2, + "label": null, + "name": "alt_name", + "query": "Namespace", + "skipUrlSync": false, + "type": "constant" + }, + { + "description": null, + "error": null, + "hide": 2, + "label": null, + "name": "alt_by", + "query": "by (namespace)", + "skipUrlSync": false, + "type": "constant" + }, + { + "description": null, + "error": null, + "hide": 2, + "label": null, + "name": "alt_legend_format", + "query": "{{namespace}}", + "skipUrlSync": false, + "type": "constant" + }, + { + "allValue": ".*", + "current": { + "selected": true, + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": "$ds_prometheus", + "definition": "", + "description": null, + "error": null, + "hide": 0, + "includeAll": true, + "label": "Controller", + "multi": true, + "name": "controller", + "options": [], + "query": { + "query": "label_values(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\"}, controller)", + "refId": "main-controller-Variable-Query" + }, + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "description": null, + "error": null, + "hide": 2, + "label": "App", + "name": "app", + "query": ".*", + "skipUrlSync": false, + "type": "constant" + }, + { + "description": null, + "error": null, + "hide": 2, + "label": "Node", + "name": "node", + "query": ".*", + "skipUrlSync": false, + "type": "constant" + }, + { + "description": null, + "error": null, + "hide": 2, + "label": "Namespace", + "name": "namespace", + "query": ".*", + "skipUrlSync": false, + "type": "constant" + }, + { + "description": null, + "error": null, + "hide": 2, + "label": "Ingress", + "name": "ingress", + "query": ".*", + "skipUrlSync": false, + "type": "constant" + }, + { + "description": null, + "error": null, + "hide": 2, + "label": "Service", + "name": "service", + "query": ".*", + "skipUrlSync": false, + "type": "constant" + }, + { + "description": null, + "error": null, + "hide": 2, + "label": "Service Port", + "name": "service_port", + "query": ".*", + "skipUrlSync": false, + "type": "constant" + }, + { + "description": null, + "error": null, + "hide": 2, + "label": "VHost", + "name": "vhost", + "query": ".*", + "skipUrlSync": false, + "type": "constant" + }, + { + "description": null, + "error": null, + "hide": 2, + "label": "Location", + "name": "location", + "query": ".*", + "skipUrlSync": false, + "type": "constant" + }, + { + "allValue": ".*", + "current": { + "selected": true, + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": "$ds_prometheus", + "definition": "", + "description": null, + "error": null, + "hide": 0, + "includeAll": true, + "label": "Content Kind", + "multi": true, + "name": "content_kind", + "options": [], + "query": { + "query": "label_values(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\"}, content_kind)", + "refId": "main-content_kind-Variable-Query" + }, + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": ".*", + "current": { + "selected": true, + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": "$ds_prometheus", + "definition": "", + "description": null, + "error": null, + "hide": 2, + "includeAll": true, + "label": "Method", + "multi": true, + "name": "method", + "options": [], + "query": { + "query": "label_values(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}, method)", + "refId": "main-method-Variable-Query" + }, + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": ".*", + "current": { + "selected": true, + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": "$ds_prometheus", + "definition": "", + "description": null, + "error": null, + "hide": 2, + "includeAll": true, + "label": "Method", + "multi": true, + "name": "status", + "options": [], + "query": { + "query": "label_values(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}, status)", + "refId": "main-status-Variable-Query" + }, + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + } + ] + }, + "time": { + "from": "now-3h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "", + "title": "Ingress Nginx Controllers", + "uid": "NB8ty6Gmk", + "version": 2 +} diff --git a/dashboards/ingress/namespace-detail.json b/dashboards/ingress/namespace-detail.json new file mode 100644 index 00000000..328fed23 --- /dev/null +++ b/dashboards/ingress/namespace-detail.json @@ -0,0 +1,10382 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": "-- Grafana --", + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "limit": 100, + "name": "Annotations & Alerts", + "showIn": 0, + "target": { + "limit": 100, + "matchAny": false, + "tags": [], + "type": "dashboard" + }, + "type": "dashboard" + } + ] + }, + "editable": false, + "fiscalYearStartMonth": 0, + "gnetId": null, + "graphTooltip": 1, + "iteration": 1640793728377, + "links": [], + "liveNow": false, + "panels": [ + { + "collapsed": false, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 126, + "panels": [], + "title": "Main", + "type": "row" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "rgb(31, 120, 193)", + "mode": "fixed" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 0, + "y": 1 + }, + "id": 26, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]))", + "format": "time_series", + "instant": true, + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "Requests", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "rgb(31, 120, 193)", + "mode": "fixed" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 3, + "y": 1 + }, + "id": 111, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "sum(increase(ingress_nginx_${metric}_upstream_retries_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]))\n / sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]))\nor vector(0)", + "format": "time_series", + "instant": true, + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "Retried Requests", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "rgb(31, 120, 193)", + "mode": "fixed" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 6, + "y": 1 + }, + "id": 47, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "sum(increase(ingress_nginx_${metric}_received_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]))", + "format": "time_series", + "instant": true, + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "In Traffic", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "rgb(31, 120, 193)", + "mode": "fixed" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 9, + "y": 1 + }, + "id": 48, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "sum(increase(ingress_nginx_${metric}_sent_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]))", + "format": "time_series", + "instant": true, + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "Out Traffic", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "rgb(31, 120, 193)", + "mode": "fixed" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ops" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 12, + "y": 1 + }, + "id": 109, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]))", + "format": "time_series", + "instant": true, + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "Avg RPS", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 15, + "y": 1 + }, + "id": 65, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_request_seconds_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]))\n / sum(rate(ingress_nginx_${metric}_request_seconds_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]))\n * 1000", + "format": "time_series", + "instant": true, + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "Avg Req Time", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 18, + "y": 1 + }, + "id": 69, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "sum(increase(ingress_nginx_${metric}_upstream_response_seconds_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]))\n / sum(increase(ingress_nginx_${metric}_upstream_response_seconds_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]))\n * 1000", + "format": "time_series", + "instant": true, + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "Avg Upstr Time", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "rgb(31, 120, 193)", + "mode": "fixed" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 21, + "y": 1 + }, + "id": 110, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", scheme=\"https\"}[$__rate_interval]))\n / (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) > 0)", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "HTTPS", + "type": "stat" + }, + { + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": null, + "displayMode": "auto", + "filterable": false, + "minWidth": 64 + }, + "decimals": 2, + "displayName": "", + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Time" + }, + "properties": [ + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #A" + }, + "properties": [ + { + "id": "displayName", + "value": "RPS" + }, + { + "id": "unit", + "value": "ops" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 85 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #B" + }, + "properties": [ + { + "id": "displayName", + "value": "Retried Req" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 85 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #C" + }, + "properties": [ + { + "id": "displayName", + "value": "Req Time" + }, + { + "id": "unit", + "value": "s" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 85 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #D" + }, + "properties": [ + { + "id": "displayName", + "value": "Upstr Time" + }, + { + "id": "unit", + "value": "s" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 85 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #E" + }, + "properties": [ + { + "id": "displayName", + "value": "In Traffic" + }, + { + "id": "unit", + "value": "bps" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 85 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #F" + }, + "properties": [ + { + "id": "displayName", + "value": "Out Traffic" + }, + { + "id": "unit", + "value": "bps" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 85 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #G" + }, + "properties": [ + { + "id": "displayName", + "value": "Req Size" + }, + { + "id": "unit", + "value": "bytes" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 85 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #H" + }, + "properties": [ + { + "id": "displayName", + "value": "Resp Size" + }, + { + "id": "unit", + "value": "bytes" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 85 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #I" + }, + "properties": [ + { + "id": "displayName", + "value": "1xx" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #J" + }, + "properties": [ + { + "id": "displayName", + "value": "2xx" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 62 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #K" + }, + "properties": [ + { + "id": "displayName", + "value": "3xx" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #L" + }, + "properties": [ + { + "id": "displayName", + "value": "4xx" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 62 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #M" + }, + "properties": [ + { + "id": "displayName", + "value": "5xx" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 62 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #N" + }, + "properties": [ + { + "id": "displayName", + "value": "HTTPS" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 0 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 62 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #O" + }, + "properties": [ + { + "id": "displayName", + "value": "GET" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 62 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #P" + }, + "properties": [ + { + "id": "displayName", + "value": "POST" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 64 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #Q" + }, + "properties": [ + { + "id": "displayName", + "value": "HEAD" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 62 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #R" + }, + "properties": [ + { + "id": "displayName", + "value": "PUT" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 62 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #S" + }, + "properties": [ + { + "id": "displayName", + "value": "DELETE" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 62 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #T" + }, + "properties": [ + { + "id": "displayName", + "value": "OPTIONS" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 62 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #U" + }, + "properties": [ + { + "id": "displayName", + "value": "PATCH" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 62 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "ingress" + }, + "properties": [ + { + "id": "displayName", + "value": "Ingress" + }, + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 150 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "service" + }, + "properties": [ + { + "id": "displayName", + "value": "Service" + }, + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 120 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "service_port" + }, + "properties": [ + { + "id": "displayName", + "value": "Svc Port" + }, + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 70 + } + ] + } + ] + }, + "gridPos": { + "h": 6, + "w": 24, + "x": 0, + "y": 3 + }, + "id": 28, + "links": [], + "options": { + "showHeader": true + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "(sum(rate(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "instant": true, + "intervalFactor": 1, + "refId": "A" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_upstream_retries_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by\n / (sum(rate(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "legendFormat": "", + "refId": "B" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_request_seconds_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by\n / (sum(increase(ingress_nginx_${metric}_request_seconds_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "legendFormat": "", + "refId": "C" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_upstream_response_seconds_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by\n / (sum(increase(ingress_nginx_${metric}_upstream_response_seconds_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "legendFormat": "", + "refId": "D" + }, + { + "expr": "(sum(rate(ingress_nginx_${metric}_received_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by * 8 > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "legendFormat": "", + "refId": "E" + }, + { + "expr": "(sum(rate(ingress_nginx_${metric}_sent_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by * 8 > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "F" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_received_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by\n / (sum(increase(ingress_nginx_${metric}_received_bytes_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "G" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_sent_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by\n / (sum(increase(ingress_nginx_${metric}_sent_bytes_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "H" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"1..\"}[$__range])) $by\n/ (sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "I" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"2..\"}[$__range])) $by\n/ (sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "J" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"3..\"}[$__range])) $by\n/ (sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "K" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"4..\"}[$__range])) $by\n/ (sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "L" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"5..\"}[$__range])) $by\n/ (sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "M" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", scheme=\"https\"}[$__range])) $by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "N" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"GET\"}[$__range])) $by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "O" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"POST\"}[$__range])) $by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "P" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"HEAD\"}[$__range])) $by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "Q" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"PUT\"}[$__range])) $by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "R" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"DELETE\"}[$__range])) $by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "S" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"OPTIONS\"}[$__range])) $by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "T" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"PATCH\"}[$__range])) $by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "U" + } + ], + "title": "Average", + "transformations": [ + { + "id": "merge", + "options": { + "reducers": [] + } + }, + { + "id": "organize", + "options": { + "excludeByName": { + "Time": true + }, + "indexByName": {}, + "renameByName": {} + } + } + ], + "type": "table" + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 16, + "x": 0, + "y": 9 + }, + "hiddenSeries": false, + "id": 1, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sort": "total", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A", + "step": 20 + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $by > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Requests", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 8, + "x": 16, + "y": 9 + }, + "hiddenSeries": false, + "id": 80, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sort": "total", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $by\n / scalar(sum(rate(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))) > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Requests %", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "percentunit", + "label": "", + "logBase": 1, + "max": "1", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "3xx": "#6ED0E0", + "4xx": "#EAB839", + "5xx": "#BF1B00" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 16, + "x": 0, + "y": 14 + }, + "hiddenSeries": false, + "id": 243, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": true, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + }, + { + "alias": "2xx", + "color": "#73BF69" + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A" + }, + { + "expr": "sum(label_replace(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]), \"status_group\", \"${1}xx\", \"status\", \"([0-9])..\")) by (status_group) > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{ status_group }}", + "refId": "B", + "step": 40 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Responses", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "3xx": "#6ED0E0", + "4xx": "#EAB839", + "5xx": "#BF1B00" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 8, + "x": 16, + "y": 14 + }, + "hiddenSeries": false, + "id": 244, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": true, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(label_replace(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]), \"status_group\", \"${1}xx\", \"status\", \"([0-9])..\")) by (status_group)\n / scalar(sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))) > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{ status_group }}", + "refId": "B", + "step": 40 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Responses %", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "percentunit", + "label": "", + "logBase": 1, + "max": "1", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 8, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 16, + "x": 0, + "y": 20 + }, + "hiddenSeries": false, + "hideTimeOverride": false, + "id": 4, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sideWidth": null, + "sort": null, + "sortDesc": null, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 0, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "0.005", + "color": "#76B576" + }, + { + "alias": "0.01", + "color": "#83BC6D" + }, + { + "alias": "0.02", + "color": "#91C364" + }, + { + "alias": "0.03", + "color": "#9FCB5B" + }, + { + "alias": "0.04", + "color": "#ACD252" + }, + { + "alias": "0.05", + "color": "#BADA49" + }, + { + "alias": "0.075", + "color": "#C8E140" + }, + { + "alias": "0.1", + "color": "#D5E837" + }, + { + "alias": "0.2", + "color": "#E3F02E" + }, + { + "alias": "0.3", + "color": "#F1F725" + }, + { + "alias": "0.4", + "color": "#FFFF1C" + }, + { + "alias": "0.5", + "color": "#FAE519" + }, + { + "alias": "0.75", + "color": "#F6CC16" + }, + { + "alias": "1", + "color": "#F2B213" + }, + { + "alias": "1.5", + "color": "#EE9910" + }, + { + "alias": "2", + "color": "#EA7F0E" + }, + { + "alias": "3", + "color": "#E6660B" + }, + { + "alias": "4", + "color": "#E24C08" + }, + { + "alias": "5", + "color": "#DE3205" + }, + { + "alias": "10", + "color": "#DA1902" + }, + { + "alias": "+Inf", + "color": "#D60000" + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_lowres_upstream_response_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)", + "format": "heatmap", + "intervalFactor": 1, + "legendFormat": "{{le}}", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Upstream Response Time", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + "total" + ] + }, + "yaxes": [ + { + "decimals": null, + "format": "ops", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 8, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 8, + "x": 16, + "y": 20 + }, + "hiddenSeries": false, + "hideTimeOverride": false, + "id": 81, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sideWidth": null, + "sort": null, + "sortDesc": null, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 0, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "0.005", + "color": "#76B576" + }, + { + "alias": "0.01", + "color": "#83BC6D" + }, + { + "alias": "0.02", + "color": "#91C364" + }, + { + "alias": "0.03", + "color": "#9FCB5B" + }, + { + "alias": "0.04", + "color": "#ACD252" + }, + { + "alias": "0.05", + "color": "#BADA49" + }, + { + "alias": "0.075", + "color": "#C8E140" + }, + { + "alias": "0.1", + "color": "#D5E837" + }, + { + "alias": "0.2", + "color": "#E3F02E" + }, + { + "alias": "0.3", + "color": "#F1F725" + }, + { + "alias": "0.4", + "color": "#FFFF1C" + }, + { + "alias": "0.5", + "color": "#FAE519" + }, + { + "alias": "0.75", + "color": "#F6CC16" + }, + { + "alias": "1", + "color": "#F2B213" + }, + { + "alias": "1.5", + "color": "#EE9910" + }, + { + "alias": "2", + "color": "#EA7F0E" + }, + { + "alias": "3", + "color": "#E6660B" + }, + { + "alias": "4", + "color": "#E24C08" + }, + { + "alias": "5", + "color": "#DE3205" + }, + { + "alias": "10", + "color": "#DA1902" + }, + { + "alias": "+Inf", + "color": "#D60000" + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_lowres_upstream_response_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)\n / scalar(sum(rate(ingress_nginx_${metric}_lowres_upstream_response_seconds_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])))", + "format": "heatmap", + "intervalFactor": 1, + "legendFormat": "{{le}}", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Upstream Response Time %", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + "total" + ] + }, + "yaxes": [ + { + "format": "percentunit", + "label": null, + "logBase": 1, + "max": "1", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 8, + "x": 0, + "y": 26 + }, + "hiddenSeries": false, + "hideTimeOverride": false, + "id": 62, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sideWidth": null, + "sort": null, + "sortDesc": null, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": true, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_upstream_retries_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_upstream_retries_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $by > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Retried Requests", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + "total" + ] + }, + "yaxes": [ + { + "format": "ops", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 8, + "x": 8, + "y": 26 + }, + "hiddenSeries": false, + "hideTimeOverride": false, + "id": 112, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sideWidth": null, + "sort": null, + "sortDesc": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_upstream_retries_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $by\n/ sum(rate(ingress_nginx_${metric}_upstream_retries_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $by\n> 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Retries (per Retried Request)", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + "total" + ] + }, + "yaxes": [ + { + "format": "ops", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "3xx": "#6ED0E0", + "4xx": "#EAB839", + "5xx": "#BF1B00" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 8, + "x": 16, + "y": 26 + }, + "hiddenSeries": false, + "id": 196, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": true, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"1..\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"1..\"}[$__rate_interval])) $by > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "B", + "step": 40 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "1xx", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "3xx": "#6ED0E0", + "4xx": "#EAB839", + "5xx": "#BF1B00" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 8, + "x": 16, + "y": 30 + }, + "hiddenSeries": false, + "id": 87, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": true, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"2..\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"2..\"}[$__rate_interval])) $by > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "B", + "step": 40 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "2xx", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": null, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 8, + "x": 0, + "y": 31 + }, + "hiddenSeries": false, + "hideTimeOverride": false, + "id": 49, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sideWidth": null, + "sort": null, + "sortDesc": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_request_seconds_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $by\n / sum(rate(ingress_nginx_${metric}_request_seconds_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $by > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Avg Request Time", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + "total" + ] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": null, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 8, + "x": 8, + "y": 31 + }, + "hiddenSeries": false, + "hideTimeOverride": false, + "id": 63, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sideWidth": null, + "sort": null, + "sortDesc": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_upstream_response_seconds_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $by\n / sum(rate(ingress_nginx_${metric}_upstream_response_seconds_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $by > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Avg Upstream Response Time", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + "total" + ] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "3xx": "#6ED0E0", + "4xx": "#EAB839", + "5xx": "#BF1B00" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 8, + "x": 16, + "y": 34 + }, + "hiddenSeries": false, + "id": 10, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": true, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"3..\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"3..\"}[$__rate_interval])) $by > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "B", + "step": 40 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "3xx", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": null, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 8, + "x": 0, + "y": 36 + }, + "hiddenSeries": false, + "hideTimeOverride": false, + "id": 58, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sideWidth": null, + "sort": null, + "sortDesc": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_received_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $by\n / sum(rate(ingress_nginx_${metric}_received_bytes_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $by > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Avg Request Size", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + "total" + ] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": null, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 8, + "x": 8, + "y": 36 + }, + "hiddenSeries": false, + "hideTimeOverride": false, + "id": 73, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sideWidth": null, + "sort": null, + "sortDesc": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_sent_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $by\n / sum(rate(ingress_nginx_${metric}_sent_bytes_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $by > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Avg Response Size", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + "total" + ] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "3xx": "#6ED0E0", + "4xx": "#EAB839", + "5xx": "#BF1B00" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 8, + "x": 16, + "y": 38 + }, + "hiddenSeries": false, + "id": 18, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": true, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"4..\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"4..\"}[$__rate_interval])) $by > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "B", + "step": 40 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "4xx", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 8, + "x": 0, + "y": 41 + }, + "hiddenSeries": false, + "id": 12, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_received_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) * 8", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A", + "step": 20 + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_received_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $by * 8 > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "B", + "step": 20 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Incoming Traffic", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bps", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 8, + "x": 8, + "y": 41 + }, + "hiddenSeries": false, + "id": 9, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sort": "max", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_sent_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) * 8", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A", + "step": 20 + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_sent_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $by * 8 > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Outgoing Traffic", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bps", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "3xx": "#6ED0E0", + "4xx": "#EAB839", + "5xx": "#BF1B00" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 8, + "x": 16, + "y": 42 + }, + "hiddenSeries": false, + "id": 17, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": true, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"5..\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"5..\"}[$__rate_interval])) $by > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "B", + "step": 40 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "5xx", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "collapsed": false, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 46 + }, + "id": 195, + "panels": [], + "title": "Status Codes", + "type": "row" + }, + { + "aliasColors": { + "3xx": "#6ED0E0", + "4xx": "#EAB839", + "5xx": "#BF1B00" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 8, + "x": 0, + "y": 47 + }, + "hiddenSeries": false, + "id": 189, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": true, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": true, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"1..\"}[$__rate_interval])) by (status)\n / scalar(sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"1..\"}[$__rate_interval])))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{status}}", + "refId": "B", + "step": 40 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "1xx", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "percentunit", + "label": "", + "logBase": 1, + "max": "100", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "3xx": "#6ED0E0", + "4xx": "#EAB839", + "5xx": "#BF1B00" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 8, + "x": 8, + "y": 47 + }, + "hiddenSeries": false, + "id": 190, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": true, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": true, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"2..\"}[$__rate_interval])) by (status)\n / scalar(sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"2..\"}[$__rate_interval])))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{status}}", + "refId": "B", + "step": 40 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "2xx", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "percentunit", + "label": "", + "logBase": 1, + "max": "100", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "3xx": "#6ED0E0", + "4xx": "#EAB839", + "5xx": "#BF1B00" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 8, + "x": 16, + "y": 47 + }, + "hiddenSeries": false, + "id": 191, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": true, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": true, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"3..\"}[$__rate_interval])) by (status)\n / scalar(sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"3..\"}[$__rate_interval])))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{status}}", + "refId": "B", + "step": 40 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "3xx", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "percentunit", + "label": "", + "logBase": 1, + "max": "100", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "3xx": "#6ED0E0", + "4xx": "#EAB839", + "5xx": "#BF1B00" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 12, + "x": 0, + "y": 51 + }, + "hiddenSeries": false, + "id": 192, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": true, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": true, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"4..\"}[$__rate_interval])) by (status)\n / scalar(sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"4..\"}[$__rate_interval])))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{status}}", + "refId": "B", + "step": 40 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "4xx", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "percentunit", + "label": "", + "logBase": 1, + "max": "100", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "3xx": "#6ED0E0", + "4xx": "#EAB839", + "5xx": "#BF1B00" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 12, + "x": 12, + "y": 51 + }, + "hiddenSeries": false, + "id": 193, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": true, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": true, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"5..\"}[$__rate_interval])) by (status)\n / scalar(sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"5..\"}[$__rate_interval])))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{status}}", + "refId": "B", + "step": 40 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "5xx", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "percentunit", + "label": "", + "logBase": 1, + "max": "100", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "3xx": "#6ED0E0", + "4xx": "#EAB839", + "5xx": "#BF1B00" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 6, + "x": 0, + "y": 56 + }, + "hiddenSeries": false, + "id": 86, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": true, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "maxPerRow": 4, + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": "status", + "repeatDirection": "h", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=\"$status\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=\"$status\"}[$__rate_interval])) $by > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "B", + "step": 40 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "$status", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "collapsed": true, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 60 + }, + "id": 150, + "panels": [ + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 0, + "y": 3 + }, + "id": 130, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.3", + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_request_seconds_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))\n / sum(rate(ingress_nginx_${metric}_request_seconds_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))\n * 1000", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "Avg Req Time", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 3, + "y": 3 + }, + "id": 132, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.3", + "targets": [ + { + "expr": "histogram_quantile(0.5, sum(rate(ingress_nginx_${metric}_request_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)) * 1000", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "50th Req Time", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 6, + "y": 3 + }, + "id": 134, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.3", + "targets": [ + { + "expr": "histogram_quantile(0.9, sum(rate(ingress_nginx_${metric}_request_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)) * 1000", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "90th Req Time", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 9, + "y": 3 + }, + "id": 174, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.3", + "targets": [ + { + "expr": "histogram_quantile(0.99, sum(rate(ingress_nginx_${metric}_request_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)) * 1000", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "99th Req Time", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 12, + "y": 3 + }, + "id": 140, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.3", + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_upstream_response_seconds_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))\n / sum(rate(ingress_nginx_${metric}_upstream_response_seconds_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))\n * 1000", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "Avg Upstr Time", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 15, + "y": 3 + }, + "id": 142, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.3", + "targets": [ + { + "expr": "histogram_quantile(0.5, sum(rate(ingress_nginx_${metric}_upstream_response_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)) * 1000", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "50th Upstr Time", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 18, + "y": 3 + }, + "id": 144, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.3", + "targets": [ + { + "expr": "histogram_quantile(0.9, sum(rate(ingress_nginx_${metric}_upstream_response_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)) * 1000", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "90th Upstr Time", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 21, + "y": 3 + }, + "id": 146, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.3", + "targets": [ + { + "expr": "histogram_quantile(0.99, sum(rate(ingress_nginx_${metric}_upstream_response_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)) * 1000", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "99th Upstr Time", + "type": "stat" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": null, + "fill": 0, + "gridPos": { + "h": 5, + "w": 12, + "x": 0, + "y": 5 + }, + "hideTimeOverride": false, + "id": 136, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sideWidth": null, + "sort": null, + "sortDesc": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Avg", + "fill": 2, + "linewidth": 0 + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "histogram_quantile(0.99, sum(rate(ingress_nginx_${metric}_request_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)) * 1000", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "99th", + "refId": "A" + }, + { + "expr": "histogram_quantile(0.9, sum(rate(ingress_nginx_${metric}_request_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)) * 1000", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "90th", + "refId": "B" + }, + { + "expr": "histogram_quantile(0.5, sum(rate(ingress_nginx_${metric}_request_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)) * 1000", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "50th", + "refId": "C" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_request_seconds_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))\n / sum(rate(ingress_nginx_${metric}_request_seconds_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))\n * 1000", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Avg", + "refId": "D" + } + ], + "thresholds": [], + "timeFrom": null, + "timeShift": null, + "title": "Request Time", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + "total" + ] + }, + "yaxes": [ + { + "format": "ms", + "label": null, + "logBase": 10, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": null, + "fill": 0, + "gridPos": { + "h": 5, + "w": 12, + "x": 12, + "y": 5 + }, + "hideTimeOverride": false, + "id": 148, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sideWidth": null, + "sort": null, + "sortDesc": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Avg", + "fill": 2, + "linewidth": 0 + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "histogram_quantile(0.99, sum(rate(ingress_nginx_${metric}_upstream_response_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)) * 1000", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "99th", + "refId": "A" + }, + { + "expr": "histogram_quantile(0.9, sum(rate(ingress_nginx_${metric}_upstream_response_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)) * 1000", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "90th", + "refId": "B" + }, + { + "expr": "histogram_quantile(0.5, sum(rate(ingress_nginx_${metric}_upstream_response_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)) * 1000", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "50th", + "refId": "C" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_upstream_response_seconds_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))\n / sum(rate(ingress_nginx_${metric}_upstream_response_seconds_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))\n * 1000", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Avg", + "refId": "D" + } + ], + "thresholds": [], + "timeFrom": null, + "timeShift": null, + "title": "Upstream Response Time", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + "total" + ] + }, + "yaxes": [ + { + "format": "ms", + "label": null, + "logBase": 10, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "title": "Request Time and Upstream Response Time", + "type": "row" + }, + { + "collapsed": true, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 61 + }, + "id": 211, + "panels": [ + { + "cards": { + "cardPadding": 0, + "cardRound": 0 + }, + "color": { + "cardColor": "#b4ff00", + "colorScale": "sqrt", + "colorScheme": "interpolateYlGnBu", + "exponent": 0.5, + "max": null, + "min": 0, + "mode": "spectrum" + }, + "dataFormat": "tsbuckets", + "datasource": null, + "gridPos": { + "h": 21, + "w": 12, + "x": 0, + "y": 11 + }, + "heatmap": {}, + "highlightCards": true, + "id": 152, + "legend": { + "show": true + }, + "links": [], + "targets": [ + { + "expr": "sum(increase(ingress_nginx_${metric}_request_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le) > 0", + "format": "heatmap", + "intervalFactor": 1, + "legendFormat": "{{le}}", + "refId": "A" + } + ], + "title": "Request Time", + "tooltip": { + "show": true, + "showHistogram": true + }, + "type": "heatmap", + "xAxis": { + "show": true + }, + "xBucketNumber": null, + "xBucketSize": null, + "yAxis": { + "decimals": 1, + "format": "s", + "logBase": 1, + "max": null, + "min": null, + "show": true, + "splitFactor": null + }, + "yBucketBound": "auto", + "yBucketNumber": null, + "yBucketSize": null + }, + { + "cards": { + "cardPadding": 0, + "cardRound": 0 + }, + "color": { + "cardColor": "#b4ff00", + "colorScale": "sqrt", + "colorScheme": "interpolateYlGnBu", + "exponent": 0.5, + "max": null, + "min": 0, + "mode": "spectrum" + }, + "dataFormat": "tsbuckets", + "datasource": null, + "gridPos": { + "h": 21, + "w": 12, + "x": 12, + "y": 11 + }, + "heatmap": {}, + "highlightCards": true, + "id": 153, + "legend": { + "show": true + }, + "links": [], + "targets": [ + { + "expr": "sum(increase(ingress_nginx_${metric}_upstream_response_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le) > 0", + "format": "heatmap", + "intervalFactor": 1, + "legendFormat": "{{le}}", + "refId": "A" + } + ], + "title": "Upstream Response Time", + "tooltip": { + "show": true, + "showHistogram": true + }, + "type": "heatmap", + "xAxis": { + "show": true + }, + "xBucketNumber": null, + "xBucketSize": null, + "yAxis": { + "decimals": 1, + "format": "s", + "logBase": 1, + "max": null, + "min": null, + "show": true, + "splitFactor": null + }, + "yBucketBound": "auto", + "yBucketNumber": null, + "yBucketSize": null + } + ], + "title": "Request Time Heatmap and Upstream Response Time Heatmap", + "type": "row" + }, + { + "collapsed": true, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 62 + }, + "id": 160, + "panels": [ + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 0, + "y": 5 + }, + "id": 171, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.3", + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_received_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))\n / sum(rate(ingress_nginx_${metric}_received_bytes_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "Avg Req Size", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 3, + "y": 5 + }, + "id": 172, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.3", + "targets": [ + { + "expr": "histogram_quantile(0.5, sum(rate(ingress_nginx_${metric}_received_bytes_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le))", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "50th Req Size", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 6, + "y": 5 + }, + "id": 173, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.3", + "targets": [ + { + "expr": "histogram_quantile(0.9, sum(rate(ingress_nginx_${metric}_received_bytes_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le))", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "90th Req Size", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 9, + "y": 5 + }, + "id": 128, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.3", + "targets": [ + { + "expr": "histogram_quantile(0.99, sum(rate(ingress_nginx_${metric}_received_bytes_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le))", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "99th Req Size", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 12, + "y": 5 + }, + "id": 175, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.3", + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_sent_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))\n / sum(rate(ingress_nginx_${metric}_sent_bytes_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "Avg Resp Size", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 15, + "y": 5 + }, + "id": 176, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.3", + "targets": [ + { + "expr": "histogram_quantile(0.5, sum(rate(ingress_nginx_${metric}_sent_bytes_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le))", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "50th Resp Size", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 18, + "y": 5 + }, + "id": 177, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.3", + "targets": [ + { + "expr": "histogram_quantile(0.9, sum(rate(ingress_nginx_${metric}_sent_bytes_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le))", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "90th Resp Size", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 21, + "y": 5 + }, + "id": 178, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.3", + "targets": [ + { + "expr": "histogram_quantile(0.99, sum(rate(ingress_nginx_${metric}_sent_bytes_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le))", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "99th Resp Size", + "type": "stat" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": null, + "fill": 0, + "gridPos": { + "h": 4, + "w": 12, + "x": 0, + "y": 7 + }, + "hideTimeOverride": false, + "id": 155, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sideWidth": null, + "sort": null, + "sortDesc": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Avg", + "fill": 2, + "linewidth": 0 + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "histogram_quantile(0.99, sum(rate(ingress_nginx_${metric}_received_bytes_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "99th", + "refId": "A" + }, + { + "expr": "histogram_quantile(0.9, sum(rate(ingress_nginx_${metric}_received_bytes_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "90th", + "refId": "B" + }, + { + "expr": "histogram_quantile(0.5, sum(rate(ingress_nginx_${metric}_received_bytes_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "50th", + "refId": "C" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_received_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))\n / sum(rate(ingress_nginx_${metric}_received_bytes_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Avg", + "refId": "D" + } + ], + "thresholds": [], + "timeFrom": null, + "timeShift": null, + "title": "Request Size", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + "total" + ] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 2, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": null, + "fill": 0, + "gridPos": { + "h": 4, + "w": 12, + "x": 12, + "y": 7 + }, + "hideTimeOverride": false, + "id": 157, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sideWidth": null, + "sort": null, + "sortDesc": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Avg", + "fill": 2, + "linewidth": 0 + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "histogram_quantile(0.99, sum(rate(ingress_nginx_${metric}_sent_bytes_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "99th", + "refId": "A" + }, + { + "expr": "histogram_quantile(0.9, sum(rate(ingress_nginx_${metric}_sent_bytes_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "90th", + "refId": "B" + }, + { + "expr": "histogram_quantile(0.5, sum(rate(ingress_nginx_${metric}_sent_bytes_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "50th", + "refId": "C" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_sent_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))\n / sum(rate(ingress_nginx_${metric}_sent_bytes_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Avg", + "refId": "D" + } + ], + "thresholds": [], + "timeFrom": null, + "timeShift": null, + "title": "Response Size", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + "total" + ] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 2, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "title": "Request Size and Response Size", + "type": "row" + }, + { + "collapsed": true, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 63 + }, + "id": 209, + "panels": [ + { + "cards": { + "cardPadding": 0, + "cardRound": 0 + }, + "color": { + "cardColor": "#b4ff00", + "colorScale": "sqrt", + "colorScheme": "interpolateYlGnBu", + "exponent": 0.5, + "max": null, + "min": 0, + "mode": "spectrum" + }, + "dataFormat": "tsbuckets", + "datasource": null, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 6 + }, + "heatmap": {}, + "highlightCards": true, + "id": 158, + "legend": { + "show": true + }, + "links": [], + "targets": [ + { + "expr": "sum(increase(ingress_nginx_${metric}_received_bytes_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)", + "format": "heatmap", + "intervalFactor": 1, + "legendFormat": "{{le}}", + "refId": "A" + } + ], + "title": "Request Size", + "tooltip": { + "show": true, + "showHistogram": true + }, + "type": "heatmap", + "xAxis": { + "show": true + }, + "xBucketNumber": null, + "xBucketSize": null, + "yAxis": { + "decimals": 0, + "format": "bytes", + "logBase": 1, + "max": null, + "min": null, + "show": true, + "splitFactor": null + }, + "yBucketBound": "auto", + "yBucketNumber": null, + "yBucketSize": null + }, + { + "cards": { + "cardPadding": 0, + "cardRound": 0 + }, + "color": { + "cardColor": "#b4ff00", + "colorScale": "sqrt", + "colorScheme": "interpolateYlGnBu", + "exponent": 0.5, + "max": null, + "min": 0, + "mode": "spectrum" + }, + "dataFormat": "tsbuckets", + "datasource": null, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 6 + }, + "heatmap": {}, + "highlightCards": true, + "id": 161, + "legend": { + "show": true + }, + "links": [], + "targets": [ + { + "expr": "sum(increase(ingress_nginx_${metric}_sent_bytes_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)", + "format": "heatmap", + "intervalFactor": 1, + "legendFormat": "{{le}}", + "refId": "A" + } + ], + "title": "Response Size", + "tooltip": { + "show": true, + "showHistogram": true + }, + "type": "heatmap", + "xAxis": { + "show": true + }, + "xBucketNumber": null, + "xBucketSize": null, + "yAxis": { + "decimals": 0, + "format": "bytes", + "logBase": 1, + "max": null, + "min": null, + "show": true, + "splitFactor": null + }, + "yBucketBound": "auto", + "yBucketNumber": null, + "yBucketSize": null + } + ], + "title": "Request Size Heatmap and Response Size Heatmap", + "type": "row" + }, + { + "collapsed": true, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 64 + }, + "id": 89, + "panels": [ + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "gridPos": { + "h": 6, + "w": 12, + "x": 0, + "y": 7 + }, + "id": 61, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sort": "total", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (method)\n / scalar(sum(rate(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{method}}", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeShift": null, + "title": "Method %", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "percentunit", + "label": "", + "logBase": 1, + "max": "1", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "gridPos": { + "h": 6, + "w": 12, + "x": 12, + "y": 7 + }, + "id": 60, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sort": "total", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\"}[$__rate_interval])) by (content_kind)\n/ scalar(sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\"}[$__rate_interval])))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{content_kind}}", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeShift": null, + "title": "Content Kind %", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "percentunit", + "label": "", + "logBase": 1, + "max": "1", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "gridPos": { + "h": 4, + "w": 12, + "x": 0, + "y": 13 + }, + "id": 90, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sort": "total", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": "method", + "repeatDirection": "v", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"$method\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"$method\"}[$__rate_interval])) $by > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeShift": null, + "title": "$method", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "gridPos": { + "h": 4, + "w": 12, + "x": 12, + "y": 13 + }, + "id": 97, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sort": "total", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": "content_kind", + "repeatDirection": "v", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=\"$content_kind\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=\"$content_kind\"}[$__rate_interval])) $by > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeShift": null, + "title": "$content_kind", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "title": "Request Method and Content Kind", + "type": "row" + }, + { + "collapsed": true, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 65 + }, + "id": 239, + "panels": [ + { + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": null, + "displayMode": "auto" + }, + "decimals": 2, + "displayName": "", + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Time" + }, + "properties": [ + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #A" + }, + "properties": [ + { + "id": "displayName", + "value": "RPS" + }, + { + "id": "unit", + "value": "ops" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #B" + }, + "properties": [ + { + "id": "displayName", + "value": "Upstr Time" + }, + { + "id": "unit", + "value": "s" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #C" + }, + "properties": [ + { + "id": "displayName", + "value": "Upstr Traffic" + }, + { + "id": "unit", + "value": "bps" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #D" + }, + "properties": [ + { + "id": "displayName", + "value": "Upstr Resp" + }, + { + "id": "unit", + "value": "bytes" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #E" + }, + "properties": [ + { + "id": "displayName", + "value": "1xx" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #F" + }, + "properties": [ + { + "id": "displayName", + "value": "2xx" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #G" + }, + "properties": [ + { + "id": "displayName", + "value": "3xx" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #H" + }, + "properties": [ + { + "id": "displayName", + "value": "4xx" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #I" + }, + "properties": [ + { + "id": "displayName", + "value": "5xx" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "pod_ip" + }, + "properties": [ + { + "id": "displayName", + "value": "Pod IP" + }, + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + } + ] + }, + "gridPos": { + "h": 6, + "w": 24, + "x": 0, + "y": 66 + }, + "id": 213, + "links": [], + "options": { + "showHeader": true + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "(sum(rate(ingress_nginx_${metric}_backend_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\"}[$__range])) by (pod_ip) > 0)\nor sum(irate(ingress_nginx_${metric}_backend_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\"}[$__range])) by (pod_ip)", + "format": "table", + "instant": true, + "intervalFactor": 1, + "refId": "A" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_backend_lowres_upstream_response_seconds_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\"}[$__range])) by (pod_ip)\n / (sum(increase(ingress_nginx_${metric}_backend_lowres_upstream_response_seconds_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\"}[$__range])) by (pod_ip) > 0)\nor sum(irate(ingress_nginx_${metric}_backend_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\"}[$__range])) by (pod_ip)", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "legendFormat": "", + "refId": "B" + }, + { + "expr": "(sum(rate(ingress_nginx_${metric}_backend_upstream_bytes_received_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\"}[$__range])) by (pod_ip) * 8 > 0)\nor sum(irate(ingress_nginx_${metric}_backend_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\"}[$__range])) by (pod_ip)", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "legendFormat": "", + "refId": "C" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_backend_upstream_bytes_received_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\"}[$__range])) by (pod_ip)\n / (sum(increase(ingress_nginx_${metric}_backend_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\"}[$__range])) by (pod_ip) > 0)\nor sum(irate(ingress_nginx_${metric}_backend_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\"}[$__range])) by (pod_ip)", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "D" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_backend_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\", status_class=\"1xx\"}[$__range])) by (pod_ip)\n/ (sum(increase(ingress_nginx_${metric}_backend_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\"}[$__range])) by (pod_ip) > 0)\nor sum(irate(ingress_nginx_${metric}_backend_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\"}[$__range])) by (pod_ip)", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "E" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_backend_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\", status_class=\"2xx\"}[$__range])) by (pod_ip)\n/ (sum(increase(ingress_nginx_${metric}_backend_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\"}[$__range])) by (pod_ip) > 0)\nor sum(irate(ingress_nginx_${metric}_backend_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\"}[$__range])) by (pod_ip)", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "F" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_backend_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\", status_class=\"3xx\"}[$__range])) by (pod_ip)\n/ (sum(increase(ingress_nginx_${metric}_backend_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\"}[$__range])) by (pod_ip) > 0)\nor sum(irate(ingress_nginx_${metric}_backend_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\"}[$__range])) by (pod_ip)", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "G" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_backend_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\", status_class=\"4xx\"}[$__range])) by (pod_ip)\n/ (sum(increase(ingress_nginx_${metric}_backend_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\"}[$__range])) by (pod_ip) > 0)\nor sum(irate(ingress_nginx_${metric}_backend_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\"}[$__range])) by (pod_ip)", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "H" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_backend_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\", status_class=\"5xx\"}[$__range])) by (pod_ip)\n/ (sum(increase(ingress_nginx_${metric}_backend_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\"}[$__range])) by (pod_ip) > 0)\nor sum(irate(ingress_nginx_${metric}_backend_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\"}[$__range])) by (pod_ip)", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "I" + } + ], + "title": "Average", + "transformations": [ + { + "id": "merge", + "options": { + "reducers": [] + } + }, + { + "id": "filterFieldsByName", + "options": { + "include": { + "names": [ + "pod_ip", + "Value #A", + "Value #B", + "Value #C", + "Value #D", + "Value #E", + "Value #F", + "Value #G", + "Value #H", + "Value #I" + ] + } + } + } + ], + "type": "table" + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 16, + "x": 0, + "y": 72 + }, + "hiddenSeries": false, + "id": 215, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sort": "total", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_backend_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A", + "step": 20 + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_backend_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\"}[$__rate_interval])) by (pod_ip) > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{pod_ip}}", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Backend Responses", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 8, + "x": 16, + "y": 72 + }, + "hiddenSeries": false, + "id": 217, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sort": "total", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_backend_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\"}[$__rate_interval])) by (pod_ip)\n / scalar(sum(rate(ingress_nginx_${metric}_backend_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\"}[$__rate_interval]))) > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{pod_ip}}", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Backend Responses %", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "percentunit", + "label": "", + "logBase": 1, + "max": "1", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": null, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 8, + "x": 0, + "y": 77 + }, + "hiddenSeries": false, + "hideTimeOverride": false, + "id": 219, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sideWidth": null, + "sort": null, + "sortDesc": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_backend_lowres_upstream_response_seconds_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\"}[$__rate_interval])) by (pod_ip)\n / sum(rate(ingress_nginx_${metric}_backend_lowres_upstream_response_seconds_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\"}[$__rate_interval])) by (pod_ip) > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{pod_ip}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Avg Backend Response Time", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + "total" + ] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": null, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 8, + "x": 8, + "y": 77 + }, + "hiddenSeries": false, + "hideTimeOverride": false, + "id": 221, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sideWidth": null, + "sort": null, + "sortDesc": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_backend_upstream_bytes_received_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\"}[$__rate_interval])) by (pod_ip)\n / sum(rate(ingress_nginx_${metric}_backend_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\"}[$__rate_interval])) by (pod_ip) > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{pod_ip}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Avg Backend Response Size", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + "total" + ] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 8, + "x": 16, + "y": 77 + }, + "hiddenSeries": false, + "id": 223, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sort": "max", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_backend_upstream_bytes_received_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\"}[$__rate_interval])) * 8", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A", + "step": 20 + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_backend_upstream_bytes_received_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\"}[$__rate_interval])) by (pod_ip) * 8 > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{pod_ip}}", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Backend Traffic", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bps", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "3xx": "#6ED0E0", + "4xx": "#EAB839", + "5xx": "#BF1B00" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 8, + "x": 0, + "y": 82 + }, + "hiddenSeries": false, + "id": 225, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": true, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_backend_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\", status_class=\"1xx\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_backend_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\", status_class=\"1xx\"}[$__rate_interval])) by (pod_ip) > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{pod_ip}}", + "refId": "B", + "step": 40 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "1xx", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "3xx": "#6ED0E0", + "4xx": "#EAB839", + "5xx": "#BF1B00" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 8, + "x": 8, + "y": 82 + }, + "hiddenSeries": false, + "id": 227, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": true, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_backend_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\", status_class=\"2xx\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_backend_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\", status_class=\"2xx\"}[$__rate_interval])) by (pod_ip) > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{pod_ip}}", + "refId": "B", + "step": 40 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "2xx", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "3xx": "#6ED0E0", + "4xx": "#EAB839", + "5xx": "#BF1B00" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 8, + "x": 16, + "y": 82 + }, + "hiddenSeries": false, + "id": 229, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": true, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_backend_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\", status_class=\"3xx\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_backend_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\", status_class=\"3xx\"}[$__rate_interval])) by (pod_ip) > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{pod_ip}}", + "refId": "B", + "step": 40 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "3xx", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "3xx": "#6ED0E0", + "4xx": "#EAB839", + "5xx": "#BF1B00" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 12, + "x": 0, + "y": 86 + }, + "hiddenSeries": false, + "id": 231, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": true, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_backend_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\", status_class=\"4xx\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_backend_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\", status_class=\"4xx\"}[$__rate_interval])) by (pod_ip) > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{pod_ip}}", + "refId": "B", + "step": 40 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "4xx", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "3xx": "#6ED0E0", + "4xx": "#EAB839", + "5xx": "#BF1B00" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 12, + "x": 12, + "y": 86 + }, + "hiddenSeries": false, + "id": 233, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": true, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_backend_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\", status_class=\"5xx\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_backend_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\", status_class=\"5xx\"}[$__rate_interval])) by (pod_ip) > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{pod_ip}}", + "refId": "B", + "step": 40 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "5xx", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 8, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 16, + "x": 0, + "y": 91 + }, + "hiddenSeries": false, + "hideTimeOverride": false, + "id": 235, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sideWidth": null, + "sort": null, + "sortDesc": null, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 0, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": "pod_ip", + "repeatDirection": "v", + "seriesOverrides": [ + { + "alias": "0.005", + "color": "#76B576" + }, + { + "alias": "0.01", + "color": "#83BC6D" + }, + { + "alias": "0.02", + "color": "#91C364" + }, + { + "alias": "0.03", + "color": "#9FCB5B" + }, + { + "alias": "0.04", + "color": "#ACD252" + }, + { + "alias": "0.05", + "color": "#BADA49" + }, + { + "alias": "0.075", + "color": "#C8E140" + }, + { + "alias": "0.1", + "color": "#D5E837" + }, + { + "alias": "0.2", + "color": "#E3F02E" + }, + { + "alias": "0.3", + "color": "#F1F725" + }, + { + "alias": "0.4", + "color": "#FFFF1C" + }, + { + "alias": "0.5", + "color": "#FAE519" + }, + { + "alias": "0.75", + "color": "#F6CC16" + }, + { + "alias": "1", + "color": "#F2B213" + }, + { + "alias": "1.5", + "color": "#EE9910" + }, + { + "alias": "2", + "color": "#EA7F0E" + }, + { + "alias": "3", + "color": "#E6660B" + }, + { + "alias": "4", + "color": "#E24C08" + }, + { + "alias": "5", + "color": "#DE3205" + }, + { + "alias": "10", + "color": "#DA1902" + }, + { + "alias": "+Inf", + "color": "#D60000" + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_backend_lowres_upstream_response_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\"}[$__rate_interval])) by (le)", + "format": "heatmap", + "intervalFactor": 1, + "legendFormat": "{{le}}", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "$pod_ip: Backend Response Time", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + "total" + ] + }, + "yaxes": [ + { + "decimals": null, + "format": "ops", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 8, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 8, + "x": 16, + "y": 91 + }, + "hiddenSeries": false, + "hideTimeOverride": false, + "id": 237, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sideWidth": null, + "sort": null, + "sortDesc": null, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 0, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": "pod_ip", + "repeatDirection": "v", + "seriesOverrides": [ + { + "alias": "0.005", + "color": "#76B576" + }, + { + "alias": "0.01", + "color": "#83BC6D" + }, + { + "alias": "0.02", + "color": "#91C364" + }, + { + "alias": "0.03", + "color": "#9FCB5B" + }, + { + "alias": "0.04", + "color": "#ACD252" + }, + { + "alias": "0.05", + "color": "#BADA49" + }, + { + "alias": "0.075", + "color": "#C8E140" + }, + { + "alias": "0.1", + "color": "#D5E837" + }, + { + "alias": "0.2", + "color": "#E3F02E" + }, + { + "alias": "0.3", + "color": "#F1F725" + }, + { + "alias": "0.4", + "color": "#FFFF1C" + }, + { + "alias": "0.5", + "color": "#FAE519" + }, + { + "alias": "0.75", + "color": "#F6CC16" + }, + { + "alias": "1", + "color": "#F2B213" + }, + { + "alias": "1.5", + "color": "#EE9910" + }, + { + "alias": "2", + "color": "#EA7F0E" + }, + { + "alias": "3", + "color": "#E6660B" + }, + { + "alias": "4", + "color": "#E24C08" + }, + { + "alias": "5", + "color": "#DE3205" + }, + { + "alias": "10", + "color": "#DA1902" + }, + { + "alias": "+Inf", + "color": "#D60000" + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_backend_lowres_upstream_response_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\"}[$__rate_interval])) by (le)\n / scalar(sum(rate(ingress_nginx_${metric}_backend_lowres_upstream_response_seconds_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\"}[$__rate_interval])))", + "format": "heatmap", + "intervalFactor": 1, + "legendFormat": "{{le}}", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "$pod_ip: Backend Response Time %", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + "total" + ] + }, + "yaxes": [ + { + "format": "percentunit", + "label": null, + "logBase": 1, + "max": "1", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "title": "Backends (Content Kind filter is ignored)", + "type": "row" + }, + { + "collapsed": true, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 66 + }, + "id": 46, + "panels": [ + { + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": null, + "displayMode": "auto", + "minWidth": 64 + }, + "decimals": 2, + "displayName": "", + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Time" + }, + "properties": [ + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #A" + }, + "properties": [ + { + "id": "displayName", + "value": "RPS" + }, + { + "id": "unit", + "value": "ops" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 85 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #B" + }, + "properties": [ + { + "id": "displayName", + "value": "Retried Req" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 85 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #C" + }, + "properties": [ + { + "id": "displayName", + "value": "Req Time" + }, + { + "id": "unit", + "value": "s" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 85 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #D" + }, + "properties": [ + { + "id": "displayName", + "value": "Resp Time" + }, + { + "id": "unit", + "value": "s" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 85 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #E" + }, + "properties": [ + { + "id": "displayName", + "value": "In Traffic" + }, + { + "id": "unit", + "value": "bps" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 85 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #F" + }, + "properties": [ + { + "id": "displayName", + "value": "Out Traffic" + }, + { + "id": "unit", + "value": "bps" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 85 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #G" + }, + "properties": [ + { + "id": "displayName", + "value": "Req Size" + }, + { + "id": "unit", + "value": "bytes" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 85 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #H" + }, + "properties": [ + { + "id": "displayName", + "value": "Resp Size" + }, + { + "id": "unit", + "value": "bytes" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 85 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #I" + }, + "properties": [ + { + "id": "displayName", + "value": "1xx" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #J" + }, + "properties": [ + { + "id": "displayName", + "value": "2xx" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #K" + }, + "properties": [ + { + "id": "displayName", + "value": "3xx" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #L" + }, + "properties": [ + { + "id": "displayName", + "value": "4xx" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #M" + }, + "properties": [ + { + "id": "displayName", + "value": "5xx" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #N" + }, + "properties": [ + { + "id": "displayName", + "value": "HTTPS" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #O" + }, + "properties": [ + { + "id": "displayName", + "value": "GET" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #P" + }, + "properties": [ + { + "id": "displayName", + "value": "POST" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #Q" + }, + "properties": [ + { + "id": "displayName", + "value": "HEAD" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #R" + }, + "properties": [ + { + "id": "displayName", + "value": "PUT" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #S" + }, + "properties": [ + { + "id": "displayName", + "value": "DELETE" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #T" + }, + "properties": [ + { + "id": "displayName", + "value": "OPTIONS" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #U" + }, + "properties": [ + { + "id": "displayName", + "value": "PATCH" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "vhost" + }, + "properties": [ + { + "id": "displayName", + "value": "VHost" + }, + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "links", + "value": [ + { + "targetBlank": false, + "title": "Open VHost", + "url": "/d/D38hRqGmk/vhosts?var-vhost=${__value.raw}&${__url_time_range}" + } + ] + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 200 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "location" + }, + "properties": [ + { + "id": "displayName", + "value": "Location" + }, + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "links", + "value": [ + { + "targetBlank": false, + "title": "Open VHost Detail", + "url": "/d/a4hXN3Gik/vhost-detail?var-vhost=${__data.fields[VHost]}&var-location=${__value.raw}&${__url_time_range}" + } + ] + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 150 + } + ] + } + ] + }, + "gridPos": { + "h": 6, + "w": 24, + "x": 0, + "y": 67 + }, + "id": 42, + "links": [], + "options": { + "showHeader": true + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "(sum(rate(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "instant": true, + "intervalFactor": 1, + "refId": "A" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_upstream_retries_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by\n / (sum(rate(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "legendFormat": "", + "refId": "B" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_request_seconds_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by\n / (sum(increase(ingress_nginx_${metric}_request_seconds_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "legendFormat": "", + "refId": "C" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_upstream_response_seconds_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by\n / (sum(increase(ingress_nginx_${metric}_upstream_response_seconds_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "legendFormat": "", + "refId": "D" + }, + { + "expr": "(sum(rate(ingress_nginx_${metric}_received_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by * 8 > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "legendFormat": "", + "refId": "E" + }, + { + "expr": "(sum(rate(ingress_nginx_${metric}_sent_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by * 8 > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "F" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_received_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by\n / (sum(increase(ingress_nginx_${metric}_received_bytes_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "G" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_sent_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by\n / (sum(increase(ingress_nginx_${metric}_sent_bytes_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "H" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"1..\"}[$__range])) $alt_by\n/ (sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "I" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"2..\"}[$__range])) $alt_by\n/ (sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "J" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"3..\"}[$__range])) $alt_by\n/ (sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "K" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"4..\"}[$__range])) $alt_by\n/ (sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "L" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"5..\"}[$__range])) $alt_by\n/ (sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "M" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", scheme=\"https\"}[$__range])) $alt_by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "N" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"GET\"}[$__range])) $alt_by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "O" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"POST\"}[$__range])) $alt_by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "P" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"HEAD\"}[$__range])) $alt_by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "Q" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"PUT\"}[$__range])) $alt_by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "R" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"DELETE\"}[$__range])) $alt_by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "S" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"OPTIONS\"}[$__range])) $alt_by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "T" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"PATCH\"}[$__range])) $alt_by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "U" + } + ], + "title": "Average", + "transformations": [ + { + "id": "merge", + "options": { + "reducers": [] + } + }, + { + "id": "filterFieldsByName", + "options": { + "include": { + "names": [ + "location", + "vhost", + "Value #A", + "Value #B", + "Value #C", + "Value #D", + "Value #E", + "Value #F", + "Value #G", + "Value #H", + "Value #I", + "Value #J", + "Value #K", + "Value #L", + "Value #M", + "Value #N", + "Value #O", + "Value #P", + "Value #Q", + "Value #R", + "Value #S", + "Value #T", + "Value #U" + ] + } + } + } + ], + "type": "table" + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 8, + "x": 0, + "y": 73 + }, + "hiddenSeries": false, + "id": 39, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sort": "total", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": true, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $alt_by > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$alt_legend_format", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Requests per $alt_name", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": "", + "logBase": 1, + "max": "100", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 1, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 8, + "x": 8, + "y": 73 + }, + "hiddenSeries": false, + "id": 41, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": true, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_received_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $alt_by * 8 > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$alt_legend_format", + "refId": "B", + "step": 20 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Incoming Traffic per $alt_name", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bps", + "label": null, + "logBase": 1, + "max": "100", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 1, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 8, + "x": 16, + "y": 73 + }, + "hiddenSeries": false, + "id": 40, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sort": "max", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": true, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_sent_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $alt_by * 8 > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$alt_legend_format", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Outgoing Traffic per $alt_name", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bps", + "label": null, + "logBase": 1, + "max": "100", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "title": "By $alt_name", + "type": "row" + } + ], + "refresh": "30s", + "schemaVersion": 32, + "style": "dark", + "tags": [ + "ingress" + ], + "templating": { + "list": [ + { + "current": { + "selected": false, + "text": "default", + "value": "default" + }, + "description": null, + "error": null, + "hide": 0, + "includeAll": false, + "label": "Prometheus", + "multi": false, + "name": "ds_prometheus", + "options": [], + "query": "prometheus", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + }, + { + "description": null, + "error": null, + "hide": 2, + "label": null, + "name": "metric", + "query": "detail", + "skipUrlSync": false, + "type": "constant" + }, + { + "description": null, + "error": null, + "hide": 2, + "label": null, + "name": "by", + "query": "by (ingress, service, service_port)", + "skipUrlSync": false, + "type": "constant" + }, + { + "description": null, + "error": null, + "hide": 2, + "label": null, + "name": "legend_format", + "query": "{{ingress}} → {{service}}:{{service_port}}", + "skipUrlSync": false, + "type": "constant" + }, + { + "description": null, + "error": null, + "hide": 2, + "label": null, + "name": "alt_name", + "query": "VHost and Location", + "skipUrlSync": false, + "type": "constant" + }, + { + "description": null, + "error": null, + "hide": 2, + "label": null, + "name": "alt_by", + "query": "by (vhost, location)", + "skipUrlSync": false, + "type": "constant" + }, + { + "description": null, + "error": null, + "hide": 2, + "label": null, + "name": "alt_legend_format", + "query": "{{vhost}}{{location}}", + "skipUrlSync": false, + "type": "constant" + }, + { + "description": null, + "error": null, + "hide": 2, + "label": "Controller", + "name": "controller", + "query": ".*", + "skipUrlSync": false, + "type": "constant" + }, + { + "description": null, + "error": null, + "hide": 2, + "label": "App", + "name": "app", + "query": ".*", + "skipUrlSync": false, + "type": "constant" + }, + { + "description": null, + "error": null, + "hide": 2, + "label": "Node", + "name": "node", + "query": ".*", + "skipUrlSync": false, + "type": "constant" + }, + { + "allValue": ".*", + "current": { + "selected": false, + "text": "d8-monitoring", + "value": "d8-monitoring" + }, + "datasource": "$ds_prometheus", + "definition": "", + "description": null, + "error": null, + "hide": 0, + "includeAll": false, + "label": "Namespace", + "multi": false, + "name": "namespace", + "options": [], + "query": { + "query": "label_values(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\"}, namespace)", + "refId": "main-namespace-Variable-Query" + }, + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": ".*", + "current": { + "selected": true, + "text": [ + "grafana" + ], + "value": [ + "grafana" + ] + }, + "datasource": "$ds_prometheus", + "definition": "", + "description": null, + "error": null, + "hide": 0, + "includeAll": true, + "label": "Ingress", + "multi": true, + "name": "ingress", + "options": [], + "query": { + "query": "label_values(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", namespace=~\"$namespace\"}, ingress)", + "refId": "main-ingress-Variable-Query" + }, + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": ".*", + "current": { + "selected": true, + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": "$ds_prometheus", + "definition": "", + "description": null, + "error": null, + "hide": 0, + "includeAll": true, + "label": "Service", + "multi": true, + "name": "service", + "options": [], + "query": { + "query": "label_values(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", namespace=~\"$namespace\", ingress=~\"$ingress\"}, service)", + "refId": "main-service-Variable-Query" + }, + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": ".*", + "current": { + "selected": true, + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": "$ds_prometheus", + "definition": "", + "description": null, + "error": null, + "hide": 0, + "includeAll": true, + "label": "Service Port", + "multi": true, + "name": "service_port", + "options": [], + "query": { + "query": "label_values(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\"}, service_port)", + "refId": "main-service_port-Variable-Query" + }, + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "current": { + "selected": true, + "text": "without default backend", + "value": "[^_]*" + }, + "hide": 0, + "includeAll": false, + "label": "VHost", + "multi": false, + "name": "vhost", + "options": [ + { + "selected": true, + "text": "without default backend", + "value": "[^_]*" + }, + { + "selected": false, + "text": "all", + "value": ".*" + }, + { + "selected": false, + "text": "default backend", + "value": "_" + } + ], + "query": "[^_]*,.*,_", + "skipUrlSync": false, + "type": "custom" + }, + { + "description": null, + "error": null, + "hide": 2, + "label": "Location", + "name": "location", + "query": ".*", + "skipUrlSync": false, + "type": "constant" + }, + { + "allValue": ".*", + "current": { + "selected": true, + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": "$ds_prometheus", + "definition": "", + "description": null, + "error": null, + "hide": 0, + "includeAll": true, + "label": "Content Kind", + "multi": true, + "name": "content_kind", + "options": [], + "query": { + "query": "label_values(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\"}, content_kind)", + "refId": "main-content_kind-Variable-Query" + }, + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": ".*", + "current": { + "selected": true, + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": "$ds_prometheus", + "definition": "", + "description": null, + "error": null, + "hide": 2, + "includeAll": true, + "label": "Method", + "multi": true, + "name": "method", + "options": [], + "query": { + "query": "label_values(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}, method)", + "refId": "main-method-Variable-Query" + }, + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": ".*", + "current": { + "selected": true, + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": "$ds_prometheus", + "definition": "", + "description": null, + "error": null, + "hide": 2, + "includeAll": true, + "label": "Method", + "multi": true, + "name": "status", + "options": [], + "query": { + "query": "label_values(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}, status)", + "refId": "main-status-Variable-Query" + }, + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "current": { + "selected": true, + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": "$ds_prometheus", + "definition": "", + "description": null, + "error": null, + "hide": 2, + "includeAll": true, + "label": "Pod IP", + "multi": true, + "name": "pod_ip", + "options": [], + "query": { + "query": "label_values(ingress_nginx_${metric}_backend_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\"}, pod_ip)", + "refId": "main-pod_ip-Variable-Query" + }, + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + } + ] + }, + "time": { + "from": "now-3h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "", + "title": "Namespace Detail", + "uid": "oipwXCMik", + "version": 2 +} diff --git a/dashboards/ingress/namespaces.json b/dashboards/ingress/namespaces.json new file mode 100644 index 00000000..eee476fd --- /dev/null +++ b/dashboards/ingress/namespaces.json @@ -0,0 +1,8270 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": "-- Grafana --", + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "limit": 100, + "name": "Annotations & Alerts", + "showIn": 0, + "target": { + "limit": 100, + "matchAny": false, + "tags": [], + "type": "dashboard" + }, + "type": "dashboard" + } + ] + }, + "editable": false, + "fiscalYearStartMonth": 0, + "gnetId": null, + "graphTooltip": 1, + "iteration": 1640794303229, + "links": [], + "liveNow": false, + "panels": [ + { + "collapsed": false, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 126, + "panels": [], + "title": "Main", + "type": "row" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "rgb(31, 120, 193)", + "mode": "fixed" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 0, + "y": 1 + }, + "id": 26, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]))", + "format": "time_series", + "instant": true, + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "Requests", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "rgb(31, 120, 193)", + "mode": "fixed" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 3, + "y": 1 + }, + "id": 111, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "sum(increase(ingress_nginx_${metric}_upstream_retries_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]))\n / sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]))\nor vector(0)", + "format": "time_series", + "instant": true, + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "Retried Requests", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "rgb(31, 120, 193)", + "mode": "fixed" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 6, + "y": 1 + }, + "id": 47, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "sum(increase(ingress_nginx_${metric}_received_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]))", + "format": "time_series", + "instant": true, + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "In Traffic", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "rgb(31, 120, 193)", + "mode": "fixed" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 9, + "y": 1 + }, + "id": 48, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "sum(increase(ingress_nginx_${metric}_sent_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]))", + "format": "time_series", + "instant": true, + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "Out Traffic", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "rgb(31, 120, 193)", + "mode": "fixed" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ops" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 12, + "y": 1 + }, + "id": 109, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]))", + "format": "time_series", + "instant": true, + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "Avg RPS", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 15, + "y": 1 + }, + "id": 65, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_request_seconds_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]))\n / sum(rate(ingress_nginx_${metric}_request_seconds_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]))\n * 1000", + "format": "time_series", + "instant": true, + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "Avg Req Time", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 18, + "y": 1 + }, + "id": 69, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "sum(increase(ingress_nginx_${metric}_upstream_response_seconds_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]))\n / sum(increase(ingress_nginx_${metric}_upstream_response_seconds_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]))\n * 1000", + "format": "time_series", + "instant": true, + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "Avg Upstr Time", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "rgb(31, 120, 193)", + "mode": "fixed" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 21, + "y": 1 + }, + "id": 110, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", scheme=\"https\"}[$__rate_interval]))\n / (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) > 0)", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "HTTPS", + "type": "stat" + }, + { + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": null, + "displayMode": "auto", + "minWidth": 65 + }, + "decimals": 2, + "displayName": "", + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Time" + }, + "properties": [ + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #A" + }, + "properties": [ + { + "id": "displayName", + "value": "RPS" + }, + { + "id": "unit", + "value": "ops" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #B" + }, + "properties": [ + { + "id": "displayName", + "value": "Retried Req" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #C" + }, + "properties": [ + { + "id": "displayName", + "value": "Req Time" + }, + { + "id": "unit", + "value": "s" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #D" + }, + "properties": [ + { + "id": "displayName", + "value": "Upstr Time" + }, + { + "id": "unit", + "value": "s" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #E" + }, + "properties": [ + { + "id": "displayName", + "value": "In Traffic" + }, + { + "id": "unit", + "value": "bps" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #F" + }, + "properties": [ + { + "id": "displayName", + "value": "Out Traffic" + }, + { + "id": "unit", + "value": "bps" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #G" + }, + "properties": [ + { + "id": "displayName", + "value": "Req Size" + }, + { + "id": "unit", + "value": "bytes" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #H" + }, + "properties": [ + { + "id": "displayName", + "value": "Resp Size" + }, + { + "id": "unit", + "value": "bytes" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #I" + }, + "properties": [ + { + "id": "displayName", + "value": "1xx" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #J" + }, + "properties": [ + { + "id": "displayName", + "value": "2xx" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #K" + }, + "properties": [ + { + "id": "displayName", + "value": "3xx" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #L" + }, + "properties": [ + { + "id": "displayName", + "value": "4xx" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #M" + }, + "properties": [ + { + "id": "displayName", + "value": "5xx" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #N" + }, + "properties": [ + { + "id": "displayName", + "value": "HTTPS" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #O" + }, + "properties": [ + { + "id": "displayName", + "value": "GET" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #P" + }, + "properties": [ + { + "id": "displayName", + "value": "POST" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #Q" + }, + "properties": [ + { + "id": "displayName", + "value": "HEAD" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #R" + }, + "properties": [ + { + "id": "displayName", + "value": "PUT" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #S" + }, + "properties": [ + { + "id": "displayName", + "value": "DELETE" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #T" + }, + "properties": [ + { + "id": "displayName", + "value": "OPTIONS" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #U" + }, + "properties": [ + { + "id": "displayName", + "value": "PATCH" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "namespace" + }, + "properties": [ + { + "id": "displayName", + "value": "Namespace" + }, + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "links", + "value": [ + { + "targetBlank": false, + "title": "Open Namespace Detail", + "url": "/d/oipwXCMik/namespace-detail?var-namespace=${__value.raw}&${__url_time_range}" + } + ] + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 160 + } + ] + } + ] + }, + "gridPos": { + "h": 6, + "w": 24, + "x": 0, + "y": 3 + }, + "id": 28, + "links": [], + "options": { + "showHeader": true + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "(sum(rate(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "instant": true, + "intervalFactor": 1, + "refId": "A" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_upstream_retries_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by\n / (sum(rate(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "legendFormat": "", + "refId": "B" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_request_seconds_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by\n / (sum(increase(ingress_nginx_${metric}_request_seconds_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "legendFormat": "", + "refId": "C" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_upstream_response_seconds_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by\n / (sum(increase(ingress_nginx_${metric}_upstream_response_seconds_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "legendFormat": "", + "refId": "D" + }, + { + "expr": "(sum(rate(ingress_nginx_${metric}_received_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by * 8 > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "legendFormat": "", + "refId": "E" + }, + { + "expr": "(sum(rate(ingress_nginx_${metric}_sent_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by * 8 > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "F" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_received_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by\n / (sum(increase(ingress_nginx_${metric}_received_bytes_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "G" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_sent_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by\n / (sum(increase(ingress_nginx_${metric}_sent_bytes_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "H" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"1..\"}[$__range])) $by\n/ (sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "I" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"2..\"}[$__range])) $by\n/ (sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "J" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"3..\"}[$__range])) $by\n/ (sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "K" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"4..\"}[$__range])) $by\n/ (sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "L" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"5..\"}[$__range])) $by\n/ (sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "M" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", scheme=\"https\"}[$__range])) $by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "N" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"GET\"}[$__range])) $by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "O" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"POST\"}[$__range])) $by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "P" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"HEAD\"}[$__range])) $by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "Q" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"PUT\"}[$__range])) $by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "R" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"DELETE\"}[$__range])) $by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "S" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"OPTIONS\"}[$__range])) $by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "T" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"PATCH\"}[$__range])) $by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "U" + } + ], + "title": "Average", + "transformations": [ + { + "id": "merge", + "options": { + "reducers": [] + } + }, + { + "id": "filterFieldsByName", + "options": { + "include": { + "names": [ + "namespace", + "Value #A", + "Value #B", + "Value #C", + "Value #D", + "Value #E", + "Value #F", + "Value #G", + "Value #H", + "Value #I", + "Value #J", + "Value #K", + "Value #L", + "Value #M", + "Value #N", + "Value #O", + "Value #P", + "Value #Q", + "Value #R", + "Value #S", + "Value #T", + "Value #U" + ] + } + } + } + ], + "type": "table" + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 16, + "x": 0, + "y": 9 + }, + "hiddenSeries": false, + "id": 1, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sort": "total", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A", + "step": 20 + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $by > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Requests", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 8, + "x": 16, + "y": 9 + }, + "hiddenSeries": false, + "id": 80, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sort": "total", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $by\n / scalar(sum(rate(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))) > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Requests %", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "percentunit", + "label": "", + "logBase": 1, + "max": "1", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "3xx": "#6ED0E0", + "4xx": "#EAB839", + "5xx": "#BF1B00" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 16, + "x": 0, + "y": 14 + }, + "hiddenSeries": false, + "id": 212, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": true, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + }, + { + "alias": "2xx", + "color": "#73BF69" + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A" + }, + { + "expr": "sum(label_replace(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]), \"status_group\", \"${1}xx\", \"status\", \"([0-9])..\")) by (status_group) > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{ status_group }}", + "refId": "B", + "step": 40 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Responses", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "3xx": "#6ED0E0", + "4xx": "#EAB839", + "5xx": "#BF1B00" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 8, + "x": 16, + "y": 14 + }, + "hiddenSeries": false, + "id": 229, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": true, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(label_replace(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]), \"status_group\", \"${1}xx\", \"status\", \"([0-9])..\")) by (status_group)\n / scalar(sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))) > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{status_group}}", + "refId": "B", + "step": 40 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Responses %", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "percentunit", + "label": "", + "logBase": 1, + "max": "1", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 8, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 16, + "x": 0, + "y": 20 + }, + "hiddenSeries": false, + "hideTimeOverride": false, + "id": 4, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sideWidth": null, + "sort": null, + "sortDesc": null, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 0, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "0.005", + "color": "#76B576" + }, + { + "alias": "0.01", + "color": "#83BC6D" + }, + { + "alias": "0.02", + "color": "#91C364" + }, + { + "alias": "0.03", + "color": "#9FCB5B" + }, + { + "alias": "0.04", + "color": "#ACD252" + }, + { + "alias": "0.05", + "color": "#BADA49" + }, + { + "alias": "0.075", + "color": "#C8E140" + }, + { + "alias": "0.1", + "color": "#D5E837" + }, + { + "alias": "0.2", + "color": "#E3F02E" + }, + { + "alias": "0.3", + "color": "#F1F725" + }, + { + "alias": "0.4", + "color": "#FFFF1C" + }, + { + "alias": "0.5", + "color": "#FAE519" + }, + { + "alias": "0.75", + "color": "#F6CC16" + }, + { + "alias": "1", + "color": "#F2B213" + }, + { + "alias": "1.5", + "color": "#EE9910" + }, + { + "alias": "2", + "color": "#EA7F0E" + }, + { + "alias": "3", + "color": "#E6660B" + }, + { + "alias": "4", + "color": "#E24C08" + }, + { + "alias": "5", + "color": "#DE3205" + }, + { + "alias": "10", + "color": "#DA1902" + }, + { + "alias": "+Inf", + "color": "#D60000" + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_lowres_upstream_response_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)", + "format": "heatmap", + "intervalFactor": 1, + "legendFormat": "{{le}}", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Upstream Response Time", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + "total" + ] + }, + "yaxes": [ + { + "decimals": null, + "format": "ops", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 8, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 8, + "x": 16, + "y": 20 + }, + "hiddenSeries": false, + "hideTimeOverride": false, + "id": 81, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sideWidth": null, + "sort": null, + "sortDesc": null, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 0, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "0.005", + "color": "#76B576" + }, + { + "alias": "0.01", + "color": "#83BC6D" + }, + { + "alias": "0.02", + "color": "#91C364" + }, + { + "alias": "0.03", + "color": "#9FCB5B" + }, + { + "alias": "0.04", + "color": "#ACD252" + }, + { + "alias": "0.05", + "color": "#BADA49" + }, + { + "alias": "0.075", + "color": "#C8E140" + }, + { + "alias": "0.1", + "color": "#D5E837" + }, + { + "alias": "0.2", + "color": "#E3F02E" + }, + { + "alias": "0.3", + "color": "#F1F725" + }, + { + "alias": "0.4", + "color": "#FFFF1C" + }, + { + "alias": "0.5", + "color": "#FAE519" + }, + { + "alias": "0.75", + "color": "#F6CC16" + }, + { + "alias": "1", + "color": "#F2B213" + }, + { + "alias": "1.5", + "color": "#EE9910" + }, + { + "alias": "2", + "color": "#EA7F0E" + }, + { + "alias": "3", + "color": "#E6660B" + }, + { + "alias": "4", + "color": "#E24C08" + }, + { + "alias": "5", + "color": "#DE3205" + }, + { + "alias": "10", + "color": "#DA1902" + }, + { + "alias": "+Inf", + "color": "#D60000" + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_lowres_upstream_response_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)\n / scalar(sum(rate(ingress_nginx_${metric}_lowres_upstream_response_seconds_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])))", + "format": "heatmap", + "intervalFactor": 1, + "legendFormat": "{{le}}", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Upstream Response Time %", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + "total" + ] + }, + "yaxes": [ + { + "format": "percentunit", + "label": null, + "logBase": 1, + "max": "1", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 8, + "x": 0, + "y": 26 + }, + "hiddenSeries": false, + "hideTimeOverride": false, + "id": 62, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sideWidth": null, + "sort": null, + "sortDesc": null, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": true, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_upstream_retries_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_upstream_retries_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $by > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Retried Requests", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + "total" + ] + }, + "yaxes": [ + { + "format": "ops", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 8, + "x": 8, + "y": 26 + }, + "hiddenSeries": false, + "hideTimeOverride": false, + "id": 112, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sideWidth": null, + "sort": null, + "sortDesc": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_upstream_retries_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $by\n/ sum(rate(ingress_nginx_${metric}_upstream_retries_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $by\n> 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Retries (per Retried Request)", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + "total" + ] + }, + "yaxes": [ + { + "format": "ops", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "3xx": "#6ED0E0", + "4xx": "#EAB839", + "5xx": "#BF1B00" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 8, + "x": 16, + "y": 26 + }, + "hiddenSeries": false, + "id": 196, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": true, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"1..\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"1..\"}[$__rate_interval])) $by > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "B", + "step": 40 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "1xx", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "3xx": "#6ED0E0", + "4xx": "#EAB839", + "5xx": "#BF1B00" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 8, + "x": 16, + "y": 30 + }, + "hiddenSeries": false, + "id": 87, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": true, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"2..\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"2..\"}[$__rate_interval])) $by > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "B", + "step": 40 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "2xx", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": null, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 8, + "x": 0, + "y": 31 + }, + "hiddenSeries": false, + "hideTimeOverride": false, + "id": 49, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sideWidth": null, + "sort": null, + "sortDesc": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_request_seconds_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $by\n / sum(rate(ingress_nginx_${metric}_request_seconds_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $by > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Avg Request Time", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + "total" + ] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": null, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 8, + "x": 8, + "y": 31 + }, + "hiddenSeries": false, + "hideTimeOverride": false, + "id": 63, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sideWidth": null, + "sort": null, + "sortDesc": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_upstream_response_seconds_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $by\n / sum(rate(ingress_nginx_${metric}_upstream_response_seconds_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $by > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Avg Upstream Response Time", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + "total" + ] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "3xx": "#6ED0E0", + "4xx": "#EAB839", + "5xx": "#BF1B00" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 8, + "x": 16, + "y": 34 + }, + "hiddenSeries": false, + "id": 10, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": true, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"3..\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"3..\"}[$__rate_interval])) $by > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "B", + "step": 40 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "3xx", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": null, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 8, + "x": 0, + "y": 36 + }, + "hiddenSeries": false, + "hideTimeOverride": false, + "id": 58, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sideWidth": null, + "sort": null, + "sortDesc": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_received_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $by\n / sum(rate(ingress_nginx_${metric}_received_bytes_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $by > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Avg Request Size", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + "total" + ] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": null, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 8, + "x": 8, + "y": 36 + }, + "hiddenSeries": false, + "hideTimeOverride": false, + "id": 73, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sideWidth": null, + "sort": null, + "sortDesc": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_sent_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $by\n / sum(rate(ingress_nginx_${metric}_sent_bytes_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $by > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Avg Response Size", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + "total" + ] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "3xx": "#6ED0E0", + "4xx": "#EAB839", + "5xx": "#BF1B00" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 8, + "x": 16, + "y": 38 + }, + "hiddenSeries": false, + "id": 18, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": true, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"4..\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"4..\"}[$__rate_interval])) $by > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "B", + "step": 40 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "4xx", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 8, + "x": 0, + "y": 41 + }, + "hiddenSeries": false, + "id": 12, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_received_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) * 8", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A", + "step": 20 + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_received_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $by * 8 > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "B", + "step": 20 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Incoming Traffic", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bps", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 8, + "x": 8, + "y": 41 + }, + "hiddenSeries": false, + "id": 9, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sort": "max", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_sent_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) * 8", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A", + "step": 20 + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_sent_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $by * 8 > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Outgoing Traffic", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bps", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "3xx": "#6ED0E0", + "4xx": "#EAB839", + "5xx": "#BF1B00" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 8, + "x": 16, + "y": 42 + }, + "hiddenSeries": false, + "id": 17, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": true, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"5..\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"5..\"}[$__rate_interval])) $by > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "B", + "step": 40 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "5xx", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "collapsed": true, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 46 + }, + "id": 195, + "panels": [ + { + "aliasColors": { + "3xx": "#6ED0E0", + "4xx": "#EAB839", + "5xx": "#BF1B00" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "gridPos": { + "h": 4, + "w": 8, + "x": 0, + "y": 47 + }, + "id": 189, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": true, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "percentage": true, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"1..\"}[$__rate_interval])) by (status)\n / scalar(sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"1..\"}[$__rate_interval])))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{status}}", + "refId": "B", + "step": 40 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "1xx", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "percentunit", + "label": "", + "logBase": 1, + "max": "100", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "3xx": "#6ED0E0", + "4xx": "#EAB839", + "5xx": "#BF1B00" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "gridPos": { + "h": 4, + "w": 8, + "x": 8, + "y": 47 + }, + "id": 190, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": true, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "percentage": true, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"2..\"}[$__rate_interval])) by (status)\n / scalar(sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"2..\"}[$__rate_interval])))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{status}}", + "refId": "B", + "step": 40 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "2xx", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "percentunit", + "label": "", + "logBase": 1, + "max": "100", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "3xx": "#6ED0E0", + "4xx": "#EAB839", + "5xx": "#BF1B00" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "gridPos": { + "h": 4, + "w": 8, + "x": 16, + "y": 47 + }, + "id": 191, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": true, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "percentage": true, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"3..\"}[$__rate_interval])) by (status)\n / scalar(sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"3..\"}[$__rate_interval])))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{status}}", + "refId": "B", + "step": 40 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "3xx", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "percentunit", + "label": "", + "logBase": 1, + "max": "100", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "3xx": "#6ED0E0", + "4xx": "#EAB839", + "5xx": "#BF1B00" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "gridPos": { + "h": 5, + "w": 12, + "x": 0, + "y": 51 + }, + "id": 192, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": true, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "percentage": true, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"4..\"}[$__rate_interval])) by (status)\n / scalar(sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"4..\"}[$__rate_interval])))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{status}}", + "refId": "B", + "step": 40 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "4xx", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "percentunit", + "label": "", + "logBase": 1, + "max": "100", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "3xx": "#6ED0E0", + "4xx": "#EAB839", + "5xx": "#BF1B00" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "gridPos": { + "h": 5, + "w": 12, + "x": 12, + "y": 51 + }, + "id": 193, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": true, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "percentage": true, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"5..\"}[$__rate_interval])) by (status)\n / scalar(sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"5..\"}[$__rate_interval])))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{status}}", + "refId": "B", + "step": 40 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "5xx", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "percentunit", + "label": "", + "logBase": 1, + "max": "100", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "3xx": "#6ED0E0", + "4xx": "#EAB839", + "5xx": "#BF1B00" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "gridPos": { + "h": 4, + "w": 6, + "x": 0, + "y": 56 + }, + "id": 86, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": true, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "maxPerRow": 4, + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": "status", + "repeatDirection": "h", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=\"$status\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=\"$status\"}[$__rate_interval])) $by > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "B", + "step": 40 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "$status", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "title": "Status Codes", + "type": "row" + }, + { + "collapsed": true, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 47 + }, + "id": 150, + "panels": [ + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 0, + "y": 3 + }, + "id": 130, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.3", + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_request_seconds_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))\n / sum(rate(ingress_nginx_${metric}_request_seconds_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))\n * 1000", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "Avg Req Time", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 3, + "y": 3 + }, + "id": 132, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.3", + "targets": [ + { + "expr": "histogram_quantile(0.5, sum(rate(ingress_nginx_${metric}_request_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)) * 1000", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "50th Req Time", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 6, + "y": 3 + }, + "id": 134, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.3", + "targets": [ + { + "expr": "histogram_quantile(0.9, sum(rate(ingress_nginx_${metric}_request_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)) * 1000", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "90th Req Time", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 9, + "y": 3 + }, + "id": 174, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.3", + "targets": [ + { + "expr": "histogram_quantile(0.99, sum(rate(ingress_nginx_${metric}_request_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)) * 1000", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "99th Req Time", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 12, + "y": 3 + }, + "id": 140, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.3", + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_upstream_response_seconds_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))\n / sum(rate(ingress_nginx_${metric}_upstream_response_seconds_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))\n * 1000", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "Avg Upstr Time", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 15, + "y": 3 + }, + "id": 142, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.3", + "targets": [ + { + "expr": "histogram_quantile(0.5, sum(rate(ingress_nginx_${metric}_upstream_response_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)) * 1000", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "50th Upstr Time", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 18, + "y": 3 + }, + "id": 144, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.3", + "targets": [ + { + "expr": "histogram_quantile(0.9, sum(rate(ingress_nginx_${metric}_upstream_response_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)) * 1000", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "90th Upstr Time", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 21, + "y": 3 + }, + "id": 146, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.3", + "targets": [ + { + "expr": "histogram_quantile(0.99, sum(rate(ingress_nginx_${metric}_upstream_response_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)) * 1000", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "99th Upstr Time", + "type": "stat" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": null, + "fill": 0, + "gridPos": { + "h": 5, + "w": 12, + "x": 0, + "y": 5 + }, + "hideTimeOverride": false, + "id": 136, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sideWidth": null, + "sort": null, + "sortDesc": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Avg", + "fill": 2, + "linewidth": 0 + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "histogram_quantile(0.99, sum(rate(ingress_nginx_${metric}_request_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)) * 1000", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "99th", + "refId": "A" + }, + { + "expr": "histogram_quantile(0.9, sum(rate(ingress_nginx_${metric}_request_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)) * 1000", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "90th", + "refId": "B" + }, + { + "expr": "histogram_quantile(0.5, sum(rate(ingress_nginx_${metric}_request_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)) * 1000", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "50th", + "refId": "C" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_request_seconds_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))\n / sum(rate(ingress_nginx_${metric}_request_seconds_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))\n * 1000", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Avg", + "refId": "D" + } + ], + "thresholds": [], + "timeFrom": null, + "timeShift": null, + "title": "Request Time", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + "total" + ] + }, + "yaxes": [ + { + "format": "ms", + "label": null, + "logBase": 10, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": null, + "fill": 0, + "gridPos": { + "h": 5, + "w": 12, + "x": 12, + "y": 5 + }, + "hideTimeOverride": false, + "id": 148, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sideWidth": null, + "sort": null, + "sortDesc": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Avg", + "fill": 2, + "linewidth": 0 + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "histogram_quantile(0.99, sum(rate(ingress_nginx_${metric}_upstream_response_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)) * 1000", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "99th", + "refId": "A" + }, + { + "expr": "histogram_quantile(0.9, sum(rate(ingress_nginx_${metric}_upstream_response_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)) * 1000", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "90th", + "refId": "B" + }, + { + "expr": "histogram_quantile(0.5, sum(rate(ingress_nginx_${metric}_upstream_response_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)) * 1000", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "50th", + "refId": "C" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_upstream_response_seconds_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))\n / sum(rate(ingress_nginx_${metric}_upstream_response_seconds_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))\n * 1000", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Avg", + "refId": "D" + } + ], + "thresholds": [], + "timeFrom": null, + "timeShift": null, + "title": "Upstream Response Time", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + "total" + ] + }, + "yaxes": [ + { + "format": "ms", + "label": null, + "logBase": 10, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "title": "Request Time and Upstream Response Time", + "type": "row" + }, + { + "collapsed": true, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 48 + }, + "id": 211, + "panels": [ + { + "cards": { + "cardPadding": 0, + "cardRound": 0 + }, + "color": { + "cardColor": "#b4ff00", + "colorScale": "sqrt", + "colorScheme": "interpolateYlGnBu", + "exponent": 0.5, + "max": null, + "min": 0, + "mode": "spectrum" + }, + "dataFormat": "tsbuckets", + "datasource": null, + "gridPos": { + "h": 21, + "w": 12, + "x": 0, + "y": 11 + }, + "heatmap": {}, + "highlightCards": true, + "id": 152, + "legend": { + "show": true + }, + "links": [], + "targets": [ + { + "expr": "sum(increase(ingress_nginx_${metric}_request_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le) > 0", + "format": "heatmap", + "intervalFactor": 1, + "legendFormat": "{{le}}", + "refId": "A" + } + ], + "title": "Request Time", + "tooltip": { + "show": true, + "showHistogram": true + }, + "type": "heatmap", + "xAxis": { + "show": true + }, + "xBucketNumber": null, + "xBucketSize": null, + "yAxis": { + "decimals": 1, + "format": "s", + "logBase": 1, + "max": null, + "min": null, + "show": true, + "splitFactor": null + }, + "yBucketBound": "auto", + "yBucketNumber": null, + "yBucketSize": null + }, + { + "cards": { + "cardPadding": 0, + "cardRound": 0 + }, + "color": { + "cardColor": "#b4ff00", + "colorScale": "sqrt", + "colorScheme": "interpolateYlGnBu", + "exponent": 0.5, + "max": null, + "min": 0, + "mode": "spectrum" + }, + "dataFormat": "tsbuckets", + "datasource": null, + "gridPos": { + "h": 21, + "w": 12, + "x": 12, + "y": 11 + }, + "heatmap": {}, + "highlightCards": true, + "id": 153, + "legend": { + "show": true + }, + "links": [], + "targets": [ + { + "expr": "sum(increase(ingress_nginx_${metric}_upstream_response_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le) > 0", + "format": "heatmap", + "intervalFactor": 1, + "legendFormat": "{{le}}", + "refId": "A" + } + ], + "title": "Upstream Response Time", + "tooltip": { + "show": true, + "showHistogram": true + }, + "type": "heatmap", + "xAxis": { + "show": true + }, + "xBucketNumber": null, + "xBucketSize": null, + "yAxis": { + "decimals": 1, + "format": "s", + "logBase": 1, + "max": null, + "min": null, + "show": true, + "splitFactor": null + }, + "yBucketBound": "auto", + "yBucketNumber": null, + "yBucketSize": null + } + ], + "title": "Request Time Heatmap and Upstream Response Time Heatmap", + "type": "row" + }, + { + "collapsed": true, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 49 + }, + "id": 160, + "panels": [ + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 0, + "y": 5 + }, + "id": 171, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.3", + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_received_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))\n / sum(rate(ingress_nginx_${metric}_received_bytes_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "Avg Req Size", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 3, + "y": 5 + }, + "id": 172, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.3", + "targets": [ + { + "expr": "histogram_quantile(0.5, sum(rate(ingress_nginx_${metric}_received_bytes_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le))", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "50th Req Size", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 6, + "y": 5 + }, + "id": 173, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.3", + "targets": [ + { + "expr": "histogram_quantile(0.9, sum(rate(ingress_nginx_${metric}_received_bytes_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le))", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "90th Req Size", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 9, + "y": 5 + }, + "id": 128, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.3", + "targets": [ + { + "expr": "histogram_quantile(0.99, sum(rate(ingress_nginx_${metric}_received_bytes_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le))", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "99th Req Size", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 12, + "y": 5 + }, + "id": 175, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.3", + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_sent_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))\n / sum(rate(ingress_nginx_${metric}_sent_bytes_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "Avg Resp Size", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 15, + "y": 5 + }, + "id": 176, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.3", + "targets": [ + { + "expr": "histogram_quantile(0.5, sum(rate(ingress_nginx_${metric}_sent_bytes_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le))", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "50th Resp Size", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 18, + "y": 5 + }, + "id": 177, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.3", + "targets": [ + { + "expr": "histogram_quantile(0.9, sum(rate(ingress_nginx_${metric}_sent_bytes_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le))", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "90th Resp Size", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 21, + "y": 5 + }, + "id": 178, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.3", + "targets": [ + { + "expr": "histogram_quantile(0.99, sum(rate(ingress_nginx_${metric}_sent_bytes_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le))", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "99th Resp Size", + "type": "stat" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": null, + "fill": 0, + "gridPos": { + "h": 4, + "w": 12, + "x": 0, + "y": 7 + }, + "hideTimeOverride": false, + "id": 155, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sideWidth": null, + "sort": null, + "sortDesc": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Avg", + "fill": 2, + "linewidth": 0 + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "histogram_quantile(0.99, sum(rate(ingress_nginx_${metric}_received_bytes_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "99th", + "refId": "A" + }, + { + "expr": "histogram_quantile(0.9, sum(rate(ingress_nginx_${metric}_received_bytes_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "90th", + "refId": "B" + }, + { + "expr": "histogram_quantile(0.5, sum(rate(ingress_nginx_${metric}_received_bytes_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "50th", + "refId": "C" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_received_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))\n / sum(rate(ingress_nginx_${metric}_received_bytes_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Avg", + "refId": "D" + } + ], + "thresholds": [], + "timeFrom": null, + "timeShift": null, + "title": "Request Size", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + "total" + ] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 2, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": null, + "fill": 0, + "gridPos": { + "h": 4, + "w": 12, + "x": 12, + "y": 7 + }, + "hideTimeOverride": false, + "id": 157, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sideWidth": null, + "sort": null, + "sortDesc": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Avg", + "fill": 2, + "linewidth": 0 + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "histogram_quantile(0.99, sum(rate(ingress_nginx_${metric}_sent_bytes_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "99th", + "refId": "A" + }, + { + "expr": "histogram_quantile(0.9, sum(rate(ingress_nginx_${metric}_sent_bytes_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "90th", + "refId": "B" + }, + { + "expr": "histogram_quantile(0.5, sum(rate(ingress_nginx_${metric}_sent_bytes_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "50th", + "refId": "C" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_sent_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))\n / sum(rate(ingress_nginx_${metric}_sent_bytes_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Avg", + "refId": "D" + } + ], + "thresholds": [], + "timeFrom": null, + "timeShift": null, + "title": "Response Size", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + "total" + ] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 2, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "title": "Request Size and Response Size", + "type": "row" + }, + { + "collapsed": true, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 50 + }, + "id": 209, + "panels": [ + { + "cards": { + "cardPadding": 0, + "cardRound": 0 + }, + "color": { + "cardColor": "#b4ff00", + "colorScale": "sqrt", + "colorScheme": "interpolateYlGnBu", + "exponent": 0.5, + "max": null, + "min": 0, + "mode": "spectrum" + }, + "dataFormat": "tsbuckets", + "datasource": null, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 6 + }, + "heatmap": {}, + "highlightCards": true, + "id": 158, + "legend": { + "show": true + }, + "links": [], + "targets": [ + { + "expr": "sum(increase(ingress_nginx_${metric}_received_bytes_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)", + "format": "heatmap", + "intervalFactor": 1, + "legendFormat": "{{le}}", + "refId": "A" + } + ], + "title": "Request Size", + "tooltip": { + "show": true, + "showHistogram": true + }, + "type": "heatmap", + "xAxis": { + "show": true + }, + "xBucketNumber": null, + "xBucketSize": null, + "yAxis": { + "decimals": 0, + "format": "bytes", + "logBase": 1, + "max": null, + "min": null, + "show": true, + "splitFactor": null + }, + "yBucketBound": "auto", + "yBucketNumber": null, + "yBucketSize": null + }, + { + "cards": { + "cardPadding": 0, + "cardRound": 0 + }, + "color": { + "cardColor": "#b4ff00", + "colorScale": "sqrt", + "colorScheme": "interpolateYlGnBu", + "exponent": 0.5, + "max": null, + "min": 0, + "mode": "spectrum" + }, + "dataFormat": "tsbuckets", + "datasource": null, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 6 + }, + "heatmap": {}, + "highlightCards": true, + "id": 161, + "legend": { + "show": true + }, + "links": [], + "targets": [ + { + "expr": "sum(increase(ingress_nginx_${metric}_sent_bytes_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)", + "format": "heatmap", + "intervalFactor": 1, + "legendFormat": "{{le}}", + "refId": "A" + } + ], + "title": "Response Size", + "tooltip": { + "show": true, + "showHistogram": true + }, + "type": "heatmap", + "xAxis": { + "show": true + }, + "xBucketNumber": null, + "xBucketSize": null, + "yAxis": { + "decimals": 0, + "format": "bytes", + "logBase": 1, + "max": null, + "min": null, + "show": true, + "splitFactor": null + }, + "yBucketBound": "auto", + "yBucketNumber": null, + "yBucketSize": null + } + ], + "title": "Request Size Heatmap and Response Size Heatmap", + "type": "row" + }, + { + "collapsed": true, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 51 + }, + "id": 89, + "panels": [ + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "gridPos": { + "h": 6, + "w": 12, + "x": 0, + "y": 43 + }, + "id": 61, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sort": "total", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (method)\n / scalar(sum(rate(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{method}}", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeShift": null, + "title": "Method %", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "percentunit", + "label": "", + "logBase": 1, + "max": "1", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "gridPos": { + "h": 6, + "w": 12, + "x": 12, + "y": 43 + }, + "id": 60, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sort": "total", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\"}[$__rate_interval])) by (content_kind)\n/ scalar(sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\"}[$__rate_interval])))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{content_kind}}", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeShift": null, + "title": "Content Kind %", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "percentunit", + "label": "", + "logBase": 1, + "max": "1", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "gridPos": { + "h": 4, + "w": 12, + "x": 0, + "y": 49 + }, + "id": 90, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sort": "total", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": "method", + "repeatDirection": "v", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"$method\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"$method\"}[$__rate_interval])) $by > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeShift": null, + "title": "$method", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "gridPos": { + "h": 4, + "w": 12, + "x": 12, + "y": 49 + }, + "id": 97, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sort": "total", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": "content_kind", + "repeatDirection": "v", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=\"$content_kind\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=\"$content_kind\"}[$__rate_interval])) $by > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeShift": null, + "title": "$content_kind", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "title": "Request Method and Content Kind", + "type": "row" + }, + { + "collapsed": true, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 52 + }, + "id": 79, + "panels": [ + { + "circleMaxSize": "10", + "circleMinSize": 2, + "colors": [ + "#890f02", + "#890f02" + ], + "datasource": "$ds_prometheus", + "decimals": 0, + "esGeoPoint": "geohash", + "esLocationName": "place", + "esMetric": "Value", + "gridPos": { + "h": 18, + "w": 24, + "x": 0, + "y": 33 + }, + "hideEmpty": false, + "hideZero": false, + "id": 75, + "initialZoom": "3", + "links": [], + "locationData": "geohash", + "mapCenter": "Europe", + "mapCenterLatitude": 46, + "mapCenterLongitude": 14, + "maxDataPoints": 1, + "showLegend": false, + "stickyLabels": false, + "targets": [ + { + "expr": "sum(increase(ingress_nginx_${metric}_geohash_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) by (geohash, place) > 0", + "format": "table", + "instant": true, + "intervalFactor": 1, + "refId": "A" + } + ], + "thresholds": "", + "title": "Requests", + "transparent": false, + "type": "grafana-worldmap-panel", + "unitPlural": "", + "unitSingle": "", + "valueName": "total" + } + ], + "title": "Map", + "type": "row" + }, + { + "collapsed": true, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 53 + }, + "id": 46, + "panels": [ + { + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": null, + "displayMode": "auto", + "minWidth": 64 + }, + "decimals": 2, + "displayName": "", + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Time" + }, + "properties": [ + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #A" + }, + "properties": [ + { + "id": "displayName", + "value": "RPS" + }, + { + "id": "unit", + "value": "ops" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 85 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #B" + }, + "properties": [ + { + "id": "displayName", + "value": "Retried Req" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 85 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #C" + }, + "properties": [ + { + "id": "displayName", + "value": "Req Time" + }, + { + "id": "unit", + "value": "s" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 85 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #D" + }, + "properties": [ + { + "id": "displayName", + "value": "Resp Time" + }, + { + "id": "unit", + "value": "s" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 85 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #E" + }, + "properties": [ + { + "id": "displayName", + "value": "In Traffic" + }, + { + "id": "unit", + "value": "bps" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 85 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #F" + }, + "properties": [ + { + "id": "displayName", + "value": "Out Traffic" + }, + { + "id": "unit", + "value": "bps" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 85 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #G" + }, + "properties": [ + { + "id": "displayName", + "value": "Req Size" + }, + { + "id": "unit", + "value": "bytes" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 85 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #H" + }, + "properties": [ + { + "id": "displayName", + "value": "Resp Size" + }, + { + "id": "unit", + "value": "bytes" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 85 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #I" + }, + "properties": [ + { + "id": "displayName", + "value": "1xx" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #J" + }, + "properties": [ + { + "id": "displayName", + "value": "2xx" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #K" + }, + "properties": [ + { + "id": "displayName", + "value": "3xx" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #L" + }, + "properties": [ + { + "id": "displayName", + "value": "4xx" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #M" + }, + "properties": [ + { + "id": "displayName", + "value": "5xx" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #N" + }, + "properties": [ + { + "id": "displayName", + "value": "HTTPS" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #O" + }, + "properties": [ + { + "id": "displayName", + "value": "GET" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #P" + }, + "properties": [ + { + "id": "displayName", + "value": "POST" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #Q" + }, + "properties": [ + { + "id": "displayName", + "value": "HEAD" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #R" + }, + "properties": [ + { + "id": "displayName", + "value": "PUT" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #S" + }, + "properties": [ + { + "id": "displayName", + "value": "DELETE" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #T" + }, + "properties": [ + { + "id": "displayName", + "value": "OPTIONS" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #U" + }, + "properties": [ + { + "id": "displayName", + "value": "PATCH" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "vhost" + }, + "properties": [ + { + "id": "displayName", + "value": "VHost" + }, + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "links", + "value": [ + { + "targetBlank": false, + "title": "Open VHost", + "url": "/d/D38hRqGmk/vhosts?var-vhost=${__value.raw}&${__url_time_range}" + } + ] + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 300 + } + ] + } + ] + }, + "gridPos": { + "h": 6, + "w": 24, + "x": 0, + "y": 54 + }, + "id": 42, + "links": [], + "options": { + "showHeader": true + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "(sum(rate(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "instant": true, + "intervalFactor": 1, + "refId": "A" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_upstream_retries_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by\n / (sum(rate(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "legendFormat": "", + "refId": "B" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_request_seconds_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by\n / (sum(increase(ingress_nginx_${metric}_request_seconds_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "legendFormat": "", + "refId": "C" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_upstream_response_seconds_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by\n / (sum(increase(ingress_nginx_${metric}_upstream_response_seconds_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "legendFormat": "", + "refId": "D" + }, + { + "expr": "(sum(rate(ingress_nginx_${metric}_received_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by * 8 > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "legendFormat": "", + "refId": "E" + }, + { + "expr": "(sum(rate(ingress_nginx_${metric}_sent_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by * 8 > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "F" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_received_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by\n / (sum(increase(ingress_nginx_${metric}_received_bytes_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "G" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_sent_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by\n / (sum(increase(ingress_nginx_${metric}_sent_bytes_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "H" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"1..\"}[$__range])) $alt_by\n/ (sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "I" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"2..\"}[$__range])) $alt_by\n/ (sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "J" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"3..\"}[$__range])) $alt_by\n/ (sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "K" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"4..\"}[$__range])) $alt_by\n/ (sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "L" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"5..\"}[$__range])) $alt_by\n/ (sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "M" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", scheme=\"https\"}[$__range])) $alt_by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "N" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"GET\"}[$__range])) $alt_by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "O" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"POST\"}[$__range])) $alt_by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "P" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"HEAD\"}[$__range])) $alt_by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "Q" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"PUT\"}[$__range])) $alt_by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "R" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"DELETE\"}[$__range])) $alt_by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "S" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"OPTIONS\"}[$__range])) $alt_by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "T" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"PATCH\"}[$__range])) $alt_by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "U" + } + ], + "title": "Average", + "transformations": [ + { + "id": "merge", + "options": { + "reducers": [] + } + }, + { + "id": "filterFieldsByName", + "options": { + "include": { + "names": [ + "vhost", + "Value #A", + "Value #B", + "Value #C", + "Value #D", + "Value #E", + "Value #F", + "Value #G", + "Value #H", + "Value #I", + "Value #J", + "Value #K", + "Value #L", + "Value #M", + "Value #N", + "Value #O", + "Value #P", + "Value #Q", + "Value #R", + "Value #S", + "Value #T", + "Value #U" + ] + } + } + } + ], + "type": "table" + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 8, + "x": 0, + "y": 60 + }, + "hiddenSeries": false, + "id": 39, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sort": "total", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": true, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $alt_by > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$alt_legend_format", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Requests per $alt_name", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": "", + "logBase": 1, + "max": "100", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 1, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 8, + "x": 8, + "y": 60 + }, + "hiddenSeries": false, + "id": 41, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": true, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_received_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $alt_by * 8 > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$alt_legend_format", + "refId": "B", + "step": 20 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Incoming Traffic per $alt_name", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bps", + "label": null, + "logBase": 1, + "max": "100", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 1, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 8, + "x": 16, + "y": 60 + }, + "hiddenSeries": false, + "id": 40, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sort": "max", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": true, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_sent_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $alt_by * 8 > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$alt_legend_format", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Outgoing Traffic per $alt_name", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bps", + "label": null, + "logBase": 1, + "max": "100", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "title": "By $alt_name", + "type": "row" + } + ], + "refresh": "30s", + "schemaVersion": 32, + "style": "dark", + "tags": [ + "ingress" + ], + "templating": { + "list": [ + { + "current": { + "selected": false, + "text": "default", + "value": "default" + }, + "description": null, + "error": null, + "hide": 0, + "includeAll": false, + "label": "Prometheus", + "multi": false, + "name": "ds_prometheus", + "options": [], + "query": "prometheus", + "queryValue": "", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + }, + { + "description": null, + "error": null, + "hide": 2, + "label": null, + "name": "metric", + "query": "overall", + "skipUrlSync": false, + "type": "constant" + }, + { + "description": null, + "error": null, + "hide": 2, + "label": null, + "name": "by", + "query": "by (namespace)", + "skipUrlSync": false, + "type": "constant" + }, + { + "description": null, + "error": null, + "hide": 2, + "label": null, + "name": "legend_format", + "query": "{{namespace}}", + "skipUrlSync": false, + "type": "constant" + }, + { + "description": null, + "error": null, + "hide": 2, + "label": null, + "name": "alt_name", + "query": "VHost", + "skipUrlSync": false, + "type": "constant" + }, + { + "description": null, + "error": null, + "hide": 2, + "label": null, + "name": "alt_by", + "query": "by (vhost)", + "skipUrlSync": false, + "type": "constant" + }, + { + "description": null, + "error": null, + "hide": 2, + "label": null, + "name": "alt_legend_format", + "query": "{{vhost}}", + "skipUrlSync": false, + "type": "constant" + }, + { + "description": null, + "error": null, + "hide": 2, + "label": "Controller", + "name": "controller", + "query": ".*", + "skipUrlSync": false, + "type": "constant" + }, + { + "description": null, + "error": null, + "hide": 2, + "label": "App", + "name": "app", + "query": ".*", + "skipUrlSync": false, + "type": "constant" + }, + { + "description": null, + "error": null, + "hide": 2, + "label": "Node", + "name": "node", + "query": ".*", + "skipUrlSync": false, + "type": "constant" + }, + { + "allValue": ".*", + "current": { + "selected": true, + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": "$ds_prometheus", + "definition": "", + "description": null, + "error": null, + "hide": 0, + "includeAll": true, + "label": "Namespace", + "multi": true, + "name": "namespace", + "options": [], + "query": { + "query": "label_values(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\"}, namespace)", + "refId": "main-namespace-Variable-Query" + }, + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "description": null, + "error": null, + "hide": 2, + "label": "Ingress", + "name": "ingress", + "query": ".*", + "skipUrlSync": false, + "type": "constant" + }, + { + "description": null, + "error": null, + "hide": 2, + "label": "Service", + "name": "service", + "query": ".*", + "skipUrlSync": false, + "type": "constant" + }, + { + "description": null, + "error": null, + "hide": 2, + "label": "Service Port", + "name": "service_port", + "query": ".*", + "skipUrlSync": false, + "type": "constant" + }, + { + "current": { + "selected": true, + "text": "without default backend", + "value": "[^_]*" + }, + "hide": 0, + "includeAll": false, + "label": "VHost", + "multi": false, + "name": "vhost", + "options": [ + { + "selected": true, + "text": "without default backend", + "value": "[^_]*" + }, + { + "selected": false, + "text": "all", + "value": ".*" + }, + { + "selected": false, + "text": "default backend", + "value": "_" + } + ], + "query": "[^_]*,.*,_", + "skipUrlSync": false, + "type": "custom" + }, + { + "description": null, + "error": null, + "hide": 2, + "label": "Location", + "name": "location", + "query": ".*", + "skipUrlSync": false, + "type": "constant" + }, + { + "allValue": ".*", + "current": { + "selected": true, + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": "$ds_prometheus", + "definition": "", + "description": null, + "error": null, + "hide": 0, + "includeAll": true, + "label": "Content Kind", + "multi": true, + "name": "content_kind", + "options": [], + "query": { + "query": "label_values(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\"}, content_kind)", + "refId": "main-content_kind-Variable-Query" + }, + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": ".*", + "current": { + "selected": true, + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": "$ds_prometheus", + "definition": "", + "description": null, + "error": null, + "hide": 2, + "includeAll": true, + "label": "Method", + "multi": true, + "name": "method", + "options": [], + "query": { + "query": "label_values(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}, method)", + "refId": "main-method-Variable-Query" + }, + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": ".*", + "current": { + "selected": true, + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": "$ds_prometheus", + "definition": "", + "description": null, + "error": null, + "hide": 2, + "includeAll": true, + "label": "Method", + "multi": true, + "name": "status", + "options": [], + "query": { + "query": "label_values(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}, status)", + "refId": "main-status-Variable-Query" + }, + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + } + ] + }, + "time": { + "from": "now-24h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "", + "title": "Namespaces", + "uid": "Z-phNqGmz", + "version": 2 +} diff --git a/dashboards/ingress/vhost-detail.json b/dashboards/ingress/vhost-detail.json new file mode 100644 index 00000000..51003cec --- /dev/null +++ b/dashboards/ingress/vhost-detail.json @@ -0,0 +1,10247 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": "-- Grafana --", + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "limit": 100, + "name": "Annotations & Alerts", + "showIn": 0, + "target": { + "limit": 100, + "matchAny": false, + "tags": [], + "type": "dashboard" + }, + "type": "dashboard" + } + ] + }, + "editable": false, + "fiscalYearStartMonth": 0, + "gnetId": null, + "graphTooltip": 1, + "iteration": 1640793707081, + "links": [], + "liveNow": false, + "panels": [ + { + "collapsed": false, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 126, + "panels": [], + "title": "Main", + "type": "row" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "rgb(31, 120, 193)", + "mode": "fixed" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 0, + "y": 1 + }, + "id": 26, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]))", + "format": "time_series", + "instant": true, + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "Requests", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "rgb(31, 120, 193)", + "mode": "fixed" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 3, + "y": 1 + }, + "id": 111, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "sum(increase(ingress_nginx_${metric}_upstream_retries_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]))\n / sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]))\nor vector(0)", + "format": "time_series", + "instant": true, + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "Retried Requests", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "rgb(31, 120, 193)", + "mode": "fixed" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 6, + "y": 1 + }, + "id": 47, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "sum(increase(ingress_nginx_${metric}_received_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]))", + "format": "time_series", + "instant": true, + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "In Traffic", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "rgb(31, 120, 193)", + "mode": "fixed" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 9, + "y": 1 + }, + "id": 48, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "sum(increase(ingress_nginx_${metric}_sent_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]))", + "format": "time_series", + "instant": true, + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "Out Traffic", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "rgb(31, 120, 193)", + "mode": "fixed" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ops" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 12, + "y": 1 + }, + "id": 109, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]))", + "format": "time_series", + "instant": true, + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "Avg RPS", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 15, + "y": 1 + }, + "id": 65, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_request_seconds_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]))\n / sum(rate(ingress_nginx_${metric}_request_seconds_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]))\n * 1000", + "format": "time_series", + "instant": true, + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "Avg Req Time", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 18, + "y": 1 + }, + "id": 69, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "sum(increase(ingress_nginx_${metric}_upstream_response_seconds_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]))\n / sum(increase(ingress_nginx_${metric}_upstream_response_seconds_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]))\n * 1000", + "format": "time_series", + "instant": true, + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "Avg Upstr Time", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "rgb(31, 120, 193)", + "mode": "fixed" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 21, + "y": 1 + }, + "id": 110, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", scheme=\"https\"}[$__rate_interval]))\n / (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) > 0)", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "HTTPS", + "type": "stat" + }, + { + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": null, + "displayMode": "auto", + "minWidth": 65 + }, + "decimals": 2, + "displayName": "", + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Time" + }, + "properties": [ + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #A" + }, + "properties": [ + { + "id": "displayName", + "value": "RPS" + }, + { + "id": "unit", + "value": "ops" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #B" + }, + "properties": [ + { + "id": "displayName", + "value": "Retried Req" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #C" + }, + "properties": [ + { + "id": "displayName", + "value": "Req Time" + }, + { + "id": "unit", + "value": "s" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #D" + }, + "properties": [ + { + "id": "displayName", + "value": "Upstr Time" + }, + { + "id": "unit", + "value": "s" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #E" + }, + "properties": [ + { + "id": "displayName", + "value": "In Traffic" + }, + { + "id": "unit", + "value": "bps" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #F" + }, + "properties": [ + { + "id": "displayName", + "value": "Out Traffic" + }, + { + "id": "unit", + "value": "bps" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #G" + }, + "properties": [ + { + "id": "displayName", + "value": "Req Size" + }, + { + "id": "unit", + "value": "bytes" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #H" + }, + "properties": [ + { + "id": "displayName", + "value": "Resp Size" + }, + { + "id": "unit", + "value": "bytes" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #I" + }, + "properties": [ + { + "id": "displayName", + "value": "1xx" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #J" + }, + "properties": [ + { + "id": "displayName", + "value": "2xx" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #K" + }, + "properties": [ + { + "id": "displayName", + "value": "3xx" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #L" + }, + "properties": [ + { + "id": "displayName", + "value": "4xx" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #M" + }, + "properties": [ + { + "id": "displayName", + "value": "5xx" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #N" + }, + "properties": [ + { + "id": "displayName", + "value": "HTTPS" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #O" + }, + "properties": [ + { + "id": "displayName", + "value": "GET" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #P" + }, + "properties": [ + { + "id": "displayName", + "value": "POST" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #Q" + }, + "properties": [ + { + "id": "displayName", + "value": "HEAD" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #R" + }, + "properties": [ + { + "id": "displayName", + "value": "PUT" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #S" + }, + "properties": [ + { + "id": "displayName", + "value": "DELETE" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #T" + }, + "properties": [ + { + "id": "displayName", + "value": "OPTIONS" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #U" + }, + "properties": [ + { + "id": "displayName", + "value": "PATCH" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "vhost" + }, + "properties": [ + { + "id": "displayName", + "value": "VHost" + }, + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 200 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "location" + }, + "properties": [ + { + "id": "displayName", + "value": "Location" + }, + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 150 + }, + { + "id": "custom.filterable", + "value": false + } + ] + } + ] + }, + "gridPos": { + "h": 6, + "w": 24, + "x": 0, + "y": 3 + }, + "id": 28, + "links": [], + "options": { + "showHeader": true + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "(sum(rate(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": true, + "instant": true, + "intervalFactor": 1, + "refId": "A" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_upstream_retries_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by\n / (sum(rate(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "legendFormat": "", + "refId": "B" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_request_seconds_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by\n / (sum(increase(ingress_nginx_${metric}_request_seconds_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "legendFormat": "", + "refId": "C" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_upstream_response_seconds_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by\n / (sum(increase(ingress_nginx_${metric}_upstream_response_seconds_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "legendFormat": "", + "refId": "D" + }, + { + "expr": "(sum(rate(ingress_nginx_${metric}_received_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by * 8 > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "legendFormat": "", + "refId": "E" + }, + { + "expr": "(sum(rate(ingress_nginx_${metric}_sent_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by * 8 > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "F" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_received_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by\n / (sum(increase(ingress_nginx_${metric}_received_bytes_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "G" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_sent_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by\n / (sum(increase(ingress_nginx_${metric}_sent_bytes_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "H" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"1..\"}[$__range])) $by\n/ (sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "I" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"2..\"}[$__range])) $by\n/ (sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "J" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"3..\"}[$__range])) $by\n/ (sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "K" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"4..\"}[$__range])) $by\n/ (sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "L" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"5..\"}[$__range])) $by\n/ (sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "M" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", scheme=\"https\"}[$__range])) $by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "N" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"GET\"}[$__range])) $by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "O" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"POST\"}[$__range])) $by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "P" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"HEAD\"}[$__range])) $by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "Q" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"PUT\"}[$__range])) $by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "R" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"DELETE\"}[$__range])) $by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "S" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"OPTIONS\"}[$__range])) $by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "T" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"PATCH\"}[$__range])) $by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "U" + } + ], + "title": "Average", + "transformations": [ + { + "id": "merge", + "options": { + "reducers": [] + } + }, + { + "id": "filterFieldsByName", + "options": { + "include": { + "names": [ + "location", + "vhost", + "Value #B", + "Value #C", + "Value #D", + "Value #E", + "Value #F", + "Value #G", + "Value #H", + "Value #I", + "Value #J", + "Value #K", + "Value #L", + "Value #M", + "Value #N", + "Value #O", + "Value #P", + "Value #Q", + "Value #R", + "Value #S", + "Value #T", + "Value #U" + ] + } + } + } + ], + "type": "table" + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 16, + "x": 0, + "y": 9 + }, + "hiddenSeries": false, + "id": 1, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sort": "total", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A", + "step": 20 + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $by > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Requests", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 8, + "x": 16, + "y": 9 + }, + "hiddenSeries": false, + "id": 80, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sort": "total", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $by\n / scalar(sum(rate(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))) > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Requests %", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "percentunit", + "label": "", + "logBase": 1, + "max": "1", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "3xx": "#6ED0E0", + "4xx": "#EAB839", + "5xx": "#BF1B00" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 16, + "x": 0, + "y": 14 + }, + "hiddenSeries": false, + "id": 244, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": true, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + }, + { + "alias": "2xx", + "color": "#73BF69" + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A" + }, + { + "expr": "sum(label_replace(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]), \"status_group\", \"${1}xx\", \"status\", \"([0-9])..\")) by (status_group)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{ status_group }}", + "refId": "B", + "step": 40 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Responses", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "3xx": "#6ED0E0", + "4xx": "#EAB839", + "5xx": "#BF1B00" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 8, + "x": 16, + "y": 14 + }, + "hiddenSeries": false, + "id": 251, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": true, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(label_replace(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]), \"status_group\", \"${1}xx\", \"status\", \"([0-9])..\")) by (status_group)\n / scalar(sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))) > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{ status_group }}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Responses %", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "percentunit", + "label": "", + "logBase": 1, + "max": "1", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 8, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 16, + "x": 0, + "y": 20 + }, + "hiddenSeries": false, + "hideTimeOverride": false, + "id": 4, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sideWidth": null, + "sort": null, + "sortDesc": null, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 0, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "0.005", + "color": "#76B576" + }, + { + "alias": "0.01", + "color": "#83BC6D" + }, + { + "alias": "0.02", + "color": "#91C364" + }, + { + "alias": "0.03", + "color": "#9FCB5B" + }, + { + "alias": "0.04", + "color": "#ACD252" + }, + { + "alias": "0.05", + "color": "#BADA49" + }, + { + "alias": "0.075", + "color": "#C8E140" + }, + { + "alias": "0.1", + "color": "#D5E837" + }, + { + "alias": "0.2", + "color": "#E3F02E" + }, + { + "alias": "0.3", + "color": "#F1F725" + }, + { + "alias": "0.4", + "color": "#FFFF1C" + }, + { + "alias": "0.5", + "color": "#FAE519" + }, + { + "alias": "0.75", + "color": "#F6CC16" + }, + { + "alias": "1", + "color": "#F2B213" + }, + { + "alias": "1.5", + "color": "#EE9910" + }, + { + "alias": "2", + "color": "#EA7F0E" + }, + { + "alias": "3", + "color": "#E6660B" + }, + { + "alias": "4", + "color": "#E24C08" + }, + { + "alias": "5", + "color": "#DE3205" + }, + { + "alias": "10", + "color": "#DA1902" + }, + { + "alias": "+Inf", + "color": "#D60000" + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_lowres_upstream_response_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)", + "format": "heatmap", + "intervalFactor": 1, + "legendFormat": "{{le}}", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Upstream Response Time", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + "total" + ] + }, + "yaxes": [ + { + "decimals": null, + "format": "ops", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 8, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 8, + "x": 16, + "y": 20 + }, + "hiddenSeries": false, + "hideTimeOverride": false, + "id": 81, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sideWidth": null, + "sort": null, + "sortDesc": null, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 0, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "0.005", + "color": "#76B576" + }, + { + "alias": "0.01", + "color": "#83BC6D" + }, + { + "alias": "0.02", + "color": "#91C364" + }, + { + "alias": "0.03", + "color": "#9FCB5B" + }, + { + "alias": "0.04", + "color": "#ACD252" + }, + { + "alias": "0.05", + "color": "#BADA49" + }, + { + "alias": "0.075", + "color": "#C8E140" + }, + { + "alias": "0.1", + "color": "#D5E837" + }, + { + "alias": "0.2", + "color": "#E3F02E" + }, + { + "alias": "0.3", + "color": "#F1F725" + }, + { + "alias": "0.4", + "color": "#FFFF1C" + }, + { + "alias": "0.5", + "color": "#FAE519" + }, + { + "alias": "0.75", + "color": "#F6CC16" + }, + { + "alias": "1", + "color": "#F2B213" + }, + { + "alias": "1.5", + "color": "#EE9910" + }, + { + "alias": "2", + "color": "#EA7F0E" + }, + { + "alias": "3", + "color": "#E6660B" + }, + { + "alias": "4", + "color": "#E24C08" + }, + { + "alias": "5", + "color": "#DE3205" + }, + { + "alias": "10", + "color": "#DA1902" + }, + { + "alias": "+Inf", + "color": "#D60000" + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_lowres_upstream_response_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)\n / scalar(sum(rate(ingress_nginx_${metric}_lowres_upstream_response_seconds_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])))", + "format": "heatmap", + "intervalFactor": 1, + "legendFormat": "{{le}}", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Upstream Response Time %", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + "total" + ] + }, + "yaxes": [ + { + "format": "percentunit", + "label": null, + "logBase": 1, + "max": "1", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 8, + "x": 0, + "y": 26 + }, + "hiddenSeries": false, + "hideTimeOverride": false, + "id": 62, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sideWidth": null, + "sort": null, + "sortDesc": null, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": true, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_upstream_retries_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_upstream_retries_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $by > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Retried Requests", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + "total" + ] + }, + "yaxes": [ + { + "format": "ops", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 8, + "x": 8, + "y": 26 + }, + "hiddenSeries": false, + "hideTimeOverride": false, + "id": 112, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sideWidth": null, + "sort": null, + "sortDesc": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_upstream_retries_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $by\n/ sum(rate(ingress_nginx_${metric}_upstream_retries_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $by\n> 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Retries (per Retried Request)", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + "total" + ] + }, + "yaxes": [ + { + "format": "ops", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "3xx": "#6ED0E0", + "4xx": "#EAB839", + "5xx": "#BF1B00" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 8, + "x": 16, + "y": 26 + }, + "hiddenSeries": false, + "id": 196, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": true, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"1..\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"1..\"}[$__rate_interval])) $by > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "B", + "step": 40 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "1xx", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "3xx": "#6ED0E0", + "4xx": "#EAB839", + "5xx": "#BF1B00" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 8, + "x": 16, + "y": 30 + }, + "hiddenSeries": false, + "id": 87, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": true, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"2..\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"2..\"}[$__rate_interval])) $by > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "B", + "step": 40 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "2xx", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": null, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 8, + "x": 0, + "y": 31 + }, + "hiddenSeries": false, + "hideTimeOverride": false, + "id": 49, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sideWidth": null, + "sort": null, + "sortDesc": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_request_seconds_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $by\n / sum(rate(ingress_nginx_${metric}_request_seconds_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $by > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Avg Request Time", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + "total" + ] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": null, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 8, + "x": 8, + "y": 31 + }, + "hiddenSeries": false, + "hideTimeOverride": false, + "id": 63, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sideWidth": null, + "sort": null, + "sortDesc": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_upstream_response_seconds_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $by\n / sum(rate(ingress_nginx_${metric}_upstream_response_seconds_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $by > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Avg Upstream Response Time", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + "total" + ] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "3xx": "#6ED0E0", + "4xx": "#EAB839", + "5xx": "#BF1B00" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 8, + "x": 16, + "y": 34 + }, + "hiddenSeries": false, + "id": 10, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": true, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"3..\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"3..\"}[$__rate_interval])) $by > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "B", + "step": 40 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "3xx", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": null, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 8, + "x": 0, + "y": 36 + }, + "hiddenSeries": false, + "hideTimeOverride": false, + "id": 58, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sideWidth": null, + "sort": null, + "sortDesc": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_received_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $by\n / sum(rate(ingress_nginx_${metric}_received_bytes_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $by > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Avg Request Size", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + "total" + ] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": null, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 8, + "x": 8, + "y": 36 + }, + "hiddenSeries": false, + "hideTimeOverride": false, + "id": 73, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sideWidth": null, + "sort": null, + "sortDesc": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_sent_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $by\n / sum(rate(ingress_nginx_${metric}_sent_bytes_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $by > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Avg Response Size", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + "total" + ] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "3xx": "#6ED0E0", + "4xx": "#EAB839", + "5xx": "#BF1B00" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 8, + "x": 16, + "y": 38 + }, + "hiddenSeries": false, + "id": 18, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": true, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"4..\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"4..\"}[$__rate_interval])) $by > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "B", + "step": 40 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "4xx", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 8, + "x": 0, + "y": 41 + }, + "hiddenSeries": false, + "id": 12, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_received_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) * 8", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A", + "step": 20 + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_received_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $by * 8 > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "B", + "step": 20 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Incoming Traffic", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bps", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 8, + "x": 8, + "y": 41 + }, + "hiddenSeries": false, + "id": 9, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sort": "max", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_sent_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) * 8", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A", + "step": 20 + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_sent_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $by * 8 > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Outgoing Traffic", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bps", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "3xx": "#6ED0E0", + "4xx": "#EAB839", + "5xx": "#BF1B00" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 8, + "x": 16, + "y": 42 + }, + "hiddenSeries": false, + "id": 17, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": true, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"5..\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"5..\"}[$__rate_interval])) $by > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "B", + "step": 40 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "5xx", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "collapsed": false, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 46 + }, + "id": 195, + "panels": [], + "title": "Status Codes", + "type": "row" + }, + { + "aliasColors": { + "3xx": "#6ED0E0", + "4xx": "#EAB839", + "5xx": "#BF1B00" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 8, + "x": 0, + "y": 47 + }, + "hiddenSeries": false, + "id": 189, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": true, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": true, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"1..\"}[$__rate_interval])) by (status)\n / scalar(sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"1..\"}[$__rate_interval])))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{status}}", + "refId": "B", + "step": 40 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "1xx", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "percentunit", + "label": "", + "logBase": 1, + "max": "100", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "3xx": "#6ED0E0", + "4xx": "#EAB839", + "5xx": "#BF1B00" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 8, + "x": 8, + "y": 47 + }, + "hiddenSeries": false, + "id": 190, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": true, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": true, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"2..\"}[$__rate_interval])) by (status)\n / scalar(sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"2..\"}[$__rate_interval])))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{status}}", + "refId": "B", + "step": 40 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "2xx", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "percentunit", + "label": "", + "logBase": 1, + "max": "100", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "3xx": "#6ED0E0", + "4xx": "#EAB839", + "5xx": "#BF1B00" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 8, + "x": 16, + "y": 47 + }, + "hiddenSeries": false, + "id": 191, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": true, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": true, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"3..\"}[$__rate_interval])) by (status)\n / scalar(sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"3..\"}[$__rate_interval])))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{status}}", + "refId": "B", + "step": 40 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "3xx", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "percentunit", + "label": "", + "logBase": 1, + "max": "100", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "3xx": "#6ED0E0", + "4xx": "#EAB839", + "5xx": "#BF1B00" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 12, + "x": 0, + "y": 51 + }, + "hiddenSeries": false, + "id": 192, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": true, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": true, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"4..\"}[$__rate_interval])) by (status)\n / scalar(sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"4..\"}[$__rate_interval])))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{status}}", + "refId": "B", + "step": 40 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "4xx", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "percentunit", + "label": "", + "logBase": 1, + "max": "100", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "3xx": "#6ED0E0", + "4xx": "#EAB839", + "5xx": "#BF1B00" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 12, + "x": 12, + "y": 51 + }, + "hiddenSeries": false, + "id": 193, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": true, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": true, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"5..\"}[$__rate_interval])) by (status)\n / scalar(sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"5..\"}[$__rate_interval])))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{status}}", + "refId": "B", + "step": 40 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "5xx", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "percentunit", + "label": "", + "logBase": 1, + "max": "100", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "3xx": "#6ED0E0", + "4xx": "#EAB839", + "5xx": "#BF1B00" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 6, + "x": 0, + "y": 56 + }, + "hiddenSeries": false, + "id": 86, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": true, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "maxPerRow": 4, + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": "status", + "repeatDirection": "h", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=\"$status\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=\"$status\"}[$__rate_interval])) $by > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "B", + "step": 40 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "$status", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "collapsed": true, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 60 + }, + "id": 150, + "panels": [ + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 0, + "y": 2 + }, + "id": 130, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.3", + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_request_seconds_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))\n / sum(rate(ingress_nginx_${metric}_request_seconds_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))\n * 1000", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "Avg Req Time", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 3, + "y": 2 + }, + "id": 132, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.3", + "targets": [ + { + "expr": "histogram_quantile(0.5, sum(rate(ingress_nginx_${metric}_request_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)) * 1000", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "50th Req Time", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 6, + "y": 2 + }, + "id": 134, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.3", + "targets": [ + { + "expr": "histogram_quantile(0.9, sum(rate(ingress_nginx_${metric}_request_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)) * 1000", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "90th Req Time", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 9, + "y": 2 + }, + "id": 174, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.3", + "targets": [ + { + "expr": "histogram_quantile(0.99, sum(rate(ingress_nginx_${metric}_request_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)) * 1000", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "99th Req Time", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 12, + "y": 2 + }, + "id": 140, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.3", + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_upstream_response_seconds_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))\n / sum(rate(ingress_nginx_${metric}_upstream_response_seconds_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))\n * 1000", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "Avg Upstr Time", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 15, + "y": 2 + }, + "id": 142, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.3", + "targets": [ + { + "expr": "histogram_quantile(0.5, sum(rate(ingress_nginx_${metric}_upstream_response_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)) * 1000", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "50th Upstr Time", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 18, + "y": 2 + }, + "id": 144, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.3", + "targets": [ + { + "expr": "histogram_quantile(0.9, sum(rate(ingress_nginx_${metric}_upstream_response_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)) * 1000", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "90th Upstr Time", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 21, + "y": 2 + }, + "id": 146, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.3", + "targets": [ + { + "expr": "histogram_quantile(0.99, sum(rate(ingress_nginx_${metric}_upstream_response_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)) * 1000", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "99th Upstr Time", + "type": "stat" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": null, + "fill": 0, + "gridPos": { + "h": 5, + "w": 12, + "x": 0, + "y": 4 + }, + "hideTimeOverride": false, + "id": 136, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sideWidth": null, + "sort": null, + "sortDesc": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Avg", + "fill": 2, + "linewidth": 0 + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "histogram_quantile(0.99, sum(rate(ingress_nginx_${metric}_request_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)) * 1000", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "99th", + "refId": "A" + }, + { + "expr": "histogram_quantile(0.9, sum(rate(ingress_nginx_${metric}_request_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)) * 1000", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "90th", + "refId": "B" + }, + { + "expr": "histogram_quantile(0.5, sum(rate(ingress_nginx_${metric}_request_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)) * 1000", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "50th", + "refId": "C" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_request_seconds_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))\n / sum(rate(ingress_nginx_${metric}_request_seconds_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))\n * 1000", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Avg", + "refId": "D" + } + ], + "thresholds": [], + "timeFrom": null, + "timeShift": null, + "title": "Request Time", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + "total" + ] + }, + "yaxes": [ + { + "format": "ms", + "label": null, + "logBase": 10, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": null, + "fill": 0, + "gridPos": { + "h": 5, + "w": 12, + "x": 12, + "y": 4 + }, + "hideTimeOverride": false, + "id": 148, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sideWidth": null, + "sort": null, + "sortDesc": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Avg", + "fill": 2, + "linewidth": 0 + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "histogram_quantile(0.99, sum(rate(ingress_nginx_${metric}_upstream_response_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)) * 1000", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "99th", + "refId": "A" + }, + { + "expr": "histogram_quantile(0.9, sum(rate(ingress_nginx_${metric}_upstream_response_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)) * 1000", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "90th", + "refId": "B" + }, + { + "expr": "histogram_quantile(0.5, sum(rate(ingress_nginx_${metric}_upstream_response_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)) * 1000", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "50th", + "refId": "C" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_upstream_response_seconds_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))\n / sum(rate(ingress_nginx_${metric}_upstream_response_seconds_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))\n * 1000", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Avg", + "refId": "D" + } + ], + "thresholds": [], + "timeFrom": null, + "timeShift": null, + "title": "Upstream Response Time", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + "total" + ] + }, + "yaxes": [ + { + "format": "ms", + "label": null, + "logBase": 10, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "title": "Request Time and Upstream Response Time", + "type": "row" + }, + { + "collapsed": true, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 61 + }, + "id": 211, + "panels": [ + { + "cards": { + "cardPadding": 0, + "cardRound": 0 + }, + "color": { + "cardColor": "#b4ff00", + "colorScale": "sqrt", + "colorScheme": "interpolateYlGnBu", + "exponent": 0.5, + "max": null, + "min": 0, + "mode": "spectrum" + }, + "dataFormat": "tsbuckets", + "datasource": null, + "gridPos": { + "h": 21, + "w": 12, + "x": 0, + "y": 9 + }, + "heatmap": {}, + "highlightCards": true, + "id": 152, + "legend": { + "show": true + }, + "links": [], + "targets": [ + { + "expr": "sum(increase(ingress_nginx_${metric}_request_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le) > 0", + "format": "heatmap", + "intervalFactor": 1, + "legendFormat": "{{le}}", + "refId": "A" + } + ], + "title": "Request Time", + "tooltip": { + "show": true, + "showHistogram": true + }, + "type": "heatmap", + "xAxis": { + "show": true + }, + "xBucketNumber": null, + "xBucketSize": null, + "yAxis": { + "decimals": 1, + "format": "s", + "logBase": 1, + "max": null, + "min": null, + "show": true, + "splitFactor": null + }, + "yBucketBound": "auto", + "yBucketNumber": null, + "yBucketSize": null + }, + { + "cards": { + "cardPadding": 0, + "cardRound": 0 + }, + "color": { + "cardColor": "#b4ff00", + "colorScale": "sqrt", + "colorScheme": "interpolateYlGnBu", + "exponent": 0.5, + "max": null, + "min": 0, + "mode": "spectrum" + }, + "dataFormat": "tsbuckets", + "datasource": null, + "gridPos": { + "h": 21, + "w": 12, + "x": 12, + "y": 9 + }, + "heatmap": {}, + "highlightCards": true, + "id": 153, + "legend": { + "show": true + }, + "links": [], + "targets": [ + { + "expr": "sum(increase(ingress_nginx_${metric}_upstream_response_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le) > 0", + "format": "heatmap", + "intervalFactor": 1, + "legendFormat": "{{le}}", + "refId": "A" + } + ], + "title": "Upstream Response Time", + "tooltip": { + "show": true, + "showHistogram": true + }, + "type": "heatmap", + "xAxis": { + "show": true + }, + "xBucketNumber": null, + "xBucketSize": null, + "yAxis": { + "decimals": 1, + "format": "s", + "logBase": 1, + "max": null, + "min": null, + "show": true, + "splitFactor": null + }, + "yBucketBound": "auto", + "yBucketNumber": null, + "yBucketSize": null + } + ], + "title": "Request Time Heatmap and Upstream Response Time Heatmap", + "type": "row" + }, + { + "collapsed": true, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 62 + }, + "id": 160, + "panels": [ + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 0, + "y": 5 + }, + "id": 171, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.3", + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_received_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))\n / sum(rate(ingress_nginx_${metric}_received_bytes_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "Avg Req Size", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 3, + "y": 5 + }, + "id": 172, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.3", + "targets": [ + { + "expr": "histogram_quantile(0.5, sum(rate(ingress_nginx_${metric}_received_bytes_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le))", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "50th Req Size", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 6, + "y": 5 + }, + "id": 173, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.3", + "targets": [ + { + "expr": "histogram_quantile(0.9, sum(rate(ingress_nginx_${metric}_received_bytes_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le))", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "90th Req Size", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 9, + "y": 5 + }, + "id": 128, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.3", + "targets": [ + { + "expr": "histogram_quantile(0.99, sum(rate(ingress_nginx_${metric}_received_bytes_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le))", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "99th Req Size", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 12, + "y": 5 + }, + "id": 175, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.3", + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_sent_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))\n / sum(rate(ingress_nginx_${metric}_sent_bytes_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "Avg Resp Size", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 15, + "y": 5 + }, + "id": 176, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.3", + "targets": [ + { + "expr": "histogram_quantile(0.5, sum(rate(ingress_nginx_${metric}_sent_bytes_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le))", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "50th Resp Size", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 18, + "y": 5 + }, + "id": 177, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.3", + "targets": [ + { + "expr": "histogram_quantile(0.9, sum(rate(ingress_nginx_${metric}_sent_bytes_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le))", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "90th Resp Size", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 21, + "y": 5 + }, + "id": 178, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.3", + "targets": [ + { + "expr": "histogram_quantile(0.99, sum(rate(ingress_nginx_${metric}_sent_bytes_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le))", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "99th Resp Size", + "type": "stat" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": null, + "fill": 0, + "gridPos": { + "h": 4, + "w": 12, + "x": 0, + "y": 7 + }, + "hideTimeOverride": false, + "id": 155, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sideWidth": null, + "sort": null, + "sortDesc": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Avg", + "fill": 2, + "linewidth": 0 + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "histogram_quantile(0.99, sum(rate(ingress_nginx_${metric}_received_bytes_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "99th", + "refId": "A" + }, + { + "expr": "histogram_quantile(0.9, sum(rate(ingress_nginx_${metric}_received_bytes_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "90th", + "refId": "B" + }, + { + "expr": "histogram_quantile(0.5, sum(rate(ingress_nginx_${metric}_received_bytes_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "50th", + "refId": "C" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_received_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))\n / sum(rate(ingress_nginx_${metric}_received_bytes_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Avg", + "refId": "D" + } + ], + "thresholds": [], + "timeFrom": null, + "timeShift": null, + "title": "Request Size", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + "total" + ] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 2, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": null, + "fill": 0, + "gridPos": { + "h": 4, + "w": 12, + "x": 12, + "y": 7 + }, + "hideTimeOverride": false, + "id": 157, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sideWidth": null, + "sort": null, + "sortDesc": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Avg", + "fill": 2, + "linewidth": 0 + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "histogram_quantile(0.99, sum(rate(ingress_nginx_${metric}_sent_bytes_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "99th", + "refId": "A" + }, + { + "expr": "histogram_quantile(0.9, sum(rate(ingress_nginx_${metric}_sent_bytes_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "90th", + "refId": "B" + }, + { + "expr": "histogram_quantile(0.5, sum(rate(ingress_nginx_${metric}_sent_bytes_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "50th", + "refId": "C" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_sent_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))\n / sum(rate(ingress_nginx_${metric}_sent_bytes_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Avg", + "refId": "D" + } + ], + "thresholds": [], + "timeFrom": null, + "timeShift": null, + "title": "Response Size", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + "total" + ] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 2, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "title": "Request Size and Response Size", + "type": "row" + }, + { + "collapsed": true, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 63 + }, + "id": 209, + "panels": [ + { + "cards": { + "cardPadding": 0, + "cardRound": 0 + }, + "color": { + "cardColor": "#b4ff00", + "colorScale": "sqrt", + "colorScheme": "interpolateYlGnBu", + "exponent": 0.5, + "max": null, + "min": 0, + "mode": "spectrum" + }, + "dataFormat": "tsbuckets", + "datasource": null, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 6 + }, + "heatmap": {}, + "highlightCards": true, + "id": 158, + "legend": { + "show": true + }, + "links": [], + "targets": [ + { + "expr": "sum(increase(ingress_nginx_${metric}_received_bytes_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)", + "format": "heatmap", + "intervalFactor": 1, + "legendFormat": "{{le}}", + "refId": "A" + } + ], + "title": "Request Size", + "tooltip": { + "show": true, + "showHistogram": true + }, + "type": "heatmap", + "xAxis": { + "show": true + }, + "xBucketNumber": null, + "xBucketSize": null, + "yAxis": { + "decimals": 0, + "format": "bytes", + "logBase": 1, + "max": null, + "min": null, + "show": true, + "splitFactor": null + }, + "yBucketBound": "auto", + "yBucketNumber": null, + "yBucketSize": null + }, + { + "cards": { + "cardPadding": 0, + "cardRound": 0 + }, + "color": { + "cardColor": "#b4ff00", + "colorScale": "sqrt", + "colorScheme": "interpolateYlGnBu", + "exponent": 0.5, + "max": null, + "min": 0, + "mode": "spectrum" + }, + "dataFormat": "tsbuckets", + "datasource": null, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 6 + }, + "heatmap": {}, + "highlightCards": true, + "id": 161, + "legend": { + "show": true + }, + "links": [], + "targets": [ + { + "expr": "sum(increase(ingress_nginx_${metric}_sent_bytes_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)", + "format": "heatmap", + "intervalFactor": 1, + "legendFormat": "{{le}}", + "refId": "A" + } + ], + "title": "Response Size", + "tooltip": { + "show": true, + "showHistogram": true + }, + "type": "heatmap", + "xAxis": { + "show": true + }, + "xBucketNumber": null, + "xBucketSize": null, + "yAxis": { + "decimals": 0, + "format": "bytes", + "logBase": 1, + "max": null, + "min": null, + "show": true, + "splitFactor": null + }, + "yBucketBound": "auto", + "yBucketNumber": null, + "yBucketSize": null + } + ], + "title": "Request Size Heatmap and Response Size Heatmap", + "type": "row" + }, + { + "collapsed": true, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 64 + }, + "id": 89, + "panels": [ + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "gridPos": { + "h": 6, + "w": 12, + "x": 0, + "y": 43 + }, + "id": 61, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sort": "total", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (method)\n / scalar(sum(rate(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{method}}", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeShift": null, + "title": "Method %", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "percentunit", + "label": "", + "logBase": 1, + "max": "1", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "gridPos": { + "h": 6, + "w": 12, + "x": 12, + "y": 43 + }, + "id": 60, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sort": "total", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\"}[$__rate_interval])) by (content_kind)\n/ scalar(sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\"}[$__rate_interval])))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{content_kind}}", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeShift": null, + "title": "Content Kind %", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "percentunit", + "label": "", + "logBase": 1, + "max": "1", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "gridPos": { + "h": 4, + "w": 12, + "x": 0, + "y": 49 + }, + "id": 90, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sort": "total", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": "method", + "repeatDirection": "v", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"$method\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"$method\"}[$__rate_interval])) $by > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeShift": null, + "title": "$method", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "gridPos": { + "h": 4, + "w": 12, + "x": 12, + "y": 49 + }, + "id": 97, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sort": "total", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": "content_kind", + "repeatDirection": "v", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=\"$content_kind\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=\"$content_kind\"}[$__rate_interval])) $by > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeShift": null, + "title": "$content_kind", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "title": "Request Method and Content Kind", + "type": "row" + }, + { + "collapsed": true, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 65 + }, + "id": 239, + "panels": [ + { + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": null, + "displayMode": "auto" + }, + "decimals": 2, + "displayName": "", + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Time" + }, + "properties": [ + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #A" + }, + "properties": [ + { + "id": "displayName", + "value": "RPS" + }, + { + "id": "unit", + "value": "ops" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #B" + }, + "properties": [ + { + "id": "displayName", + "value": "Upstr Time" + }, + { + "id": "unit", + "value": "s" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #C" + }, + "properties": [ + { + "id": "displayName", + "value": "Upstr Traffic" + }, + { + "id": "unit", + "value": "bps" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #D" + }, + "properties": [ + { + "id": "displayName", + "value": "Upstr Resp" + }, + { + "id": "unit", + "value": "bytes" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #E" + }, + "properties": [ + { + "id": "displayName", + "value": "1xx" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #F" + }, + "properties": [ + { + "id": "displayName", + "value": "2xx" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #G" + }, + "properties": [ + { + "id": "displayName", + "value": "3xx" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #H" + }, + "properties": [ + { + "id": "displayName", + "value": "4xx" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #I" + }, + "properties": [ + { + "id": "displayName", + "value": "5xx" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "pod_ip" + }, + "properties": [ + { + "id": "displayName", + "value": "Pod IP" + }, + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + } + ] + }, + "gridPos": { + "h": 6, + "w": 24, + "x": 0, + "y": 66 + }, + "id": 213, + "links": [], + "options": { + "showHeader": true + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "(sum(rate(ingress_nginx_${metric}_backend_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\"}[$__range])) by (pod_ip) > 0)\nor sum(irate(ingress_nginx_${metric}_backend_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\"}[$__range])) by (pod_ip)", + "format": "table", + "instant": true, + "intervalFactor": 1, + "refId": "A" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_backend_lowres_upstream_response_seconds_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\"}[$__range])) by (pod_ip)\n / (sum(increase(ingress_nginx_${metric}_backend_lowres_upstream_response_seconds_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\"}[$__range])) by (pod_ip) > 0)\nor sum(irate(ingress_nginx_${metric}_backend_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\"}[$__range])) by (pod_ip)", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "legendFormat": "", + "refId": "B" + }, + { + "expr": "(sum(rate(ingress_nginx_${metric}_backend_upstream_bytes_received_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\"}[$__range])) by (pod_ip) * 8 > 0)\nor sum(irate(ingress_nginx_${metric}_backend_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\"}[$__range])) by (pod_ip)", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "legendFormat": "", + "refId": "C" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_backend_upstream_bytes_received_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\"}[$__range])) by (pod_ip)\n / (sum(increase(ingress_nginx_${metric}_backend_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\"}[$__range])) by (pod_ip) > 0)\nor sum(irate(ingress_nginx_${metric}_backend_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\"}[$__range])) by (pod_ip)", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "D" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_backend_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\", status_class=\"1xx\"}[$__range])) by (pod_ip)\n/ (sum(increase(ingress_nginx_${metric}_backend_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\"}[$__range])) by (pod_ip) > 0)\nor sum(irate(ingress_nginx_${metric}_backend_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\"}[$__range])) by (pod_ip)", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "E" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_backend_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\", status_class=\"2xx\"}[$__range])) by (pod_ip)\n/ (sum(increase(ingress_nginx_${metric}_backend_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\"}[$__range])) by (pod_ip) > 0)\nor sum(irate(ingress_nginx_${metric}_backend_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\"}[$__range])) by (pod_ip)", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "F" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_backend_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\", status_class=\"3xx\"}[$__range])) by (pod_ip)\n/ (sum(increase(ingress_nginx_${metric}_backend_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\"}[$__range])) by (pod_ip) > 0)\nor sum(irate(ingress_nginx_${metric}_backend_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\"}[$__range])) by (pod_ip)", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "G" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_backend_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\", status_class=\"4xx\"}[$__range])) by (pod_ip)\n/ (sum(increase(ingress_nginx_${metric}_backend_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\"}[$__range])) by (pod_ip) > 0)\nor sum(irate(ingress_nginx_${metric}_backend_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\"}[$__range])) by (pod_ip)", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "H" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_backend_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\", status_class=\"5xx\"}[$__range])) by (pod_ip)\n/ (sum(increase(ingress_nginx_${metric}_backend_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\"}[$__range])) by (pod_ip) > 0)\nor sum(irate(ingress_nginx_${metric}_backend_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\"}[$__range])) by (pod_ip)", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "I" + } + ], + "title": "Average", + "transformations": [ + { + "id": "merge", + "options": { + "reducers": [] + } + }, + { + "id": "filterFieldsByName", + "options": { + "include": { + "names": [ + "pod_ip", + "Value #A", + "Value #B", + "Value #C", + "Value #D", + "Value #E", + "Value #F", + "Value #G", + "Value #H", + "Value #I" + ] + } + } + } + ], + "type": "table" + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 16, + "x": 0, + "y": 72 + }, + "hiddenSeries": false, + "id": 215, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sort": "total", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_backend_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A", + "step": 20 + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_backend_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\"}[$__rate_interval])) by (pod_ip) > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{pod_ip}}", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Backend Responses", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 8, + "x": 16, + "y": 72 + }, + "hiddenSeries": false, + "id": 217, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sort": "total", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_backend_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\"}[$__rate_interval])) by (pod_ip)\n / scalar(sum(rate(ingress_nginx_${metric}_backend_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\"}[$__rate_interval]))) > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{pod_ip}}", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Backend Responses %", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "percentunit", + "label": "", + "logBase": 1, + "max": "1", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": null, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 8, + "x": 0, + "y": 77 + }, + "hiddenSeries": false, + "hideTimeOverride": false, + "id": 219, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sideWidth": null, + "sort": null, + "sortDesc": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_backend_lowres_upstream_response_seconds_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\"}[$__rate_interval])) by (pod_ip)\n / sum(rate(ingress_nginx_${metric}_backend_lowres_upstream_response_seconds_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\"}[$__rate_interval])) by (pod_ip) > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{pod_ip}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Avg Backend Response Time", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + "total" + ] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": null, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 8, + "x": 8, + "y": 77 + }, + "hiddenSeries": false, + "hideTimeOverride": false, + "id": 221, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sideWidth": null, + "sort": null, + "sortDesc": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_backend_upstream_bytes_received_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\"}[$__rate_interval])) by (pod_ip)\n / sum(rate(ingress_nginx_${metric}_backend_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\"}[$__rate_interval])) by (pod_ip) > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{pod_ip}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Avg Backend Response Size", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + "total" + ] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 8, + "x": 16, + "y": 77 + }, + "hiddenSeries": false, + "id": 223, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sort": "max", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_backend_upstream_bytes_received_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\"}[$__rate_interval])) * 8", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A", + "step": 20 + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_backend_upstream_bytes_received_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\"}[$__rate_interval])) by (pod_ip) * 8 > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{pod_ip}}", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Backend Traffic", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bps", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "3xx": "#6ED0E0", + "4xx": "#EAB839", + "5xx": "#BF1B00" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 8, + "x": 0, + "y": 82 + }, + "hiddenSeries": false, + "id": 225, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": true, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_backend_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\", status_class=\"1xx\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_backend_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\", status_class=\"1xx\"}[$__rate_interval])) by (pod_ip) > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{pod_ip}}", + "refId": "B", + "step": 40 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "1xx", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "3xx": "#6ED0E0", + "4xx": "#EAB839", + "5xx": "#BF1B00" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 8, + "x": 8, + "y": 82 + }, + "hiddenSeries": false, + "id": 227, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": true, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_backend_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\", status_class=\"2xx\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_backend_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\", status_class=\"2xx\"}[$__rate_interval])) by (pod_ip) > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{pod_ip}}", + "refId": "B", + "step": 40 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "2xx", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "3xx": "#6ED0E0", + "4xx": "#EAB839", + "5xx": "#BF1B00" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 8, + "x": 16, + "y": 82 + }, + "hiddenSeries": false, + "id": 229, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": true, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_backend_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\", status_class=\"3xx\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_backend_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\", status_class=\"3xx\"}[$__rate_interval])) by (pod_ip) > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{pod_ip}}", + "refId": "B", + "step": 40 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "3xx", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "3xx": "#6ED0E0", + "4xx": "#EAB839", + "5xx": "#BF1B00" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 12, + "x": 0, + "y": 86 + }, + "hiddenSeries": false, + "id": 231, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": true, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_backend_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\", status_class=\"4xx\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_backend_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\", status_class=\"4xx\"}[$__rate_interval])) by (pod_ip) > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{pod_ip}}", + "refId": "B", + "step": 40 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "4xx", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "3xx": "#6ED0E0", + "4xx": "#EAB839", + "5xx": "#BF1B00" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 12, + "x": 12, + "y": 86 + }, + "hiddenSeries": false, + "id": 233, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": true, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_backend_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\", status_class=\"5xx\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_backend_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\", status_class=\"5xx\"}[$__rate_interval])) by (pod_ip) > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{pod_ip}}", + "refId": "B", + "step": 40 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "5xx", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 8, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 16, + "x": 0, + "y": 91 + }, + "hiddenSeries": false, + "hideTimeOverride": false, + "id": 235, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sideWidth": null, + "sort": null, + "sortDesc": null, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 0, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": "pod_ip", + "repeatDirection": "v", + "seriesOverrides": [ + { + "alias": "0.005", + "color": "#76B576" + }, + { + "alias": "0.01", + "color": "#83BC6D" + }, + { + "alias": "0.02", + "color": "#91C364" + }, + { + "alias": "0.03", + "color": "#9FCB5B" + }, + { + "alias": "0.04", + "color": "#ACD252" + }, + { + "alias": "0.05", + "color": "#BADA49" + }, + { + "alias": "0.075", + "color": "#C8E140" + }, + { + "alias": "0.1", + "color": "#D5E837" + }, + { + "alias": "0.2", + "color": "#E3F02E" + }, + { + "alias": "0.3", + "color": "#F1F725" + }, + { + "alias": "0.4", + "color": "#FFFF1C" + }, + { + "alias": "0.5", + "color": "#FAE519" + }, + { + "alias": "0.75", + "color": "#F6CC16" + }, + { + "alias": "1", + "color": "#F2B213" + }, + { + "alias": "1.5", + "color": "#EE9910" + }, + { + "alias": "2", + "color": "#EA7F0E" + }, + { + "alias": "3", + "color": "#E6660B" + }, + { + "alias": "4", + "color": "#E24C08" + }, + { + "alias": "5", + "color": "#DE3205" + }, + { + "alias": "10", + "color": "#DA1902" + }, + { + "alias": "+Inf", + "color": "#D60000" + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_backend_lowres_upstream_response_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\"}[$__rate_interval])) by (le)", + "format": "heatmap", + "intervalFactor": 1, + "legendFormat": "{{le}}", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "$pod_ip: Backend Response Time", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + "total" + ] + }, + "yaxes": [ + { + "decimals": null, + "format": "ops", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 8, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 8, + "x": 16, + "y": 91 + }, + "hiddenSeries": false, + "hideTimeOverride": false, + "id": 237, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sideWidth": null, + "sort": null, + "sortDesc": null, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 0, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": "pod_ip", + "repeatDirection": "v", + "seriesOverrides": [ + { + "alias": "0.005", + "color": "#76B576" + }, + { + "alias": "0.01", + "color": "#83BC6D" + }, + { + "alias": "0.02", + "color": "#91C364" + }, + { + "alias": "0.03", + "color": "#9FCB5B" + }, + { + "alias": "0.04", + "color": "#ACD252" + }, + { + "alias": "0.05", + "color": "#BADA49" + }, + { + "alias": "0.075", + "color": "#C8E140" + }, + { + "alias": "0.1", + "color": "#D5E837" + }, + { + "alias": "0.2", + "color": "#E3F02E" + }, + { + "alias": "0.3", + "color": "#F1F725" + }, + { + "alias": "0.4", + "color": "#FFFF1C" + }, + { + "alias": "0.5", + "color": "#FAE519" + }, + { + "alias": "0.75", + "color": "#F6CC16" + }, + { + "alias": "1", + "color": "#F2B213" + }, + { + "alias": "1.5", + "color": "#EE9910" + }, + { + "alias": "2", + "color": "#EA7F0E" + }, + { + "alias": "3", + "color": "#E6660B" + }, + { + "alias": "4", + "color": "#E24C08" + }, + { + "alias": "5", + "color": "#DE3205" + }, + { + "alias": "10", + "color": "#DA1902" + }, + { + "alias": "+Inf", + "color": "#D60000" + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_backend_lowres_upstream_response_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\"}[$__rate_interval])) by (le)\n / scalar(sum(rate(ingress_nginx_${metric}_backend_lowres_upstream_response_seconds_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", pod_ip=~\"$pod_ip\"}[$__rate_interval])))", + "format": "heatmap", + "intervalFactor": 1, + "legendFormat": "{{le}}", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "$pod_ip: Backend Response Time %", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + "total" + ] + }, + "yaxes": [ + { + "format": "percentunit", + "label": null, + "logBase": 1, + "max": "1", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "title": "Backends (Content Kind filter is ignored)", + "type": "row" + }, + { + "collapsed": true, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 66 + }, + "id": 46, + "panels": [ + { + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": null, + "displayMode": "auto", + "minWidth": 64 + }, + "decimals": 2, + "displayName": "", + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Time" + }, + "properties": [ + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #A" + }, + "properties": [ + { + "id": "displayName", + "value": "RPS" + }, + { + "id": "unit", + "value": "ops" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 85 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #B" + }, + "properties": [ + { + "id": "displayName", + "value": "Retried Req" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #C" + }, + "properties": [ + { + "id": "displayName", + "value": "Req Time" + }, + { + "id": "unit", + "value": "s" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #D" + }, + "properties": [ + { + "id": "displayName", + "value": "Resp Time" + }, + { + "id": "unit", + "value": "s" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 85 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #E" + }, + "properties": [ + { + "id": "displayName", + "value": "In Traffic" + }, + { + "id": "unit", + "value": "bps" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 85 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #F" + }, + "properties": [ + { + "id": "displayName", + "value": "Out Traffic" + }, + { + "id": "unit", + "value": "bps" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 85 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #G" + }, + "properties": [ + { + "id": "displayName", + "value": "Req Size" + }, + { + "id": "unit", + "value": "bytes" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 85 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #H" + }, + "properties": [ + { + "id": "displayName", + "value": "Resp Size" + }, + { + "id": "unit", + "value": "bytes" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 85 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #I" + }, + "properties": [ + { + "id": "displayName", + "value": "1xx" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #J" + }, + "properties": [ + { + "id": "displayName", + "value": "2xx" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #K" + }, + "properties": [ + { + "id": "displayName", + "value": "3xx" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #L" + }, + "properties": [ + { + "id": "displayName", + "value": "4xx" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #M" + }, + "properties": [ + { + "id": "displayName", + "value": "5xx" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #N" + }, + "properties": [ + { + "id": "displayName", + "value": "HTTPS" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #O" + }, + "properties": [ + { + "id": "displayName", + "value": "GET" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #P" + }, + "properties": [ + { + "id": "displayName", + "value": "POST" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #Q" + }, + "properties": [ + { + "id": "displayName", + "value": "HEAD" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #R" + }, + "properties": [ + { + "id": "displayName", + "value": "PUT" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #S" + }, + "properties": [ + { + "id": "displayName", + "value": "DELETE" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #T" + }, + "properties": [ + { + "id": "displayName", + "value": "OPTIONS" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #U" + }, + "properties": [ + { + "id": "displayName", + "value": "PATCH" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "namespace" + }, + "properties": [ + { + "id": "displayName", + "value": "Namespace" + }, + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "links", + "value": [ + { + "targetBlank": false, + "title": "Open Namespace", + "url": "/d/Z-phNqGmz/namespaces?var-namespace=${__value.raw}&${__url_time_range}" + } + ] + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 120 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "ingress" + }, + "properties": [ + { + "id": "displayName", + "value": "Ingress" + }, + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "links", + "value": [ + { + "targetBlank": false, + "title": "Open Ingress", + "url": "/d/oipwXCMik/namespace-detail?var-namespace=${__data.fields[Namespace]}&var-ingress=${__value.raw}&${__url_time_range}" + } + ] + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 100 + } + ] + } + ] + }, + "gridPos": { + "h": 6, + "w": 24, + "x": 0, + "y": 97 + }, + "id": 42, + "links": [], + "options": { + "showHeader": true + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "(sum(rate(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "instant": true, + "intervalFactor": 1, + "refId": "A" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_upstream_retries_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by\n / (sum(rate(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "legendFormat": "", + "refId": "B" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_request_seconds_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by\n / (sum(increase(ingress_nginx_${metric}_request_seconds_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "legendFormat": "", + "refId": "C" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_upstream_response_seconds_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by\n / (sum(increase(ingress_nginx_${metric}_upstream_response_seconds_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "legendFormat": "", + "refId": "D" + }, + { + "expr": "(sum(rate(ingress_nginx_${metric}_received_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by * 8 > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "legendFormat": "", + "refId": "E" + }, + { + "expr": "(sum(rate(ingress_nginx_${metric}_sent_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by * 8 > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "F" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_received_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by\n / (sum(increase(ingress_nginx_${metric}_received_bytes_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "G" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_sent_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by\n / (sum(increase(ingress_nginx_${metric}_sent_bytes_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "H" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"1..\"}[$__range])) $alt_by\n/ (sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "I" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"2..\"}[$__range])) $alt_by\n/ (sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "J" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"3..\"}[$__range])) $alt_by\n/ (sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "K" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"4..\"}[$__range])) $alt_by\n/ (sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "L" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"5..\"}[$__range])) $alt_by\n/ (sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "M" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", scheme=\"https\"}[$__range])) $alt_by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "N" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"GET\"}[$__range])) $alt_by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "O" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"POST\"}[$__range])) $alt_by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "P" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"HEAD\"}[$__range])) $alt_by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "Q" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"PUT\"}[$__range])) $alt_by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "R" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"DELETE\"}[$__range])) $alt_by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "S" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"OPTIONS\"}[$__range])) $alt_by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "T" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"PATCH\"}[$__range])) $alt_by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "U" + } + ], + "title": "Average", + "transformations": [ + { + "id": "merge", + "options": { + "reducers": [] + } + }, + { + "id": "filterFieldsByName", + "options": { + "include": { + "names": [ + "ingress", + "namespace", + "Value #A", + "Value #B", + "Value #C", + "Value #D", + "Value #E", + "Value #F", + "Value #G", + "Value #H", + "Value #I", + "Value #J", + "Value #K", + "Value #L", + "Value #M", + "Value #N", + "Value #O", + "Value #P", + "Value #Q", + "Value #R", + "Value #S", + "Value #T", + "Value #U" + ] + } + } + } + ], + "type": "table" + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 8, + "x": 0, + "y": 103 + }, + "hiddenSeries": false, + "id": 39, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sort": "total", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": true, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $alt_by > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$alt_legend_format", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Requests per $alt_name", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": "", + "logBase": 1, + "max": "100", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 1, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 8, + "x": 8, + "y": 103 + }, + "hiddenSeries": false, + "id": 41, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": true, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_received_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $alt_by * 8 > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$alt_legend_format", + "refId": "B", + "step": 20 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Incoming Traffic per $alt_name", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bps", + "label": null, + "logBase": 1, + "max": "100", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 1, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 8, + "x": 16, + "y": 103 + }, + "hiddenSeries": false, + "id": 40, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sort": "max", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": true, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_sent_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $alt_by * 8 > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$alt_legend_format", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Outgoing Traffic per $alt_name", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bps", + "label": null, + "logBase": 1, + "max": "100", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "title": "By $alt_name", + "type": "row" + } + ], + "refresh": "30s", + "schemaVersion": 32, + "style": "dark", + "tags": [ + "ingress" + ], + "templating": { + "list": [ + { + "current": { + "selected": false, + "text": "default", + "value": "default" + }, + "description": null, + "error": null, + "hide": 0, + "includeAll": false, + "label": "Prometheus", + "multi": false, + "name": "ds_prometheus", + "options": [], + "query": "prometheus", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + }, + { + "description": null, + "error": null, + "hide": 2, + "label": null, + "name": "metric", + "query": "detail", + "skipUrlSync": false, + "type": "constant" + }, + { + "description": null, + "error": null, + "hide": 2, + "label": null, + "name": "by", + "query": "by (vhost, location)", + "skipUrlSync": false, + "type": "constant" + }, + { + "description": null, + "error": null, + "hide": 2, + "label": null, + "name": "legend_format", + "query": "{{vhost}}{{location}}", + "skipUrlSync": false, + "type": "constant" + }, + { + "description": null, + "error": null, + "hide": 2, + "label": null, + "name": "alt_name", + "query": "Ingress", + "skipUrlSync": false, + "type": "constant" + }, + { + "description": null, + "error": null, + "hide": 2, + "label": null, + "name": "alt_by", + "query": "by (namespace, ingress)", + "skipUrlSync": false, + "type": "constant" + }, + { + "description": null, + "error": null, + "hide": 2, + "label": null, + "name": "alt_legend_format", + "query": "{{namespace}}/{{ingress}}", + "skipUrlSync": false, + "type": "constant" + }, + { + "allValue": ".*", + "current": { + "selected": true, + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": "$ds_prometheus", + "definition": "label_values(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\"}, controller)", + "description": null, + "error": null, + "hide": 0, + "includeAll": true, + "label": "Controller", + "multi": true, + "name": "controller", + "options": [], + "query": { + "query": "label_values(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\"}, controller)", + "refId": "main-controller-Variable-Query" + }, + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "description": null, + "error": null, + "hide": 2, + "label": "App", + "name": "app", + "query": ".*", + "skipUrlSync": false, + "type": "constant" + }, + { + "description": null, + "error": null, + "hide": 2, + "label": "Node", + "name": "node", + "query": ".*", + "skipUrlSync": false, + "type": "constant" + }, + { + "description": null, + "error": null, + "hide": 2, + "label": "Namespace", + "name": "namespace", + "query": ".*", + "skipUrlSync": false, + "type": "constant" + }, + { + "description": null, + "error": null, + "hide": 2, + "label": "Ingress", + "name": "ingress", + "query": ".*", + "skipUrlSync": false, + "type": "constant" + }, + { + "description": null, + "error": null, + "hide": 2, + "label": "Service", + "name": "service", + "query": ".*", + "skipUrlSync": false, + "type": "constant" + }, + { + "description": null, + "error": null, + "hide": 2, + "label": "Service Port", + "name": "service_port", + "query": ".*", + "skipUrlSync": false, + "type": "constant" + }, + { + "allValue": ".*", + "current": { + "text": "example.com", + "value": "example.com" + }, + "datasource": "$ds_prometheus", + "definition": "", + "description": null, + "error": null, + "hide": 0, + "includeAll": false, + "label": "VHost", + "multi": false, + "name": "vhost", + "options": [], + "query": { + "query": "label_values(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\"}, vhost)", + "refId": "main-vhost-Variable-Query" + }, + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": ".*", + "current": { + "selected": true, + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": "$ds_prometheus", + "definition": "", + "description": null, + "error": null, + "hide": 0, + "includeAll": true, + "label": "Location", + "multi": true, + "name": "location", + "options": [], + "query": { + "query": "label_values(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", vhost=~\"$vhost\"}, location)", + "refId": "main-location-Variable-Query" + }, + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": ".*", + "current": { + "selected": true, + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": "$ds_prometheus", + "definition": "", + "description": null, + "error": null, + "hide": 0, + "includeAll": true, + "label": "Content Kind", + "multi": true, + "name": "content_kind", + "options": [], + "query": { + "query": "label_values(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\"}, content_kind)", + "refId": "main-content_kind-Variable-Query" + }, + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": ".*", + "current": { + "selected": true, + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": "$ds_prometheus", + "definition": "", + "description": null, + "error": null, + "hide": 2, + "includeAll": true, + "label": "Method", + "multi": true, + "name": "method", + "options": [], + "query": { + "query": "label_values(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}, method)", + "refId": "main-method-Variable-Query" + }, + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": ".*", + "current": { + "selected": true, + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": "$ds_prometheus", + "definition": "", + "description": null, + "error": null, + "hide": 2, + "includeAll": true, + "label": "Method", + "multi": true, + "name": "status", + "options": [], + "query": { + "query": "label_values(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}, status)", + "refId": "main-status-Variable-Query" + }, + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "current": { + "selected": true, + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": "$ds_prometheus", + "definition": "", + "description": null, + "error": null, + "hide": 2, + "includeAll": true, + "label": "Pod IP", + "multi": true, + "name": "pod_ip", + "options": [], + "query": { + "query": "label_values(ingress_nginx_${metric}_backend_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\"}, pod_ip)", + "refId": "main-pod_ip-Variable-Query" + }, + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + } + ] + }, + "time": { + "from": "now-3h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "", + "title": "VHost Detail", + "uid": "a4hXN3Gik", + "version": 2 +} diff --git a/dashboards/ingress/vhosts.json b/dashboards/ingress/vhosts.json new file mode 100644 index 00000000..fc885041 --- /dev/null +++ b/dashboards/ingress/vhosts.json @@ -0,0 +1,8311 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": "-- Grafana --", + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "limit": 100, + "name": "Annotations & Alerts", + "showIn": 0, + "target": { + "limit": 100, + "matchAny": false, + "tags": [], + "type": "dashboard" + }, + "type": "dashboard" + } + ] + }, + "editable": false, + "fiscalYearStartMonth": 0, + "gnetId": null, + "graphTooltip": 1, + "iteration": 1640794161395, + "links": [], + "liveNow": false, + "panels": [ + { + "collapsed": false, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 126, + "panels": [], + "title": "Main", + "type": "row" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "rgb(31, 120, 193)", + "mode": "fixed" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 0, + "y": 1 + }, + "id": 26, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]))", + "format": "time_series", + "instant": true, + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "Requests", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "rgb(31, 120, 193)", + "mode": "fixed" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 3, + "y": 1 + }, + "id": 111, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "sum(increase(ingress_nginx_${metric}_upstream_retries_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]))\n / sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]))\nor vector(0)", + "format": "time_series", + "instant": true, + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "Retried Requests", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "rgb(31, 120, 193)", + "mode": "fixed" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 6, + "y": 1 + }, + "id": 47, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "sum(increase(ingress_nginx_${metric}_received_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]))", + "format": "time_series", + "instant": true, + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "In Traffic", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "rgb(31, 120, 193)", + "mode": "fixed" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 9, + "y": 1 + }, + "id": 48, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "sum(increase(ingress_nginx_${metric}_sent_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]))", + "format": "time_series", + "instant": true, + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "Out Traffic", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "rgb(31, 120, 193)", + "mode": "fixed" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ops" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 12, + "y": 1 + }, + "id": 109, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]))", + "format": "time_series", + "instant": true, + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "Avg RPS", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 15, + "y": 1 + }, + "id": 65, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_request_seconds_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]))\n / sum(rate(ingress_nginx_${metric}_request_seconds_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]))\n * 1000", + "format": "time_series", + "instant": true, + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "Avg Req Time", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 18, + "y": 1 + }, + "id": 69, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "sum(increase(ingress_nginx_${metric}_upstream_response_seconds_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]))\n / sum(increase(ingress_nginx_${metric}_upstream_response_seconds_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]))\n * 1000", + "format": "time_series", + "instant": true, + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "Avg Upstr Time", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "rgb(31, 120, 193)", + "mode": "fixed" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 21, + "y": 1 + }, + "id": 110, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", scheme=\"https\"}[$__rate_interval]))\n / (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) > 0)", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "HTTPS", + "type": "stat" + }, + { + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": null, + "displayMode": "auto", + "minWidth": 65 + }, + "decimals": 2, + "displayName": "", + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Time" + }, + "properties": [ + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #A" + }, + "properties": [ + { + "id": "displayName", + "value": "RPS" + }, + { + "id": "unit", + "value": "ops" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #B" + }, + "properties": [ + { + "id": "displayName", + "value": "Retried Req" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #C" + }, + "properties": [ + { + "id": "displayName", + "value": "Req Time" + }, + { + "id": "unit", + "value": "s" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #D" + }, + "properties": [ + { + "id": "displayName", + "value": "Upstr Time" + }, + { + "id": "unit", + "value": "s" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #E" + }, + "properties": [ + { + "id": "displayName", + "value": "In Traffic" + }, + { + "id": "unit", + "value": "bps" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #F" + }, + "properties": [ + { + "id": "displayName", + "value": "Out Traffic" + }, + { + "id": "unit", + "value": "bps" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #G" + }, + "properties": [ + { + "id": "displayName", + "value": "Req Size" + }, + { + "id": "unit", + "value": "bytes" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #H" + }, + "properties": [ + { + "id": "displayName", + "value": "Resp Size" + }, + { + "id": "unit", + "value": "bytes" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #I" + }, + "properties": [ + { + "id": "displayName", + "value": "1xx" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #J" + }, + "properties": [ + { + "id": "displayName", + "value": "2xx" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #K" + }, + "properties": [ + { + "id": "displayName", + "value": "3xx" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #L" + }, + "properties": [ + { + "id": "displayName", + "value": "4xx" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #M" + }, + "properties": [ + { + "id": "displayName", + "value": "5xx" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #N" + }, + "properties": [ + { + "id": "displayName", + "value": "HTTPS" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #O" + }, + "properties": [ + { + "id": "displayName", + "value": "GET" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #P" + }, + "properties": [ + { + "id": "displayName", + "value": "POST" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #Q" + }, + "properties": [ + { + "id": "displayName", + "value": "HEAD" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #R" + }, + "properties": [ + { + "id": "displayName", + "value": "PUT" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #S" + }, + "properties": [ + { + "id": "displayName", + "value": "DELETE" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #T" + }, + "properties": [ + { + "id": "displayName", + "value": "OPTIONS" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #U" + }, + "properties": [ + { + "id": "displayName", + "value": "PATCH" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "vhost" + }, + "properties": [ + { + "id": "displayName", + "value": "VHost" + }, + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "links", + "value": [ + { + "targetBlank": false, + "title": "Open VHost Detail", + "url": "/d/a4hXN3Gik/vhost-detail?var-vhost=${__value.raw}&${__url_time_range}" + } + ] + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 270 + } + ] + } + ] + }, + "gridPos": { + "h": 6, + "w": 24, + "x": 0, + "y": 3 + }, + "id": 28, + "links": [], + "options": { + "showHeader": true + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "(sum(rate(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "A" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_upstream_retries_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by\n / (sum(rate(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "legendFormat": "", + "refId": "B" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_request_seconds_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by\n / (sum(increase(ingress_nginx_${metric}_request_seconds_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "legendFormat": "", + "refId": "C" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_upstream_response_seconds_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by\n / (sum(increase(ingress_nginx_${metric}_upstream_response_seconds_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "legendFormat": "", + "refId": "D" + }, + { + "expr": "(sum(rate(ingress_nginx_${metric}_received_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by * 8 > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "legendFormat": "", + "refId": "E" + }, + { + "expr": "(sum(rate(ingress_nginx_${metric}_sent_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by * 8 > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "F" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_received_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by\n / (sum(increase(ingress_nginx_${metric}_received_bytes_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "G" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_sent_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by\n / (sum(increase(ingress_nginx_${metric}_sent_bytes_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "H" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"1..\"}[$__range])) $by\n/ (sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "I" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"2..\"}[$__range])) $by\n/ (sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "J" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"3..\"}[$__range])) $by\n/ (sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "K" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"4..\"}[$__range])) $by\n/ (sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "L" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"5..\"}[$__range])) $by\n/ (sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "M" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", scheme=\"https\"}[$__range])) $by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "N" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"GET\"}[$__range])) $by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "O" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"POST\"}[$__range])) $by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "P" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"HEAD\"}[$__range])) $by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "Q" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"PUT\"}[$__range])) $by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "R" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"DELETE\"}[$__range])) $by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "S" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"OPTIONS\"}[$__range])) $by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "T" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"PATCH\"}[$__range])) $by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "U" + } + ], + "title": "Average", + "transformations": [ + { + "id": "merge", + "options": { + "reducers": [] + } + }, + { + "id": "filterFieldsByName", + "options": { + "include": { + "names": [ + "vhost", + "Value #A", + "Value #B", + "Value #C", + "Value #D", + "Value #E", + "Value #F", + "Value #G", + "Value #H", + "Value #I", + "Value #J", + "Value #K", + "Value #L", + "Value #M", + "Value #N", + "Value #O", + "Value #P", + "Value #Q", + "Value #R", + "Value #S", + "Value #T", + "Value #U" + ] + } + } + } + ], + "type": "table" + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 16, + "x": 0, + "y": 9 + }, + "hiddenSeries": false, + "id": 1, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sort": "total", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A", + "step": 20 + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $by > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Requests", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 8, + "x": 16, + "y": 9 + }, + "hiddenSeries": false, + "id": 80, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sort": "total", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $by\n / scalar(sum(rate(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))) > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Requests %", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "percentunit", + "label": "", + "logBase": 1, + "max": "1", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "3xx": "#6ED0E0", + "4xx": "#EAB839", + "5xx": "#BF1B00" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 16, + "x": 0, + "y": 14 + }, + "hiddenSeries": false, + "id": 242, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": true, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + }, + { + "alias": "2xx", + "color": "#73BF69" + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A" + }, + { + "expr": "sum(label_replace(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]), \"status_group\", \"${1}xx\", \"status\", \"([0-9])..\")) by (status_group) > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{ status_group }}", + "refId": "B", + "step": 40 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Responses", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "3xx": "#6ED0E0", + "4xx": "#EAB839", + "5xx": "#BF1B00" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 8, + "x": 16, + "y": 14 + }, + "hiddenSeries": false, + "id": 241, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": true, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(label_replace(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]), \"status_group\", \"${1}xx\", \"status\", \"([0-9])..\")) by (status_group)\n / scalar(sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))) > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{status_group}}", + "refId": "B", + "step": 40 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Responses %", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "percentunit", + "label": "", + "logBase": 1, + "max": "1", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 8, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 16, + "x": 0, + "y": 20 + }, + "hiddenSeries": false, + "hideTimeOverride": false, + "id": 4, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sideWidth": null, + "sort": null, + "sortDesc": null, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 0, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "0.005", + "color": "#76B576" + }, + { + "alias": "0.01", + "color": "#83BC6D" + }, + { + "alias": "0.02", + "color": "#91C364" + }, + { + "alias": "0.03", + "color": "#9FCB5B" + }, + { + "alias": "0.04", + "color": "#ACD252" + }, + { + "alias": "0.05", + "color": "#BADA49" + }, + { + "alias": "0.075", + "color": "#C8E140" + }, + { + "alias": "0.1", + "color": "#D5E837" + }, + { + "alias": "0.2", + "color": "#E3F02E" + }, + { + "alias": "0.3", + "color": "#F1F725" + }, + { + "alias": "0.4", + "color": "#FFFF1C" + }, + { + "alias": "0.5", + "color": "#FAE519" + }, + { + "alias": "0.75", + "color": "#F6CC16" + }, + { + "alias": "1", + "color": "#F2B213" + }, + { + "alias": "1.5", + "color": "#EE9910" + }, + { + "alias": "2", + "color": "#EA7F0E" + }, + { + "alias": "3", + "color": "#E6660B" + }, + { + "alias": "4", + "color": "#E24C08" + }, + { + "alias": "5", + "color": "#DE3205" + }, + { + "alias": "10", + "color": "#DA1902" + }, + { + "alias": "+Inf", + "color": "#D60000" + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_lowres_upstream_response_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)", + "format": "heatmap", + "intervalFactor": 1, + "legendFormat": "{{le}}", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Upstream Response Time", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + "total" + ] + }, + "yaxes": [ + { + "decimals": null, + "format": "ops", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 8, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 8, + "x": 16, + "y": 20 + }, + "hiddenSeries": false, + "hideTimeOverride": false, + "id": 81, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sideWidth": null, + "sort": null, + "sortDesc": null, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 0, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "0.005", + "color": "#76B576" + }, + { + "alias": "0.01", + "color": "#83BC6D" + }, + { + "alias": "0.02", + "color": "#91C364" + }, + { + "alias": "0.03", + "color": "#9FCB5B" + }, + { + "alias": "0.04", + "color": "#ACD252" + }, + { + "alias": "0.05", + "color": "#BADA49" + }, + { + "alias": "0.075", + "color": "#C8E140" + }, + { + "alias": "0.1", + "color": "#D5E837" + }, + { + "alias": "0.2", + "color": "#E3F02E" + }, + { + "alias": "0.3", + "color": "#F1F725" + }, + { + "alias": "0.4", + "color": "#FFFF1C" + }, + { + "alias": "0.5", + "color": "#FAE519" + }, + { + "alias": "0.75", + "color": "#F6CC16" + }, + { + "alias": "1", + "color": "#F2B213" + }, + { + "alias": "1.5", + "color": "#EE9910" + }, + { + "alias": "2", + "color": "#EA7F0E" + }, + { + "alias": "3", + "color": "#E6660B" + }, + { + "alias": "4", + "color": "#E24C08" + }, + { + "alias": "5", + "color": "#DE3205" + }, + { + "alias": "10", + "color": "#DA1902" + }, + { + "alias": "+Inf", + "color": "#D60000" + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_lowres_upstream_response_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)\n / scalar(sum(rate(ingress_nginx_${metric}_lowres_upstream_response_seconds_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])))", + "format": "heatmap", + "intervalFactor": 1, + "legendFormat": "{{le}}", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Upstream Response Time %", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + "total" + ] + }, + "yaxes": [ + { + "format": "percentunit", + "label": null, + "logBase": 1, + "max": "1", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 8, + "x": 0, + "y": 26 + }, + "hiddenSeries": false, + "hideTimeOverride": false, + "id": 62, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sideWidth": null, + "sort": null, + "sortDesc": null, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": true, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_upstream_retries_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_upstream_retries_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $by > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Retried Requests", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + "total" + ] + }, + "yaxes": [ + { + "format": "ops", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 8, + "x": 8, + "y": 26 + }, + "hiddenSeries": false, + "hideTimeOverride": false, + "id": 112, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sideWidth": null, + "sort": null, + "sortDesc": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_upstream_retries_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $by\n/ sum(rate(ingress_nginx_${metric}_upstream_retries_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $by\n> 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Retries (per Retried Request)", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + "total" + ] + }, + "yaxes": [ + { + "format": "ops", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "3xx": "#6ED0E0", + "4xx": "#EAB839", + "5xx": "#BF1B00" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 8, + "x": 16, + "y": 26 + }, + "hiddenSeries": false, + "id": 196, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": true, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"1..\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"1..\"}[$__rate_interval])) $by > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "B", + "step": 40 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "1xx", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "3xx": "#6ED0E0", + "4xx": "#EAB839", + "5xx": "#BF1B00" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 8, + "x": 16, + "y": 30 + }, + "hiddenSeries": false, + "id": 87, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": true, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"2..\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"2..\"}[$__rate_interval])) $by > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "B", + "step": 40 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "2xx", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": null, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 8, + "x": 0, + "y": 31 + }, + "hiddenSeries": false, + "hideTimeOverride": false, + "id": 49, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sideWidth": null, + "sort": null, + "sortDesc": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_request_seconds_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $by\n / sum(rate(ingress_nginx_${metric}_request_seconds_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $by > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Avg Request Time", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + "total" + ] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": null, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 8, + "x": 8, + "y": 31 + }, + "hiddenSeries": false, + "hideTimeOverride": false, + "id": 63, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sideWidth": null, + "sort": null, + "sortDesc": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_upstream_response_seconds_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $by\n / sum(rate(ingress_nginx_${metric}_upstream_response_seconds_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $by > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Avg Upstream Response Time", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + "total" + ] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "3xx": "#6ED0E0", + "4xx": "#EAB839", + "5xx": "#BF1B00" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 8, + "x": 16, + "y": 34 + }, + "hiddenSeries": false, + "id": 10, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": true, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"3..\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"3..\"}[$__rate_interval])) $by > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "B", + "step": 40 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "3xx", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": null, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 8, + "x": 0, + "y": 36 + }, + "hiddenSeries": false, + "hideTimeOverride": false, + "id": 58, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sideWidth": null, + "sort": null, + "sortDesc": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_received_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $by\n / sum(rate(ingress_nginx_${metric}_received_bytes_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $by > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Avg Request Size", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + "total" + ] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": null, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 8, + "x": 8, + "y": 36 + }, + "hiddenSeries": false, + "hideTimeOverride": false, + "id": 73, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sideWidth": null, + "sort": null, + "sortDesc": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_sent_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $by\n / sum(rate(ingress_nginx_${metric}_sent_bytes_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $by > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Avg Response Size", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + "total" + ] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "3xx": "#6ED0E0", + "4xx": "#EAB839", + "5xx": "#BF1B00" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 8, + "x": 16, + "y": 38 + }, + "hiddenSeries": false, + "id": 18, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": true, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"4..\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"4..\"}[$__rate_interval])) $by > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "B", + "step": 40 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "4xx", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 8, + "x": 0, + "y": 41 + }, + "hiddenSeries": false, + "id": 12, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_received_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) * 8", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A", + "step": 20 + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_received_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $by * 8 > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "B", + "step": 20 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Incoming Traffic", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bps", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 8, + "x": 8, + "y": 41 + }, + "hiddenSeries": false, + "id": 9, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sort": "max", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_sent_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) * 8", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A", + "step": 20 + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_sent_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $by * 8 > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Outgoing Traffic", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bps", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "3xx": "#6ED0E0", + "4xx": "#EAB839", + "5xx": "#BF1B00" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 8, + "x": 16, + "y": 42 + }, + "hiddenSeries": false, + "id": 17, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": true, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"5..\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"5..\"}[$__rate_interval])) $by > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "B", + "step": 40 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "5xx", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "collapsed": false, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 46 + }, + "id": 195, + "panels": [], + "title": "Status Codes", + "type": "row" + }, + { + "aliasColors": { + "3xx": "#6ED0E0", + "4xx": "#EAB839", + "5xx": "#BF1B00" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 8, + "x": 0, + "y": 47 + }, + "hiddenSeries": false, + "id": 189, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": true, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": true, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"1..\"}[$__rate_interval])) by (status)\n / scalar(sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"1..\"}[$__rate_interval])))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{status}}", + "refId": "B", + "step": 40 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "1xx", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "percentunit", + "label": "", + "logBase": 1, + "max": "100", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "3xx": "#6ED0E0", + "4xx": "#EAB839", + "5xx": "#BF1B00" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 8, + "x": 8, + "y": 47 + }, + "hiddenSeries": false, + "id": 190, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": true, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": true, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"2..\"}[$__rate_interval])) by (status)\n / scalar(sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"2..\"}[$__rate_interval])))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{status}}", + "refId": "B", + "step": 40 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "2xx", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "percentunit", + "label": "", + "logBase": 1, + "max": "100", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "3xx": "#6ED0E0", + "4xx": "#EAB839", + "5xx": "#BF1B00" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 8, + "x": 16, + "y": 47 + }, + "hiddenSeries": false, + "id": 191, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": true, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": true, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"3..\"}[$__rate_interval])) by (status)\n / scalar(sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"3..\"}[$__rate_interval])))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{status}}", + "refId": "B", + "step": 40 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "3xx", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "percentunit", + "label": "", + "logBase": 1, + "max": "100", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "3xx": "#6ED0E0", + "4xx": "#EAB839", + "5xx": "#BF1B00" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 12, + "x": 0, + "y": 51 + }, + "hiddenSeries": false, + "id": 192, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": true, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": true, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"4..\"}[$__rate_interval])) by (status)\n / scalar(sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"4..\"}[$__rate_interval])))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{status}}", + "refId": "B", + "step": 40 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "4xx", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "percentunit", + "label": "", + "logBase": 1, + "max": "100", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "3xx": "#6ED0E0", + "4xx": "#EAB839", + "5xx": "#BF1B00" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 12, + "x": 12, + "y": 51 + }, + "hiddenSeries": false, + "id": 193, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": true, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": true, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"5..\"}[$__rate_interval])) by (status)\n / scalar(sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"5..\"}[$__rate_interval])))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{status}}", + "refId": "B", + "step": 40 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "5xx", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "percentunit", + "label": "", + "logBase": 1, + "max": "100", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "3xx": "#6ED0E0", + "4xx": "#EAB839", + "5xx": "#BF1B00" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 6, + "x": 0, + "y": 56 + }, + "hiddenSeries": false, + "id": 86, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": true, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "maxPerRow": 4, + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": "status", + "repeatDirection": "h", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=\"$status\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=\"$status\"}[$__rate_interval])) $by > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "B", + "step": 40 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "$status", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "collapsed": true, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 60 + }, + "id": 150, + "panels": [ + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 0, + "y": 42 + }, + "id": 130, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.3", + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_request_seconds_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))\n / sum(rate(ingress_nginx_${metric}_request_seconds_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))\n * 1000", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "Avg Req Time", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 3, + "y": 42 + }, + "id": 132, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.3", + "targets": [ + { + "expr": "histogram_quantile(0.5, sum(rate(ingress_nginx_${metric}_request_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)) * 1000", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "50th Req Time", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 6, + "y": 42 + }, + "id": 134, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.3", + "targets": [ + { + "expr": "histogram_quantile(0.9, sum(rate(ingress_nginx_${metric}_request_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)) * 1000", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "90th Req Time", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 9, + "y": 42 + }, + "id": 174, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.3", + "targets": [ + { + "expr": "histogram_quantile(0.99, sum(rate(ingress_nginx_${metric}_request_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)) * 1000", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "99th Req Time", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 12, + "y": 42 + }, + "id": 140, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.3", + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_upstream_response_seconds_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))\n / sum(rate(ingress_nginx_${metric}_upstream_response_seconds_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))\n * 1000", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "Avg Upstr Time", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 15, + "y": 42 + }, + "id": 142, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.3", + "targets": [ + { + "expr": "histogram_quantile(0.5, sum(rate(ingress_nginx_${metric}_upstream_response_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)) * 1000", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "50th Upstr Time", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 18, + "y": 42 + }, + "id": 144, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.3", + "targets": [ + { + "expr": "histogram_quantile(0.9, sum(rate(ingress_nginx_${metric}_upstream_response_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)) * 1000", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "90th Upstr Time", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 21, + "y": 42 + }, + "id": 146, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.3", + "targets": [ + { + "expr": "histogram_quantile(0.99, sum(rate(ingress_nginx_${metric}_upstream_response_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)) * 1000", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "99th Upstr Time", + "type": "stat" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": null, + "fill": 0, + "gridPos": { + "h": 5, + "w": 12, + "x": 0, + "y": 44 + }, + "hideTimeOverride": false, + "id": 136, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sideWidth": null, + "sort": null, + "sortDesc": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Avg", + "fill": 2, + "linewidth": 0 + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "histogram_quantile(0.99, sum(rate(ingress_nginx_${metric}_request_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)) * 1000", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "99th", + "refId": "A" + }, + { + "expr": "histogram_quantile(0.9, sum(rate(ingress_nginx_${metric}_request_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)) * 1000", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "90th", + "refId": "B" + }, + { + "expr": "histogram_quantile(0.5, sum(rate(ingress_nginx_${metric}_request_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)) * 1000", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "50th", + "refId": "C" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_request_seconds_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))\n / sum(rate(ingress_nginx_${metric}_request_seconds_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))\n * 1000", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Avg", + "refId": "D" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Request Time", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + "total" + ] + }, + "yaxes": [ + { + "format": "ms", + "label": null, + "logBase": 10, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": null, + "fill": 0, + "gridPos": { + "h": 5, + "w": 12, + "x": 12, + "y": 44 + }, + "hideTimeOverride": false, + "id": 148, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sideWidth": null, + "sort": null, + "sortDesc": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Avg", + "fill": 2, + "linewidth": 0 + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "histogram_quantile(0.99, sum(rate(ingress_nginx_${metric}_upstream_response_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)) * 1000", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "99th", + "refId": "A" + }, + { + "expr": "histogram_quantile(0.9, sum(rate(ingress_nginx_${metric}_upstream_response_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)) * 1000", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "90th", + "refId": "B" + }, + { + "expr": "histogram_quantile(0.5, sum(rate(ingress_nginx_${metric}_upstream_response_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)) * 1000", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "50th", + "refId": "C" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_upstream_response_seconds_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))\n / sum(rate(ingress_nginx_${metric}_upstream_response_seconds_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))\n * 1000", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Avg", + "refId": "D" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Upstream Response Time", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + "total" + ] + }, + "yaxes": [ + { + "format": "ms", + "label": null, + "logBase": 10, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "title": "Request Time and Upstream Response Time", + "type": "row" + }, + { + "collapsed": true, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 61 + }, + "id": 214, + "panels": [ + { + "cards": { + "cardPadding": 0, + "cardRound": 0 + }, + "color": { + "cardColor": "#b4ff00", + "colorScale": "sqrt", + "colorScheme": "interpolateYlGnBu", + "exponent": 0.5, + "max": null, + "min": 0, + "mode": "spectrum" + }, + "dataFormat": "tsbuckets", + "datasource": null, + "gridPos": { + "h": 21, + "w": 12, + "x": 0, + "y": 4 + }, + "heatmap": {}, + "highlightCards": true, + "id": 152, + "legend": { + "show": true + }, + "links": [], + "targets": [ + { + "expr": "sum(increase(ingress_nginx_${metric}_request_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le) > 0", + "format": "heatmap", + "intervalFactor": 1, + "legendFormat": "{{le}}", + "refId": "A" + } + ], + "title": "Request Time", + "tooltip": { + "show": true, + "showHistogram": true + }, + "type": "heatmap", + "xAxis": { + "show": true + }, + "xBucketNumber": null, + "xBucketSize": null, + "yAxis": { + "decimals": 1, + "format": "s", + "logBase": 1, + "max": null, + "min": null, + "show": true, + "splitFactor": null + }, + "yBucketBound": "auto", + "yBucketNumber": null, + "yBucketSize": null + }, + { + "cards": { + "cardPadding": 0, + "cardRound": 0 + }, + "color": { + "cardColor": "#b4ff00", + "colorScale": "sqrt", + "colorScheme": "interpolateYlGnBu", + "exponent": 0.5, + "max": null, + "min": 0, + "mode": "spectrum" + }, + "dataFormat": "tsbuckets", + "datasource": null, + "gridPos": { + "h": 21, + "w": 12, + "x": 12, + "y": 4 + }, + "heatmap": {}, + "highlightCards": true, + "id": 153, + "legend": { + "show": true + }, + "links": [], + "targets": [ + { + "expr": "sum(increase(ingress_nginx_${metric}_upstream_response_seconds_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le) > 0", + "format": "heatmap", + "intervalFactor": 1, + "legendFormat": "{{le}}", + "refId": "A" + } + ], + "title": "Upstream Response Time", + "tooltip": { + "show": true, + "showHistogram": true + }, + "type": "heatmap", + "xAxis": { + "show": true + }, + "xBucketNumber": null, + "xBucketSize": null, + "yAxis": { + "decimals": 1, + "format": "s", + "logBase": 1, + "max": null, + "min": null, + "show": true, + "splitFactor": null + }, + "yBucketBound": "auto", + "yBucketNumber": null, + "yBucketSize": null + } + ], + "title": "Request Time Heatmap and Upstream Response Time Heatmap", + "type": "row" + }, + { + "collapsed": true, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 62 + }, + "id": 160, + "panels": [ + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 0, + "y": 5 + }, + "id": 171, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.3", + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_received_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))\n / sum(rate(ingress_nginx_${metric}_received_bytes_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "Avg Req Size", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 3, + "y": 5 + }, + "id": 172, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.3", + "targets": [ + { + "expr": "histogram_quantile(0.5, sum(rate(ingress_nginx_${metric}_received_bytes_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le))", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "50th Req Size", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 6, + "y": 5 + }, + "id": 173, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.3", + "targets": [ + { + "expr": "histogram_quantile(0.9, sum(rate(ingress_nginx_${metric}_received_bytes_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le))", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "90th Req Size", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 9, + "y": 5 + }, + "id": 128, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.3", + "targets": [ + { + "expr": "histogram_quantile(0.99, sum(rate(ingress_nginx_${metric}_received_bytes_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le))", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "99th Req Size", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 12, + "y": 5 + }, + "id": 175, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.3", + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_sent_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))\n / sum(rate(ingress_nginx_${metric}_sent_bytes_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "Avg Resp Size", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 15, + "y": 5 + }, + "id": 176, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.3", + "targets": [ + { + "expr": "histogram_quantile(0.5, sum(rate(ingress_nginx_${metric}_sent_bytes_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le))", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "50th Resp Size", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 18, + "y": 5 + }, + "id": 177, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.3", + "targets": [ + { + "expr": "histogram_quantile(0.9, sum(rate(ingress_nginx_${metric}_sent_bytes_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le))", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "90th Resp Size", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 21, + "y": 5 + }, + "id": 178, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.3", + "targets": [ + { + "expr": "histogram_quantile(0.99, sum(rate(ingress_nginx_${metric}_sent_bytes_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le))", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "99th Resp Size", + "type": "stat" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": null, + "fill": 0, + "gridPos": { + "h": 4, + "w": 12, + "x": 0, + "y": 7 + }, + "hideTimeOverride": false, + "id": 155, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sideWidth": null, + "sort": null, + "sortDesc": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Avg", + "fill": 2, + "linewidth": 0 + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "histogram_quantile(0.99, sum(rate(ingress_nginx_${metric}_received_bytes_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "99th", + "refId": "A" + }, + { + "expr": "histogram_quantile(0.9, sum(rate(ingress_nginx_${metric}_received_bytes_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "90th", + "refId": "B" + }, + { + "expr": "histogram_quantile(0.5, sum(rate(ingress_nginx_${metric}_received_bytes_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "50th", + "refId": "C" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_received_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))\n / sum(rate(ingress_nginx_${metric}_received_bytes_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Avg", + "refId": "D" + } + ], + "thresholds": [], + "timeFrom": null, + "timeShift": null, + "title": "Request Size", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + "total" + ] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 2, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": null, + "fill": 0, + "gridPos": { + "h": 4, + "w": 12, + "x": 12, + "y": 7 + }, + "hideTimeOverride": false, + "id": 157, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sideWidth": null, + "sort": null, + "sortDesc": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Avg", + "fill": 2, + "linewidth": 0 + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "histogram_quantile(0.99, sum(rate(ingress_nginx_${metric}_sent_bytes_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "99th", + "refId": "A" + }, + { + "expr": "histogram_quantile(0.9, sum(rate(ingress_nginx_${metric}_sent_bytes_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "90th", + "refId": "B" + }, + { + "expr": "histogram_quantile(0.5, sum(rate(ingress_nginx_${metric}_sent_bytes_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "50th", + "refId": "C" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_sent_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))\n / sum(rate(ingress_nginx_${metric}_sent_bytes_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Avg", + "refId": "D" + } + ], + "thresholds": [], + "timeFrom": null, + "timeShift": null, + "title": "Response Size", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + "total" + ] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 2, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "title": "Request Size and Response Size", + "type": "row" + }, + { + "collapsed": true, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 63 + }, + "id": 212, + "panels": [ + { + "cards": { + "cardPadding": 0, + "cardRound": 0 + }, + "color": { + "cardColor": "#b4ff00", + "colorScale": "sqrt", + "colorScheme": "interpolateYlGnBu", + "exponent": 0.5, + "max": null, + "min": 0, + "mode": "spectrum" + }, + "dataFormat": "tsbuckets", + "datasource": null, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 6 + }, + "heatmap": {}, + "highlightCards": true, + "id": 158, + "legend": { + "show": true + }, + "links": [], + "targets": [ + { + "expr": "sum(increase(ingress_nginx_${metric}_received_bytes_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)", + "format": "heatmap", + "intervalFactor": 1, + "legendFormat": "{{le}}", + "refId": "A" + } + ], + "title": "Request Size", + "tooltip": { + "show": true, + "showHistogram": true + }, + "type": "heatmap", + "xAxis": { + "show": true + }, + "xBucketNumber": null, + "xBucketSize": null, + "yAxis": { + "decimals": 0, + "format": "bytes", + "logBase": 1, + "max": null, + "min": null, + "show": true, + "splitFactor": null + }, + "yBucketBound": "auto", + "yBucketNumber": null, + "yBucketSize": null + }, + { + "cards": { + "cardPadding": 0, + "cardRound": 0 + }, + "color": { + "cardColor": "#b4ff00", + "colorScale": "sqrt", + "colorScheme": "interpolateYlGnBu", + "exponent": 0.5, + "max": null, + "min": 0, + "mode": "spectrum" + }, + "dataFormat": "tsbuckets", + "datasource": null, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 6 + }, + "heatmap": {}, + "highlightCards": true, + "id": 161, + "legend": { + "show": true + }, + "links": [], + "targets": [ + { + "expr": "sum(increase(ingress_nginx_${metric}_sent_bytes_bucket{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (le)", + "format": "heatmap", + "intervalFactor": 1, + "legendFormat": "{{le}}", + "refId": "A" + } + ], + "title": "Response Size", + "tooltip": { + "show": true, + "showHistogram": true + }, + "type": "heatmap", + "xAxis": { + "show": true + }, + "xBucketNumber": null, + "xBucketSize": null, + "yAxis": { + "decimals": 0, + "format": "bytes", + "logBase": 1, + "max": null, + "min": null, + "show": true, + "splitFactor": null + }, + "yBucketBound": "auto", + "yBucketNumber": null, + "yBucketSize": null + } + ], + "title": "Request Size Heatmap and Response Size Heatmap", + "type": "row" + }, + { + "collapsed": true, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 64 + }, + "id": 89, + "panels": [ + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "gridPos": { + "h": 6, + "w": 12, + "x": 0, + "y": 7 + }, + "id": 61, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sort": "total", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) by (method)\n / scalar(sum(rate(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{method}}", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeShift": null, + "title": "Method %", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "percentunit", + "label": "", + "logBase": 1, + "max": "1", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "gridPos": { + "h": 6, + "w": 12, + "x": 12, + "y": 7 + }, + "id": 60, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sort": "total", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\"}[$__rate_interval])) by (content_kind)\n/ scalar(sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\"}[$__rate_interval])))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{content_kind}}", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeShift": null, + "title": "Content Kind %", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "percentunit", + "label": "", + "logBase": 1, + "max": "1", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "gridPos": { + "h": 4, + "w": 12, + "x": 0, + "y": 13 + }, + "id": 90, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sort": "total", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": "method", + "repeatDirection": "v", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"$method\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"$method\"}[$__rate_interval])) $by > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeShift": null, + "title": "$method", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "gridPos": { + "h": 4, + "w": 12, + "x": 12, + "y": 13 + }, + "id": 97, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sort": "total", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": "content_kind", + "repeatDirection": "v", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=\"$content_kind\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=\"$content_kind\"}[$__rate_interval])) $by > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$legend_format", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeShift": null, + "title": "$content_kind", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "title": "Request Method and Content Kind", + "type": "row" + }, + { + "collapsed": true, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 65 + }, + "id": 79, + "panels": [ + { + "circleMaxSize": "10", + "circleMinSize": 2, + "colors": [ + "#890f02", + "#890f02" + ], + "datasource": "$ds_prometheus", + "decimals": 0, + "esGeoPoint": "geohash", + "esLocationName": "place", + "esMetric": "Value", + "gridPos": { + "h": 18, + "w": 24, + "x": 0, + "y": 47 + }, + "hideEmpty": false, + "hideZero": false, + "id": 75, + "initialZoom": "3", + "links": [], + "locationData": "geohash", + "mapCenter": "Europe", + "mapCenterLatitude": 46, + "mapCenterLongitude": 14, + "maxDataPoints": 1, + "showLegend": false, + "stickyLabels": false, + "targets": [ + { + "expr": "sum(increase(ingress_nginx_${metric}_geohash_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) by (geohash, place) > 0", + "format": "table", + "instant": true, + "intervalFactor": 1, + "refId": "A" + } + ], + "thresholds": "", + "title": "Requests", + "transparent": false, + "type": "grafana-worldmap-panel", + "unitPlural": "", + "unitSingle": "", + "valueName": "total" + } + ], + "title": "Map", + "type": "row" + }, + { + "collapsed": true, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 66 + }, + "id": 46, + "panels": [ + { + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": null, + "displayMode": "auto", + "minWidth": 64 + }, + "decimals": 2, + "displayName": "", + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Time" + }, + "properties": [ + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #A" + }, + "properties": [ + { + "id": "displayName", + "value": "RPS" + }, + { + "id": "unit", + "value": "ops" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 85 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #B" + }, + "properties": [ + { + "id": "displayName", + "value": "Retried Req" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #C" + }, + "properties": [ + { + "id": "displayName", + "value": "Req Time" + }, + { + "id": "unit", + "value": "s" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 85 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #D" + }, + "properties": [ + { + "id": "displayName", + "value": "Resp Time" + }, + { + "id": "unit", + "value": "s" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 85 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #E" + }, + "properties": [ + { + "id": "displayName", + "value": "In Traffic" + }, + { + "id": "unit", + "value": "bps" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 85 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #F" + }, + "properties": [ + { + "id": "displayName", + "value": "Out Traffic" + }, + { + "id": "unit", + "value": "bps" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 85 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #G" + }, + "properties": [ + { + "id": "displayName", + "value": "Req Size" + }, + { + "id": "unit", + "value": "bytes" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 85 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #H" + }, + "properties": [ + { + "id": "displayName", + "value": "Resp Size" + }, + { + "id": "unit", + "value": "bytes" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 85 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #I" + }, + "properties": [ + { + "id": "displayName", + "value": "1xx" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #J" + }, + "properties": [ + { + "id": "displayName", + "value": "2xx" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #K" + }, + "properties": [ + { + "id": "displayName", + "value": "3xx" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #L" + }, + "properties": [ + { + "id": "displayName", + "value": "4xx" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #M" + }, + "properties": [ + { + "id": "displayName", + "value": "5xx" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #N" + }, + "properties": [ + { + "id": "displayName", + "value": "HTTPS" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #O" + }, + "properties": [ + { + "id": "displayName", + "value": "GET" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #P" + }, + "properties": [ + { + "id": "displayName", + "value": "POST" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #Q" + }, + "properties": [ + { + "id": "displayName", + "value": "HEAD" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #R" + }, + "properties": [ + { + "id": "displayName", + "value": "PUT" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #S" + }, + "properties": [ + { + "id": "displayName", + "value": "DELETE" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #T" + }, + "properties": [ + { + "id": "displayName", + "value": "OPTIONS" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #U" + }, + "properties": [ + { + "id": "displayName", + "value": "PATCH" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "namespace" + }, + "properties": [ + { + "id": "displayName", + "value": "Namespace" + }, + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "links", + "value": [ + { + "targetBlank": false, + "title": "Open Namespace", + "url": "/d/Z-phNqGmz/namespaces?var-namespace=${__value.raw}&${__url_time_range}" + } + ] + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 140 + } + ] + } + ] + }, + "gridPos": { + "h": 6, + "w": 24, + "x": 0, + "y": 67 + }, + "id": 42, + "links": [], + "options": { + "showHeader": true + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "(sum(rate(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "instant": true, + "intervalFactor": 1, + "refId": "A" + }, + { + "expr": "sum(rate(ingress_nginx_${metric}_upstream_retries_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by\n / (sum(rate(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "legendFormat": "", + "refId": "B" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_request_seconds_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by\n / (sum(increase(ingress_nginx_${metric}_request_seconds_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "legendFormat": "", + "refId": "C" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_upstream_response_seconds_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by\n / (sum(increase(ingress_nginx_${metric}_upstream_response_seconds_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "legendFormat": "", + "refId": "D" + }, + { + "expr": "(sum(rate(ingress_nginx_${metric}_received_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by * 8 > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "legendFormat": "", + "refId": "E" + }, + { + "expr": "(sum(rate(ingress_nginx_${metric}_sent_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by * 8 > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "F" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_received_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by\n / (sum(increase(ingress_nginx_${metric}_received_bytes_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "G" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_sent_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by\n / (sum(increase(ingress_nginx_${metric}_sent_bytes_count{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "H" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"1..\"}[$__range])) $alt_by\n/ (sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "I" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"2..\"}[$__range])) $alt_by\n/ (sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "J" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"3..\"}[$__range])) $alt_by\n/ (sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "K" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"4..\"}[$__range])) $alt_by\n/ (sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "L" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", status=~\"5..\"}[$__range])) $alt_by\n/ (sum(increase(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "M" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", scheme=\"https\"}[$__range])) $alt_by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "N" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"GET\"}[$__range])) $alt_by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "O" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"POST\"}[$__range])) $alt_by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "P" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"HEAD\"}[$__range])) $alt_by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "Q" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"PUT\"}[$__range])) $alt_by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "R" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"DELETE\"}[$__range])) $alt_by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "S" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"OPTIONS\"}[$__range])) $alt_by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "T" + }, + { + "expr": "sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\", method=\"PATCH\"}[$__range])) $alt_by\n/ (sum(increase(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range])) $alt_by > 0)\nor sum(irate(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__range]) * 0) $alt_by", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "refId": "U" + } + ], + "title": "Average", + "transformations": [ + { + "id": "merge", + "options": { + "reducers": [] + } + }, + { + "id": "filterFieldsByName", + "options": { + "include": { + "names": [ + "namespace", + "Value #A", + "Value #B", + "Value #C", + "Value #D", + "Value #E", + "Value #F", + "Value #G", + "Value #H", + "Value #I", + "Value #J", + "Value #K", + "Value #L", + "Value #M", + "Value #N", + "Value #O", + "Value #P", + "Value #Q", + "Value #R", + "Value #S", + "Value #T", + "Value #U" + ] + } + } + } + ], + "type": "table" + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 8, + "x": 0, + "y": 73 + }, + "hiddenSeries": false, + "id": 39, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sort": "total", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": true, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $alt_by > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$alt_legend_format", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Requests per $alt_name", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": "", + "logBase": 1, + "max": "100", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 1, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 8, + "x": 8, + "y": 73 + }, + "hiddenSeries": false, + "id": 41, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": true, + "show": false, + "sort": "max", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": true, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_received_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $alt_by * 8 > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$alt_legend_format", + "refId": "B", + "step": 20 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Incoming Traffic per $alt_name", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bps", + "label": null, + "logBase": 1, + "max": "100", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 1, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 8, + "x": 16, + "y": 73 + }, + "hiddenSeries": false, + "id": 40, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sort": "max", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": true, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ingress_nginx_${metric}_sent_bytes_sum{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}[$__rate_interval])) $alt_by * 8 > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "$alt_legend_format", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Outgoing Traffic per $alt_name", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bps", + "label": null, + "logBase": 1, + "max": "100", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "title": "By $alt_name", + "type": "row" + } + ], + "refresh": "30s", + "schemaVersion": 32, + "style": "dark", + "tags": [ + "ingress" + ], + "templating": { + "list": [ + { + "current": { + "selected": false, + "text": "default", + "value": "default" + }, + "description": null, + "error": null, + "hide": 0, + "includeAll": false, + "label": "Prometheus", + "multi": false, + "name": "ds_prometheus", + "options": [], + "query": "prometheus", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + }, + { + "description": null, + "error": null, + "hide": 2, + "label": null, + "name": "metric", + "query": "overall", + "skipUrlSync": false, + "type": "constant" + }, + { + "description": null, + "error": null, + "hide": 2, + "label": null, + "name": "by", + "query": "by (vhost)", + "skipUrlSync": false, + "type": "constant" + }, + { + "description": null, + "error": null, + "hide": 2, + "label": null, + "name": "legend_format", + "query": "{{vhost}}", + "skipUrlSync": false, + "type": "constant" + }, + { + "description": null, + "error": null, + "hide": 2, + "label": null, + "name": "alt_name", + "query": "Namespace", + "skipUrlSync": false, + "type": "constant" + }, + { + "description": null, + "error": null, + "hide": 2, + "label": null, + "name": "alt_by", + "query": "by (namespace)", + "skipUrlSync": false, + "type": "constant" + }, + { + "description": null, + "error": null, + "hide": 2, + "label": null, + "name": "alt_legend_format", + "query": "{{namespace}}", + "skipUrlSync": false, + "type": "constant" + }, + { + "allValue": ".*", + "current": { + "selected": true, + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": "$ds_prometheus", + "definition": "label_values(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\"}, controller)", + "description": null, + "error": null, + "hide": 0, + "includeAll": true, + "label": "Controller", + "multi": true, + "name": "controller", + "options": [], + "query": { + "query": "label_values(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\"}, controller)", + "refId": "main-controller-Variable-Query" + }, + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "description": null, + "error": null, + "hide": 2, + "label": "App", + "name": "app", + "query": ".*", + "skipUrlSync": false, + "type": "constant" + }, + { + "description": null, + "error": null, + "hide": 2, + "label": "Node", + "name": "node", + "query": ".*", + "skipUrlSync": false, + "type": "constant" + }, + { + "description": null, + "error": null, + "hide": 2, + "label": "Namespace", + "name": "namespace", + "query": ".*", + "skipUrlSync": false, + "type": "constant" + }, + { + "description": null, + "error": null, + "hide": 2, + "label": "Ingress", + "name": "ingress", + "query": ".*", + "skipUrlSync": false, + "type": "constant" + }, + { + "description": null, + "error": null, + "hide": 2, + "label": "Service", + "name": "service", + "query": ".*", + "skipUrlSync": false, + "type": "constant" + }, + { + "description": null, + "error": null, + "hide": 2, + "label": "Service Port", + "name": "service_port", + "query": ".*", + "skipUrlSync": false, + "type": "constant" + }, + { + "allValue": ".*", + "current": { + "selected": true, + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": "$ds_prometheus", + "definition": "", + "description": null, + "error": null, + "hide": 0, + "includeAll": true, + "label": "VHost", + "multi": true, + "name": "vhost", + "options": [], + "query": { + "query": "label_values(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\"}, vhost)", + "refId": "main-vhost-Variable-Query" + }, + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "description": null, + "error": null, + "hide": 2, + "label": "Location", + "name": "location", + "query": ".*", + "skipUrlSync": false, + "type": "constant" + }, + { + "allValue": ".*", + "current": { + "selected": true, + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": "$ds_prometheus", + "definition": "", + "description": null, + "error": null, + "hide": 0, + "includeAll": true, + "label": "Content Kind", + "multi": true, + "name": "content_kind", + "options": [], + "query": { + "query": "label_values(ingress_nginx_${metric}_info{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\"}, content_kind)", + "refId": "main-content_kind-Variable-Query" + }, + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": ".*", + "current": { + "selected": true, + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": "$ds_prometheus", + "definition": "", + "description": null, + "error": null, + "hide": 2, + "includeAll": true, + "label": "Method", + "multi": true, + "name": "method", + "options": [], + "query": { + "query": "label_values(ingress_nginx_${metric}_requests_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}, method)", + "refId": "main-method-Variable-Query" + }, + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": ".*", + "current": { + "selected": true, + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": "$ds_prometheus", + "definition": "", + "description": null, + "error": null, + "hide": 2, + "includeAll": true, + "label": "Method", + "multi": true, + "name": "status", + "options": [], + "query": { + "query": "label_values(ingress_nginx_${metric}_responses_total{job=\"nginx-ingress-controller\", controller=~\"$controller\", app=~\"$app\", node=~\"$node\", namespace=~\"$namespace\", ingress=~\"$ingress\", service=~\"$service\", service_port=~\"$service_port\", vhost=~\"$vhost\", location=~\"$location\", content_kind=~\"$content_kind\"}, status)", + "refId": "main-status-Variable-Query" + }, + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + } + ] + }, + "time": { + "from": "now-3h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "", + "title": "VHosts", + "uid": "D38hRqGmk", + "version": 2 +} diff --git a/dashboards/main/capacity-planning.json b/dashboards/main/capacity-planning.json new file mode 100644 index 00000000..47abe1a8 --- /dev/null +++ b/dashboards/main/capacity-planning.json @@ -0,0 +1,2474 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "target": { + "limit": 100, + "matchAny": false, + "tags": [], + "type": "dashboard" + }, + "type": "dashboard" + } + ] + }, + "description": "", + "editable": false, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": 20, + "iteration": 1663071955430, + "links": [], + "liveNow": false, + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 3, + "x": 0, + "y": 0 + }, + "id": 19, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.9", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "expr": "sum(kube_node_status_condition{node=~\"$node\", condition=\"Ready\", status=\"true\"} == 1)", + "refId": "A" + } + ], + "title": "Ready Nodes", + "transparent": true, + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "blue", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 3, + "x": 3, + "y": 0 + }, + "id": 20, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.9", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "expr": "sum(kube_node_info{node=~\"$node\"})", + "refId": "A" + } + ], + "title": "All Nodes", + "transparent": true, + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "yellow", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 3, + "x": 6, + "y": 0 + }, + "id": 27, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.9", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "expr": "sum(max by (namespace) (kube_namespace_status_phase{namespace=~\"$namespace\", phase=\"Active\"}))", + "refId": "A" + } + ], + "title": "Namespaces", + "transparent": true, + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "gridPos": { + "h": 6, + "w": 9, + "x": 11, + "y": 0 + }, + "id": 25, + "options": { + "content": "✓ If you have pods in pending state in your cluster, it can be caused because the scheduler cannot find a node with enough memory and CPU allocatable.
\n✓ Check that you have at least 1 node in your cluster with enough allocatable CPU and memory to accomplish the requests of the pending pods. Be sure that the node with enough resources has not a taint or is not unscheduleable.
\n✓ Check that that node has pods available to schedule in it.
\n✓ If the nodes ran out of allocatable resources you can try to adjust the requests of your pods to optimize the capacity of your nodes using the Memory Allocation Optimization and CPU Allocation Optimization dashboards. If this is not possible, you will have to increase the number of nodes in your cluster.
\n✓ If there are enough resources in the nodes, go to the Main folder dashboards and check the available resource in the quotas of the namespace.", + "mode": "markdown" + }, + "pluginVersion": "8.5.9", + "title": "Tips", + "transparent": true, + "type": "text" + }, + { + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 6 + }, + "id": 44, + "title": "Capacity", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "continuous-GrYlRd" + }, + "mappings": [], + "max": 1, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 3, + "x": 0, + "y": 7 + }, + "id": 42, + "links": [], + "options": { + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": true + }, + "pluginVersion": "8.5.9", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "editorMode": "code", + "expr": "sum(sum by (node) (avg_over_time(kube_pod_container_resource_requests{resource=\"cpu\",unit=\"core\",node=~\"$node\"}[$__rate_interval])* on (uid) group_left(phase) kube_pod_status_phase{phase=\"Running\"})) / sum(sum by (node) (avg_over_time(kube_node_status_allocatable{resource=\"cpu\",unit=\"core\",node=~\"$node\"}[$__rate_interval])))", + "hide": false, + "legendFormat": "Total", + "range": true, + "refId": "B" + } + ], + "title": "% Requested CPU", + "transparent": true, + "type": "gauge" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "continuous-GrYlRd" + }, + "mappings": [], + "max": 1, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 3, + "x": 3, + "y": 7 + }, + "id": 41, + "links": [], + "options": { + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": true + }, + "pluginVersion": "8.5.9", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "editorMode": "code", + "expr": "sum(sum by (node) (avg_over_time(kube_pod_container_resource_requests{resource=\"memory\",node=~\"$node\"}[$__rate_interval])* on (uid) group_left(phase) kube_pod_status_phase{phase=\"Running\"})) / sum(sum by (node) (avg_over_time(kube_node_status_allocatable{resource=\"memory\",unit=\"byte\",node=~\"$node\"}[$__rate_interval])))", + "hide": false, + "legendFormat": "Total", + "range": true, + "refId": "B" + } + ], + "title": "% Requested Memory", + "transparent": true, + "type": "gauge" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "description": "How much CPU is actually used in the cluster (CPU usage / Allocatable CPU).", + "fieldConfig": { + "defaults": { + "color": { + "mode": "continuous-GrYlRd" + }, + "mappings": [], + "max": 1, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 3, + "x": 7, + "y": 7 + }, + "id": 46, + "links": [], + "options": { + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": true + }, + "pluginVersion": "8.5.9", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "editorMode": "code", + "expr": "sum(sum by (node) (rate(container_cpu_usage_seconds_total{container!=\"POD\",container!=\"\",node=~\"$node\"}[$__rate_interval])))\n / sum(sum by (node) (avg_over_time(kube_node_status_allocatable{resource=\"cpu\",unit=\"core\",node=~\"$node\"}[$__rate_interval])))", + "hide": false, + "legendFormat": "Total", + "range": true, + "refId": "B" + } + ], + "title": "% Actual CPU Usage", + "transparent": true, + "type": "gauge" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "description": "How much memory is actually used in the cluster (Memory usage / Allocatable Memory).", + "fieldConfig": { + "defaults": { + "color": { + "mode": "continuous-GrYlRd" + }, + "mappings": [], + "max": 1, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 3, + "x": 10, + "y": 7 + }, + "id": 45, + "links": [], + "options": { + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": true + }, + "pluginVersion": "8.5.9", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "editorMode": "code", + "expr": "sum(sum by (node) (container_memory_working_set_bytes:without_kmem{container!=\"POD\",container!=\"\",node=~\"$node\"})) / sum(sum by (node) (avg_over_time(kube_node_status_allocatable{resource=\"memory\",unit=\"byte\",node=~\"$node\"}[$__rate_interval])))", + "hide": false, + "legendFormat": "Total", + "range": true, + "refId": "B" + } + ], + "title": "% Actual Memory Usage", + "transparent": true, + "type": "gauge" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "description": "How many requested cores are used (Actual CPU / Requested CPU).", + "fieldConfig": { + "defaults": { + "color": { + "mode": "continuous-GrYlRd" + }, + "mappings": [], + "max": 1, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 3, + "x": 14, + "y": 7 + }, + "id": 47, + "links": [], + "options": { + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": true + }, + "pluginVersion": "8.5.9", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "editorMode": "code", + "expr": "sum(sum by (node) (rate(container_cpu_usage_seconds_total{container!=\"POD\",container!=\"\",node=~\"$node\"}[$__rate_interval]))) / sum(sum by (node) (avg_over_time(kube_pod_container_resource_requests{resource=\"cpu\",unit=\"core\",node=~\"$node\"}[$__rate_interval])))", + "hide": false, + "legendFormat": "Total", + "range": true, + "refId": "B" + } + ], + "title": "% Used Requested CPU", + "transparent": true, + "type": "gauge" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "description": "How much requested memory is used (Actual Memory / Requested Memory). ", + "fieldConfig": { + "defaults": { + "color": { + "mode": "continuous-GrYlRd" + }, + "mappings": [], + "max": 1, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 3, + "x": 17, + "y": 7 + }, + "id": 48, + "links": [], + "options": { + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": true + }, + "pluginVersion": "8.5.9", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "editorMode": "code", + "expr": "sum(sum by (node) (container_memory_working_set_bytes:without_kmem{container!=\"POD\",container!=\"\",node=~\"$node\"} )) / sum(sum by (node) (avg_over_time(kube_pod_container_resource_requests{resource=\"memory\",node=~\"$node\"}[$__rate_interval])))", + "hide": false, + "legendFormat": "__auto", + "range": true, + "refId": "B" + } + ], + "title": "% Used Requested Memory", + "transparent": true, + "type": "gauge" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "description": "Pods number in the cluster / Allocatable Pods.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "continuous-GrYlRd" + }, + "mappings": [], + "max": 1, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 3, + "x": 21, + "y": 7 + }, + "id": 40, + "links": [], + "options": { + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": true + }, + "pluginVersion": "8.5.9", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "editorMode": "code", + "expr": "sum(((max by (pod, namespace)(kube_pod_container_status_running))==1) * on (pod, namespace) group_right() (kube_pod_info{node=~\"$node\"}==1) \n) / sum(sum by (node) (avg_over_time(kube_node_status_allocatable{resource=\"pods\",node=~\"$node\"}[$__rate_interval])))", + "hide": false, + "legendFormat": "Total", + "range": true, + "refId": "B" + } + ], + "title": "% Pods Usage", + "transparent": true, + "type": "gauge" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 15 + }, + "id": 34, + "panels": [], + "title": "Allocatable / Requested / Unused", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "description": "This represents the total [CPU resource requests](https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/#meaning-of-cpu) in the cluster.\nFor comparison the total [allocatable CPU cores](https://github.com/kubernetes/community/blob/master/contributors/design-proposals/node-allocatable.md) is also shown.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 100, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "stepAfter", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Total" + }, + "properties": [ + { + "id": "custom.fillOpacity", + "value": 0 + }, + { + "id": "custom.stacking", + "value": { + "group": "A", + "mode": "none" + } + } + ] + } + ] + }, + "gridPos": { + "h": 11, + "w": 8, + "x": 0, + "y": 16 + }, + "id": 1, + "links": [], + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom" + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "8.5.9", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "editorMode": "code", + "expr": "sum by (node) (avg_over_time(kube_node_status_allocatable{resource=\"cpu\",unit=\"core\",node=~\"$node\"}[$__rate_interval]))", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "{{ node }}", + "range": true, + "refId": "A", + "step": 20 + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "editorMode": "code", + "expr": "sum(sum by (node) (avg_over_time(kube_node_status_allocatable{resource=\"cpu\",unit=\"core\",node=~\"$node\"}[$__rate_interval])))", + "hide": false, + "legendFormat": "Total", + "range": true, + "refId": "B" + } + ], + "title": "Allocatable CPU", + "transformations": [], + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 100, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "stepAfter", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Total" + }, + "properties": [ + { + "id": "custom.fillOpacity", + "value": 0 + }, + { + "id": "custom.stacking", + "value": { + "group": "A", + "mode": "none" + } + } + ] + } + ] + }, + "gridPos": { + "h": 11, + "w": 8, + "x": 8, + "y": 16 + }, + "id": 28, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom" + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "8.5.9", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "editorMode": "code", + "expr": "sum by (node) (avg_over_time(kube_node_status_allocatable{resource=\"cpu\",node=~\"$node\"}[$__rate_interval])) - on(node) (sum by (node) (avg_over_time(kube_pod_container_resource_requests{resource=\"cpu\",unit=\"core\",node=~\"$node\"}[$__rate_interval])* on (uid) group_left(phase) kube_pod_status_phase{phase=\"Running\"}))", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "{{ node }}", + "range": true, + "refId": "A", + "step": 20 + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "editorMode": "code", + "expr": "sum(sum by (node) (avg_over_time(kube_node_status_allocatable{resource=\"cpu\",node=~\"$node\"}[$__rate_interval])) - on(node) (sum by (node) (avg_over_time(kube_pod_container_resource_requests{resource=\"cpu\",unit=\"core\",node=~\"$node\"}[$__rate_interval])* on (uid) group_left(phase) kube_pod_status_phase{phase=\"Running\"})))", + "hide": false, + "legendFormat": "Total", + "range": true, + "refId": "B" + } + ], + "title": "Unrequested CPU", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "description": "Difference between requested cores and used cores.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 100, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "stepAfter", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Total" + }, + "properties": [ + { + "id": "custom.fillOpacity", + "value": 0 + }, + { + "id": "custom.stacking", + "value": { + "group": "A", + "mode": "none" + } + } + ] + } + ] + }, + "gridPos": { + "h": 11, + "w": 8, + "x": 16, + "y": 16 + }, + "id": 31, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom" + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "8.5.9", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "editorMode": "code", + "expr": "sum by (node) (rate(container_cpu_usage_seconds_total{container!=\"POD\",container!=\"\",node=~\"$node\"}[$__rate_interval]) - on (namespace,pod,container,node) group_left avg by (namespace,pod,container, node)(kube_pod_container_resource_requests{resource=\"cpu\",node=~\"$node\"})) * -1 > 0\n", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "{{ node }}", + "range": true, + "refId": "A", + "step": 20 + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "editorMode": "code", + "expr": "sum(sum by (node) (rate(container_cpu_usage_seconds_total{container!=\"POD\",container!=\"\",node=~\"$node\"}[$__rate_interval]) - on (namespace,pod,container,node) group_left avg by (namespace,pod,container, node)(kube_pod_container_resource_requests{resource=\"cpu\",node=~\"$node\"})) * -1 > 0)", + "hide": false, + "legendFormat": "Total", + "range": true, + "refId": "B" + } + ], + "title": "Unused Requested CPU (Idle)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "description": "This represents the total [memory resource requests](https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/#meaning-of-memory) in the cluster.\nFor comparison the total [allocatable memory](https://github.com/kubernetes/community/blob/master/contributors/design-proposals/node-allocatable.md) is also shown.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 100, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "stepAfter", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Total" + }, + "properties": [ + { + "id": "custom.stacking", + "value": { + "group": "A", + "mode": "none" + } + }, + { + "id": "custom.fillOpacity", + "value": 0 + } + ] + } + ] + }, + "gridPos": { + "h": 11, + "w": 8, + "x": 0, + "y": 27 + }, + "id": 23, + "links": [], + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom" + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "8.5.9", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "editorMode": "code", + "expr": "sum by (node) (avg_over_time(kube_node_status_allocatable{resource=\"memory\",unit=\"byte\",node=~\"$node\"}[$__rate_interval]))", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "{{ node }}", + "range": true, + "refId": "A", + "step": 20 + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "editorMode": "code", + "expr": "sum(sum by (node) (avg_over_time(kube_node_status_allocatable{resource=\"memory\",unit=\"byte\",node=~\"$node\"}[$__rate_interval])))", + "hide": false, + "legendFormat": "Total", + "range": true, + "refId": "B" + } + ], + "title": "Allocatable Memory", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 100, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "stepAfter", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Total" + }, + "properties": [ + { + "id": "custom.fillOpacity", + "value": 0 + }, + { + "id": "custom.stacking", + "value": { + "group": "A", + "mode": "none" + } + } + ] + } + ] + }, + "gridPos": { + "h": 11, + "w": 8, + "x": 8, + "y": 27 + }, + "id": 29, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom" + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "8.5.9", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "editorMode": "code", + "expr": "sum by (node) (avg_over_time(kube_node_status_allocatable{resource=\"memory\",node=~\"$node\"}[$__rate_interval])) - on(node) (sum by (node) (avg_over_time(kube_pod_container_resource_requests{resource=\"memory\",node=~\"$node\"}[$__rate_interval])* on (uid) group_left(phase) kube_pod_status_phase{phase=\"Running\"}))", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "{{ node }}", + "range": true, + "refId": "A", + "step": 20 + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "editorMode": "code", + "expr": "sum(sum by (node) (avg_over_time(kube_node_status_allocatable{resource=\"memory\",node=~\"$node\"}[$__rate_interval])) - on(node) (sum by (node) (avg_over_time(kube_pod_container_resource_requests{resource=\"memory\",node=~\"$node\"}[$__rate_interval])* on (uid) group_left(phase) kube_pod_status_phase{phase=\"Running\"})))", + "hide": false, + "legendFormat": "Total", + "range": true, + "refId": "B" + } + ], + "title": "Unrequested Memory", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "description": "Difference between requested memory and used memory.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 100, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "stepAfter", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "noValue": "0", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "decbytes" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Total" + }, + "properties": [ + { + "id": "custom.fillOpacity", + "value": 0 + }, + { + "id": "custom.stacking", + "value": { + "group": "A", + "mode": "none" + } + } + ] + } + ] + }, + "gridPos": { + "h": 11, + "w": 8, + "x": 16, + "y": 27 + }, + "id": 32, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom" + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "8.5.9", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "editorMode": "code", + "expr": "(sum by (node) (container_memory_working_set_bytes:without_kmem{container!=\"POD\",container!=\"\",node=~\"$node\"} ) - sum by (node) (kube_pod_container_resource_requests{resource=\"memory\",node=~\"$node\"})) * -1 > 0\n", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "{{ node }}", + "range": true, + "refId": "A", + "step": 20 + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "editorMode": "code", + "expr": "sum((sum by (node) (container_memory_working_set_bytes:without_kmem{container!=\"POD\",container!=\"\",node=~\"$node\"} ) - sum by (node) (kube_pod_container_resource_requests{resource=\"memory\",node=~\"$node\"})) * -1 > 0)", + "hide": false, + "legendFormat": "Total", + "range": true, + "refId": "B" + } + ], + "title": "Unused Requested Memory", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 100, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "stepAfter", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Total" + }, + "properties": [ + { + "id": "custom.fillOpacity", + "value": 0 + }, + { + "id": "custom.stacking", + "value": { + "group": "A", + "mode": "none" + } + } + ] + } + ] + }, + "gridPos": { + "h": 11, + "w": 13, + "x": 0, + "y": 38 + }, + "id": 26, + "links": [], + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom" + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "8.5.9", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "editorMode": "code", + "expr": "sum by (node) (avg_over_time(kube_node_status_allocatable{resource=\"pods\",node=~\"$node\"}[$__rate_interval]))", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "{{ node }}", + "range": true, + "refId": "A", + "step": 20 + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "editorMode": "code", + "expr": "sum(sum by (node) (avg_over_time(kube_node_status_allocatable{resource=\"pods\",node=~\"$node\"}[$__rate_interval])))", + "hide": false, + "legendFormat": "Total", + "range": true, + "refId": "B" + } + ], + "title": "Allocatable Pods", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 100, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "stepAfter", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Total" + }, + "properties": [ + { + "id": "custom.fillOpacity", + "value": 0 + }, + { + "id": "custom.stacking", + "value": { + "group": "A", + "mode": "none" + } + } + ] + } + ] + }, + "gridPos": { + "h": 11, + "w": 11, + "x": 13, + "y": 38 + }, + "id": 30, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom" + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "8.5.9", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "editorMode": "code", + "expr": "sum by (node) (avg_over_time(kube_node_status_allocatable{resource=\"pods\",node=~\"$node\"}[$__rate_interval])) - on(node) (count by (node) (\n ((max by (pod, namespace)(kube_pod_container_status_running))==1) * on (pod, namespace) group_right() (kube_pod_info{node=~\"$node\"}==1) \n))", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "{{ node }}", + "range": true, + "refId": "A", + "step": 20 + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "editorMode": "code", + "expr": "sum(sum by (node) (avg_over_time(kube_node_status_allocatable{resource=\"pods\",node=~\"$node\"}[$__rate_interval])) - on(node) (count by (node) (\n ((max by (pod, namespace)(kube_pod_container_status_running))==1) * on (pod, namespace) group_right() (kube_pod_info{node=~\"$node\"}==1) \n)))", + "hide": false, + "legendFormat": "Total", + "range": true, + "refId": "B" + } + ], + "title": "Available Pod slots", + "type": "timeseries" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 49 + }, + "id": 39, + "panels": [], + "title": "Top", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "displayMode": "auto", + "inspect": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "#EAB839", + "value": 0.5 + }, + { + "color": "dark-orange", + "value": 1 + }, + { + "color": "red", + "value": 1.5 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Value" + }, + "properties": [ + { + "id": "custom.displayMode", + "value": "color-background" + } + ] + } + ] + }, + "gridPos": { + "h": 12, + "w": 12, + "x": 0, + "y": 50 + }, + "id": 36, + "options": { + "footer": { + "fields": "", + "reducer": [ + "sum" + ], + "show": false + }, + "showHeader": true + }, + "pluginVersion": "8.5.9", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "editorMode": "code", + "exemplar": false, + "expr": "topk(10, (sum by (namespace,pod,container)((rate(container_cpu_usage_seconds_total{namespace=~\"$namespace\",container!=\"POD\",container!=\"\",node=~\"$node\"}[$__rate_interval])) - on (namespace,pod,container) group_left avg by (namespace,pod,container)(kube_pod_container_resource_requests{resource=\"cpu\",node=~\"$node\"}))) * -1 > 0)\n", + "format": "table", + "instant": true, + "range": false, + "refId": "A" + } + ], + "title": "Top 10 CPU overrequested containers", + "transformations": [ + { + "id": "filterFieldsByName", + "options": { + "include": { + "names": [ + "container", + "namespace", + "pod", + "Value" + ] + } + } + }, + { + "id": "organize", + "options": { + "excludeByName": {}, + "indexByName": { + "Value": 3, + "container": 2, + "namespace": 0, + "pod": 1 + }, + "renameByName": { + "Value": "Cores", + "container": "Container", + "namespace": "Namespace", + "pod": "Pod" + } + } + } + ], + "transparent": true, + "type": "table" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "displayMode": "auto", + "inspect": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "yellow", + "value": 500000000 + }, + { + "color": "#EAB839", + "value": 1000000000 + }, + { + "color": "red", + "value": 2000000000 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Value" + }, + "properties": [ + { + "id": "custom.displayMode", + "value": "color-background" + }, + { + "id": "unit", + "value": "bytes" + } + ] + } + ] + }, + "gridPos": { + "h": 12, + "w": 12, + "x": 12, + "y": 50 + }, + "id": 37, + "options": { + "footer": { + "fields": "", + "reducer": [ + "sum" + ], + "show": false + }, + "showHeader": true, + "sortBy": [] + }, + "pluginVersion": "8.5.9", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "editorMode": "code", + "exemplar": false, + "expr": "topk(10, (sum by (namespace,container,pod) (container_memory_working_set_bytes:without_kmem{container!=\"POD\",container!=\"\",namespace=~\"$namespace\",node=~\"$node\"}) - on (namespace,pod,container) avg by (namespace,pod,container)(kube_pod_container_resource_requests{resource=\"memory\",namespace=~\"$namespace\",node=~\"$node\"})) * -1 >0)\n", + "format": "table", + "instant": true, + "range": false, + "refId": "A" + } + ], + "title": "Top 10 Memory overrequested containers", + "transformations": [ + { + "id": "filterFieldsByName", + "options": { + "include": { + "names": [ + "container", + "namespace", + "pod", + "Value" + ] + } + } + }, + { + "id": "organize", + "options": { + "excludeByName": {}, + "indexByName": { + "Value": 3, + "container": 2, + "namespace": 0, + "pod": 1 + }, + "renameByName": { + "Value": "Bytes", + "container": "Container", + "namespace": "Namespace", + "pod": "Pod" + } + } + } + ], + "transparent": true, + "type": "table" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "displayMode": "auto", + "inspect": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "#EAB839", + "value": 0.5 + }, + { + "color": "dark-orange", + "value": 1 + }, + { + "color": "red", + "value": 1.5 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Value" + }, + "properties": [ + { + "id": "custom.displayMode", + "value": "color-background" + } + ] + } + ] + }, + "gridPos": { + "h": 12, + "w": 12, + "x": 0, + "y": 62 + }, + "id": 49, + "options": { + "footer": { + "fields": "", + "reducer": [ + "sum" + ], + "show": false + }, + "showHeader": true + }, + "pluginVersion": "8.5.9", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "editorMode": "code", + "exemplar": false, + "expr": "topk(10, (sum by (namespace,pod,container)((rate(container_cpu_usage_seconds_total{namespace=~\"$namespace\",container!=\"POD\",container!=\"\",node=~\"$node\"}[$__rate_interval])) - on (namespace,pod,container) group_left avg by (namespace,pod,container)(kube_pod_container_resource_requests{resource=\"cpu\",node=~\"$node\"}))) > 0)\n", + "format": "table", + "instant": true, + "range": false, + "refId": "A" + } + ], + "title": "Top 10 CPU underrequested containers", + "transformations": [ + { + "id": "filterFieldsByName", + "options": { + "include": { + "names": [ + "container", + "namespace", + "pod", + "Value" + ] + } + } + }, + { + "id": "organize", + "options": { + "excludeByName": {}, + "indexByName": { + "Value": 3, + "container": 2, + "namespace": 0, + "pod": 1 + }, + "renameByName": { + "Value": "Cores", + "container": "Container", + "namespace": "Namespace", + "pod": "Pod" + } + } + } + ], + "transparent": true, + "type": "table" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "displayMode": "auto", + "inspect": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "yellow", + "value": 500000000 + }, + { + "color": "#EAB839", + "value": 1000000000 + }, + { + "color": "red", + "value": 2000000000 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Value" + }, + "properties": [ + { + "id": "custom.displayMode", + "value": "color-background" + }, + { + "id": "unit", + "value": "bytes" + } + ] + } + ] + }, + "gridPos": { + "h": 12, + "w": 12, + "x": 12, + "y": 62 + }, + "id": 50, + "options": { + "footer": { + "fields": "", + "reducer": [ + "sum" + ], + "show": false + }, + "showHeader": true, + "sortBy": [] + }, + "pluginVersion": "8.5.9", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "editorMode": "code", + "exemplar": false, + "expr": "topk(10, (sum by (namespace,container,pod) (container_memory_working_set_bytes:without_kmem{container!=\"POD\",container!=\"\",namespace=~\"$namespace\",node=~\"$node\"}) - on (namespace,pod,container) avg by (namespace,pod,container)(kube_pod_container_resource_requests{resource=\"memory\",namespace=~\"$namespace\",node=~\"$node\"})) >0)\n", + "format": "table", + "instant": true, + "range": false, + "refId": "A" + } + ], + "title": "Top 10 Memory underrequested containers", + "transformations": [ + { + "id": "filterFieldsByName", + "options": { + "include": { + "names": [ + "container", + "namespace", + "pod", + "Value" + ] + } + } + }, + { + "id": "organize", + "options": { + "excludeByName": {}, + "indexByName": { + "Value": 3, + "container": 2, + "namespace": 0, + "pod": 1 + }, + "renameByName": { + "Value": "Bytes", + "container": "Container", + "namespace": "Namespace", + "pod": "Pod" + } + } + } + ], + "transparent": true, + "type": "table" + } + ], + "refresh": "30s", + "schemaVersion": 36, + "style": "dark", + "tags": [], + "templating": { + "list": [ + { + "current": { + "selected": false, + "text": "default", + "value": "default" + }, + "hide": 0, + "includeAll": false, + "label": "Prometheus", + "multi": false, + "name": "ds_prometheus", + "options": [], + "query": "prometheus", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + }, + { + "allValue": "", + "current": { + "selected": true, + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "definition": "label_values(up{job=\"node-exporter\"}, node)", + "hide": 0, + "includeAll": true, + "label": "Nodes", + "multi": true, + "name": "node", + "options": [], + "query": { + "query": "label_values(up{job=\"node-exporter\"}, node)", + "refId": "main-node-Variable-Query" + }, + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": "", + "current": { + "selected": true, + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "definition": "label_values(kube_pod_info{node=~\"$node\"}, namespace)", + "hide": 0, + "includeAll": true, + "label": "Namespace", + "multi": true, + "name": "namespace", + "options": [], + "query": { + "query": "label_values(kube_pod_info{node=~\"$node\"}, namespace)", + "refId": "StandardVariableQuery" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "filters": [], + "hide": 0, + "name": "Filters", + "skipUrlSync": false, + "type": "adhoc" + } + ] + }, + "time": { + "from": "now-3h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "browser", + "title": "Capacity Planning", + "uid": "Tf3tuvziz1fds", + "version": 1, + "weekStart": "" +} diff --git a/dashboards/main/controller.json b/dashboards/main/controller.json new file mode 100644 index 00000000..8972c204 --- /dev/null +++ b/dashboards/main/controller.json @@ -0,0 +1,4353 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": "-- Grafana --", + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "target": { + "limit": 100, + "matchAny": false, + "tags": [], + "type": "dashboard" + }, + "type": "dashboard" + } + ] + }, + "editable": false, + "fiscalYearStartMonth": 0, + "gnetId": null, + "graphTooltip": 1, + "id": 23, + "iteration": 1640791408237, + "links": [], + "liveNow": false, + "panels": [ + { + "datasource": null, + "description": "Note that this table shows the average values for the entire period selected in the dashboard. Consequently, it may contain information about Pods or namespaces that were changed or deleted during the selected period.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": null, + "displayMode": "auto", + "filterable": false, + "minWidth": 70 + }, + "decimals": 2, + "displayName": "", + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "pod" + }, + "properties": [ + { + "id": "displayName", + "value": "Pod Name" + }, + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "links", + "value": [ + { + "targetBlank": true, + "title": "Pod Details", + "url": "/d/m41rB4yiz1/pod?var-ds_prometheus=${ds_prometheus}&var-namespace=${namespace}&var-pod=${__value.raw}&${__url_time_range}" + } + ] + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 250 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #A" + }, + "properties": [ + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.width" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "node" + }, + "properties": [ + { + "id": "displayName", + "value": "Node" + }, + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #C" + }, + "properties": [ + { + "id": "displayName", + "value": "VPA Type" + }, + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "mappings", + "value": [ + { + "options": { + "0": { + "text": "Off" + }, + "1": { + "text": "Initial" + }, + "2": { + "text": "Auto" + }, + "3": { + "text": "Recreate" + }, + "5": { + "text": "-" + } + }, + "type": "value" + } + ] + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #D" + }, + "properties": [ + { + "id": "displayName", + "value": "CPU" + }, + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 3 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #E" + }, + "properties": [ + { + "id": "displayName", + "value": "Req CPU" + }, + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #F" + }, + "properties": [ + { + "id": "displayName", + "value": "VPA CPU" + }, + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 3 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #G" + }, + "properties": [ + { + "id": "displayName", + "value": "Over-req CPU" + }, + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #H" + }, + "properties": [ + { + "id": "displayName", + "value": "Under-req CPU" + }, + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #I" + }, + "properties": [ + { + "id": "displayName", + "value": "Throttling cores" + }, + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #J" + }, + "properties": [ + { + "id": "displayName", + "value": "Memory" + }, + { + "id": "unit", + "value": "bytes" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #K" + }, + "properties": [ + { + "id": "displayName", + "value": "Req Memory" + }, + { + "id": "unit", + "value": "bytes" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #L" + }, + "properties": [ + { + "id": "displayName", + "value": "VPA Memory" + }, + { + "id": "unit", + "value": "bytes" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #M" + }, + "properties": [ + { + "id": "displayName", + "value": "Over-req Memory" + }, + { + "id": "unit", + "value": "bytes" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #N" + }, + "properties": [ + { + "id": "displayName", + "value": "Under-req Memory" + }, + { + "id": "unit", + "value": "bytes" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #O" + }, + "properties": [ + { + "id": "displayName", + "value": "RX Network" + }, + { + "id": "unit", + "value": "Bps" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "mappings", + "value": [ + { + "type": "value", + "options": { + "-1": { + "text": "hostNet", + "index": 0 + } + } + } + ] + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #P" + }, + "properties": [ + { + "id": "displayName", + "value": "TX Network" + }, + { + "id": "unit", + "value": "Bps" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "mappings", + "value": [ + { + "type": "value", + "options": { + "-1": { + "text": "hostNet", + "index": 0 + } + } + } + ] + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #Q" + }, + "properties": [ + { + "id": "displayName", + "value": "Read IOPS" + }, + { + "id": "unit", + "value": "iops" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #R" + }, + "properties": [ + { + "id": "displayName", + "value": "Write IOPS" + }, + { + "id": "unit", + "value": "iops" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #S" + }, + "properties": [ + { + "id": "displayName", + "value": "Pod Restarts" + }, + { + "id": "unit", + "value": "short" + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Pod Name" + }, + "properties": [ + { + "id": "custom.width", + "value": 225 + } + ] + } + ] + }, + "gridPos": { + "h": 7, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 2, + "links": [], + "options": { + "showHeader": true, + "sortBy": [] + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "sum by (pod) (avg_over_time(kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\", pod=~\"$pod\"}[$__range]) )", + "format": "table", + "hide": false, + "instant": true, + "interval": "", + "intervalFactor": 1, + "legendFormat": "Pod Name", + "refId": "A" + }, + { + "expr": "sum by (pod, node) (\n sum by (pod, node) (avg_over_time(kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\", pod=~\"$pod\"}[$__range])) * on (pod, node) group_right() avg_over_time(kube_pod_info{node=~\"$node\", namespace=\"$namespace\", pod=~\"$pod\"}[$__range])\n)", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "legendFormat": "Node", + "refId": "B" + }, + { + "expr": "sum by (pod) (avg_over_time(kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\", pod=~\"$pod\"}[$__range]) * on (controller_type, controller_name) group_left() sum by (controller_type, controller_name) (avg_over_time(vpa_target_recommendation{namespace=\"$namespace\", update_mode=\"Off\"}[$__range]))) * 0\nor\nsum by (pod) (avg_over_time(kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\", pod=~\"$pod\"}[$__range]) * on (controller_type, controller_name) group_left() sum by (controller_type, controller_name) (avg_over_time(vpa_target_recommendation{namespace=\"$namespace\", update_mode=\"Initial\"}[$__range]))) * 0 + 1\nor\nsum by (pod) (avg_over_time(kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\", pod=~\"$pod\"}[$__range]) * on (controller_type, controller_name) group_left() sum by (controller_type, controller_name) (avg_over_time(vpa_target_recommendation{namespace=\"$namespace\", update_mode=\"Auto\"}[$__range]))) * 0 + 2\nor\nsum by (pod) (avg_over_time(kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\", pod=~\"$pod\"}[$__range]) * on (controller_type, controller_name) group_left() sum by (controller_type, controller_name) (avg_over_time(vpa_target_recommendation{namespace=\"$namespace\", update_mode=\"Recreate\"}[$__range]))) * 0 + 3\nor\nsum by (pod) (avg_over_time(kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\", pod=~\"$pod\"}[$__range])) * 0 + 5", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "legendFormat": "VPA Type", + "refId": "C" + }, + { + "expr": "(\n sum by (pod) (avg_over_time(kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\", pod=~\"$pod\"}[$__range])) \n * on (pod)\n sum by (pod) (rate(container_cpu_usage_seconds_total{node=~\"$node\", container!=\"POD\", namespace=\"$namespace\", pod=~\"$pod\"}[$__range]))\n)\nor\nsum by (pod) (avg_over_time(kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\", pod=~\"$pod\"}[$__range]) * 0)", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "legendFormat": "CPU", + "refId": "D" + }, + { + "expr": "(\n sum by (pod) (avg_over_time(kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\", pod=~\"$pod\"}[$__range])) \n * on (pod)\n sum by (pod) (avg_over_time(kube_pod_container_resource_requests{resource=\"cpu\",unit=\"core\",node=~\"$node\", namespace=\"$namespace\", pod=~\"$pod\"}[$__range]))\n)\nor\nsum by (pod) (avg_over_time(kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\", pod=~\"$pod\"}[$__range]) * 0)", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "legendFormat": "Req CPU", + "refId": "E" + }, + { + "expr": "sum by (pod)\n(\n avg_over_time(kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\", pod=~\"$pod\"}[$__range])\n * on (controller_type, controller_name) group_left()\n sum by (controller_type, controller_name) (avg_over_time(vpa_target_recommendation{container!=\"POD\", namespace=\"$namespace\", resource=\"cpu\"}[$__range]))\n)\nor\nsum by (pod) (avg_over_time(kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\", pod=~\"$pod\"}[$__range]) * 0)", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "legendFormat": "VPA CPU", + "refId": "F" + }, + { + "expr": "(\n sum by (pod) (avg_over_time(kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\", pod=~\"$pod\"}[$__range])) \n * on (pod)\n sum by (pod)\n (\n sum by (namespace, pod) (avg_over_time(kube_pod_container_resource_requests{resource=\"cpu\",unit=\"core\",node=~\"$node\", namespace=\"$namespace\", pod=~\"$pod\"}[$__range]))\n -\n sum by (namespace, pod) (rate(container_cpu_usage_seconds_total{node=~\"$node\", namespace=\"$namespace\", pod=~\"$pod\", container!=\"POD\"}[$__range]))\n ) > 0\n)\nor\nsum by (pod) (avg_over_time(kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\", pod=~\"$pod\"}[$__range]) * 0)", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "legendFormat": "Over-req CPU", + "refId": "G" + }, + { + "expr": "(\n sum by (pod) (avg_over_time(kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\", pod=~\"$pod\"}[$__range])) \n * on (pod)\n sum by (pod) \n (\n (\n (\n sum by (namespace, pod) (rate(container_cpu_usage_seconds_total{node=~\"$node\", namespace=\"$namespace\", pod=~\"$pod\"}[$__range]))\n -\n sum by (namespace, pod) (avg_over_time(kube_pod_container_resource_requests{resource=\"cpu\",unit=\"core\",node=~\"$node\", namespace=\"$namespace\", pod=~\"$pod\", container!=\"POD\"}[$__range]))\n ) or sum by (namespace, pod) (rate(container_cpu_usage_seconds_total{node=~\"$node\", namespace=\"$namespace\", pod=~\"$pod\", container!=\"POD\"}[$__range]))\n ) > 0\n )\n)\nor\nsum by (pod) (avg_over_time(kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\", pod=~\"$pod\"}[$__range]) * 0)", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "legendFormat": "Under-req CPU", + "refId": "H" + }, + { + "expr": "(\n sum by (pod) (avg_over_time(kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\", pod=~\"$pod\"}[$__range])) \n * on (pod)\n sum by (pod) (\n sum by (pod) (rate(container_cpu_cfs_throttled_periods_total{node=~\"$node\", namespace=\"$namespace\", pod=~\"$pod\"}[$__range]))\n /\n sum by (pod) (rate(container_cpu_cfs_periods_total{node=~\"$node\", namespace=\"$namespace\", pod=~\"$pod\"}[$__range]))\n * on (pod)\n sum by (pod) (avg_over_time(kube_pod_container_resource_limits{resource=\"cpu\",unit=\"core\",node=~\"$node\", namespace=\"$namespace\", pod=~\"$pod\"}[$__range]))\n )\n)\nor\nsum by (pod) (avg_over_time(kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\", pod=~\"$pod\"}[$__range]) * 0)", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "legendFormat": "Throttling cores", + "refId": "I" + }, + { + "expr": "(\n sum by (pod) (avg_over_time(kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\", pod=~\"$pod\"}[$__range])) \n * on (pod)\n sum by (pod) (avg_over_time(container_memory_working_set_bytes:without_kmem{node=~\"$node\", container!=\"POD\", namespace=\"$namespace\", pod=~\"$pod\"}[$__range]))\n)\nor\nsum by (pod) (avg_over_time(kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\", pod=~\"$pod\"}[$__range]) * 0)", + "format": "table", + "instant": true, + "intervalFactor": 1, + "legendFormat": "Memory", + "refId": "J" + }, + { + "expr": "(\n sum by (pod) (avg_over_time(kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\", pod=~\"$pod\"}[$__range])) \n * on (pod)\n sum by (pod) (avg_over_time(kube_pod_container_resource_requests{resource=\"memory\",unit=\"byte\",node=~\"$node\", namespace=\"$namespace\", pod=~\"$pod\"}[$__range]))\n)\nor\nsum by (pod) (avg_over_time(kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\", pod=~\"$pod\"}[$__range]) * 0)", + "format": "table", + "instant": true, + "intervalFactor": 1, + "legendFormat": "Req Memory", + "refId": "K" + }, + { + "expr": "sum by (pod)\n(\n avg_over_time(kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\", pod=~\"$pod\"}[$__range])\n * on (controller_type, controller_name) group_left()\n sum by (controller_type, controller_name) (avg_over_time(vpa_target_recommendation{container!=\"POD\", namespace=\"$namespace\", resource=\"memory\"}[$__range]))\n)\nor\nsum by (pod) (avg_over_time(kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\", pod=~\"$pod\"}[$__range]) * 0)", + "format": "table", + "instant": true, + "intervalFactor": 1, + "legendFormat": "VPA Memory", + "refId": "L" + }, + { + "expr": "(\n sum by (pod) (avg_over_time(kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\", pod=~\"$pod\"}[$__range])) \n * on (pod)\n sum by (pod)\n (\n (\n (\n sum by (namespace, pod) (avg_over_time(kube_pod_container_resource_requests{resource=\"memory\",unit=\"byte\",node=~\"$node\", namespace=\"$namespace\", pod=~\"$pod\"}[$__range]))\n -\n sum by (namespace, pod) (avg_over_time(container_memory_working_set_bytes:without_kmem{node=~\"$node\", namespace=\"$namespace\", pod=~\"$pod\", container!=\"POD\"}[$__range]))\n ) > 0\n )\n )\n)\nor\nsum by (pod) (avg_over_time(kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\", pod=~\"$pod\"}[$__range]) * 0)", + "format": "table", + "instant": true, + "intervalFactor": 1, + "legendFormat": "Over-req Memory", + "refId": "M" + }, + { + "expr": "(\n sum by (pod) (avg_over_time(kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\", pod=~\"$pod\"}[$__range])) \n * on (pod)\n sum by (pod)\n (\n (\n (\n sum by (namespace, pod) (avg_over_time(container_memory_working_set_bytes:without_kmem{node=~\"$node\", namespace=\"$namespace\", pod=~\"$pod\"}[$__range]))\n -\n sum by (namespace, pod) (avg_over_time(kube_pod_container_resource_requests{resource=\"memory\",unit=\"byte\",node=~\"$node\", namespace=\"$namespace\", pod=~\"$pod\", container!=\"POD\"}[$__range]))\n ) or sum by (namespace, pod) (avg_over_time(container_memory_working_set_bytes:without_kmem{node=~\"$node\", namespace=\"$namespace\", pod=~\"$pod\", container!=\"POD\"}[$__range]))\n ) > 0\n )\n)\nor\nsum by (pod) (avg_over_time(kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\", pod=~\"$pod\"}[$__range]) * 0)", + "format": "table", + "instant": true, + "intervalFactor": 1, + "legendFormat": "Under-req Memory", + "refId": "N" + }, + { + "expr": "(\n # Select data rates if Pod had 'hostNetwork: false' during the selected period.\n max_over_time(kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\", pod=~\"$pod\"}[$__range])\n * on(pod)\n max_over_time(kube_pod_info{host_network=\"false\",namespace=\"$namespace\", pod=~\"$pod\"}[$__range])\n * on(pod)\n # Sum data rates for all interfaces of the Pod.\n sum by (pod) (rate(container_network_receive_bytes_total{node=~\"$node\", namespace=\"$namespace\", pod=~\"$pod\"}[$__range]))\n) or (\n # Return -1 if the Pod had 'hostNetwork: false' during the selected period.\n max_over_time(kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\", pod=~\"$pod\"}[$__range])\n * on(pod)\n max_over_time(kube_pod_info{host_network=\"true\",namespace=\"$namespace\", pod=~\"$pod\"}[$__range])\n * -1\n)", + "format": "table", + "instant": true, + "intervalFactor": 1, + "legendFormat": "RX Network", + "refId": "O" + }, + { + "expr": "(\n # Select data rates if Pod had 'hostNetwork: false' during the selected period.\n max_over_time(kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\", pod=~\"$pod\"}[$__range])\n * on(pod)\n max_over_time(kube_pod_info{host_network=\"false\",namespace=\"$namespace\", pod=~\"$pod\"}[$__range])\n * on(pod)\n # Sum data rates for all interfaces of the Pod.\n sum by (pod) (rate(container_network_transmit_bytes_total{node=~\"$node\", namespace=\"$namespace\", pod=~\"$pod\"}[$__range]))\n) or (\n # Return -1 if the Pod had 'hostNetwork: false' during the selected period.\n max_over_time(kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\", pod=~\"$pod\"}[$__range])\n * on(pod)\n max_over_time(kube_pod_info{host_network=\"true\",namespace=\"$namespace\", pod=~\"$pod\"}[$__range])\n * -1\n)", + "format": "table", + "instant": true, + "intervalFactor": 1, + "legendFormat": "TX Network", + "refId": "P" + }, + { + "expr": "(\n sum by (pod) (avg_over_time(kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\", pod=~\"$pod\"}[$__range])) \n * on (pod)\n sum by (pod) (rate(container_fs_reads_total{node=~\"$node\", container!=\"POD\", namespace=\"$namespace\", pod=~\"$pod\"}[$__range]))\n)\nor\nsum by (pod) (avg_over_time(kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\", pod=~\"$pod\"}[$__range]) * 0)", + "format": "table", + "instant": true, + "intervalFactor": 1, + "legendFormat": "Read IOPS", + "refId": "Q" + }, + { + "expr": "(\n sum by (pod) (avg_over_time(kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\", pod=~\"$pod\"}[$__range])) \n * on (pod)\n sum by (pod) (rate(container_fs_writes_total{node=~\"$node\", container!=\"POD\", namespace=\"$namespace\", pod=~\"$pod\"}[$__range]))\n)\nor\nsum by (pod) (avg_over_time(kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\", pod=~\"$pod\"}[$__range]) * 0)", + "format": "table", + "instant": true, + "intervalFactor": 1, + "legendFormat": "Write IOPS", + "refId": "R" + }, + { + "expr": "(\n sum by (pod) (avg_over_time(kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\", pod=~\"$pod\"}[$__range])) \n * on (pod)\n sum by (pod) (increase(kube_pod_container_status_restarts_total{namespace=\"$namespace\", pod=~\"$pod\"}[$__range]))\n)\nor\nsum by (pod) (avg_over_time(kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\", pod=~\"$pod\"}[$__range]) * 0)", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "legendFormat": "Pod restart count", + "refId": "S" + } + ], + "title": "Pods", + "transformations": [ + { + "id": "merge", + "options": { + "reducers": [] + } + }, + { + "id": "filterFieldsByName", + "options": { + "include": { + "names": [ + "pod", + "node", + "Value #C", + "Value #D", + "Value #E", + "Value #F", + "Value #G", + "Value #H", + "Value #I", + "Value #J", + "Value #K", + "Value #L", + "Value #M", + "Value #N", + "Value #O", + "Value #P", + "Value #Q", + "Value #R", + "Value #S" + ] + } + } + }, + { + "id": "sortBy", + "options": { + "fields": {}, + "sort": [ + { + "field": "pod" + } + ] + } + } + ], + "type": "table" + }, + { + "cards": { + "cardHSpacing": 2, + "cardMinWidth": 5, + "cardRound": null, + "cardVSpacing": 2 + }, + "color": { + "cardColor": "#b4ff00", + "colorScale": "sqrt", + "colorScheme": "interpolateGnYlRd", + "defaultColor": "#757575", + "exponent": 0.5, + "mode": "discrete", + "thresholds": [ + { + "color": "#99440a", + "tooltip": "Some container is not running", + "value": "5" + }, + { + "color": "#e5ac0e", + "tooltip": "Pending", + "value": "1" + }, + { + "color": "rgb(215, 215, 215)", + "tooltip": "Unknown", + "value": "2" + }, + { + "color": "#bf1b00", + "tooltip": "Failed", + "value": "3" + }, + { + "color": "#e0f9d7", + "tooltip": "Succeeded", + "value": "4" + }, + { + "color": "#508642", + "tooltip": "Running", + "value": "0" + } + ] + }, + "datasource": "$ds_prometheus", + "gridPos": { + "h": 8, + "w": 24, + "x": 0, + "y": 7 + }, + "highlightCards": true, + "id": 53, + "legend": { + "show": true + }, + "links": [], + "nullPointMode": "as empty", + "pageSize": 15, + "seriesFilterIndex": -1, + "statusmap": { + "ConfigVersion": "v1" + }, + "targets": [ + { + "expr": "(\n min by (pod) (\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\"}\n * on (pod) group_right()\n min_over_time(kube_pod_status_phase{namespace=\"$namespace\", pod=~\"$pod\", phase=\"Running\"}[$__rate_interval])\n ) == 1\n) * 0", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "{{ pod }}", + "refId": "A" + }, + { + "expr": "(\n min by (pod, phase) (\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\"}\n * on (pod) group_right()\n min_over_time(kube_pod_status_phase{namespace=\"$namespace\", pod=~\"$pod\", phase=\"Pending\"}[$__rate_interval])\n ) == 1\n) * 1", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "{{ pod }}", + "refId": "B" + }, + { + "expr": "(\n min by (pod, phase) (\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\"}\n * on (pod) group_right()\n min_over_time(kube_pod_status_phase{namespace=\"$namespace\", pod=~\"$pod\", phase=\"Unknown\"}[$__rate_interval])\n ) == 1\n) * 2", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "{{ pod }}", + "refId": "C" + }, + { + "expr": "(\n min by (pod, phase) (\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\"}\n * on (pod) group_right()\n min_over_time(kube_pod_status_phase{namespace=\"$namespace\", pod=~\"$pod\", phase=\"Failed\"}[$__rate_interval])\n ) == 1\n) * 3", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "{{ pod }}", + "refId": "D" + }, + { + "expr": "(\n min by (pod, phase) (\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\"}\n * on (pod) group_right()\n min_over_time(kube_pod_status_phase{namespace=\"$namespace\", pod=~\"$pod\", phase=\"Succeeded\"}[$__rate_interval])\n ) == 1\n) * 4", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "{{ pod }}", + "refId": "E" + }, + { + "expr": "(\n min by (pod) (\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\"}\n * on (pod) group_right()\n min by (pod) (min_over_time(kube_pod_container_status_ready{namespace=\"$namespace\", pod=~\"$pod\"}[$__rate_interval]))\n ) == 0\n) + 5", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "{{ pod }}", + "refId": "F" + } + ], + "title": "Status", + "tooltip": { + "extraInfo": "", + "freezeOnClick": true, + "items": [], + "show": true, + "showExtraInfo": false, + "showItems": false + }, + "type": "flant-statusmap-panel", + "useMax": true, + "usingPagination": false, + "xAxis": { + "show": true + }, + "yAxis": { + "maxWidth": -1, + "minWidth": -1, + "show": true + }, + "yAxisSort": "metrics", + "yLabel": { + "delimiter": "", + "labelTemplate": "", + "usingSplitLabel": false + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 0, + "description": "The number of Pod restarts", + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 3, + "w": 24, + "x": 0, + "y": 15 + }, + "hiddenSeries": false, + "id": 107, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "(\n sum by (pod) (avg_over_time(kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\", pod=~\"$pod\"}[$__rate_interval])) \n * on (pod)\n sum by (pod) (increase(kube_pod_container_status_restarts_total{namespace=\"$namespace\", pod=~\"$pod\"}[$__rate_interval]))\n) > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{ pod }}", + "refId": "A" + }, + { + "expr": "sum (\n sum by (pod) (avg_over_time(kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\", pod=~\"$pod\"}[$__rate_interval])) \n * on (pod)\n sum by (pod) (increase(kube_pod_container_status_restarts_total{namespace=\"$namespace\", pod=~\"$pod\"}[$__rate_interval]))\n)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Pods restarts", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 0, + "format": "short", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "collapsed": false, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 18 + }, + "id": 4, + "panels": [], + "title": "CPU", + "type": "row" + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 19 + }, + "hiddenSeries": false, + "id": 6, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": true, + "targets": [ + { + "expr": "sum by(pod) (\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\", pod=~\"$pod\"}\n * on (pod)\n sum by (pod) (rate(container_cpu_usage_seconds_total{node=~\"$node\", container!=\"POD\", pod=~\"$pod\", namespace=\"$namespace\"}[$__rate_interval]))\n)", + "format": "time_series", + "instant": false, + "intervalFactor": 1, + "legendFormat": "{{ pod }}", + "refId": "A" + }, + { + "expr": "sum (\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\", pod=~\"$pod\"}\n * on (pod)\n sum by (pod) (rate(container_cpu_usage_seconds_total{node=~\"$node\", container!=\"POD\", pod=~\"$pod\", namespace=\"$namespace\"}[$__rate_interval]))\n)", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Usage by pod", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "cores", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "description": "The total value may not equal the sum of system and user times because of the kernel's cgroup accounting peculiarities. Read more here: https://www.kernel.org/doc/Documentation/cgroup-v1/cpuacct.txt", + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 19 + }, + "hiddenSeries": false, + "id": 7, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + }, + { + "alias": "System", + "color": "#e24d42" + }, + { + "alias": "User", + "color": "#1f78c1" + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": true, + "targets": [ + { + "expr": "sum (\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\", pod=~\"$pod\"}\n * on (pod)\n sum by (pod) (rate(container_cpu_system_seconds_total{node=~\"$node\", container!=\"POD\", pod=~\"$pod\", namespace=\"$namespace\"}[$__rate_interval]))\n)", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "System", + "refId": "A" + }, + { + "expr": "sum (\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\", pod=~\"$pod\"}\n * on (pod)\n sum by (pod) (rate(container_cpu_user_seconds_total{node=~\"$node\", container!=\"POD\", pod=~\"$pod\", namespace=\"$namespace\"}[$__rate_interval]))\n)", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "User", + "refId": "B" + }, + { + "expr": "sum (\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\", pod=~\"$pod\"}\n * on (pod)\n sum by (pod) (rate(container_cpu_usage_seconds_total{node=~\"$node\", container!=\"POD\", pod=~\"$pod\", namespace=\"$namespace\"}[$__rate_interval]))\n)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "D" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Usage by state", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "cores", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "description": "This graph shows the requested CPU resources higher than the actual CPU consumption. In other words, it shows CPU resources that can be \"freed\" without affecting the service.", + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 28 + }, + "hiddenSeries": false, + "id": 59, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": true, + "targets": [ + { + "expr": "sum by (pod)\n (\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\", pod=~\"$pod\"}\n * on (pod)\n sum by (pod) (\n sum by(namespace, pod, container) (avg_over_time(kube_pod_container_resource_requests{resource=\"cpu\",unit=\"core\",node=~\"$node\", namespace=\"$namespace\", pod=~\"$pod\"}[$__rate_interval]))\n -\n sum by(namespace, pod, container) (rate(container_cpu_usage_seconds_total{node=~\"$node\", container!=\"POD\", namespace=\"$namespace\", pod=~\"$pod\"}[$__rate_interval]))\n ) > 0\n )", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{ pod }}", + "refId": "A" + }, + { + "expr": "sum\n (\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\", pod=~\"$pod\"}\n * on (pod)\n sum by (pod) (\n sum by(namespace, pod, container) (avg_over_time(kube_pod_container_resource_requests{resource=\"cpu\",unit=\"core\",node=~\"$node\", namespace=\"$namespace\", pod=~\"$pod\"}[$__rate_interval]))\n -\n sum by(namespace, pod, container) (rate(container_cpu_usage_seconds_total{node=~\"$node\", namespace=\"$namespace\", pod=~\"$pod\", container!=\"POD\"}[$__rate_interval]))\n ) > 0\n )", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Over-requested by pod", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "cores", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "description": "This graph shows the requested CPU resources lower than the actual CPU consumption. In other words, it shows CPU resources that need to be \"reserved\" for the service to run smoothly.", + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 28 + }, + "hiddenSeries": false, + "id": 64, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": true, + "targets": [ + { + "expr": " (\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\", pod=~\"$pod\"}\n * on (pod)\n sum by (pod) (\n (\n sum by(namespace, pod, container) (rate(container_cpu_usage_seconds_total{node=~\"$node\", namespace=\"$namespace\", pod=~\"$pod\"}[$__rate_interval]))\n -\n sum by(namespace, pod, container) (avg_over_time(kube_pod_container_resource_requests{resource=\"cpu\",unit=\"core\",node=~\"$node\", namespace=\"$namespace\", pod=~\"$pod\", container!=\"POD\"}[$__rate_interval]))\n )\n or\n sum by(namespace, pod, container) (rate(container_cpu_usage_seconds_total{node=~\"$node\", namespace=\"$namespace\", pod=~\"$pod\"}[$__rate_interval]))\n )\n) > 0", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "{{ pod }}", + "refId": "A" + }, + { + "expr": "sum (\n (\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\", pod=~\"$pod\"}\n * on (pod)\n sum by (pod) (\n (\n sum by(namespace, pod, container) (rate(container_cpu_usage_seconds_total{node=~\"$node\", namespace=\"$namespace\", pod=~\"$pod\"}[$__rate_interval]))\n -\n sum by(namespace, pod, container) (avg_over_time(kube_pod_container_resource_requests{resource=\"cpu\",unit=\"core\",node=~\"$node\", namespace=\"$namespace\", pod=~\"$pod\", container!=\"POD\"}[$__rate_interval]))\n )\n or\n sum by(namespace, pod, container) (rate(container_cpu_usage_seconds_total{node=~\"$node\", namespace=\"$namespace\", pod=~\"$pod\"}[$__rate_interval]))\n )\n ) > 0\n )", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Under-requested by pod", + "tooltip": { + "shared": true, + "sort": 1, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "cores", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "description": "The absence of data on the graph means that container resources are not set", + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 24, + "x": 0, + "y": 36 + }, + "hiddenSeries": false, + "id": 31, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": true, + "min": false, + "rightSide": true, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "(\n sum by (pod) (\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\", pod=~\"$pod\"}\n * on (pod)\n sum by (pod) (rate(container_cpu_cfs_throttled_periods_total{node=~\"$node\", namespace=\"$namespace\", pod=~\"$pod\"}[$__rate_interval]))) \n / \n sum by (pod) (rate(container_cpu_cfs_periods_total{node=~\"$node\", namespace=\"$namespace\", pod=~\"$pod\"}[$__rate_interval]))\n) \n* \nsum by (pod) (kube_pod_container_resource_limits{resource=\"cpu\",unit=\"core\",node=~\"$node\", namespace=\"$namespace\", pod=~\"$pod\"})", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{ pod }}", + "refId": "A" + }, + { + "expr": "sum (\n (\n sum by (pod) (\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\", pod=~\"$pod\"}\n * on (pod)\n sum by (pod) (rate(container_cpu_cfs_throttled_periods_total{node=~\"$node\", namespace=\"$namespace\", pod=~\"$pod\"}[$__rate_interval]))) \n / \n sum by (pod) (rate(container_cpu_cfs_periods_total{node=~\"$node\", namespace=\"$namespace\", pod=~\"$pod\"}[$__rate_interval]))\n ) \n * \n sum by (pod) (kube_pod_container_resource_limits{resource=\"cpu\",unit=\"core\",node=~\"$node\", namespace=\"$namespace\", pod=~\"$pod\"})\n)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Throttling", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": null, + "format": "short", + "label": "cores", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "collapsed": true, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 41 + }, + "id": 61, + "panels": [ + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "description": "The total value may not equal the sum of system and user times because of the kernel's cgroup accounting peculiarities. Read more here: https://www.kernel.org/doc/Documentation/cgroup-v1/cpuacct.txt", + "fill": 0, + "gridPos": { + "h": 9, + "w": 6, + "x": 0, + "y": 43 + }, + "id": 62, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": "pod", + "repeatDirection": "h", + "seriesOverrides": [ + { + "alias": "Usage", + "color": "#629e51" + }, + { + "alias": "Requests", + "color": "#f4d598" + }, + { + "alias": "Limits", + "color": "#c15c17" + }, + { + "alias": "VPA Target", + "color": "#447ebc" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "sum by(pod) (rate(container_cpu_usage_seconds_total{node=~\"$node\", container!=\"POD\", pod=\"$pod\", namespace=\"$namespace\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Usage", + "refId": "A" + }, + { + "expr": "sum by(pod) (avg_over_time(kube_pod_container_resource_requests{resource=\"cpu\",unit=\"core\",node=~\"$node\", namespace=\"$namespace\", pod=\"$pod\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Requests", + "refId": "D" + }, + { + "expr": "sum by (pod)\n(\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\", pod=~\"$pod\"}\n * on (controller_type, controller_name) group_left()\n sum by (controller_type, controller_name) (avg_over_time(vpa_target_recommendation{container!=\"POD\", namespace=\"$namespace\", resource=\"cpu\"}[$__rate_interval]))\n)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "VPA Target", + "refId": "C" + }, + { + "expr": "sum by(pod) (avg_over_time(kube_pod_container_resource_limits{resource=\"cpu\",unit=\"core\",node=~\"$node\", namespace=\"$namespace\", pod=\"$pod\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Limits", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "$pod", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "cores", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "title": "Pods CPU", + "type": "row" + }, + { + "collapsed": true, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 42 + }, + "id": 9, + "panels": [ + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "description": "The total value may not equal the sum of system and user times because of the kernel's cgroup accounting peculiarities. Read more here: https://www.kernel.org/doc/Documentation/cgroup-v1/cpuacct.txt", + "fill": 1, + "gridPos": { + "h": 9, + "w": 6, + "x": 0, + "y": 44 + }, + "id": 11, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": "pod", + "repeatDirection": "h", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + }, + { + "alias": "System", + "color": "#e24d42" + }, + { + "alias": "User", + "color": "#1f78c1" + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": true, + "targets": [ + { + "expr": "sum by(pod) (rate(container_cpu_system_seconds_total{node=~\"$node\", container!=\"POD\", pod=\"$pod\", namespace=\"$namespace\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "System", + "refId": "A" + }, + { + "expr": "sum by(pod) (rate(container_cpu_user_seconds_total{node=~\"$node\", container!=\"POD\", pod=\"$pod\", namespace=\"$namespace\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "User", + "refId": "B" + }, + { + "expr": "sum by(pod) (rate(container_cpu_usage_seconds_total{node=~\"$node\", container!=\"POD\", pod=\"$pod\", namespace=\"$namespace\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "D" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "$pod", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "cores", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "title": "Pods CPU by state", + "type": "row" + }, + { + "collapsed": false, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 43 + }, + "id": 13, + "panels": [], + "title": "Memory", + "type": "row" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 44 + }, + "hiddenSeries": false, + "id": 15, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "lines": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum by(pod) (\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\", pod=~\"$pod\"}\n * on (pod)\n sum by (pod) (avg_over_time(container_memory_working_set_bytes:without_kmem{node=~\"$node\", container!=\"POD\", pod=~\"$pod\", namespace=\"$namespace\"}[$__rate_interval]))\n)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{ pod }}", + "refId": "A" + }, + { + "expr": "sum(\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\", pod=~\"$pod\"}\n * on (pod)\n sum by (pod) (avg_over_time(container_memory_working_set_bytes:without_kmem{node=~\"$node\", container!=\"POD\", pod=~\"$pod\", namespace=\"$namespace\"}[$__rate_interval]))\n)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Usage by pod", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "description": "The Working set bytes metric is the actual memory used by the container, as it includes active file memory. When its value approaches the limit, the container can be killed by the OOMKiller. This value can be higher than the sum RSS and Cache since not all active file memory is Cache.", + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 44 + }, + "hiddenSeries": false, + "id": 16, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Working set bytes without kmem", + "color": "rgb(0, 0, 0)", + "dashes": true, + "fill": 0, + "linewidth": 2, + "stack": false + }, + { + "alias": "Kmem", + "color": "rgb(255, 0, 0)", + "dashes": true, + "fill": 0, + "linewidth": 2, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum (\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\", pod=~\"$pod\"}\n * on (pod)\n sum by (pod) (avg_over_time(container_memory_rss{node=~\"$node\", namespace=\"$namespace\", pod=~\"$pod\", container!=\"POD\"}[$__rate_interval]))\n)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "RSS", + "refId": "A" + }, + { + "expr": "sum (\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\", pod=~\"$pod\"}\n * on (pod)\n sum by (pod) (avg_over_time(container_memory_cache{node=~\"$node\", namespace=\"$namespace\", pod=~\"$pod\", container!=\"POD\"}[$__rate_interval]))\n)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Cache", + "refId": "B" + }, + { + "expr": "sum (\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\", pod=~\"$pod\"}\n * on (pod)\n sum by (pod) (avg_over_time(container_memory_swap{node=~\"$node\", namespace=\"$namespace\", pod=~\"$pod\", container!=\"POD\"}[$__rate_interval]))\n)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Swap", + "refId": "C" + }, + { + "expr": "sum (\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\", pod=~\"$pod\"}\n * on (pod)\n sum by (pod) (avg_over_time(container_memory_working_set_bytes:without_kmem{node=~\"$node\", namespace=\"$namespace\", pod=~\"$pod\", container!=\"POD\"}[$__rate_interval]))\n)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Working set bytes without kmem", + "refId": "D" + }, + { + "expr": "sum (\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\", pod=~\"$pod\"}\n * on (pod)\n sum by (pod) (avg_over_time(container_memory:kmem{node=~\"$node\", namespace=\"$namespace\", pod=~\"$pod\", container!=\"POD\"}[$__rate_interval]))\n)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Kmem", + "refId": "E" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Usage by state", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "description": "This graph shows the requested Memory resources higher than the actual Memory consumption. In other words, it shows Memory resources that can be \"freed\" without affecting the service.", + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 53 + }, + "hiddenSeries": false, + "id": 63, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "lines": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "(\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\", pod=~\"$pod\"}\n * on (pod) group_left()\n sum by (pod)\n (\n (\n sum by (namespace, pod, container) (avg_over_time(kube_pod_container_resource_requests{resource=\"memory\",unit=\"byte\",node=~\"$node\", namespace=\"$namespace\"}[$__rate_interval]))\n -\n sum by (namespace, pod, container) (avg_over_time(container_memory_working_set_bytes:without_kmem{node=~\"$node\", namespace=\"$namespace\", container!=\"POD\"}[$__rate_interval]))\n ) > 0\n )\n)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{ pod }}", + "refId": "A" + }, + { + "expr": "sum\n(\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\", pod=~\"$pod\"}\n * on (pod) group_left()\n sum by (pod)\n (\n (\n sum by (namespace, pod, container) (avg_over_time(kube_pod_container_resource_requests{resource=\"memory\",unit=\"byte\",node=~\"$node\", namespace=\"$namespace\"}[$__rate_interval]))\n -\n sum by (namespace, pod, container) (avg_over_time(container_memory_working_set_bytes:without_kmem{node=~\"$node\", namespace=\"$namespace\", container!=\"POD\"}[$__rate_interval]))\n ) > 0\n )\n)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Over-requested by pod", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": null, + "format": "bytes", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "description": "This graph shows the requested Memory resources higher than the actual Memory consumption. In other words, it shows Memory resources that need to be \"reserved\" for the service to run smoothly.", + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 53 + }, + "hiddenSeries": false, + "id": 75, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "lines": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "(\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\", pod=~\"$pod\"}\n * on (pod) group_left()\n sum by (pod)\n (\n (\n (\n sum by (namespace, pod, container) (avg_over_time(container_memory_working_set_bytes:without_kmem{node=~\"$node\", namespace=\"$namespace\"}[$__rate_interval]))\n -\n sum by (namespace, pod, container) (avg_over_time(kube_pod_container_resource_requests{resource=\"memory\",unit=\"byte\",node=~\"$node\", namespace=\"$namespace\", container!=\"POD\"}[$__rate_interval]))\n ) or sum by (namespace, pod, container) (avg_over_time(container_memory_working_set_bytes:without_kmem{node=~\"$node\", namespace=\"$namespace\", container!=\"POD\"}[$__rate_interval]))\n ) > 0\n )\n)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{ pod }}", + "refId": "A" + }, + { + "expr": "sum\n(\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\", pod=~\"$pod\"}\n * on (pod) group_left()\n sum by (pod)\n (\n (\n (\n sum by (namespace, pod, container) (avg_over_time(container_memory_working_set_bytes:without_kmem{node=~\"$node\", namespace=\"$namespace\"}[$__rate_interval]))\n -\n sum by (namespace, pod, container) (avg_over_time(kube_pod_container_resource_requests{resource=\"memory\",unit=\"byte\",node=~\"$node\", namespace=\"$namespace\", container!=\"POD\"}[$__rate_interval]))\n ) or sum by (namespace, pod, container) (avg_over_time(container_memory_working_set_bytes:without_kmem{node=~\"$node\", namespace=\"$namespace\", container!=\"POD\"}[$__rate_interval]))\n ) > 0\n )\n)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Under-requested by pod", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": null, + "format": "bytes", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "collapsed": true, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 62 + }, + "id": 18, + "panels": [ + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "description": "The Working set bytes metric is the actual memory used by the container, as it includes active file memory. When its value approaches the limit, the container can be killed by the OOMKiller. This value can be higher than the sum RSS and Cache since not all active file memory is Cache.", + "fill": 1, + "gridPos": { + "h": 9, + "w": 6, + "x": 0, + "y": 64 + }, + "id": 19, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": "pod", + "repeatDirection": "h", + "seriesOverrides": [ + { + "alias": "Working set bytes without kmem", + "color": "rgb(0, 0, 0)", + "dashes": true, + "fill": 0, + "linewidth": 2, + "stack": false + }, + { + "alias": "Kmem", + "color": "rgb(255, 0, 0)", + "dashes": true, + "fill": 0, + "linewidth": 2, + "stack": false + }, + { + "alias": "Limits", + "color": "#c15c17", + "dashes": true, + "fill": 0, + "lines": false, + "linewidth": 2, + "stack": false + }, + { + "alias": "Requests", + "color": "#f4d598", + "dashes": true, + "fill": 0, + "lines": false, + "linewidth": 2, + "stack": false + }, + { + "alias": "VPA Target", + "color": "#447ebc", + "dashes": true, + "fill": 0, + "lines": false, + "linewidth": 2, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum by (pod) (avg_over_time(container_memory_rss{node=~\"$node\", namespace=\"$namespace\", pod=~\"$pod\", container!=\"POD\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "RSS", + "refId": "A" + }, + { + "expr": "sum by (pod) (avg_over_time(container_memory_cache{node=~\"$node\", namespace=\"$namespace\", pod=~\"$pod\", container!=\"POD\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Cache", + "refId": "B" + }, + { + "expr": "sum by (pod) (avg_over_time(container_memory_swap{node=~\"$node\", namespace=\"$namespace\", pod=~\"$pod\", container!=\"POD\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Swap", + "refId": "C" + }, + { + "expr": "sum by (pod) (avg_over_time(container_memory_working_set_bytes:without_kmem{node=~\"$node\", namespace=\"$namespace\", pod=~\"$pod\", container!=\"POD\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Working set bytes without kmem", + "refId": "D" + }, + { + "expr": "sum by (pod)\n(\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\", pod=~\"$pod\"}\n * on (controller_type, controller_name) group_left()\n sum by (controller_type, controller_name) (avg_over_time(vpa_target_recommendation{namespace=\"$namespace\", container!=\"POD\", resource=\"memory\"}[$__rate_interval]))\n)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "VPA Target", + "refId": "E" + }, + { + "expr": "sum by(pod) (avg_over_time(kube_pod_container_resource_limits{resource=\"memory\",unit=\"byte\",node=~\"$node\", namespace=\"$namespace\", pod=~\"$pod\", container!=\"POD\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Limits", + "refId": "F" + }, + { + "expr": "sum by(pod) (avg_over_time(kube_pod_container_resource_requests{resource=\"memory\",unit=\"byte\",node=~\"$node\", namespace=\"$namespace\", pod=~\"$pod\", container!=\"POD\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Requests", + "refId": "G" + }, + { + "expr": "sum by(pod) (avg_over_time(container_memory:kmem{node=~\"$node\", namespace=\"$namespace\", pod=~\"$pod\", container!=\"POD\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Kmem", + "refId": "H" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "$pod", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "title": "Pods Memory", + "type": "row" + }, + { + "collapsed": false, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 63 + }, + "id": 39, + "panels": [], + "title": "Network", + "type": "row" + }, + { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisPlacement": "auto", + "axisLabel": "", + "barAlignment": 0, + "drawStyle": "bars", + "fillOpacity": 100, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 0, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [ + { + "options": { + "-1": { + "color": "transparent", + "index": 0, + "text": "Network graph for Pod with hostNetwork: true is meaningless" + } + }, + "type": "value" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "Bps" + }, + "overrides": [ + { + "matcher": { + "id": "byFrameRefID", + "options": "B" + }, + "properties": [ + { + "id": "min", + "value": 0 + }, + { + "id": "max", + "value": 0 + }, + { + "id": "custom.axisPlacement", + "value": "hidden" + }, + { + "id": "color", + "value": { + "mode": "fixed", + "fixedColor": "transparent" + } + } + ] + } + ] + }, + "datasource": { + "uid": "${ds_prometheus}", + "type": "prometheus" + }, + "description": "This graph shows Network Receive (except for the hostNetwork Pods)", + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 64 + }, + "id": 41, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean" + ], + "displayMode": "table", + "placement": "right" + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "8.5.13", + "targets": [ + { + "expr": "kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\", pod=~\"$pod\"} \n* on(pod)\nkube_pod_info{host_network=\"false\", namespace=\"$namespace\", pod=~\"$pod\"}\n* on(pod)\nsum by (pod) (rate(container_network_receive_bytes_total{node=~\"$node\", namespace=\"$namespace\", pod=~\"$pod\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{ pod }}", + "refId": "A" + }, + { + "expr": "sum (\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\", pod=~\"$pod\"} \n * on(pod)\n kube_pod_info{host_network=\"false\", namespace=\"$namespace\", pod=~\"$pod\"}\n * on(pod)\n sum by (pod) (rate(container_network_receive_bytes_total{node=~\"$node\", namespace=\"$namespace\", pod=~\"$pod\"}[$__rate_interval]))\n)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "B" + }, + { + "expr": "# Return -1 for Pods with 'hostNetwork: true' to use in value mappings.\nkube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\", pod=~\"$pod\"} \n* on (pod)\nkube_pod_info{host_network=\"true\", namespace=\"$namespace\", pod=~\"$pod\"} \n*\n-1", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{ pod }}", + "refId": "C" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Receive", + "transformations": [], + "type": "timeseries" + }, + { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisPlacement": "auto", + "axisLabel": "", + "barAlignment": 0, + "drawStyle": "bars", + "fillOpacity": 100, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 0, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [ + { + "options": { + "-1": { + "color": "transparent", + "index": 0, + "text": "Network graph for Pod with hostNetwork: true is meaningless" + } + }, + "type": "value" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "Bps" + }, + "overrides": [ + { + "matcher": { + "id": "byFrameRefID", + "options": "B" + }, + "properties": [ + { + "id": "min", + "value": 0 + }, + { + "id": "max", + "value": 0 + }, + { + "id": "custom.axisPlacement", + "value": "hidden" + }, + { + "id": "color", + "value": { + "mode": "fixed", + "fixedColor": "transparent" + } + } + ] + } + ] + }, + "datasource": { + "uid": "${ds_prometheus}", + "type": "prometheus" + }, + "description": "This graph shows Network Transmit (except for the hostNetwork Pods)", + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 64 + }, + "id": 57, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean" + ], + "displayMode": "table", + "placement": "right" + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "8.5.13", + "targets": [ + { + "expr": "kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\", pod=~\"$pod\"} \n* on(pod)\nkube_pod_info{host_network=\"false\", namespace=\"$namespace\", pod=~\"$pod\"}\n* on(pod)\nsum by (pod) (rate(container_network_transmit_bytes_total{node=~\"$node\", namespace=\"$namespace\", pod=~\"$pod\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{ pod }}", + "refId": "A" + }, + { + "expr": "sum (\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\", pod=~\"$pod\"} \n * on(pod)\n kube_pod_info{host_network=\"false\", namespace=\"$namespace\", pod=~\"$pod\"}\n * on(pod)\n sum by (pod) (rate(container_network_transmit_bytes_total{node=~\"$node\", namespace=\"$namespace\", pod=~\"$pod\"}[$__rate_interval]))\n)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "B" + }, + { + "expr": "# Return -1 for Pods with 'hostNetwork: true' to use in value mappings.\nkube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\", pod=~\"$pod\"} \n* on (pod)\nkube_pod_info{host_network=\"true\", namespace=\"$namespace\", pod=~\"$pod\"} \n*\n-1", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{ pod }}", + "refId": "C" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Transmit", + "transformations": [], + "type": "timeseries" + }, + { + "collapsed": false, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 73 + }, + "id": 45, + "panels": [], + "title": "IOPS", + "type": "row" + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 74 + }, + "hiddenSeries": false, + "id": 43, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum by(pod) (\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\"}\n * on (pod)\n sum by (pod) (rate(container_fs_reads_total{node=~\"$node\", container!=\"POD\", pod=~\"$pod\", namespace=\"$namespace\"}[$__rate_interval]))\n)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{ pod }}", + "refId": "A" + }, + { + "expr": "sum (\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\"}\n * on (pod)\n sum by (pod) (rate(container_fs_reads_total{node=~\"$node\", container!=\"POD\", pod=~\"$pod\", namespace=\"$namespace\"}[$__rate_interval]))\n)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Read", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "iops", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 74 + }, + "hiddenSeries": false, + "id": 58, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum by(pod) (\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\"}\n * on (pod)\n sum by (pod) (rate(container_fs_writes_total{node=~\"$node\", container!=\"POD\", pod=~\"$pod\", namespace=\"$namespace\"}[$__rate_interval]))\n)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{ pod }}", + "refId": "A" + }, + { + "expr": "sum (\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\"}\n * on (pod)\n sum by (pod) (rate(container_fs_writes_total{node=~\"$node\", container!=\"POD\", pod=~\"$pod\", namespace=\"$namespace\"}[$__rate_interval]))\n)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Write", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "iops", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "collapsed": false, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 82 + }, + "id": 81, + "panels": [], + "title": "PVC", + "type": "row" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "description": "This graph does not show any localstorage-related information due to incorrectly calculating the occupied space on localstorage disks", + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 83 + }, + "hiddenSeries": false, + "id": 82, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "fill": 0, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum by (namespace, controller, persistentvolumeclaim) (\n max by (namespace, controller, persistentvolumeclaim)\n (\n sum by (namespace, persistentvolumeclaim) (\n max_over_time(kubelet_volume_stats_capacity_bytes{node=~\"$node\", namespace=\"$namespace\"}[$__rate_interval])\n ) \n\n * max by (namespace, persistentvolumeclaim) (\n label_replace(\n max_over_time(kube_persistentvolumeclaim_info{namespace=\"$namespace\"}[$__rate_interval]),\n \"persistentvolume\", \"$1\", \"volumename\", \"(.*)\")\n + on (persistentvolume) group_left() max by (persistentvolume) (kube_persistentvolume_is_local == 0)\n )\n\n * on (namespace, persistentvolumeclaim) group_left(pod) \n max by (namespace, persistentvolumeclaim, pod) (\n max_over_time(kube_pod_spec_volumes_persistentvolumeclaims_info{namespace=\"$namespace\"}[$__rate_interval])\n ) \n\n * on (namespace, pod) group_left(controller)\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=~\"$controller\", pod=~\"$pod\"} \n )\n)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Provisioned {{ persistentvolumeclaim }}", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "PVC Provisioned (except local storage classes)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "description": "This graph does not show any localstorage-related information due to incorrectly calculating the occupied space on localstorage disks", + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 83 + }, + "hiddenSeries": false, + "id": 84, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "/Total/", + "fill": 0, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum by (pod, persistentvolumeclaim)\n(\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\", pod=~\"$pod\"}\n * on (pod) group_right(persistentvolumeclaim)\n (\n (avg_over_time(kubelet_volume_stats_capacity_bytes{node=~\"$node\", namespace=\"$namespace\"}[$__rate_interval]) - avg_over_time(kubelet_volume_stats_available_bytes{node=~\"$node\", namespace=\"$namespace\"}[$__rate_interval]))\n * \n on (namespace, persistentvolumeclaim) group_left (pod) \n (\n max by (namespace, persistentvolumeclaim, pod) (\n avg_over_time(kube_pod_spec_volumes_persistentvolumeclaims_info{namespace=\"$namespace\"}[$__rate_interval])) \n * on (namespace, persistentvolumeclaim) group_right(pod) \n max by (namespace, persistentvolumeclaim) (\n label_replace(\n max_over_time(kube_persistentvolumeclaim_info{namespace=\"$namespace\"}[$__rate_interval]),\n \"persistentvolume\", \"$1\", \"volumename\", \"(.*)\")\n + on (persistentvolume) group_left() max by (persistentvolume) (kube_persistentvolume_is_local == 0))\n * on (namespace, persistentvolumeclaim) group_right (pod)\n avg_over_time(kube_persistentvolumeclaim_status_phase{namespace=\"$namespace\", phase=\"Bound\"}[$__rate_interval])\n )\n )\n)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Usage {{ persistentvolumeclaim }}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "PVC Usage (except local storage classes)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "description": "This graph does not show any localstorage-related information due to incorrectly calculating the occupied space on localstorage disks", + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 24, + "x": 0, + "y": 90 + }, + "hiddenSeries": false, + "id": 83, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "/Total .*/", + "fill": 0, + "linewidth": 2, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum by (pod, persistentvolumeclaim)\n(\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\", pod=~\"$pod\"}\n * on (pod) group_right(persistentvolumeclaim) (\n (\n avg_over_time(kubelet_volume_stats_capacity_bytes{node=~\"$node\", namespace=\"$namespace\"}[$__rate_interval]) - avg_over_time(kubelet_volume_stats_available_bytes{node=~\"$node\", namespace=\"$namespace\"}[$__rate_interval])\n ) * \n on (namespace, persistentvolumeclaim) group_left (pod) \n (\n max by (namespace, persistentvolumeclaim, pod) (\n avg_over_time(kube_pod_spec_volumes_persistentvolumeclaims_info{namespace=\"$namespace\"}[$__rate_interval])) \n * on (namespace, persistentvolumeclaim) group_right(pod) \n max by (namespace, persistentvolumeclaim) (\n label_replace(\n max_over_time(kube_persistentvolumeclaim_info{namespace=\"$namespace\"}[$__rate_interval]),\n \"persistentvolume\", \"$1\", \"volumename\", \"(.*)\")\n + on (persistentvolume) group_left() max by (persistentvolume) (kube_persistentvolume_is_local == 0))\n * on (namespace, persistentvolumeclaim) group_right (pod)\n avg_over_time(kube_persistentvolumeclaim_status_phase{namespace=\"$namespace\", phase=\"Bound\"}[$__rate_interval])\n )\n )\n)\n/\n(\nsum by (pod, persistentvolumeclaim)\n(\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\"}\n * on (pod) group_right(persistentvolumeclaim)\n (\n avg_over_time(kubelet_volume_stats_capacity_bytes{node=~\"$node\", namespace=\"$namespace\"}[$__rate_interval])\n * \n on (namespace, persistentvolumeclaim) group_left (pod) \n (\n avg_over_time(kube_pod_spec_volumes_persistentvolumeclaims_info{namespace=\"$namespace\"}[$__rate_interval])\n * on (namespace, persistentvolumeclaim) group_left (pod) \n (\n max by (namespace, persistentvolumeclaim, pod) (\n avg_over_time(kube_pod_spec_volumes_persistentvolumeclaims_info{namespace=\"$namespace\"}[$__rate_interval])) \n * on (namespace, persistentvolumeclaim) group_right(pod) \n max by (namespace, persistentvolumeclaim) (\n label_replace(\n max_over_time(kube_persistentvolumeclaim_info{namespace=\"$namespace\"}[$__rate_interval]),\n \"persistentvolume\", \"$1\", \"volumename\", \"(.*)\")\n + on (persistentvolume) group_left() max by (persistentvolume) (kube_persistentvolume_is_local == 0))\n * on (namespace, persistentvolumeclaim) group_right (pod)\n avg_over_time(kube_persistentvolumeclaim_status_phase{namespace=\"$namespace\", phase=\"Bound\"}[$__rate_interval])\n )\n )\n)))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Usage {{ persistentvolumeclaim }}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "PVC Usage in % (except local storage classes)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "percentunit", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "collapsed": true, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 98 + }, + "id": 88, + "panels": [ + { + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": null, + "displayMode": "auto" + }, + "decimals": 2, + "displayName": "", + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Time" + }, + "properties": [ + { + "id": "displayName", + "value": "Time" + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "persistentvolumeclaim" + }, + "properties": [ + { + "id": "displayName", + "value": "Name" + }, + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "storageclass" + }, + "properties": [ + { + "id": "displayName", + "value": "StorageClass" + }, + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #B" + }, + "properties": [ + { + "id": "displayName", + "value": "Requested" + }, + { + "id": "unit", + "value": "bytes" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #C" + }, + "properties": [ + { + "id": "displayName", + "value": "Provisioned" + }, + { + "id": "unit", + "value": "bytes" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #D" + }, + "properties": [ + { + "id": "displayName", + "value": "Capacity" + }, + { + "id": "unit", + "value": "bytes" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #E" + }, + "properties": [ + { + "id": "displayName", + "value": "Used bytes" + }, + { + "id": "unit", + "value": "bytes" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #F" + }, + "properties": [ + { + "id": "displayName", + "value": "Used inodes" + }, + { + "id": "unit", + "value": "short" + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #G" + }, + "properties": [ + { + "id": "displayName", + "value": "Used bytes (%)" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #H" + }, + "properties": [ + { + "id": "displayName", + "value": "Used inodes (%)" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "pod" + }, + "properties": [ + { + "id": "displayName", + "value": "Used by pod" + }, + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + } + ] + }, + "gridPos": { + "h": 9, + "w": 24, + "x": 0, + "y": 99 + }, + "id": 86, + "links": [], + "options": { + "showHeader": true + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "max by (namespace, persistentvolumeclaim, storageclass) (\n kube_persistentvolumeclaim_info{namespace=\"$namespace\"}\n) \nand on (namespace, persistentvolumeclaim) \nmax by (namespace, persistentvolumeclaim) (\n kube_pod_spec_volumes_persistentvolumeclaims_info{namespace=\"$namespace\", pod=~\"$pod\"}\n * on (namespace, pod) group_left(controller)\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=~\"$controller\", pod=~\"$pod\"} \n)", + "format": "table", + "instant": true, + "intervalFactor": 1, + "legendFormat": "Name, storageclass", + "refId": "A" + }, + { + "expr": "max by (namespace, persistentvolumeclaim, storageclass) (\n avg_over_time(kube_persistentvolumeclaim_resource_requests_storage_bytes{namespace=\"$namespace\"}[$__range])\n) \nand on (namespace, persistentvolumeclaim) \nmax by (namespace, persistentvolumeclaim) (\n kube_pod_spec_volumes_persistentvolumeclaims_info{namespace=\"$namespace\", pod=~\"$pod\"}\n * on (namespace, pod) group_left(controller)\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=~\"$controller\", pod=~\"$pod\"}\n)", + "format": "table", + "hide": false, + "instant": true, + "interval": "", + "intervalFactor": 1, + "legendFormat": "Requested (pvc)", + "refId": "B" + }, + { + "expr": "max by (namespace, persistentvolumeclaim, storageclass) (\n label_replace(\n kube_persistentvolumeclaim_info{namespace=\"$namespace\"},\n \"persistentvolume\", \"$1\", \"volumename\", \"(.*)\") \n * on (persistentvolume) group_left() \n kube_persistentvolume_capacity_bytes\n) \nand on (namespace, persistentvolumeclaim) \nmax by (namespace, persistentvolumeclaim) (\n kube_pod_spec_volumes_persistentvolumeclaims_info{namespace=\"$namespace\", pod=~\"$pod\"}\n * on (namespace, pod) group_left(controller)\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=~\"$controller\", pod=~\"$pod\"} \n)", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "legendFormat": "Provisioned (pv)", + "refId": "C" + }, + { + "expr": "max by (namespace, persistentvolumeclaim, storageclass) (\n avg_over_time(kubelet_volume_stats_capacity_bytes{node=~\"$node\", namespace=\"$namespace\"}[$__range])\n) \nand on (namespace, persistentvolumeclaim) \nmax by (namespace, persistentvolumeclaim) (\n kube_pod_spec_volumes_persistentvolumeclaims_info{namespace=\"$namespace\", pod=~\"$pod\"}\n * on (namespace, pod) group_left(controller)\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=~\"$controller\", pod=~\"$pod\"} \n)", + "format": "table", + "instant": true, + "intervalFactor": 1, + "legendFormat": "Capacity (real)", + "refId": "D" + }, + { + "expr": "max by (namespace, persistentvolumeclaim, storageclass) (\n avg_over_time(kubelet_volume_stats_capacity_bytes{node=~\"$node\", namespace=\"$namespace\"}[$__range]) - avg_over_time(kubelet_volume_stats_available_bytes{node=~\"$node\", namespace=\"$namespace\"}[$__range])\n) \nand on (namespace, persistentvolumeclaim) \nmax by (namespace, persistentvolumeclaim) (\n kube_pod_spec_volumes_persistentvolumeclaims_info{namespace=\"$namespace\", pod=~\"$pod\"}\n * on (namespace, pod) group_left(controller)\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=~\"$controller\", pod=~\"$pod\"} \n)", + "format": "table", + "instant": true, + "intervalFactor": 1, + "legendFormat": "Used bytes", + "refId": "E" + }, + { + "expr": "max by (namespace, persistentvolumeclaim, storageclass) (\n avg_over_time(kubelet_volume_stats_inodes_used{node=~\"$node\", namespace=\"$namespace\"}[$__range])\n) \nand on (namespace, persistentvolumeclaim) \nmax by (namespace, persistentvolumeclaim) (\n kube_pod_spec_volumes_persistentvolumeclaims_info{namespace=\"$namespace\", pod=~\"$pod\"}\n * on (namespace, pod) group_left(controller)\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=~\"$controller\", pod=~\"$pod\"} \n)", + "format": "table", + "instant": true, + "intervalFactor": 1, + "legendFormat": "Used inodes", + "refId": "F" + }, + { + "expr": "max by (namespace, persistentvolumeclaim, storageclass) (\n (avg_over_time(kubelet_volume_stats_capacity_bytes{node=~\"$node\", namespace=\"$namespace\"}[$__range]) - avg_over_time(kubelet_volume_stats_available_bytes{node=~\"$node\", namespace=\"$namespace\"}[$__range]))\n /\n avg_over_time(kubelet_volume_stats_capacity_bytes{node=~\"$node\", namespace=\"$namespace\"}[$__range])\n) \nand on (namespace, persistentvolumeclaim) \nmax by (namespace, persistentvolumeclaim) (\n kube_pod_spec_volumes_persistentvolumeclaims_info{namespace=\"$namespace\", pod=~\"$pod\", pod=~\"$pod\"}\n * on (namespace, pod) group_left(controller)\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=~\"$controller\"} \n)", + "format": "table", + "instant": true, + "intervalFactor": 1, + "legendFormat": "Used bytes %", + "refId": "G" + }, + { + "expr": "max by (namespace, persistentvolumeclaim, storageclass) (\n avg_over_time(kubelet_volume_stats_inodes_used{node=~\"$node\", namespace=\"$namespace\"}[$__range])\n /\n avg_over_time(kubelet_volume_stats_inodes{node=~\"$node\", namespace=\"$namespace\"}[$__range])\n) \nand on (namespace, persistentvolumeclaim) \nmax by (namespace, persistentvolumeclaim) (\n kube_pod_spec_volumes_persistentvolumeclaims_info{namespace=\"$namespace\", pod=~\"$pod\"}\n * on (namespace, pod) group_left(controller)\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=~\"$controller\", pod=~\"$pod\"} \n)", + "format": "table", + "instant": true, + "intervalFactor": 1, + "legendFormat": "Used inodes %", + "refId": "H" + }, + { + "expr": "max by (namespace, persistentvolumeclaim, pod) (\n kube_pod_spec_volumes_persistentvolumeclaims_info{namespace=\"$namespace\", pod=~\"$pod\"}\n * on (namespace, pod) group_left(controller)\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=~\"$controller\", pod=~\"$pod\"} \n)", + "format": "table", + "instant": true, + "intervalFactor": 1, + "legendFormat": "pod", + "refId": "I" + } + ], + "title": "Overview", + "transformations": [ + { + "id": "merge", + "options": { + "reducers": [] + } + }, + { + "id": "filterFieldsByName", + "options": { + "include": { + "names": [ + "persistentvolumeclaim", + "storageclass", + "Value #B", + "Value #C", + "Value #D", + "Value #E", + "Value #F", + "Value #G", + "Value #H", + "pod" + ] + } + } + } + ], + "type": "table" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "description": "This graph does not show any localstorage-related information due to incorrectly calculating the occupied space on localstorage disks", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 24, + "x": 0, + "y": 108 + }, + "hiddenSeries": false, + "id": 89, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": "persistentvolumeclaim", + "repeatDirection": "h", + "seriesOverrides": [ + { + "alias": "Total", + "fill": 0, + "stack": false + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "max by (namespace, persistentvolumeclaim, storageclass) (\n label_replace(\n kube_persistentvolumeclaim_info{namespace=\"$namespace\"},\n \"persistentvolume\", \"$1\", \"volumename\", \"(.*)\") \n * on (persistentvolume) group_left() \n avg_over_time(kube_persistentvolume_capacity_bytes[$__rate_interval])\n) \nand on (namespace, persistentvolumeclaim) \nmax by (namespace, persistentvolumeclaim) (\n kube_pod_spec_volumes_persistentvolumeclaims_info{namespace=\"$namespace\", persistentvolumeclaim=\"$persistentvolumeclaim\", pod=~\"$pod\"}\n * on (namespace, pod) group_left(controller)\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=~\"$controller\"} \n)", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "Provisioned", + "refId": "B" + }, + { + "expr": "max by (namespace, persistentvolumeclaim, storageclass) (\n avg_over_time(kubelet_volume_stats_capacity_bytes{namespace=\"$namespace\"}[$__rate_interval])\n) \nand on (namespace, persistentvolumeclaim) \nmax by (namespace, persistentvolumeclaim) (\n kube_pod_spec_volumes_persistentvolumeclaims_info{namespace=\"$namespace\", pod=~\"$pod\"}\n * on (namespace, pod) group_left(controller)\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=~\"$controller\"} \n)", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "Capacity", + "refId": "A" + }, + { + "expr": "max by (namespace, persistentvolumeclaim, storageclass) (\n avg_over_time(kubelet_volume_stats_capacity_bytes{namespace=\"$namespace\"}[$__rate_interval]) - avg_over_time(kubelet_volume_stats_available_bytes{namespace=\"$namespace\"}[$__rate_interval])\n) \nand on (namespace, persistentvolumeclaim) \nmax by (namespace, persistentvolumeclaim) (\n kube_pod_spec_volumes_persistentvolumeclaims_info{namespace=\"$namespace\", pod=~\"$pod\"}\n * on (namespace, pod) group_left(controller)\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=~\"$controller\"} \n)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Used bytes", + "refId": "C" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "$persistentvolumeclaim", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "title": "PVC Detailed", + "type": "row" + } + ], + "refresh": "30s", + "schemaVersion": 32, + "style": "dark", + "tags": [ + "main" + ], + "templating": { + "list": [ + { + "current": { + "selected": false, + "text": "default", + "value": "default" + }, + "description": null, + "error": null, + "hide": 0, + "includeAll": false, + "label": "Prometheus", + "multi": false, + "name": "ds_prometheus", + "options": [], + "query": "prometheus", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + }, + { + "allValue": ".*", + "current": { + "selected": true, + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": "$ds_prometheus", + "definition": "label_values(kubernetes_build_info, node)", + "description": null, + "error": null, + "hide": 0, + "includeAll": true, + "label": "Node", + "multi": true, + "name": "node", + "options": [], + "query": { + "query": "label_values(kubernetes_build_info, node)", + "refId": "main-node-Variable-Query" + }, + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "current": { + "selected": false, + "text": "candi-dashboard-stage", + "value": "candi-dashboard-stage" + }, + "datasource": "$ds_prometheus", + "definition": "label_values(kube_pod_info{node=~\"$node\"}, namespace)", + "description": null, + "error": null, + "hide": 0, + "includeAll": false, + "label": "Namespace", + "multi": false, + "name": "namespace", + "options": [], + "query": { + "query": "label_values(kube_pod_info{node=~\"$node\"}, namespace)", + "refId": "main-namespace-Variable-Query" + }, + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "current": { + "selected": false, + "text": "sts/postgres", + "value": "sts/postgres" + }, + "datasource": "$ds_prometheus", + "definition": "label_values(kube_controller_pod{node=~\"$node\", namespace=~\"$namespace\"}, controller)", + "description": null, + "error": null, + "hide": 0, + "includeAll": false, + "label": "Controller", + "multi": false, + "name": "controller", + "options": [], + "query": { + "query": "label_values(kube_controller_pod{node=~\"$node\", namespace=~\"$namespace\"}, controller)", + "refId": "main-controller-Variable-Query" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": ".*", + "current": { + "selected": true, + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": "$ds_prometheus", + "definition": "label_values(kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\"}, pod)", + "description": null, + "error": null, + "hide": 0, + "includeAll": true, + "label": "Pod", + "multi": true, + "name": "pod", + "options": [], + "query": { + "query": "label_values(kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\"}, pod)", + "refId": "main-pod-Variable-Query" + }, + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": ".*", + "current": { + "selected": true, + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": "$ds_prometheus", + "definition": "query_result(max_over_time(kube_pod_spec_volumes_persistentvolumeclaims_info{node=~\"$node\", namespace=\"$namespace\", pod=~\"$pod\"}[$__range]))", + "description": null, + "error": null, + "hide": 2, + "includeAll": true, + "label": "PersistentVolumeClaim", + "multi": true, + "name": "persistentvolumeclaim", + "options": [], + "query": { + "query": "query_result(max_over_time(kube_pod_spec_volumes_persistentvolumeclaims_info{node=~\"$node\", namespace=\"$namespace\", pod=~\"$pod\"}[$__range]))", + "refId": "main-persistentvolumeclaim-Variable-Query" + }, + "refresh": 2, + "regex": "/.*persistentvolumeclaim=\"([^\"]+)\".*/", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + } + ] + }, + "time": { + "from": "now-3h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "", + "title": "Namespace / Controller", + "uid": "IRPuf4ymk1", + "version": 2 +} diff --git a/dashboards/main/namespace.json b/dashboards/main/namespace.json new file mode 100644 index 00000000..eea95317 --- /dev/null +++ b/dashboards/main/namespace.json @@ -0,0 +1,4266 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "target": { + "limit": 100, + "matchAny": false, + "tags": [], + "type": "dashboard" + }, + "type": "dashboard" + } + ] + }, + "editable": false, + "fiscalYearStartMonth": 0, + "graphTooltip": 1, + "iteration": 1684513475244, + "links": [], + "liveNow": false, + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "description": "Note that this table shows the average values for the entire period selected in the dashboard. Consequently, it may contain information about Pods or namespaces that were changed or deleted during the selected period.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "displayMode": "auto", + "filterable": false, + "inspect": false, + "minWidth": 70 + }, + "decimals": 2, + "displayName": "", + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "controller" + }, + "properties": [ + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": "auto" + }, + { + "id": "displayName", + "value": "Controller" + }, + { + "id": "custom.width" + }, + { + "id": "links", + "value": [ + { + "targetBlank": true, + "title": "Controller Details", + "url": "/d/IRPuf4ymk1/controller?var-ds_prometheus=${ds_prometheus}&var-namespace=${namespace}&var-controller=${__value.raw}&${__url_time_range}" + } + ] + }, + { + "id": "custom.minWidth", + "value": 70 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #B" + }, + "properties": [ + { + "id": "displayName", + "value": "VPA Mode" + }, + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align" + }, + { + "id": "mappings", + "value": [ + { + "options": { + "0": { + "text": "Off" + }, + "1": { + "text": "Initial" + }, + "2": { + "text": "Auto" + }, + "3": { + "text": "Recreate" + }, + "5": { + "text": "-" + } + }, + "type": "value" + } + ] + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #C" + }, + "properties": [ + { + "id": "displayName", + "value": "CPU" + }, + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 3 + }, + { + "id": "custom.align" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #D" + }, + "properties": [ + { + "id": "displayName", + "value": "Req CPU" + }, + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #E" + }, + "properties": [ + { + "id": "displayName", + "value": "VPA CPU" + }, + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #F" + }, + "properties": [ + { + "id": "displayName", + "value": "Over-req CPU" + }, + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #G" + }, + "properties": [ + { + "id": "displayName", + "value": "Under-req CPU" + }, + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #H" + }, + "properties": [ + { + "id": "displayName", + "value": "Throttling cores" + }, + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #I" + }, + "properties": [ + { + "id": "displayName", + "value": "Memory" + }, + { + "id": "unit", + "value": "bytes" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #J" + }, + "properties": [ + { + "id": "displayName", + "value": "Req Memory" + }, + { + "id": "unit", + "value": "bytes" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #K" + }, + "properties": [ + { + "id": "displayName", + "value": "VPA Memory" + }, + { + "id": "unit", + "value": "bytes" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #L" + }, + "properties": [ + { + "id": "displayName", + "value": "Over-req Memory" + }, + { + "id": "unit", + "value": "bytes" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #M" + }, + "properties": [ + { + "id": "displayName", + "value": "Under-req Memory" + }, + { + "id": "unit", + "value": "bytes" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #N" + }, + "properties": [ + { + "id": "displayName", + "value": "RX Network" + }, + { + "id": "unit", + "value": "Bps" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align" + }, + { + "id": "mappings", + "value": [ + { + "options": { + "-1": { + "index": 0, + "text": "hostNet" + } + }, + "type": "value" + } + ] + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #O" + }, + "properties": [ + { + "id": "displayName", + "value": "TX Network" + }, + { + "id": "unit", + "value": "Bps" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align" + }, + { + "id": "mappings", + "value": [ + { + "options": { + "-1": { + "index": 0, + "text": "hostNet" + } + }, + "type": "value" + } + ] + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #P" + }, + "properties": [ + { + "id": "displayName", + "value": "Read IOPS" + }, + { + "id": "unit", + "value": "iops" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #Q" + }, + "properties": [ + { + "id": "displayName", + "value": "Write IOPS" + }, + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #R" + }, + "properties": [ + { + "id": "displayName", + "value": "Total replicas count" + }, + { + "id": "unit", + "value": "short" + }, + { + "id": "custom.align" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #S" + }, + "properties": [ + { + "id": "displayName", + "value": "Not ready replicas" + }, + { + "id": "unit", + "value": "short" + }, + { + "id": "custom.align" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #T" + }, + "properties": [ + { + "id": "displayName", + "value": "Pod Restarts" + }, + { + "id": "unit", + "value": "short" + }, + { + "id": "custom.align" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Controller" + }, + "properties": [ + { + "id": "custom.width", + "value": 230 + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 4, + "links": [], + "maxPerRow": 6, + "options": { + "footer": { + "fields": "", + "reducer": [ + "sum" + ], + "show": false + }, + "showHeader": true, + "sortBy": [] + }, + "pluginVersion": "8.5.13", + "repeatDirection": "h", + "targets": [ + { + "expr": "max by (job, namespace, controller, controller_name) (avg_over_time(kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller_type=~\"$controller_type\", controller=~\"$controller\"}[$__range]))", + "format": "table", + "hide": false, + "instant": true, + "interval": "", + "intervalFactor": 1, + "legendFormat": "Controller", + "refId": "A" + }, + { + "expr": "sum by (controller) (avg_over_time(kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller_type=~\"$controller_type\", controller=~\"$controller\"}[$__range]) * on (controller_type, controller_name) group_left() sum by (controller_type, controller_name) (avg_over_time(vpa_target_recommendation{namespace=\"$namespace\", update_mode=\"Off\"}[$__range]))) * 0\nor\nsum by (controller) (avg_over_time(kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller_type=~\"$controller_type\", controller=~\"$controller\"}[$__range]) * on (controller_type, controller_name) group_left() sum by (controller_type, controller_name) (avg_over_time(vpa_target_recommendation{namespace=\"$namespace\", update_mode=\"Initial\"}[$__range]))) * 0 + 1\nor\nsum by (controller) (avg_over_time(kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller_type=~\"$controller_type\", controller=~\"$controller\"}[$__range]) * on (controller_type, controller_name) group_left() sum by (controller_type, controller_name) (avg_over_time(vpa_target_recommendation{namespace=\"$namespace\", update_mode=\"Auto\"}[$__range]))) * 0 + 2\nor\nsum by (controller) (avg_over_time(kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller_type=~\"$controller_type\", controller=~\"$controller\"}[$__range]) * on (controller_type, controller_name) group_left() sum by (controller_type, controller_name) (avg_over_time(vpa_target_recommendation{namespace=\"$namespace\", update_mode=\"Recreate\"}[$__range]))) * 0 + 3\nor\nsum by (controller) (avg_over_time(kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller_type=~\"$controller_type\", controller=~\"$controller\"}[$__range])) * 0 + 5", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "legendFormat": "VPA Mode", + "refId": "B" + }, + { + "expr": "sum by (controller) (avg_over_time(kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller_type=~\"$controller_type\", controller=~\"$controller\"}[$__range]) * on (pod) group_left() sum by (pod) (rate(container_cpu_usage_seconds_total{node=~\"$node\", namespace=\"$namespace\", container!=\"POD\"}[$__range])))\nor\ncount (avg_over_time(kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller_type=~\"$controller_type\", controller=~\"$controller\"}[$__range])) by (controller) * 0", + "format": "table", + "instant": true, + "intervalFactor": 1, + "legendFormat": "CPU", + "refId": "C" + }, + { + "expr": "sum by (controller)\n (\n avg_over_time(kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller_type=~\"$controller_type\", controller=~\"$controller\"}[$__range])\n * on (pod) group_left()\n sum by (pod) (avg_over_time(kube_pod_container_resource_requests{resource=\"cpu\",unit=\"core\",node=~\"$node\", namespace=\"$namespace\"}[$__range]))\n )\nor\ncount (avg_over_time(kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller_type=~\"$controller_type\", controller=~\"$controller\"}[$__range])) by (controller) * 0", + "format": "table", + "instant": true, + "intervalFactor": 1, + "legendFormat": "Req CPU", + "refId": "D" + }, + { + "expr": "sum by (controller)\n (\n avg_over_time(kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller_type=~\"$controller_type\", controller=~\"$controller\"}[$__range])\n * on (controller_type, controller_name) group_left()\n sum by(controller_type, controller_name) (avg_over_time(vpa_target_recommendation{container!=\"POD\",namespace=\"$namespace\", resource=\"cpu\"}[$__range]))\n ) \nor\ncount (avg_over_time(kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller_type=~\"$controller_type\", controller=~\"$controller\"}[$__range])) by (controller) * 0", + "format": "table", + "instant": true, + "intervalFactor": 1, + "legendFormat": "VPA CPU", + "refId": "E" + }, + { + "expr": "sum by (controller)\n (\n avg_over_time(kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller_type=~\"$controller_type\", controller=~\"$controller\"}[$__range])\n * on (namespace, pod) group_left()\n sum by (namespace, pod)\n (\n (\n sum by(namespace, pod, container) (avg_over_time(kube_pod_container_resource_requests{resource=\"cpu\",unit=\"core\",node=~\"$node\", namespace=\"$namespace\"}[$__range]))\n -\n sum by(namespace, pod, container) (rate(container_cpu_usage_seconds_total{node=~\"$node\", container!=\"POD\", namespace=\"$namespace\"}[$__range]))\n ) > 0\n )\n )\nor\ncount (avg_over_time(kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller_type=~\"$controller_type\", controller=~\"$controller\"}[$__range])) by (controller) * 0", + "format": "table", + "instant": true, + "intervalFactor": 1, + "legendFormat": "Over-req CPU", + "refId": "F" + }, + { + "expr": "sum by (controller)\n (\n avg_over_time(kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller_type=~\"$controller_type\", controller=~\"$controller\"}[$__range])\n * on (namespace, pod) group_left()\n sum by (namespace, pod)\n (\n (\n (\n sum by(namespace, pod, container) (rate(container_cpu_usage_seconds_total{node=~\"$node\", namespace=\"$namespace\"}[$__range]))\n -\n sum by(namespace, pod, container) (avg_over_time(kube_pod_container_resource_requests{resource=\"cpu\",unit=\"core\",node=~\"$node\", container!=\"POD\", namespace=\"$namespace\"}[$__range]))\n ) or sum by(namespace, pod, container) (rate(container_cpu_usage_seconds_total{node=~\"$node\", container!=\"POD\", namespace=\"$namespace\"}[$__range]))\n ) > 0\n )\n )\nor\ncount (avg_over_time(kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller_type=~\"$controller_type\", controller=~\"$controller\"}[$__range])) by (controller) * 0", + "format": "table", + "instant": true, + "intervalFactor": 1, + "legendFormat": "Under-req CPU", + "refId": "G" + }, + { + "expr": "sum by (controller) (avg_over_time(kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller_type=~\"$controller_type\", controller=~\"$controller\"}[$__range]) * on (pod) group_left() ((sum by (pod) (rate(container_cpu_cfs_throttled_periods_total{node=~\"$node\", namespace=\"$namespace\"}[$__range])) / sum by (pod) (rate(container_cpu_cfs_periods_total{node=~\"$node\", namespace=\"$namespace\"}[$__range]))) * sum by (pod) (rate(kube_pod_container_resource_limits{resource=\"cpu\",unit=\"core\",node=~\"$node\", namespace=\"$namespace\"}[$__range]))))\nor\ncount (avg_over_time(kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller_type=~\"$controller_type\", controller=~\"$controller\"}[$__range])) by (controller) * 0", + "format": "table", + "instant": true, + "intervalFactor": 1, + "legendFormat": "Throttling cores", + "refId": "H" + }, + { + "expr": "sum by (controller) (avg_over_time(kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller_type=~\"$controller_type\", controller=~\"$controller\"}[$__range]) * on (pod) group_left() sum by (pod) (avg_over_time(container_memory_working_set_bytes:without_kmem{node=~\"$node\", namespace=\"$namespace\", container!=\"POD\"}[$__range])))\nor\ncount (avg_over_time(kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller_type=~\"$controller_type\", controller=~\"$controller\"}[$__range])) by (controller) * 0", + "format": "table", + "instant": true, + "intervalFactor": 1, + "legendFormat": "Memory", + "refId": "I" + }, + { + "expr": "sum by (controller)\n (\n avg_over_time(kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller_type=~\"$controller_type\", controller=~\"$controller\"}[$__range])\n * on (pod) group_left()\n sum by (namespace, pod)\n (\n avg_over_time(kube_pod_container_resource_requests{resource=\"memory\",unit=\"byte\",node=~\"$node\", namespace=\"$namespace\", container!=\"POD\"}[$__range])\n )\n )\n or\n count (avg_over_time(kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller_type=~\"$controller_type\", controller=~\"$controller\"}[$__range])) by (controller) * 0", + "format": "table", + "instant": true, + "intervalFactor": 1, + "legendFormat": "Req Memory", + "refId": "J" + }, + { + "expr": "sum by (controller)\n (\n avg_over_time(kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller_type=~\"$controller_type\", controller=~\"$controller\"}[$__range])\n * on (controller_type, controller_name) group_left()\n sum by(controller_type, controller_name) (avg_over_time(vpa_target_recommendation{container!=\"POD\",namespace=\"$namespace\", resource=\"memory\"}[$__range]))\n ) \n or \ncount (avg_over_time(kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller_type=~\"$controller_type\", controller=~\"$controller\"}[$__range])) by (controller) * 0", + "format": "table", + "instant": true, + "intervalFactor": 1, + "legendFormat": "VPA Memory", + "refId": "K" + }, + { + "expr": "sum by (controller)\n (\n avg_over_time(kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller_type=~\"$controller_type\", controller=~\"$controller\"}[$__range])\n * on (namespace, pod) group_left()\n sum by (namespace, pod)\n (\n (\n sum by(namespace, pod, container) (avg_over_time(kube_pod_container_resource_requests{resource=\"memory\",unit=\"byte\",node=~\"$node\", namespace=\"$namespace\"}[$__range]))\n -\n sum by(namespace, pod, container) (avg_over_time(container_memory_working_set_bytes:without_kmem{node=~\"$node\", container!=\"POD\", namespace=\"$namespace\"}[$__range]))\n ) > 0\n )\n )\nor\ncount (avg_over_time(kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller_type=~\"$controller_type\", controller=~\"$controller\"}[$__range])) by (controller) * 0", + "format": "table", + "instant": true, + "intervalFactor": 1, + "legendFormat": "Over-req Memory", + "refId": "L" + }, + { + "expr": "sum by (controller)\n (\n avg_over_time(kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller_type=~\"$controller_type\", controller=~\"$controller\"}[$__range])\n * on (namespace, pod) group_left()\n sum by (namespace, pod)\n (\n (\n (\n sum by(namespace, pod, container) (avg_over_time(container_memory_working_set_bytes:without_kmem{node=~\"$node\", namespace=\"$namespace\"}[$__range]))\n -\n sum by(namespace, pod, container) (avg_over_time(kube_pod_container_resource_requests{resource=\"memory\",unit=\"byte\",node=~\"$node\", container!=\"POD\", namespace=\"$namespace\"}[$__range]))\n ) or sum by(namespace, pod, container) (avg_over_time(container_memory_working_set_bytes:without_kmem{node=~\"$node\", container!=\"POD\", namespace=\"$namespace\"}[$__range]))\n ) > 0\n )\n )\nor\ncount (avg_over_time(kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller_type=~\"$controller_type\", controller=~\"$controller\"}[$__range])) by (controller) * 0", + "format": "table", + "instant": true, + "intervalFactor": 1, + "legendFormat": "Under-req Memory", + "refId": "M" + }, + { + "expr": "sum by(controller) ( # Data rate of the controller is a sum of data rates from its Pods.\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller_type=~\"$controller_type\", controller=~\"$controller\"} \n * on(pod)\n group_left() # Do not drop controller label from kube_controller_pod.\n sum by(pod) # Use sum if there are multiple interaces in the Pod.\n (\n rate(container_network_receive_bytes_total{node=~\"$node\", namespace=\"$namespace\"}[$__range])\n * # Select only Pods with 'hostNetwork: false', because receive_bytes values are meaningful only for Pods with hostNetwork: false.\n on(pod)\n kube_pod_info{host_network=\"false\", namespace=\"$namespace\"}\n )\n)\nor # Return -1 value for Pods with 'hostNetwork: true' to rewrite by value mapping.\n# Use max to get one '-1' per controller\n(max by(controller) (\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller_type=~\"$controller_type\", controller=~\"$controller\"}\n * on(pod)\n group_left() # Do not drop controller label from kube_controller_pod.\n (kube_pod_info{host_network=\"true\", namespace=\"$namespace\"})\n) * -1)", + "format": "table", + "instant": true, + "intervalFactor": 1, + "legendFormat": "RX Network", + "refId": "N" + }, + { + "expr": "sum by(controller) ( # Data rate of the controller is a sum of data rates from its Pods.\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller_type=~\"$controller_type\", controller=~\"$controller\"} \n * on(pod)\n group_left() # Do not drop controller label from kube_controller_pod.\n sum by(pod) # Use sum if there are multiple interaces in the Pod.\n (\n rate(container_network_transmit_bytes_total{node=~\"$node\", namespace=\"$namespace\"}[$__range])\n * # Select only Pods with 'hostNetwork: false', because receive_bytes values are meaningful only for Pods with hostNetwork: false.\n on(pod)\n kube_pod_info{host_network=\"false\", namespace=\"$namespace\"}\n )\n)\nor # Return -1 value for Pods with 'hostNetwork: true' to rewrite by value mapping.\n# Use max to get one '-1' per controller\n(max by(controller) (\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller_type=~\"$controller_type\", controller=~\"$controller\"}\n * on(pod)\n group_left() # Do not drop controller label from kube_controller_pod.\n (kube_pod_info{host_network=\"true\", namespace=\"$namespace\"})\n) * -1)", + "format": "table", + "instant": true, + "intervalFactor": 1, + "legendFormat": "TX Network", + "refId": "O" + }, + { + "expr": "sum by (controller) (avg_over_time(kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller_type=~\"$controller_type\", controller=~\"$controller\"}[$__range]) * on (pod) group_left() sum by (pod) (rate(container_fs_reads_total{node=~\"$node\", container!=\"POD\", namespace=\"$namespace\"}[$__range])))\nor\ncount (avg_over_time(kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller_type=~\"$controller_type\", controller=~\"$controller\"}[$__range])) by (controller) * 0", + "format": "table", + "instant": true, + "intervalFactor": 1, + "legendFormat": "Read IOPS", + "refId": "P" + }, + { + "expr": "sum by (controller) (avg_over_time(kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller_type=~\"$controller_type\", controller=~\"$controller\"}[$__range]) * on (pod) group_left() sum by (pod) (rate(container_fs_writes_total{node=~\"$node\", container!=\"POD\", namespace=\"$namespace\"}[$__range])))\nor\ncount (avg_over_time(kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller_type=~\"$controller_type\", controller=~\"$controller\"}[$__range])) by (controller) * 0", + "format": "table", + "instant": true, + "intervalFactor": 1, + "legendFormat": "Write IOPS", + "refId": "Q" + }, + { + "expr": "max by (controller) (max by (namespace, controller_type, controller_name, controller) (avg_over_time(kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller_type=~\"$controller_type\", controller=~\"$controller\"}[$__range])) * on (namespace, controller_type, controller_name) group_left() max by (namespace, controller_type, controller_name) (avg_over_time(kube_controller_replicas{node=~\"$node\", namespace=\"$namespace\"}[$__range])))\nor\ncount (avg_over_time(kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller_type=~\"$controller_type\", controller=~\"$controller\"}[$__range])) by (controller) * 0", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "legendFormat": "Total replicas count", + "refId": "R" + }, + { + "expr": "max by (job, namespace, controller_type, controller_name, controller) ((max by (job, namespace, controller_type, controller_name, controller) (avg_over_time(kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller_type=~\"$controller_type\", controller=~\"$controller\"}[$__range]))) * on (job, namespace, controller_type, controller_name) group_right(controller)\n(avg_over_time(kube_controller_replicas[$__range]) - avg_over_time(kube_controller_replicas_ready[$__range])))\nor\nmax by (job, namespace, controller_type, controller_name, controller) (avg_over_time(kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller_type=~\"$controller_type\", controller=~\"$controller\"}[$__range])) * 0", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "legendFormat": "Not ready replicas", + "refId": "S" + }, + { + "expr": "sum by (controller) \n (\n avg_over_time(kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller_type=~\"$controller_type\", controller=~\"$controller\"}[$__range])\n * on (pod) group_left()\n sum by (pod) (increase(kube_pod_container_status_restarts_total{node=~\"$node\", namespace=\"$namespace\"}[$__range]))\n )\nor\ncount (avg_over_time(kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller_type=~\"$controller_type\", controller=~\"$controller\"}[$__range])) by (controller) * 0", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "legendFormat": "Pod restart count", + "refId": "T" + }, + { + "expr": "sum by (controller) (avg_over_time(kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller_type=~\"$controller_type\", controller=~\"$controller\"}[$__range]) * on (pod) group_left() sum by (pod) (avg_over_time(container_memory:kmem{node=~\"$node\", namespace=\"$namespace\", container!=\"POD\"}[$__range])))\nor\ncount (avg_over_time(kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller_type=~\"$controller_type\", controller=~\"$controller\"}[$__range])) by (controller) * 0", + "format": "table", + "instant": true, + "intervalFactor": 1, + "legendFormat": "Memory", + "refId": "U" + } + ], + "title": "Controllers", + "transformations": [ + { + "id": "merge", + "options": {} + }, + { + "id": "filterFieldsByName", + "options": { + "include": { + "names": [ + "controller", + "Value #B", + "Value #C", + "Value #D", + "Value #E", + "Value #F", + "Value #G", + "Value #H", + "Value #I", + "Value #J", + "Value #K", + "Value #L", + "Value #M", + "Value #N", + "Value #O", + "Value #P", + "Value #Q", + "Value #R", + "Value #S", + "Value #T" + ] + } + } + }, + { + "id": "sortBy", + "options": { + "fields": {}, + "sort": [ + { + "field": "controller" + } + ] + } + } + ], + "type": "table" + }, + { + "cards": { + "cardHSpacing": 2, + "cardMinWidth": 5, + "cardVSpacing": 2 + }, + "color": { + "cardColor": "#b4ff00", + "colorScale": "sqrt", + "colorScheme": "interpolateGnYlRd", + "defaultColor": "#757575", + "exponent": 0.5, + "mode": "discrete", + "thresholds": [ + { + "color": "#bf1b00", + "tooltip": "100% not ready", + "value": "0" + }, + { + "color": "#508642", + "tooltip": "100% ready", + "value": "1" + }, + { + "color": "#ea6460", + "tooltip": "60-99% not ready", + "value": "2" + }, + { + "color": "#e5ac0e", + "tooltip": "30-59% not ready", + "value": "3" + }, + { + "color": "#f4d598", + "tooltip": "1-29% not ready", + "value": "4" + } + ] + }, + "datasource": { + "uid": "$ds_prometheus" + }, + "gridPos": { + "h": 8, + "w": 24, + "x": 0, + "y": 8 + }, + "hideBranding": false, + "highlightCards": true, + "id": 223, + "legend": { + "show": true + }, + "links": [], + "nullPointMode": "as empty", + "pageSize": 15, + "seriesFilterIndex": -1, + "statusmap": { + "ConfigVersion": "v1" + }, + "targets": [ + { + "expr": "((max by (job, namespace, controller_type, controller_name, controller) (kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller_type=~\"$controller_type\", controller=~\"$controller\"})) * on (job, namespace, controller_type, controller_name) group_right(controller) \n(kube_controller_replicas_ready/kube_controller_replicas == 1)) * 1", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{ controller }}", + "refId": "A" + }, + { + "expr": "((max by (job, namespace, controller_type, controller_name, controller) (kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller_type=~\"$controller_type\", controller=~\"$controller\"})) * on (job, namespace, controller_type, controller_name) group_right(controller) \n((kube_controller_replicas_ready/kube_controller_replicas > 0) and (kube_controller_replicas_ready/kube_controller_replicas < 0.3)) > bool 0) * 2", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{ controller }}", + "refId": "B" + }, + { + "expr": "((max by (job, namespace, controller_type, controller_name, controller) (kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller_type=~\"$controller_type\", controller=~\"$controller\"})) * on (job, namespace, controller_type, controller_name) group_right(controller) \n((kube_controller_replicas_ready/kube_controller_replicas >= 0.3) and (kube_controller_replicas_ready/kube_controller_replicas < 0.6)) > bool 0) * 3", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{ controller }}", + "refId": "C" + }, + { + "expr": "((max by (job, namespace, controller_type, controller_name, controller) (kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller_type=~\"$controller_type\", controller=~\"$controller\"})) * on (job, namespace, controller_type, controller_name) group_right(controller) \n((kube_controller_replicas_ready/kube_controller_replicas >= 0.6) and (kube_controller_replicas_ready/kube_controller_replicas < 1)) > bool 0) * 4", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{ controller }}", + "refId": "D" + }, + { + "expr": "((max by (job, namespace, controller_type, controller_name, controller) (kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller_type=~\"$controller_type\", controller=~\"$controller\"})) * on (job, namespace, controller_type, controller_name) group_right(controller)\n(kube_controller_replicas_ready/kube_controller_replicas == 0)) * 5", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{ controller }}", + "refId": "E" + } + ], + "title": "Status", + "tooltip": { + "extraInfo": "", + "freezeOnClick": true, + "items": [], + "show": true, + "showExtraInfo": false, + "showItems": false + }, + "type": "flant-statusmap-panel", + "useMax": true, + "usingPagination": false, + "xAxis": { + "show": true + }, + "yAxis": { + "maxWidth": -1, + "minWidth": -1, + "show": true + }, + "yAxisSort": "metrics", + "yLabel": { + "delimiter": "", + "labelTemplate": "", + "usingSplitLabel": false + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": { + "uid": "$ds_prometheus" + }, + "decimals": 0, + "description": "The number of Pods controlled by the Controller", + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 12, + "x": 0, + "y": 16 + }, + "hiddenSeries": false, + "id": 794, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.5.13", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum by (controller) \n (\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller_type=~\"$controller_type\", controller=~\"$controller\"}\n * on (pod) group_left()\n sum by (pod) (max_over_time(kube_pod_info{node=~\"$node\", namespace=\"$namespace\"}[$__rate_interval]))\n )", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{ controller }}", + "refId": "A" + }, + { + "expr": "sum \n (\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller_type=~\"$controller_type\", controller=~\"$controller\"}\n * on (pod) group_left()\n sum by (pod) (max_over_time(kube_pod_info{node=~\"$node\", namespace=\"$namespace\"}[$__rate_interval]))\n )", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "B" + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Pods count", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 0, + "format": "short", + "label": "", + "logBase": 1, + "min": "0", + "show": true + }, + { + "format": "short", + "logBase": 1, + "show": false + } + ], + "yaxis": { + "align": false + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": { + "uid": "$ds_prometheus" + }, + "decimals": 0, + "description": "The number of Pod restarts", + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 12, + "x": 12, + "y": 16 + }, + "hiddenSeries": false, + "id": 661, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.5.13", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum by (controller) \n (\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller_type=~\"$controller_type\", controller=~\"$controller\"}\n * on (pod) group_left()\n sum by (pod) (increase(kube_pod_container_status_restarts_total{node=~\"$node\", namespace=\"$namespace\"}[$__rate_interval]))\n )", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{ controller }}", + "refId": "A" + }, + { + "expr": "sum \n (\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller_type=~\"$controller_type\", controller=~\"$controller\"}\n * on (pod) group_left()\n sum by (pod) (increase(kube_pod_container_status_restarts_total{node=~\"$node\", namespace=\"$namespace\"}[$__rate_interval]))\n )", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "B" + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Pods restarts", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 0, + "format": "short", + "label": "", + "logBase": 1, + "min": "0", + "show": true + }, + { + "format": "short", + "logBase": 1, + "show": false + } + ], + "yaxis": { + "align": false + } + }, + { + "collapsed": false, + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 20 + }, + "id": 8, + "panels": [], + "title": "CPU", + "type": "row" + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": { + "uid": "$ds_prometheus" + }, + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 21 + }, + "hiddenSeries": false, + "id": 6, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.5.13", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": true, + "targets": [ + { + "expr": "sum by (controller) (kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller_type=~\"$controller_type\", controller=~\"$controller\"} * on (pod) group_left() sum by (pod) (rate(container_cpu_usage_seconds_total{node=~\"$node\", namespace=\"$namespace\", container!=\"POD\"}[$__rate_interval])))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{ controller }}", + "refId": "A" + }, + { + "expr": "sum (sum by (controller) (kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller_type=~\"$controller_type\", controller=~\"$controller\"} * on (pod) group_left() sum by (pod) (rate(container_cpu_usage_seconds_total{node=~\"$node\", namespace=\"$namespace\", container!=\"POD\"}[$__rate_interval]))))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "B" + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Usage by controller", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "cores", + "logBase": 1, + "min": "0", + "show": true + }, + { + "format": "short", + "logBase": 1, + "show": true + } + ], + "yaxis": { + "align": false + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": { + "uid": "$ds_prometheus" + }, + "description": "The total value may not equal the sum of system and user times because of the kernel's cgroup accounting peculiarities. Read more here: https://www.kernel.org/doc/Documentation/cgroup-v1/cpuacct.txt", + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 21 + }, + "hiddenSeries": false, + "id": 10, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.5.13", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + }, + { + "alias": "System", + "color": "#e24d42" + }, + { + "alias": "User", + "color": "#1f78c1" + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": true, + "targets": [ + { + "expr": "sum (sum by (controller) (kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller_type=~\"$controller_type\", controller=~\"$controller\"} * on (pod) group_left() sum by (pod) (rate(container_cpu_system_seconds_total{node=~\"$node\", namespace=\"$namespace\", container!=\"POD\"}[$__rate_interval]))))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "System", + "refId": "A" + }, + { + "expr": "sum (sum by (controller) (kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller_type=~\"$controller_type\", controller=~\"$controller\"} * on (pod) group_left() sum by (pod) (rate(container_cpu_user_seconds_total{node=~\"$node\", namespace=\"$namespace\", container!=\"POD\"}[$__rate_interval]))))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "User", + "refId": "B" + }, + { + "expr": "sum (sum by (controller) (kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller_type=~\"$controller_type\", controller=~\"$controller\"} * on (pod) group_left() sum by (pod) (rate(container_cpu_usage_seconds_total{node=~\"$node\", namespace=\"$namespace\", container!=\"POD\"}[$__rate_interval]))))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "D" + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Usage by state", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "cores", + "logBase": 1, + "min": "0", + "show": true + }, + { + "format": "short", + "logBase": 1, + "show": true + } + ], + "yaxis": { + "align": false + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": { + "uid": "$ds_prometheus" + }, + "description": "This graph shows the requested CPU resources higher than the actual CPU consumption. In other words, it shows CPU resources that can be \"freed\" without affecting the service.", + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 30 + }, + "hiddenSeries": false, + "id": 404, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.5.13", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": true, + "targets": [ + { + "expr": "sum by (controller)\n (\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller_type=~\"$controller_type\", controller=~\"$controller\"}\n * on (namespace, pod) group_left()\n sum by (namespace, pod)\n (\n (\n sum by(namespace, pod, container) (avg_over_time(kube_pod_container_resource_requests{resource=\"cpu\",unit=\"core\",node=~\"$node\", namespace=\"$namespace\"}[$__rate_interval]))\n -\n sum by(namespace, pod, container) (rate(container_cpu_usage_seconds_total{node=~\"$node\", container!=\"POD\", namespace=\"$namespace\"}[$__rate_interval]))\n ) > 0\n )\n )", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{ controller }}", + "refId": "A" + }, + { + "expr": "sum\n (\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller_type=~\"$controller_type\", controller=~\"$controller\"}\n * on (namespace, pod) group_left()\n sum by (namespace, pod)\n (\n (\n sum by(namespace, pod, container) (avg_over_time(kube_pod_container_resource_requests{resource=\"cpu\",unit=\"core\",node=~\"$node\", namespace=\"$namespace\"}[$__rate_interval]))\n -\n sum by(namespace, pod, container) (rate(container_cpu_usage_seconds_total{node=~\"$node\", container!=\"POD\", namespace=\"$namespace\"}[$__rate_interval]))\n ) > 0\n )\n )", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "B" + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Over-requested by controller", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:149", + "format": "short", + "label": "cores", + "logBase": 1, + "min": "0", + "show": true + }, + { + "$$hashKey": "object:150", + "format": "short", + "logBase": 1, + "show": true + } + ], + "yaxis": { + "align": false + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": { + "uid": "$ds_prometheus" + }, + "description": "This graph shows the requested CPU resources lower than the actual CPU consumption. In other words, it shows CPU resources that need to be \"reserved\" for the service to run smoothly.", + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 30 + }, + "hiddenSeries": false, + "id": 538, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.5.13", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": true, + "targets": [ + { + "expr": "sum by (controller)\n (\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller_type=~\"$controller_type\", controller=~\"$controller\"}\n * on (namespace, pod) group_left()\n sum by (namespace, pod)\n (\n (\n (\n sum by(namespace, pod, container) (rate(container_cpu_usage_seconds_total{node=~\"$node\", namespace=\"$namespace\"}[$__rate_interval]))\n -\n sum by(namespace, pod, container) (avg_over_time(kube_pod_container_resource_requests{resource=\"cpu\",unit=\"core\",node=~\"$node\", container!=\"POD\", namespace=\"$namespace\"}[$__rate_interval]))\n ) or sum by(namespace, pod, container) (rate(container_cpu_usage_seconds_total{node=~\"$node\", container!=\"POD\", namespace=\"$namespace\"}[$__rate_interval]))\n ) > 0\n )\n )", + "format": "time_series", + "instant": false, + "intervalFactor": 1, + "legendFormat": "{{ controller }}", + "refId": "A" + }, + { + "expr": "sum\n (\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller_type=~\"$controller_type\", controller=~\"$controller\"}\n * on (namespace, pod) group_left()\n sum by (namespace, pod)\n (\n (\n (\n sum by(namespace, pod, container) (rate(container_cpu_usage_seconds_total{node=~\"$node\", namespace=\"$namespace\"}[$__rate_interval]))\n -\n sum by(namespace, pod, container) (avg_over_time(kube_pod_container_resource_requests{resource=\"cpu\",unit=\"core\",node=~\"$node\", container!=\"POD\", namespace=\"$namespace\"}[$__rate_interval]))\n ) or sum by(namespace, pod, container) (rate(container_cpu_usage_seconds_total{node=~\"$node\", container!=\"POD\", namespace=\"$namespace\"}[$__rate_interval]))\n ) > 0\n )\n )", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "B" + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Under-requested by controller", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "cores", + "logBase": 1, + "min": "0", + "show": true + }, + { + "format": "short", + "logBase": 1, + "show": true + } + ], + "yaxis": { + "align": false + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": { + "uid": "$ds_prometheus" + }, + "description": "The absence of data on the graph means that container resources are not set", + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 24, + "x": 0, + "y": 39 + }, + "hiddenSeries": false, + "id": 262, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": false, + "rightSide": true, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.5.13", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum by (controller) (kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller_type=~\"$controller_type\", controller=~\"$controller\"} * on (pod) group_left() ((sum by (pod) (rate(container_cpu_cfs_throttled_periods_total{node=~\"$node\", namespace=\"$namespace\"}[$__rate_interval])) / sum by (pod) (rate(container_cpu_cfs_periods_total{node=~\"$node\", namespace=\"$namespace\"}[$__rate_interval]))) * sum by (pod) (kube_pod_container_resource_limits{resource=\"cpu\",unit=\"core\",node=~\"$node\", namespace=\"$namespace\"})))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{ controller }}", + "refId": "A" + }, + { + "expr": "sum (sum by (controller) (kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller_type=~\"$controller_type\", controller=~\"$controller\"} * on (pod) group_left() ((sum by (pod) (rate(container_cpu_cfs_throttled_periods_total{node=~\"$node\", namespace=\"$namespace\"}[$__rate_interval])) / sum by (pod) (rate(container_cpu_cfs_periods_total{node=~\"$node\", namespace=\"$namespace\"}[$__rate_interval]))) * sum by (pod) (kube_pod_container_resource_limits{resource=\"cpu\",unit=\"core\",node=~\"$node\", namespace=\"$namespace\"}))))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "B" + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Throttling", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "cores", + "logBase": 1, + "min": "0", + "show": true + }, + { + "format": "short", + "logBase": 1, + "show": false + } + ], + "yaxis": { + "align": false + } + }, + { + "collapsed": true, + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 46 + }, + "id": 343, + "panels": [ + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "uid": "$ds_prometheus" + }, + "description": "", + "fill": 0, + "gridPos": { + "h": 9, + "w": 6, + "x": 0, + "y": 47 + }, + "id": 341, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": "controller", + "repeatDirection": "h", + "seriesOverrides": [ + { + "alias": "Usage", + "color": "#629e51" + }, + { + "alias": "Requests", + "color": "#f4d598" + }, + { + "alias": "Limits", + "color": "#c15c17" + }, + { + "alias": "VPA Target", + "color": "#447ebc" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "sum by (controller) (kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\"} * on (pod) group_left() sum by (pod) (rate(container_cpu_usage_seconds_total{node=~\"$node\", namespace=\"$namespace\", container!=\"POD\"}[$__rate_interval])))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Usage", + "refId": "D" + }, + { + "expr": "sum by (controller)\n (\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\"}\n * on (pod) group_left()\n sum by(pod) (avg_over_time(kube_pod_container_resource_requests{resource=\"cpu\",unit=\"core\",node=~\"$node\", container!=\"POD\",namespace=\"$namespace\"}[$__rate_interval]))\n )", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Requests", + "refId": "C" + }, + { + "expr": "sum by (controller)\n (\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\"}\n * on (pod) group_left()\n sum by(pod) (avg_over_time(kube_pod_container_resource_limits{resource=\"cpu\",unit=\"core\",node=~\"$node\", container!=\"POD\",namespace=\"$namespace\"}[$__rate_interval]))\n )", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Limits", + "refId": "E" + }, + { + "expr": "sum by (controller)\n (\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\"}\n * on (controller_type, controller_name) group_left()\n sum by(controller_type, controller_name) (avg_over_time(vpa_target_recommendation{container!=\"POD\",namespace=\"$namespace\", resource=\"cpu\"}[$__rate_interval]))\n )", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "VPA Target", + "refId": "F" + } + ], + "thresholds": [], + "timeRegions": [], + "title": "$controller", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "cores", + "logBase": 1, + "min": "0", + "show": true + }, + { + "format": "short", + "logBase": 1, + "show": true + } + ], + "yaxis": { + "align": false + } + } + ], + "title": "Controllers CPU", + "type": "row" + }, + { + "collapsed": true, + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 47 + }, + "id": 12, + "panels": [ + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": { + "uid": "$ds_prometheus" + }, + "description": "The total value may not equal the sum of system and user times because of the kernel's cgroup accounting peculiarities. Read more here: https://www.kernel.org/doc/Documentation/cgroup-v1/cpuacct.txt", + "fill": 1, + "gridPos": { + "h": 9, + "w": 6, + "x": 0, + "y": 48 + }, + "id": 14, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": "controller", + "repeatDirection": "h", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + }, + { + "alias": "System", + "color": "#e24d42" + }, + { + "alias": "User", + "color": "#1f78c1" + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": true, + "targets": [ + { + "expr": "sum by (controller) (kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\"} * on (pod) group_left() sum by (pod) (rate(container_cpu_system_seconds_total{node=~\"$node\", namespace=\"$namespace\", container!=\"POD\"}[$__rate_interval])))", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "System", + "refId": "A" + }, + { + "expr": "sum by (controller) (kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\"} * on (pod) group_left() sum by (pod) (rate(container_cpu_user_seconds_total{node=~\"$node\", namespace=\"$namespace\", container!=\"POD\"}[$__rate_interval])))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "User", + "refId": "B" + }, + { + "expr": "sum by (controller) (kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\"} * on (pod) group_left() sum by (pod) (rate(container_cpu_usage_seconds_total{node=~\"$node\", namespace=\"$namespace\", container!=\"POD\"}[$__rate_interval])))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "D" + } + ], + "thresholds": [], + "timeRegions": [], + "title": "$controller", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "cores", + "logBase": 1, + "min": "0", + "show": true + }, + { + "format": "short", + "logBase": 1, + "show": true + } + ], + "yaxis": { + "align": false + } + } + ], + "title": "Controllers CPU by state", + "type": "row" + }, + { + "collapsed": false, + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 48 + }, + "id": 38, + "panels": [], + "title": "Memory", + "type": "row" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 49 + }, + "hiddenSeries": false, + "id": 40, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.5.13", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "lines": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "expr": "sum by (controller)\n (\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller_type=~\"$controller_type\", controller=~\"$controller\"}\n * on (pod) group_left()\n sum by (pod) (avg_over_time(container_memory_working_set_bytes:without_kmem{node=~\"$node\", namespace=\"$namespace\", container!=\"POD\"}[$__rate_interval]))\n )", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{ controller }}", + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "expr": "sum\n (\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller_type=~\"$controller_type\", controller=~\"$controller\"}\n * on (pod) group_left()\n sum by (pod) (avg_over_time(container_memory_working_set_bytes:without_kmem{node=~\"$node\", namespace=\"$namespace\", container!=\"POD\"}[$__rate_interval]))\n )", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "B" + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Usage by controller", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:205", + "format": "bytes", + "logBase": 1, + "min": "0", + "show": true + }, + { + "$$hashKey": "object:206", + "format": "short", + "logBase": 1, + "show": false + } + ], + "yaxis": { + "align": false + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "uid": "$ds_prometheus" + }, + "description": "The Working set bytes metric is the actual memory used by the container, as it includes active file memory. When its value approaches the limit, the container can be killed by the OOM killer. This value can be higher than the sum RSS and Cache since not all active file memory is Cache.", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 49 + }, + "hiddenSeries": false, + "id": 41, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.5.13", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Working set bytes without kmem", + "color": "rgb(0, 0, 0)", + "dashes": true, + "fill": 0, + "linewidth": 2, + "stack": false + }, + { + "alias": "Kmem", + "color": "rgb(255, 0, 0)", + "dashes": true, + "fill": 0, + "linewidth": 2, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum\n (\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller_type=~\"$controller_type\", controller=~\"$controller\"}\n * on (pod) group_left()\n sum by (pod) (avg_over_time(container_memory_rss{node=~\"$node\", namespace=\"$namespace\", container!=\"POD\"}[$__rate_interval]))\n )", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "RSS", + "refId": "A" + }, + { + "expr": "sum \n (\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller_type=~\"$controller_type\", controller=~\"$controller\"}\n * on (pod) group_left()\n sum by (pod) (avg_over_time(container_memory_cache{node=~\"$node\", namespace=\"$namespace\", container!=\"POD\"}[$__rate_interval]))\n )", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "Cache", + "refId": "B" + }, + { + "expr": "sum \n (\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller_type=~\"$controller_type\", controller=~\"$controller\"}\n * on (pod) group_left()\n sum by (pod) (avg_over_time(container_memory_swap{node=~\"$node\", namespace=\"$namespace\", container!=\"POD\"}[$__rate_interval]))\n )", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "Swap", + "refId": "C" + }, + { + "expr": "sum \n (\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller_type=~\"$controller_type\", controller=~\"$controller\"}\n * on (pod) group_left()\n sum by (pod) (avg_over_time(container_memory_working_set_bytes:without_kmem{node=~\"$node\", namespace=\"$namespace\", container!=\"POD\"}[$__rate_interval]))\n )", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Working set bytes without kmem", + "refId": "D" + }, + { + "expr": "sum \n (\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller_type=~\"$controller_type\", controller=~\"$controller\"}\n * on (pod) group_left()\n sum by (pod) (avg_over_time(container_memory:kmem{node=~\"$node\", namespace=\"$namespace\", container!=\"POD\"}[$__rate_interval]))\n )", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Kmem", + "refId": "E" + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Usage by state", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "logBase": 1, + "min": "0", + "show": true + }, + { + "format": "short", + "logBase": 1, + "show": false + } + ], + "yaxis": { + "align": false + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "description": "This graph shows the requested Memory resources higher than the actual Memory consumption. In other words, it shows Memory resources that can be \"freed\" without affecting the service.", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 58 + }, + "hiddenSeries": false, + "id": 489, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.5.13", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "lines": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "expr": "sum by (controller)\n (\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller_type=~\"$controller_type\", controller=~\"$controller\"}\n * on (namespace, pod) group_left()\n sum by (namespace, pod)\n (\n (\n sum by(namespace, pod, container) (avg_over_time(kube_pod_container_resource_requests{resource=\"memory\",unit=\"byte\",node=~\"$node\", namespace=\"$namespace\"}[$__rate_interval]))\n -\n sum by(namespace, pod, container) (avg_over_time(container_memory_working_set_bytes:without_kmem{node=~\"$node\", container!=\"POD\", namespace=\"$namespace\"}[$__rate_interval]))\n ) > 0\n )\n )", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{ controller }}", + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "expr": "sum\n (\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller_type=~\"$controller_type\", controller=~\"$controller\"}\n * on (namespace, pod) group_left()\n sum by (namespace, pod)\n (\n (\n sum by(namespace, pod, container) (avg_over_time(kube_pod_container_resource_requests{resource=\"memory\",unit=\"byte\",node=~\"$node\", namespace=\"$namespace\"}[$__rate_interval]))\n -\n sum by(namespace, pod, container) (avg_over_time(container_memory_working_set_bytes:without_kmem{node=~\"$node\", container!=\"POD\", namespace=\"$namespace\"}[$__rate_interval]))\n ) > 0\n )\n )", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "B" + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Over-requested by controller", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:95", + "format": "bytes", + "logBase": 1, + "min": "0", + "show": true + }, + { + "$$hashKey": "object:96", + "format": "short", + "logBase": 1, + "show": false + } + ], + "yaxis": { + "align": false + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "uid": "$ds_prometheus" + }, + "description": "This graph shows the requested Memory resources higher than the actual Memory consumption. In other words, it shows Memory resources that need to be \"reserved\" for the service to run smoothly.", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 58 + }, + "hiddenSeries": false, + "id": 575, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.5.13", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "lines": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum by (controller)\n (\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller_type=~\"$controller_type\", controller=~\"$controller\"}\n * on (namespace, pod) group_left()\n sum by (namespace, pod)\n (\n (\n (\n sum by(namespace, pod, container) (avg_over_time(container_memory_working_set_bytes:without_kmem{node=~\"$node\", namespace=\"$namespace\"}[$__rate_interval]))\n -\n sum by(namespace, pod, container) (avg_over_time(kube_pod_container_resource_requests{resource=\"memory\",unit=\"byte\",node=~\"$node\", container!=\"POD\", namespace=\"$namespace\"}[$__rate_interval]))\n ) or sum by(namespace, pod, container) (avg_over_time(container_memory_working_set_bytes:without_kmem{node=~\"$node\", container!=\"POD\", namespace=\"$namespace\"}[$__rate_interval]))\n ) > 0\n )\n )", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{ controller }}", + "refId": "A" + }, + { + "expr": "sum\n (\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller_type=~\"$controller_type\", controller=~\"$controller\"}\n * on (namespace, pod) group_left()\n sum by (namespace, pod)\n (\n (\n (\n sum by(namespace, pod, container) (avg_over_time(container_memory_working_set_bytes:without_kmem{node=~\"$node\", namespace=\"$namespace\"}[$__rate_interval]))\n -\n sum by(namespace, pod, container) (avg_over_time(kube_pod_container_resource_requests{resource=\"memory\",unit=\"byte\",node=~\"$node\", container!=\"POD\", namespace=\"$namespace\"}[$__rate_interval]))\n ) or sum by(namespace, pod, container) (avg_over_time(container_memory_working_set_bytes:without_kmem{node=~\"$node\", container!=\"POD\", namespace=\"$namespace\"}[$__rate_interval]))\n ) > 0\n )\n )", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "B" + }, + { + "expr": "sum by (controller)\n (\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller_type=~\"$controller_type\", controller=~\"$controller\"}\n * on (namespace, pod) group_left()\n sum by (namespace, pod)\n (\n (\n (\n sum by(namespace, pod, container) (avg_over_time(container_memory_working_set_bytes:without_kmem{node=~\"$node\", namespace=\"$namespace\"}[$__rate_interval]))\n -\n sum by(namespace, pod, container) (avg_over_time(kube_pod_container_resource_requests{resource=\"memory\",unit=\"byte\",node=~\"$node\", container!=\"POD\", namespace=\"$namespace\"}[$__rate_interval]))\n ) or sum by(namespace, pod, container) (avg_over_time(container_memory:kmem{node=~\"$node\", container!=\"POD\", namespace=\"$namespace\"}[$__rate_interval]))\n ) > 0\n )\n )", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{ controller }}", + "refId": "C" + }, + { + "expr": "sum\n (\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller_type=~\"$controller_type\", controller=~\"$controller\"}\n * on (namespace, pod) group_left()\n sum by (namespace, pod)\n (\n (\n (\n sum by(namespace, pod, container) (avg_over_time(container_memory_working_set_bytes:without_kmem{node=~\"$node\", namespace=\"$namespace\"}[$__rate_interval]))\n -\n sum by(namespace, pod, container) (avg_over_time(kube_pod_container_resource_requests{resource=\"memory\",unit=\"byte\",node=~\"$node\", container!=\"POD\", namespace=\"$namespace\"}[$__rate_interval]))\n ) or sum by(namespace, pod, container) (avg_over_time(container_memory:kmem{node=~\"$node\", container!=\"POD\", namespace=\"$namespace\"}[$__rate_interval]))\n ) > 0\n )\n )", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "D" + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Under-requested by controller", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "logBase": 1, + "min": "0", + "show": true + }, + { + "format": "short", + "logBase": 1, + "show": false + } + ], + "yaxis": { + "align": false + } + }, + { + "collapsed": true, + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 66 + }, + "id": 43, + "panels": [ + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "uid": "$ds_prometheus" + }, + "description": "The Working set bytes metric is the actual memory used by the container, as it includes active file memory. When its value approaches the limit, the container can be killed by the OOM killer. This value can be higher than the sum RSS and Cache since not all active file memory is Cache.", + "fill": 1, + "gridPos": { + "h": 9, + "w": 6, + "x": 0, + "y": 67 + }, + "id": 44, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": "controller", + "repeatDirection": "h", + "seriesOverrides": [ + { + "alias": "Working set bytes without kmem", + "color": "rgb(0, 0, 0)", + "dashes": true, + "fill": 0, + "linewidth": 2, + "stack": false + }, + { + "alias": "Kmem", + "color": "rgb(255, 0, 0)", + "dashes": true, + "fill": 0, + "linewidth": 2, + "stack": false + }, + { + "alias": "VPA Target", + "color": "#447ebc", + "dashes": true, + "fill": 0, + "lines": false, + "linewidth": 2, + "stack": false + }, + { + "alias": "Requests", + "color": "#f4d598", + "dashes": true, + "fill": 0, + "lines": false, + "linewidth": 2, + "stack": false + }, + { + "alias": "Limits", + "color": "#c15c17", + "dashes": true, + "fill": 0, + "lines": false, + "linewidth": 2, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum \n (\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\"}\n * on (pod) group_left() \n sum by (pod) (avg_over_time(container_memory_rss{node=~\"$node\", namespace=\"$namespace\", container!=\"POD\"}[$__rate_interval]))\n )", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "RSS", + "refId": "A" + }, + { + "expr": "sum\n (\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\"} \n * on (pod) group_left() \n sum by (pod) (avg_over_time(container_memory_cache{node=~\"$node\", namespace=\"$namespace\", container!=\"POD\"}[$__rate_interval]))\n )", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "Cache", + "refId": "B" + }, + { + "expr": "sum \n (\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\"}\n * on (pod) group_left() \n sum by (pod) (avg_over_time(container_memory_swap{node=~\"$node\", namespace=\"$namespace\", container!=\"POD\"}[$__rate_interval]))\n )", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "Swap", + "refId": "C" + }, + { + "expr": "sum \n (\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\"}\n * on (pod) group_left()\n sum by (pod) (avg_over_time(container_memory_working_set_bytes:without_kmem{node=~\"$node\", namespace=\"$namespace\", container!=\"POD\"}[$__rate_interval]))\n )", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Working set bytes without kmem", + "refId": "D" + }, + { + "expr": "sum \n (\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\"}\n * on (pod) group_left()\n sum by(pod) (avg_over_time(kube_pod_container_resource_requests{resource=\"memory\",unit=\"byte\",node=~\"$node\", container!=\"POD\",namespace=\"$namespace\"}[$__rate_interval]))\n ) ", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Requests", + "refId": "E" + }, + { + "expr": "sum\n (\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\"} \n * on (pod) group_left() \n sum by(pod) (avg_over_time(kube_pod_container_resource_limits{resource=\"memory\",unit=\"byte\",node=~\"$node\", container!=\"POD\",namespace=\"$namespace\"}[$__rate_interval]))\n )", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Limits", + "refId": "F" + }, + { + "expr": "sum \n (\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\"}\n * on (controller_type, controller_name) group_left()\n sum by(controller_type, controller_name) (avg_over_time(vpa_target_recommendation{container!=\"POD\",namespace=\"$namespace\", resource=\"memory\"}[$__rate_interval]))\n )", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "VPA Target", + "refId": "G" + }, + { + "expr": "sum \n (\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\"}\n * on (pod) group_left()\n sum by (pod) (avg_over_time(container_memory:kmem{node=~\"$node\", namespace=\"$namespace\", container!=\"POD\"}[$__rate_interval]))\n )", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Kmem", + "refId": "H" + } + ], + "thresholds": [], + "timeRegions": [], + "title": "$controller", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "logBase": 1, + "min": "0", + "show": true + }, + { + "format": "short", + "logBase": 1, + "show": false + } + ], + "yaxis": { + "align": false + } + } + ], + "title": "Controllers Memory", + "type": "row" + }, + { + "collapsed": false, + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 67 + }, + "id": 77, + "panels": [], + "title": "Network", + "type": "row" + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": { + "uid": "$ds_prometheus" + }, + "description": "This graph shows Network Receive (except for the hostNetwork Pods)", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 68 + }, + "hiddenSeries": false, + "id": 79, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 2, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.5.13", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "# Data rate for the controller is a sum of data rates of its Pods.\nsum by (controller) (\n # Select Pods by controller_type and controller.\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller_type=~\"$controller_type\", controller=~\"$controller\"} \n * on (pod)\n group_left() # Preserve controller label from the 'kube_controller_pod' metric.\n (\n # Select Pods with hostNetwork: false.\n kube_pod_info{host_network=\"false\",namespace=\"$namespace\"}\n * on(pod)\n # Sum data rate for all interfaces in the Pod. \n sum by (pod) (rate(container_network_receive_bytes_total{node=~\"$node\", namespace=\"$namespace\"}[$__rate_interval]))\n )\n)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{ controller }}", + "refId": "A" + }, + { + "expr": "# Total is a sum of data rates of all Pods in selected containers.\nsum (\n # Select Pods by controller_type and controller.\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller_type=~\"$controller_type\", controller=~\"$controller\"} \n * on (pod)\n # Select Pods with hostNetwork: false.\n kube_pod_info{host_network=\"false\",namespace=\"$namespace\"}\n * on(pod)\n # Sum data rate for all interfaces in the Pod. \n sum by (pod) (rate(container_network_receive_bytes_total{node=~\"$node\", namespace=\"$namespace\"}[$__rate_interval]))\n)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "B" + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Receive", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "Bps", + "logBase": 1, + "min": "0", + "show": true + }, + { + "format": "short", + "logBase": 1, + "show": true + } + ], + "yaxis": { + "align": false + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": { + "uid": "$ds_prometheus" + }, + "description": "This graph shows Network Transmit (except for the hostNetwork Pods)", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 68 + }, + "hiddenSeries": false, + "id": 240, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 2, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.5.13", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "# Data rate for the controller is a sum of data rates of its Pods.\nsum by (controller) (\n # Select Pods by controller_type and controller.\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller_type=~\"$controller_type\", controller=~\"$controller\"} \n * on (pod)\n group_left() # Preserve controller label from the 'kube_controller_pod' metric.\n (\n # Select Pods with hostNetwork: false.\n kube_pod_info{host_network=\"false\",namespace=\"$namespace\"}\n * on(pod)\n # Sum data rate for all interfaces in the Pod. \n sum by (pod) (rate(container_network_transmit_bytes_total{node=~\"$node\", namespace=\"$namespace\"}[$__rate_interval]))\n )\n)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{ controller }}", + "refId": "A" + }, + { + "expr": "# Total is a sum of data rates of all Pods in selected containers.\nsum (\n # Select Pods by controller_type and controller.\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller_type=~\"$controller_type\", controller=~\"$controller\"} \n * on (pod)\n # Select Pods with hostNetwork: false.\n kube_pod_info{host_network=\"false\",namespace=\"$namespace\"}\n * on(pod)\n # Sum data rate for all interfaces in the Pod. \n sum by (pod) (rate(container_network_transmit_bytes_total{node=~\"$node\", namespace=\"$namespace\"}[$__rate_interval]))\n)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "B" + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Transmit", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "Bps", + "logBase": 1, + "min": "0", + "show": true + }, + { + "format": "short", + "logBase": 1, + "show": true + } + ], + "yaxis": { + "align": false + } + }, + { + "collapsed": false, + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 76 + }, + "id": 154, + "panels": [], + "title": "IOPS", + "type": "row" + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": { + "uid": "$ds_prometheus" + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 77 + }, + "hiddenSeries": false, + "id": 156, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.5.13", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum by (controller) (kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller_type=~\"$controller_type\", controller=~\"$controller\"} * on (pod) group_left() sum by (pod) (rate(container_fs_reads_total{node=~\"$node\", container!=\"POD\", namespace=\"$namespace\"}[$__rate_interval])))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{ controller }}", + "refId": "A" + }, + { + "expr": "sum (sum by (controller) (kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller_type=~\"$controller_type\", controller=~\"$controller\"} * on (pod) group_left() sum by (pod) (rate(container_fs_reads_total{node=~\"$node\", container!=\"POD\", namespace=\"$namespace\"}[$__rate_interval]))))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "B" + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Read", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "iops", + "logBase": 1, + "min": "0", + "show": true + }, + { + "format": "short", + "logBase": 1, + "show": false + } + ], + "yaxis": { + "align": false + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": { + "uid": "$ds_prometheus" + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 77 + }, + "hiddenSeries": false, + "id": 241, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.5.13", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum by (controller) (kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller_type=~\"$controller_type\", controller=~\"$controller\"} * on (pod) group_left() sum by (pod) (rate(container_fs_writes_total{node=~\"$node\", container!=\"POD\", namespace=\"$namespace\"}[$__rate_interval])))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{ controller }}", + "refId": "A" + }, + { + "expr": "sum (sum by (controller) (kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller_type=~\"$controller_type\", controller=~\"$controller\"} * on (pod) group_left() sum by (pod) (rate(container_fs_writes_total{node=~\"$node\", container!=\"POD\", namespace=\"$namespace\"}[$__rate_interval]))))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "B" + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Write", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "iops", + "logBase": 1, + "min": "0", + "show": true + }, + { + "format": "short", + "logBase": 1, + "show": false + } + ], + "yaxis": { + "align": false + } + }, + { + "collapsed": false, + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 84 + }, + "id": 595, + "panels": [], + "title": "PVC", + "type": "row" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "uid": "$ds_prometheus" + }, + "description": "This graph does not show any localstorage-related information due to incorrectly calculating the occupied space on localstorage disks", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 85 + }, + "hiddenSeries": false, + "id": 598, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "/Total/", + "fill": 0, + "linewidth": 2, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum by (namespace, controller) (\n max by (namespace, controller, persistentvolumeclaim)\n (\n sum by (namespace, persistentvolumeclaim) (\n max_over_time(kubelet_volume_stats_capacity_bytes{node=~\"$node\", namespace=\"$namespace\"}[$__rate_interval])\n ) \n\n * max by (namespace, persistentvolumeclaim) (\n label_replace(\n max_over_time(kube_persistentvolumeclaim_info{namespace=\"$namespace\"}[$__rate_interval]),\n \"persistentvolume\", \"$1\", \"volumename\", \"(.*)\")\n + on (persistentvolume) group_left() max by (persistentvolume) (kube_persistentvolume_is_local == 0)\n )\n\n * on (namespace, persistentvolumeclaim) group_left(pod) \n max by (namespace, persistentvolumeclaim, pod) (\n max_over_time(kube_pod_spec_volumes_persistentvolumeclaims_info{namespace=\"$namespace\"}[$__rate_interval])\n ) \n\n * on (namespace, pod) group_left(controller)\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=~\"$controller\"} \n )\n)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Provisioned {{ controller }}", + "refId": "A" + }, + { + "expr": "sum (\n sum by (namespace, persistentvolumeclaim) (\n max_over_time(kube_persistentvolumeclaim_resource_requests_storage_bytes{namespace=\"$namespace\"}[$__rate_interval])\n ) \n * \n sum by (namespace, persistentvolumeclaim) (\n label_replace(\n max_over_time(kube_persistentvolumeclaim_info{namespace=\"$namespace\"}[$__rate_interval]),\n \"persistentvolume\", \"$1\", \"volumename\", \"(.*)\")\n + on (persistentvolume) group_left() max by (persistentvolume) (kube_persistentvolume_is_local == 0)\n\n )\n unless\n sum by (namespace, persistentvolumeclaim) (\n max_over_time(kube_pod_spec_volumes_persistentvolumeclaims_info{namespace=\"$namespace\"}[$__rate_interval])\n ) \n) \nand (count (kube_node_info) == count (kube_node_info{node=~\"$node\"}))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Unused PVC", + "refId": "B" + }, + { + "expr": "sum (\n sum by (namespace, controller) (\n max by (namespace, controller, persistentvolumeclaim)\n (\n sum by (namespace, persistentvolumeclaim) (\n max_over_time(kubelet_volume_stats_capacity_bytes{node=~\"$node\", namespace=\"$namespace\"}[$__rate_interval])\n ) \n\n * max by (namespace, persistentvolumeclaim) (\n label_replace(\n max_over_time(kube_persistentvolumeclaim_info{namespace=\"$namespace\"}[$__rate_interval]),\n \"persistentvolume\", \"$1\", \"volumename\", \"(.*)\")\n + on (persistentvolume) group_left() max by (persistentvolume) (kube_persistentvolume_is_local == 0)\n\n )\n\n * on (namespace, persistentvolumeclaim) group_left(pod) \n max by (namespace, persistentvolumeclaim, pod) (\n max_over_time(kube_pod_spec_volumes_persistentvolumeclaims_info{namespace=\"$namespace\"}[$__rate_interval])\n ) \n\n * on (namespace, pod) group_left(controller)\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=~\"$controller\"} \n )\n )\n)\n+\n(sum (\n sum by (namespace, persistentvolumeclaim) (\n max_over_time(kube_persistentvolumeclaim_resource_requests_storage_bytes{namespace=\"$namespace\"}[$__rate_interval])\n ) \n * \n sum by (namespace, persistentvolumeclaim) (\n label_replace(\n max_over_time(kube_persistentvolumeclaim_info{namespace=\"$namespace\"}[$__rate_interval]),\n \"persistentvolume\", \"$1\", \"volumename\", \"(.*)\")\n + on (persistentvolume) group_left() max by (persistentvolume) (kube_persistentvolume_is_local == 0)\n\n )\n unless\n sum by (namespace, persistentvolumeclaim) (\n max_over_time(kube_pod_spec_volumes_persistentvolumeclaims_info{namespace=\"$namespace\"}[$__rate_interval])\n ) \n) * (count (kube_node_info) == bool count (kube_node_info{node=~\"$node\"})))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "C" + } + ], + "thresholds": [], + "timeRegions": [], + "title": "PVC Provisioned (except local storage classes)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "logBase": 1, + "min": "0", + "show": true + }, + { + "format": "short", + "logBase": 1, + "show": false + } + ], + "yaxis": { + "align": false + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "uid": "$ds_prometheus" + }, + "description": "This graph does not show any localstorage-related information due to incorrectly calculating the occupied space on localstorage disks", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 85 + }, + "hiddenSeries": false, + "id": 596, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "/Total/", + "fill": 0, + "linewidth": 2, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum by (namespace, controller) (\n max by (namespace, controller, persistentvolumeclaim)\n (\n sum by (namespace, persistentvolumeclaim) (\n max_over_time(kubelet_volume_stats_capacity_bytes{node=~\"$node\", namespace=\"$namespace\"}[$__rate_interval]) - max_over_time(kubelet_volume_stats_available_bytes{node=~\"$node\", namespace=\"$namespace\"}[$__rate_interval])\n ) \n\n * max by (namespace, persistentvolumeclaim) (\n label_replace(\n max_over_time(kube_persistentvolumeclaim_info{namespace=\"$namespace\"}[$__rate_interval]),\n \"persistentvolume\", \"$1\", \"volumename\", \"(.*)\")\n + on (persistentvolume) group_left() max by (persistentvolume) (kube_persistentvolume_is_local == 0)\n )\n\n * on (namespace, persistentvolumeclaim) group_left(pod) \n max by (namespace, persistentvolumeclaim, pod) (\n max_over_time(kube_pod_spec_volumes_persistentvolumeclaims_info{namespace=\"$namespace\"}[$__rate_interval])\n ) \n\n * on (namespace, pod) group_left(controller)\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=~\"$controller\"} \n )\n)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Usage {{ controller }}", + "refId": "A" + }, + { + "expr": "sum(\n sum by (namespace, controller) (\n max by (namespace, controller, persistentvolumeclaim)\n (\n sum by (namespace, persistentvolumeclaim) (\n max_over_time(kubelet_volume_stats_capacity_bytes{node=~\"$node\", namespace=\"$namespace\"}[$__rate_interval]) - max_over_time(kubelet_volume_stats_available_bytes{node=~\"$node\", namespace=\"$namespace\"}[$__rate_interval])\n ) \n\n * max by (namespace, persistentvolumeclaim) (\n label_replace(\n max_over_time(kube_persistentvolumeclaim_info{namespace=\"$namespace\"}[$__rate_interval]),\n \"persistentvolume\", \"$1\", \"volumename\", \"(.*)\")\n + on (persistentvolume) group_left() max by (persistentvolume) (kube_persistentvolume_is_local == 0)\n )\n\n * on (namespace, persistentvolumeclaim) group_left(pod) \n max by (namespace, persistentvolumeclaim, pod) (\n max_over_time(kube_pod_spec_volumes_persistentvolumeclaims_info{namespace=\"$namespace\"}[$__rate_interval])\n ) \n\n * on (namespace, pod) group_left(controller)\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=~\"$controller\"} \n )\n )\n)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "B" + } + ], + "thresholds": [], + "timeRegions": [], + "title": "PVC Usage (except local storage classes)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "logBase": 1, + "min": "0", + "show": true + }, + { + "format": "short", + "logBase": 1, + "show": false + } + ], + "yaxis": { + "align": false + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "uid": "$ds_prometheus" + }, + "description": "This graph does not show any localstorage-related information due to incorrectly calculating the occupied space on localstorage disks", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 24, + "x": 0, + "y": 92 + }, + "hiddenSeries": false, + "id": 597, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "/Total .*/", + "fill": 0, + "linewidth": 2 + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum by (namespace, controller) (\n max by (namespace, controller, persistentvolumeclaim)\n (\n sum by (namespace, persistentvolumeclaim) (\n max_over_time(kubelet_volume_stats_capacity_bytes{node=~\"$node\", namespace=\"$namespace\"}[$__rate_interval]) - max_over_time(kubelet_volume_stats_available_bytes{node=~\"$node\", namespace=\"$namespace\"}[$__rate_interval])\n ) \n\n * max by (namespace, persistentvolumeclaim) (\n label_replace(\n max_over_time(kube_persistentvolumeclaim_info{namespace=\"$namespace\"}[$__rate_interval]),\n \"persistentvolume\", \"$1\", \"volumename\", \"(.*)\")\n + on (persistentvolume) group_left() max by (persistentvolume) (kube_persistentvolume_is_local == 0)\n )\n\n * on (namespace, persistentvolumeclaim) group_left(pod) \n max by (namespace, persistentvolumeclaim, pod) (\n max_over_time(kube_pod_spec_volumes_persistentvolumeclaims_info{namespace=\"$namespace\"}[$__rate_interval])\n ) \n\n * on (namespace, pod) group_left(controller)\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=~\"$controller\"} \n )\n)\n/\nsum by (namespace, controller) (\n max by (namespace, controller, persistentvolumeclaim)\n (\n sum by (namespace, persistentvolumeclaim) (\n max_over_time(kubelet_volume_stats_capacity_bytes{node=~\"$node\", namespace=\"$namespace\"}[$__rate_interval])\n ) \n\n * max by (namespace, persistentvolumeclaim) (\n label_replace(\n max_over_time(kube_persistentvolumeclaim_info{namespace=\"$namespace\"}[$__rate_interval]),\n \"persistentvolume\", \"$1\", \"volumename\", \"(.*)\")\n + on (persistentvolume) group_left() max by (persistentvolume) (kube_persistentvolume_is_local == 0)\n )\n\n * on (namespace, persistentvolumeclaim) group_left(pod) \n max by (namespace, persistentvolumeclaim, pod) (\n max_over_time(kube_pod_spec_volumes_persistentvolumeclaims_info{namespace=\"$namespace\"}[$__rate_interval])\n ) \n\n * on (namespace, pod) group_left(controller)\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=~\"$controller\"} \n )\n)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Usage {{ controller }}", + "refId": "A" + } + ], + "thresholds": [], + "timeRegions": [], + "title": "PVC Usage in % (except local storage classes)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "percentunit", + "logBase": 1, + "min": "0", + "show": true + }, + { + "format": "short", + "logBase": 1, + "show": false + } + ], + "yaxis": { + "align": false + } + }, + { + "collapsed": true, + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 99 + }, + "id": 602, + "panels": [ + { + "datasource": { + "uid": "$ds_prometheus" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "displayMode": "auto" + }, + "decimals": 2, + "displayName": "", + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Time" + }, + "properties": [ + { + "id": "displayName", + "value": "Time" + }, + { + "id": "custom.align" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "persistentvolumeclaim" + }, + "properties": [ + { + "id": "displayName", + "value": "Name" + }, + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "storageclass" + }, + "properties": [ + { + "id": "displayName", + "value": "StorageClass" + }, + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #B" + }, + "properties": [ + { + "id": "displayName", + "value": "Requested" + }, + { + "id": "unit", + "value": "bytes" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #C" + }, + "properties": [ + { + "id": "displayName", + "value": "Provisioned" + }, + { + "id": "unit", + "value": "bytes" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #D" + }, + "properties": [ + { + "id": "displayName", + "value": "Capacity" + }, + { + "id": "unit", + "value": "bytes" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #E" + }, + "properties": [ + { + "id": "displayName", + "value": "Used bytes" + }, + { + "id": "unit", + "value": "bytes" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #F" + }, + "properties": [ + { + "id": "displayName", + "value": "Used inodes" + }, + { + "id": "unit", + "value": "short" + }, + { + "id": "custom.align" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #G" + }, + "properties": [ + { + "id": "displayName", + "value": "Used bytes (%)" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #H" + }, + "properties": [ + { + "id": "displayName", + "value": "Used inodes (%)" + }, + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "controller" + }, + "properties": [ + { + "id": "displayName", + "value": "Used by controller" + }, + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align" + } + ] + } + ] + }, + "gridPos": { + "h": 7, + "w": 24, + "x": 0, + "y": 100 + }, + "id": 600, + "links": [], + "options": { + "showHeader": true + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "max by (persistentvolumeclaim, storageclass) (\n max by (namespace, persistentvolumeclaim) (\n max by (namespace, persistentvolumeclaim, pod) (\n max_over_time(kube_pod_spec_volumes_persistentvolumeclaims_info{namespace=\"$namespace\"}[$__range])\n ) \n * on (namespace, pod) group_left(controller)\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=~\"$controller\"}\n )\n* on (namespace, persistentvolumeclaim) group_right() kube_persistentvolumeclaim_info{namespace=\"$namespace\"})", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "legendFormat": "Name, StorageClass", + "refId": "A" + }, + { + "expr": "max by (persistentvolumeclaim) (\n max by (namespace, persistentvolumeclaim) (\n max by (namespace, persistentvolumeclaim, pod) (\n max_over_time(kube_pod_spec_volumes_persistentvolumeclaims_info{namespace=\"$namespace\"}[$__range])\n ) \n * on (namespace, pod) group_left(controller)\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=~\"$controller\"}\n )\n* on (namespace, persistentvolumeclaim) group_right() kube_persistentvolumeclaim_resource_requests_storage_bytes{namespace=\"$namespace\"})", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "legendFormat": "Requested (pvc)", + "refId": "B" + }, + { + "expr": "max by (persistentvolumeclaim) (\n max by (namespace, persistentvolumeclaim) (\n max by (namespace, persistentvolumeclaim, pod) (\n max_over_time(kube_pod_spec_volumes_persistentvolumeclaims_info{namespace=\"$namespace\"}[$__range])\n ) \n * on (namespace, pod) group_left(controller)\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=~\"$controller\"}\n )\n)\n* on (persistentvolumeclaim) group_right()\n(\nmax by (persistentvolumeclaim) (\n max by (persistentvolume) (max_over_time(kube_persistentvolume_capacity_bytes[$__range])) \n * on (persistentvolume) group_right() \n max by (persistentvolume, persistentvolumeclaim) (\n label_replace(\n max_over_time(kube_persistentvolumeclaim_info{namespace=\"$namespace\"}[$__range]),\n \"persistentvolume\", \"$1\", \"volumename\", \"(.*)\")\n )\n)\n)", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "legendFormat": "Provisioned (pv)", + "refId": "C" + }, + { + "expr": "max by (persistentvolumeclaim) (\n max_over_time(kubelet_volume_stats_capacity_bytes{node=~\"$node\", namespace=\"$namespace\"}[$__range])\n)", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "legendFormat": "Capacity (real)", + "refId": "D" + }, + { + "expr": "max by (persistentvolumeclaim) (\n max_over_time(kubelet_volume_stats_capacity_bytes{node=~\"$node\", namespace=\"$namespace\"}[$__range]) - max_over_time(kubelet_volume_stats_available_bytes{node=~\"$node\", namespace=\"$namespace\"}[$__range])\n)", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "legendFormat": "used bytes", + "refId": "E" + }, + { + "expr": "max by (persistentvolumeclaim) (\n max_over_time(kubelet_volume_stats_inodes_used{node=~\"$node\", namespace=\"$namespace\"}[$__range])\n)", + "format": "table", + "instant": true, + "intervalFactor": 1, + "legendFormat": "used inodes", + "refId": "F" + }, + { + "expr": "max by (persistentvolumeclaim) (\n (max_over_time(kubelet_volume_stats_capacity_bytes{node=~\"$node\", namespace=\"$namespace\"}[$__range]) - max_over_time(kubelet_volume_stats_available_bytes{node=~\"$node\", namespace=\"$namespace\"}[$__range]))\n / \n max_over_time(kubelet_volume_stats_capacity_bytes{node=~\"$node\", namespace=\"$namespace\"}[$__range])\n)", + "format": "table", + "instant": true, + "intervalFactor": 1, + "legendFormat": "used bytes %", + "refId": "G" + }, + { + "expr": "max by (persistentvolumeclaim) (\n max_over_time(kubelet_volume_stats_inodes_used{node=~\"$node\", namespace=\"$namespace\"}[$__range]) \n / \n max_over_time(kubelet_volume_stats_inodes{node=~\"$node\", namespace=\"$namespace\"}[$__range])\n)", + "format": "table", + "instant": true, + "intervalFactor": 1, + "legendFormat": "used inodes %", + "refId": "H" + }, + { + "expr": "sum by (persistentvolumeclaim, controller) (\n max by (namespace, persistentvolumeclaim, pod) (\n max_over_time(kube_pod_spec_volumes_persistentvolumeclaims_info{namespace=\"$namespace\"}[$__rate_interval])\n ) \n * on (namespace, pod) group_left(controller)\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=~\"$controller\"} \n)", + "format": "table", + "instant": true, + "intervalFactor": 1, + "legendFormat": "used by controller", + "refId": "I" + } + ], + "title": "Overview", + "transformations": [ + { + "id": "merge", + "options": { + "reducers": [] + } + }, + { + "id": "filterFieldsByName", + "options": { + "include": { + "names": [ + "persistentvolumeclaim", + "storageclass", + "Value #B", + "Value #C", + "Value #D", + "Value #E", + "Value #F", + "Value #G", + "Value #H", + "controller" + ] + } + } + } + ], + "type": "table" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "uid": "$ds_prometheus" + }, + "description": "", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 24, + "x": 0, + "y": 107 + }, + "hiddenSeries": false, + "id": 603, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": "persistentvolumeclaim", + "repeatDirection": "h", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "\n\nmax by (persistentvolumeclaim) (\n max by (namespace, persistentvolumeclaim) (\n max by (namespace, persistentvolumeclaim, pod) (\n max_over_time(kube_pod_spec_volumes_persistentvolumeclaims_info{namespace=\"$namespace\"}[$__range])\n ) \n * on (namespace, pod) group_left(controller)\n kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=~\"$controller\"}\n )\n)\n* on (persistentvolumeclaim) group_right()\nmax by (persistentvolumeclaim) (\n max_over_time(kube_persistentvolume_capacity_bytes[$__rate_interval]) \n * on (persistentvolume) group_right() \n (\n label_replace(\n max_over_time(kube_persistentvolumeclaim_info{namespace=\"$namespace\", persistentvolumeclaim=~\"$persistentvolumeclaim\"}[$__rate_interval]),\n \"persistentvolume\", \"$1\", \"volumename\", \"(.*)\")\n )\n)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Provisioned", + "refId": "A" + }, + { + "expr": "max by (persistentvolumeclaim) (\n max_over_time(kubelet_volume_stats_capacity_bytes{node=~\"$node\", namespace=\"$namespace\", persistentvolumeclaim=\"$persistentvolumeclaim\"}[$__rate_interval])\n)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Capacity", + "refId": "B" + }, + { + "expr": "max by (persistentvolumeclaim) (\n max_over_time(kubelet_volume_stats_capacity_bytes{node=~\"$node\", namespace=\"$namespace\", persistentvolumeclaim=\"$persistentvolumeclaim\"}[$__rate_interval]) - max_over_time(kubelet_volume_stats_available_bytes{node=~\"$node\", namespace=\"$namespace\", persistentvolumeclaim=\"$persistentvolumeclaim\"}[$__rate_interval])\n)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Used", + "refId": "C" + } + ], + "thresholds": [], + "timeRegions": [], + "title": "$persistentvolumeclaim", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 2, + "format": "bytes", + "logBase": 1, + "min": "0", + "show": true + }, + { + "format": "short", + "logBase": 1, + "show": false + } + ], + "yaxis": { + "align": false + } + } + ], + "title": "PVC Detailed", + "type": "row" + } + ], + "refresh": "", + "schemaVersion": 36, + "style": "dark", + "tags": [ + "main" + ], + "templating": { + "list": [ + { + "current": { + "selected": false, + "text": "default", + "value": "default" + }, + "hide": 0, + "includeAll": false, + "label": "Prometheus", + "multi": false, + "name": "ds_prometheus", + "options": [], + "query": "prometheus", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + }, + { + "allValue": ".*", + "current": { + "selected": true, + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "definition": "label_values(kubernetes_build_info, node)", + "hide": 0, + "includeAll": true, + "label": "Node", + "multi": true, + "name": "node", + "options": [], + "query": { + "query": "label_values(kubernetes_build_info, node)", + "refId": "main-node-Variable-Query" + }, + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "current": { + "selected": false, + "text": "d8-monitoring", + "value": "d8-monitoring" + }, + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "definition": "label_values(kube_pod_info{node=~\"$node\"}, namespace)", + "hide": 0, + "includeAll": false, + "label": "Namespace", + "multi": false, + "name": "namespace", + "options": [], + "query": { + "query": "label_values(kube_pod_info{node=~\"$node\"}, namespace)", + "refId": "main-namespace-Variable-Query" + }, + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": ".*", + "current": { + "selected": true, + "text": [ + "All" + ], + "value": [ + ".*" + ] + }, + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "definition": "label_values(kube_controller_pod{node=~\"$node\", namespace=~\"$namespace\"}, controller_type)", + "hide": 0, + "includeAll": true, + "label": "Controller Type", + "multi": true, + "name": "controller_type", + "options": [], + "query": { + "query": "label_values(kube_controller_pod{node=~\"$node\", namespace=~\"$namespace\"}, controller_type)", + "refId": "main-controller_type-Variable-Query" + }, + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": ".*", + "current": { + "selected": false, + "text": "All", + "value": "$__all" + }, + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "definition": "label_values(kube_controller_pod{node=~\"$node\", namespace=~\"$namespace\", controller_type=~\"$controller_type\"}, controller)", + "hide": 0, + "includeAll": true, + "label": "Controller", + "multi": true, + "name": "controller", + "options": [], + "query": { + "query": "label_values(kube_controller_pod{node=~\"$node\", namespace=~\"$namespace\", controller_type=~\"$controller_type\"}, controller)", + "refId": "main-controller-Variable-Query" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": ".*", + "current": { + "selected": true, + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "definition": "label_values(kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\"}, pod)", + "hide": 2, + "includeAll": true, + "label": "Pod", + "multi": true, + "name": "pod", + "options": [], + "query": { + "query": "label_values(kube_controller_pod{node=~\"$node\", namespace=\"$namespace\", controller=\"$controller\"}, pod)", + "refId": "main-pod-Variable-Query" + }, + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": ".*", + "current": { + "selected": true, + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "definition": "query_result(max_over_time(kubelet_volume_stats_capacity_bytes{node=~\"$node\", namespace=\"$namespace\"}[$__range]))", + "hide": 2, + "includeAll": true, + "label": "PersistentVolumeClaim", + "multi": true, + "name": "persistentvolumeclaim", + "options": [], + "query": { + "query": "query_result(max_over_time(kubelet_volume_stats_capacity_bytes{node=~\"$node\", namespace=\"$namespace\"}[$__range]))", + "refId": "main-persistentvolumeclaim-Variable-Query" + }, + "refresh": 2, + "regex": "/.*persistentvolumeclaim=\"([^\"]+)\".*/", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + } + ] + }, + "time": { + "from": "now-3h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "", + "title": "Namespace", + "uid": "sZzUB4ymk1", + "version": 1, + "weekStart": "" +} diff --git a/dashboards/main/namespaces.json b/dashboards/main/namespaces.json new file mode 100644 index 00000000..19292d3b --- /dev/null +++ b/dashboards/main/namespaces.json @@ -0,0 +1,3812 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": "-- Grafana --", + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "target": { + "limit": 100, + "matchAny": false, + "tags": [], + "type": "dashboard" + }, + "type": "dashboard" + } + ] + }, + "editable": false, + "fiscalYearStartMonth": 0, + "gnetId": null, + "graphTooltip": 1, + "iteration": 1638543860824, + "links": [], + "liveNow": false, + "panels": [ + { + "columns": [], + "datasource": "$ds_prometheus", + "description": "Note that this table shows the average values for the entire period selected in the dashboard. Consequently, it may contain information about Pods or namespaces that were changed or deleted during the selected period.", + "fieldConfig": { + "defaults": { + "custom": { + "align": null, + "displayMode": "auto", + "filterable": false, + "minWidth": 50 + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "namespace" + }, + "properties": [ + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "displayName", + "value": "Namespace" + }, + { + "id": "custom.width" + }, + { + "id": "links", + "value": [ + { + "targetBlank": true, + "title": "Namespace Details", + "url": "/d/sZzUB4ymk1/namespace?var-ds_prometheus=${ds_prometheus}&var-namespace=${__value.raw}&${__url_time_range}" + } + ] + }, + { + "id": "custom.minWidth", + "value": 280 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #B" + }, + "properties": [ + { + "id": "displayName", + "value": "VPA %" + }, + { + "id": "unit", + "value": "percent" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "mappings", + "value": [] + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #C" + }, + "properties": [ + { + "id": "displayName", + "value": "CPU" + }, + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 3 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #D" + }, + "properties": [ + { + "id": "displayName", + "value": "Req CPU" + }, + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #E" + }, + "properties": [ + { + "id": "displayName", + "value": "Over-req CPU" + }, + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #F" + }, + "properties": [ + { + "id": "displayName", + "value": "Under-req CPU" + }, + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #G" + }, + "properties": [ + { + "id": "displayName", + "value": "Throttling cores" + }, + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #H" + }, + "properties": [ + { + "id": "displayName", + "value": "Memory" + }, + { + "id": "unit", + "value": "bytes" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #I" + }, + "properties": [ + { + "id": "displayName", + "value": "Req Memory" + }, + { + "id": "unit", + "value": "bytes" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #J" + }, + "properties": [ + { + "id": "displayName", + "value": "Over-req Memory" + }, + { + "id": "unit", + "value": "bytes" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #K" + }, + "properties": [ + { + "id": "displayName", + "value": "Under-req Memory" + }, + { + "id": "unit", + "value": "bytes" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #L" + }, + "properties": [ + { + "id": "displayName", + "value": "RX Network" + }, + { + "id": "unit", + "value": "Bps" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #M" + }, + "properties": [ + { + "id": "displayName", + "value": "TX Network" + }, + { + "id": "unit", + "value": "Bps" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #N" + }, + "properties": [ + { + "id": "displayName", + "value": "Read IOPS" + }, + { + "id": "unit", + "value": "iops" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #O" + }, + "properties": [ + { + "id": "displayName", + "value": "Write IOPS" + }, + { + "id": "unit", + "value": "iops" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #P" + }, + "properties": [ + { + "id": "displayName", + "value": "Pod Restarts" + }, + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #Q" + }, + "properties": [ + { + "id": "displayName", + "value": "Write IOPS" + }, + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #R" + }, + "properties": [ + { + "id": "displayName", + "value": "Total replicas count" + }, + { + "id": "unit", + "value": "short" + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #S" + }, + "properties": [ + { + "id": "displayName", + "value": "Not ready replicas" + }, + { + "id": "unit", + "value": "short" + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #T" + }, + "properties": [ + { + "id": "displayName", + "value": "Pod Restarts" + }, + { + "id": "unit", + "value": "short" + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Controller" + }, + "properties": [ + { + "id": "custom.width", + "value": 212 + } + ] + } + ] + }, + "fontSize": "100%", + "gridPos": { + "h": 8, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 4, + "links": [], + "options": { + "showHeader": true + }, + "pageSize": 50, + "pluginVersion": "8.2.3", + "scroll": true, + "showHeader": true, + "sort": { + "col": 4, + "desc": true + }, + "styles": [ + { + "alias": "Time", + "align": "auto", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "pattern": "Time", + "type": "hidden" + }, + { + "alias": "Namespace", + "align": "auto", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": true, + "linkTargetBlank": true, + "linkTooltip": "Namespace", + "linkUrl": "/d/sZzUB4ymk1/namespace?var-ds_prometheus=${ds_prometheus}&var-namespace=${__value.raw}&${__url_time_range}", + "mappingType": 1, + "pattern": "namespace", + "thresholds": [], + "type": "string", + "unit": "short" + }, + { + "alias": "VPA %", + "align": "auto", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "Value #B", + "thresholds": [], + "type": "number", + "unit": "percent" + }, + { + "alias": "CPU", + "align": "auto", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "Value #C", + "thresholds": [], + "type": "number", + "unit": "short" + }, + { + "alias": "Req CPU", + "align": "auto", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 3, + "mappingType": 1, + "pattern": "Value #D", + "thresholds": [], + "type": "number", + "unit": "short" + }, + { + "alias": "Over-req CPU", + "align": "auto", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "Value #E", + "thresholds": [], + "type": "number", + "unit": "short" + }, + { + "alias": "Under-req CPU", + "align": "auto", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "Value #F", + "thresholds": [], + "type": "number", + "unit": "short" + }, + { + "alias": "Throttling cores", + "align": "auto", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "Value #G", + "thresholds": [], + "type": "number", + "unit": "short" + }, + { + "alias": "Memory", + "align": "auto", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "Value #H", + "thresholds": [], + "type": "number", + "unit": "bytes" + }, + { + "alias": "Req Memory", + "align": "auto", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "Value #I", + "thresholds": [], + "type": "number", + "unit": "bytes" + }, + { + "alias": "Over-req Memory", + "align": "auto", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "Value #J", + "thresholds": [], + "type": "number", + "unit": "bytes" + }, + { + "alias": "Under-req Memory", + "align": "auto", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "Value #K", + "thresholds": [], + "type": "number", + "unit": "bytes" + }, + { + "alias": "RX Network", + "align": "auto", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "Value #L", + "thresholds": [], + "type": "number", + "unit": "Bps" + }, + { + "alias": "TX Network", + "align": "auto", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "Value #M", + "thresholds": [], + "type": "number", + "unit": "Bps" + }, + { + "alias": "Read IOPS", + "align": "auto", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "Value #N", + "thresholds": [], + "type": "number", + "unit": "iops" + }, + { + "alias": "Write IOPS", + "align": "auto", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "Value #O", + "thresholds": [], + "type": "number", + "unit": "iops" + }, + { + "alias": "Pod Restarts", + "align": "auto", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 0, + "mappingType": 1, + "pattern": "Value #P", + "thresholds": [], + "type": "number", + "unit": "short" + }, + { + "alias": "", + "align": "auto", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "/.*/", + "thresholds": [], + "type": "hidden", + "unit": "short" + } + ], + "targets": [ + { + "expr": "max by (namespace) (avg_over_time(kube_controller_pod{node=~\"$node\", namespace=~\"$namespace\"}[$__range]))", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "legendFormat": "Namespace", + "refId": "A" + }, + { + "expr": "100 * count by (namespace) (\n sum by (namespace, verticalpodautoscaler) ( \n count by (namespace, controller_name, verticalpodautoscaler) (avg_over_time(vpa_target_recommendation{namespace=~\"$namespace\", container!=\"POD\"}[$__range]))\n / on (controller_name, namespace) group_left\n count by (namespace, controller_name) (avg_over_time(kube_controller_pod{namespace=~\"$namespace\"}[$__range]))\n )\n) \n/ count by (namespace) (sum by (namespace, controller) (avg_over_time(kube_controller_pod{namespace=~\"$namespace\"}[$__range])))\nor\ncount (avg_over_time(kube_controller_pod{node=~\"$node\", namespace=~\"$namespace\"}[$__range])) by (namespace) * 0", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "legendFormat": "VPA %", + "refId": "B" + }, + { + "expr": "sum by (namespace) (rate(container_cpu_usage_seconds_total{node=~\"$node\", namespace=~\"$namespace\", container!=\"POD\"}[$__range]))\nor\ncount (avg_over_time(kube_controller_pod{node=~\"$node\", namespace=~\"$namespace\"}[$__range])) by (namespace) * 0", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "legendFormat": "CPU", + "refId": "C" + }, + { + "expr": "sum by (namespace) (avg_over_time(kube_pod_container_resource_requests{resource=\"cpu\",unit=\"core\",node=~\"$node\", namespace=~\"$namespace\"}[$__range]))\nor\ncount(avg_over_time(kube_controller_pod{node=~\"$node\", namespace=~\"$namespace\"}[$__range])) by (namespace) * 0", + "format": "table", + "instant": true, + "intervalFactor": 1, + "legendFormat": "Req CPU", + "refId": "D" + }, + { + "expr": "sum by (namespace)\n (\n (\n sum by(namespace, pod, container) (avg_over_time(kube_pod_container_resource_requests{resource=\"cpu\",unit=\"core\",node=~\"$node\", namespace=~\"$namespace\"}[$__range]))\n -\n sum by(namespace, pod, container) (rate(container_cpu_usage_seconds_total{node=~\"$node\", container!=\"POD\", namespace=~\"$namespace\"}[$__range]))\n ) > 0\n )\nor count (avg_over_time(kube_controller_pod{node=~\"$node\", namespace=~\"$namespace\"}[$__range])) by (namespace) * 0", + "format": "table", + "instant": true, + "intervalFactor": 1, + "legendFormat": "Over-req CPU", + "refId": "E" + }, + { + "expr": "sum by (namespace)\n (\n (\n (\n sum by(namespace, pod, container) (rate(container_cpu_usage_seconds_total{node=~\"$node\", container!=\"POD\", namespace=~\"$namespace\"}[$__range]))\n -\n sum by(namespace, pod, container) (avg_over_time(kube_pod_container_resource_requests{resource=\"cpu\",unit=\"core\",node=~\"$node\", namespace=~\"$namespace\"}[$__range]))\n ) or sum by(namespace, pod, container) (rate(container_cpu_usage_seconds_total{node=~\"$node\", container!=\"POD\", namespace=~\"$namespace\"}[$__range]))\n )\n > 0\n )\nor count (avg_over_time(kube_controller_pod{node=~\"$node\", namespace=~\"$namespace\"}[$__range])) by (namespace) * 0", + "format": "table", + "instant": true, + "intervalFactor": 1, + "legendFormat": "Under-req CPU", + "refId": "F" + }, + { + "expr": "(sum by (namespace) (rate(container_cpu_cfs_throttled_periods_total{node=~\"$node\", namespace=~\"$namespace\"}[$__range])) / sum by (namespace) (rate(container_cpu_cfs_periods_total{node=~\"$node\", namespace=~\"$namespace\"}[$__range]))) * sum by (namespace) (kube_pod_container_resource_limits{resource=\"cpu\",unit=\"core\",node=~\"$node\", namespace=~\"$namespace\"})\nor\ncount (avg_over_time(kube_controller_pod{node=~\"$node\", namespace=~\"$namespace\"}[$__range])) by (namespace) * 0", + "format": "table", + "instant": true, + "intervalFactor": 1, + "legendFormat": "Throttling cores", + "refId": "G" + }, + { + "expr": "sum by (namespace) (avg_over_time(container_memory_working_set_bytes:without_kmem{node=~\"$node\", namespace=~\"$namespace\", container!=\"POD\"}[$__range]))\nor\ncount (avg_over_time(kube_controller_pod{node=~\"$node\", namespace=~\"$namespace\"}[$__range])) by (namespace) * 0", + "format": "table", + "instant": true, + "intervalFactor": 1, + "legendFormat": "Memory", + "refId": "H" + }, + { + "expr": "sum by (namespace) (avg_over_time(kube_pod_container_resource_requests{resource=\"memory\",unit=\"byte\",node=~\"$node\", namespace=~\"$namespace\"}[$__range]))\nor\ncount(avg_over_time(kube_controller_pod{node=~\"$node\", namespace=~\"$namespace\"}[$__range])) by (namespace) * 0", + "format": "table", + "instant": true, + "intervalFactor": 1, + "legendFormat": "Req Memory", + "refId": "I" + }, + { + "expr": "sum by (namespace)\n (\n (\n sum by(namespace, pod, container) (avg_over_time(kube_pod_container_resource_requests{resource=\"memory\",unit=\"byte\",node=~\"$node\", namespace=~\"$namespace\"}[$__range]))\n -\n sum by(namespace, pod, container) (avg_over_time(container_memory_working_set_bytes:without_kmem{node=~\"$node\", container!=\"POD\", namespace=~\"$namespace\"}[$__range]))\n ) > 0\n )\nor\ncount(avg_over_time(kube_controller_pod{node=~\"$node\", namespace=~\"$namespace\"}[$__range])) by (namespace) * 0", + "format": "table", + "instant": true, + "intervalFactor": 1, + "legendFormat": "Over-req Memory", + "refId": "J" + }, + { + "expr": "sum by (namespace)\n (\n (\n (\n sum by(namespace, pod, container) (avg_over_time(container_memory_working_set_bytes:without_kmem{node=~\"$node\", container!=\"POD\", namespace=~\"$namespace\"}[$__range]))\n -\n sum by(namespace, pod, container) (avg_over_time(kube_pod_container_resource_requests{resource=\"memory\",unit=\"byte\",node=~\"$node\", namespace=~\"$namespace\"}[$__range]))\n ) or sum by(namespace, pod, container) (avg_over_time(container_memory_working_set_bytes:without_kmem{node=~\"$node\", container!=\"POD\", namespace=~\"$namespace\"}[$__range]))\n )\n > 0\n )\nor count (avg_over_time(kube_controller_pod{node=~\"$node\", namespace=~\"$namespace\"}[$__range])) by (namespace) * 0", + "format": "table", + "instant": true, + "intervalFactor": 1, + "legendFormat": "Under-req Memory", + "refId": "K" + }, + { + "expr": "sum by (namespace) (rate(container_network_receive_bytes_total{node=~\"$node\", namespace=~\"$namespace\"}[$__range])) \n- \n(\n sum by (namespace) (\n sum by (namespace, pod) (rate(container_network_receive_bytes_total{node=~\"$node\", namespace=~\"$namespace\"}[$__range]))\n * \n sum by (namespace, pod) (avg_over_time(kube_pod_info{host_network=\"true\",namespace=~\"$namespace\"}[$__range]))\n )\n)\nor\ncount (avg_over_time(kube_controller_pod{node=~\"$node\", namespace=~\"$namespace\"}[$__range])) by (namespace) * 0", + "format": "table", + "instant": true, + "intervalFactor": 1, + "legendFormat": "RX Network", + "refId": "L" + }, + { + "expr": "sum by (namespace) (rate(container_network_transmit_bytes_total{node=~\"$node\", namespace=~\"$namespace\"}[$__range])) \n- \n(\n sum by (namespace) (\n sum by (namespace, pod) (rate(container_network_transmit_bytes_total{node=~\"$node\", namespace=~\"$namespace\"}[$__range]))\n * \n sum by (namespace, pod) (avg_over_time(kube_pod_info{host_network=\"true\",namespace=~\"$namespace\"}[$__range]))\n )\n)\nor\ncount (avg_over_time(kube_controller_pod{node=~\"$node\", namespace=~\"$namespace\"}[$__range])) by (namespace) * 0", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "legendFormat": "TX Network", + "refId": "M" + }, + { + "expr": "sum by (namespace) (rate(container_fs_reads_total{node=~\"$node\", namespace=~\"$namespace\", container!=\"POD\"}[$__range]))\nor\ncount (avg_over_time(kube_controller_pod{node=~\"$node\", namespace=~\"$namespace\"}[$__range])) by (namespace) * 0", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "legendFormat": "Read IOPS", + "refId": "N" + }, + { + "expr": "sum by (namespace) (rate(container_fs_writes_total{node=~\"$node\", namespace=~\"$namespace\", container!=\"POD\"}[$__range]))\nor\ncount (avg_over_time(kube_controller_pod{node=~\"$node\", namespace=~\"$namespace\"}[$__range])) by (namespace) * 0", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "legendFormat": "Write IOPS", + "refId": "O" + }, + { + "expr": "sum by (namespace) (increase(kube_pod_container_status_restarts_total{node=~\"$node\", namespace=~\"$namespace\"}[$__range]))\nor\ncount (avg_over_time(kube_controller_pod{node=~\"$node\", namespace=~\"$namespace\"}[$__range])) by (namespace) * 0", + "format": "table", + "instant": true, + "intervalFactor": 1, + "legendFormat": "Restart count", + "refId": "P" + } + ], + "title": "Average", + "transform": "table", + "transformations": [ + { + "id": "merge", + "options": {} + }, + { + "id": "filterFieldsByName", + "options": { + "include": { + "names": [ + "namespace", + "Value #B", + "Value #C", + "Value #D", + "Value #E", + "Value #F", + "Value #G", + "Value #H", + "Value #I", + "Value #J", + "Value #K", + "Value #L", + "Value #M", + "Value #N", + "Value #O", + "Value #P" + ] + } + } + }, + { + "id": "sortBy", + "options": { + "fields": {}, + "sort": [ + { + "field": "namespace" + } + ] + } + } + ], + "type": "table" + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 0, + "description": "The number of Pods in each namespace", + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 12, + "x": 0, + "y": 8 + }, + "hiddenSeries": false, + "id": 332, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sort": "current", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.3", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "count by (namespace) (max_over_time(kube_pod_info{node=~\"$node\", namespace=~\"$namespace\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{ namespace }}", + "refId": "B" + }, + { + "expr": "count(kube_pod_info{node=~\"$node\", namespace=~\"$namespace\"})", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Pods count", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 0, + "format": "short", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 0, + "description": "The number of Pod restarts", + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 12, + "x": 12, + "y": 8 + }, + "hiddenSeries": false, + "id": 564, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.3", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum by (namespace) (increase(kube_pod_container_status_restarts_total{node=~\"$node\", namespace=~\"$namespace\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{ namespace }}", + "refId": "B" + }, + { + "expr": "sum (increase(kube_pod_container_status_restarts_total{node=~\"$node\", namespace=~\"$namespace\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Pods restarts", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 0, + "format": "short", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "collapsed": false, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 12 + }, + "id": 8, + "panels": [], + "title": "CPU", + "type": "row" + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 13 + }, + "hiddenSeries": false, + "id": 6, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.3", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": true, + "targets": [ + { + "expr": "sum by (namespace) (rate(container_cpu_usage_seconds_total{node=~\"$node\", namespace=~\"$namespace\", container!=\"POD\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{ namespace }}", + "refId": "A" + }, + { + "expr": "sum (rate(container_cpu_usage_seconds_total{node=~\"$node\", namespace=~\"$namespace\", container!=\"POD\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Usage by namespace", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "cores", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "description": "The total value may not equal the sum of system and user times because of the kernel's cgroup accounting peculiarities. Read more here: https://www.kernel.org/doc/Documentation/cgroup-v1/cpuacct.txt", + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 13 + }, + "hiddenSeries": false, + "id": 10, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.3", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + }, + { + "alias": "System", + "color": "#e24d42" + }, + { + "alias": "User", + "color": "#1f78c1" + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": true, + "targets": [ + { + "expr": "sum (rate(container_cpu_system_seconds_total{node=~\"$node\", namespace=~\"$namespace\", container!=\"POD\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "System", + "refId": "A" + }, + { + "expr": "sum (rate(container_cpu_user_seconds_total{node=~\"$node\", namespace=~\"$namespace\", container!=\"POD\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "User", + "refId": "B" + }, + { + "expr": "sum (rate(container_cpu_usage_seconds_total{node=~\"$node\", namespace=~\"$namespace\", container!=\"POD\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "D" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Usage by state", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "cores", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "description": "This graph shows the requested CPU resources higher than the actual CPU consumption. In other words, it shows CPU resources that can be \"freed\" without affecting the service.", + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 22 + }, + "hiddenSeries": false, + "id": 333, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.3", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": true, + "targets": [ + { + "expr": "sum by (namespace)\n (\n (\n sum by(namespace, pod, container) (avg_over_time(kube_pod_container_resource_requests{resource=\"cpu\",unit=\"core\",node=~\"$node\", namespace=~\"$namespace\"}[$__rate_interval]))\n -\n sum by(namespace, pod, container) (rate(container_cpu_usage_seconds_total{node=~\"$node\", container!=\"POD\", namespace=~\"$namespace\"}[$__rate_interval]))\n ) > 0\n )", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{ namespace }}", + "refId": "B" + }, + { + "expr": "sum\n(\n (\n (\n sum by(namespace, pod, container) (avg_over_time(kube_pod_container_resource_requests{resource=\"cpu\",unit=\"core\",node=~\"$node\", namespace=~\"$namespace\"}[$__rate_interval]))\n -\n sum by(namespace, pod, container) (rate(container_cpu_usage_seconds_total{node=~\"$node\", container!=\"POD\", namespace=~\"$namespace\"}[$__rate_interval]))\n ) > 0\n )\n)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Over-requested by namespace", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "cores", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "description": "This graph shows the requested CPU resources lower than the actual CPU consumption. In other words, it shows CPU resources that need to be \"reserved\" for the service to run smoothly.", + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 22 + }, + "hiddenSeries": false, + "id": 386, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.3", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": true, + "targets": [ + { + "expr": "sum by (namespace)\n (\n (\n (\n sum by(namespace, pod, container) (rate(container_cpu_usage_seconds_total{node=~\"$node\", container!=\"POD\", namespace=~\"$namespace\"}[$__rate_interval]))\n -\n sum by(namespace, pod, container) (avg_over_time(kube_pod_container_resource_requests{resource=\"cpu\",unit=\"core\",node=~\"$node\", namespace=~\"$namespace\"}[$__rate_interval]))\n ) or sum by(namespace, pod, container) (rate(container_cpu_usage_seconds_total{node=~\"$node\", container!=\"POD\", namespace=~\"$namespace\"}[$__rate_interval]))\n )\n > 0\n )", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{ namespace }}", + "refId": "B" + }, + { + "expr": "sum\n (\n (\n (\n sum by(namespace, pod, container) (rate(container_cpu_usage_seconds_total{node=~\"$node\", container!=\"POD\", namespace=~\"$namespace\"}[$__rate_interval]))\n -\n sum by(namespace, pod, container) (avg_over_time(kube_pod_container_resource_requests{resource=\"cpu\",unit=\"core\",node=~\"$node\", namespace=~\"$namespace\"}[$__rate_interval]))\n ) or sum by(namespace, pod, container) (rate(container_cpu_usage_seconds_total{node=~\"$node\", container!=\"POD\", namespace=~\"$namespace\"}[$__rate_interval]))\n )\n > 0\n )", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Under-requested by namespace", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "cores", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "description": "The absence of data on the graph means that container resources are not set", + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 24, + "x": 0, + "y": 29 + }, + "hiddenSeries": false, + "id": 315, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": true, + "min": false, + "rightSide": true, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.3", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum by (namespace) ((sum by (namespace, pod) (rate(container_cpu_cfs_throttled_periods_total{node=~\"$node\", namespace=~\"$namespace\"}[$__rate_interval])) / sum by (namespace, pod) (rate(container_cpu_cfs_periods_total{node=~\"$node\", namespace=~\"$namespace\"}[$__rate_interval]))) * sum by (namespace, pod) (kube_pod_container_resource_limits{resource=\"cpu\",unit=\"core\",node=~\"$node\", namespace=~\"$namespace\"}))", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "{{ namespace }}", + "refId": "A" + }, + { + "expr": "sum(sum by (namespace) ((sum by (namespace, pod) (rate(container_cpu_cfs_throttled_periods_total{node=~\"$node\", namespace=~\"$namespace\"}[$__rate_interval])) / sum by (namespace, pod) (rate(container_cpu_cfs_periods_total{node=~\"$node\", namespace=~\"$namespace\"}[$__rate_interval]))) * sum by (namespace, pod) (kube_pod_container_resource_limits{resource=\"cpu\",unit=\"core\",node=~\"$node\", namespace=~\"$namespace\"})))", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Throttling", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "cores", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "collapsed": true, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 34 + }, + "id": 343, + "panels": [ + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "description": "", + "fill": 0, + "gridPos": { + "h": 9, + "w": 6, + "x": 0, + "y": 40 + }, + "id": 352, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": "namespace", + "repeatDirection": "h", + "seriesOverrides": [ + { + "alias": "Usage", + "color": "#629e51" + }, + { + "alias": "Requests", + "color": "#f4d598" + }, + { + "alias": "Limits", + "color": "#c15c17" + }, + { + "alias": "VPA Target", + "color": "#447ebc" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "sum by (namespace) (rate(container_cpu_usage_seconds_total{node=~\"$node\", namespace=\"$namespace\", container!=\"POD\"}[$__rate_interval]))", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "Usage", + "refId": "A" + }, + { + "expr": "sum by (namespace) (avg_over_time(kube_pod_container_resource_requests{resource=\"cpu\",unit=\"core\",node=~\"$node\", container!=\"POD\", namespace=\"$namespace\"}[$__rate_interval])* on (uid) group_left(phase) kube_pod_status_phase{phase=\"Running\"})", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Requests", + "refId": "B" + }, + { + "expr": "sum by (namespace) (avg_over_time(kube_pod_container_resource_limits{resource=\"cpu\",unit=\"core\",node=~\"$node\", container!=\"POD\", namespace=\"$namespace\"}[$__rate_interval])* on (uid) group_left(phase) kube_pod_status_phase{phase=\"Running\"})", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Limits", + "refId": "C" + }, + { + "expr": "sum by (namespace) (avg_over_time(vpa_target_recommendation{container!=\"POD\", namespace=\"$namespace\", resource=\"cpu\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "VPA Target", + "refId": "D" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "$namespace", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "cores", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "title": "Namespaces CPU", + "type": "row" + }, + { + "collapsed": true, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 35 + }, + "id": 12, + "panels": [ + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "description": "The total value may not equal the sum of system and user times because of the kernel's cgroup accounting peculiarities. Read more here: https://www.kernel.org/doc/Documentation/cgroup-v1/cpuacct.txt", + "fill": 1, + "gridPos": { + "h": 9, + "w": 6, + "x": 0, + "y": 41 + }, + "id": 14, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": "namespace", + "repeatDirection": "h", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + }, + { + "alias": "System", + "color": "#e24d42" + }, + { + "alias": "User", + "color": "#1f78c1" + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": true, + "targets": [ + { + "expr": "sum by (namespace) (rate(container_cpu_system_seconds_total{node=~\"$node\", namespace=\"$namespace\", container!=\"POD\"}[$__rate_interval]))", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "System", + "refId": "A" + }, + { + "expr": "sum by (namespace) (rate(container_cpu_user_seconds_total{node=~\"$node\", namespace=\"$namespace\", container!=\"POD\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "User", + "refId": "B" + }, + { + "expr": "sum by (namespace) (rate(container_cpu_usage_seconds_total{node=~\"$node\", namespace=\"$namespace\", container!=\"POD\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "D" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "$namespace", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "cores", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "repeat": null, + "title": "Namespaces CPU by state", + "type": "row" + }, + { + "collapsed": false, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 36 + }, + "id": 38, + "panels": [], + "title": "Memory", + "type": "row" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 37 + }, + "hiddenSeries": false, + "id": 40, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.3", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "lines": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum by (namespace) (avg_over_time(container_memory_working_set_bytes:without_kmem{node=~\"$node\", namespace=~\"$namespace\", container!=\"POD\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{ namespace }}", + "refId": "A" + }, + { + "expr": "sum (avg_over_time(container_memory_working_set_bytes:without_kmem{node=~\"$node\", namespace=~\"$namespace\", container!=\"POD\"}[$__rate_interval]))", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Usage by namespace", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "description": "The Working set bytes metric is the actual memory used by the container, as it includes active file memory. When its value approaches the limit, the container can be killed by the OOMKiller. This value can be higher than the sum RSS and Cache since not all active file memory is Cache.", + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 37 + }, + "hiddenSeries": false, + "id": 41, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.3", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Working set bytes without kmem", + "color": "rgb(0, 0, 0)", + "dashes": true, + "fill": 0, + "linewidth": 2, + "stack": false + }, + { + "alias": "Kmem", + "color": "rgb(255, 0, 0)", + "dashes": true, + "fill": 0, + "linewidth": 2, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum (avg_over_time(container_memory_rss{node=~\"$node\", namespace=~\"$namespace\", container!=\"POD\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "RSS", + "refId": "A" + }, + { + "expr": "sum (avg_over_time(container_memory_cache{node=~\"$node\", namespace=~\"$namespace\", container!=\"POD\"}[$__rate_interval]))", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "Cache", + "refId": "B" + }, + { + "expr": "sum (avg_over_time(container_memory_swap{node=~\"$node\", namespace=~\"$namespace\", container!=\"POD\"}[$__rate_interval]))", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "Swap", + "refId": "C" + }, + { + "expr": "sum (avg_over_time(container_memory_working_set_bytes:without_kmem{node=~\"$node\", namespace=~\"$namespace\", container!=\"POD\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Working set bytes without kmem", + "refId": "D" + }, + { + "expr": "sum (avg_over_time(container_memory:kmem{node=~\"$node\", namespace=~\"$namespace\", container!=\"POD\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Kmem", + "refId": "E" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Usage by state", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "description": "This graph shows the requested Memory resources higher than the actual Memory consumption. In other words, it shows Memory resources that can be \"freed\" without affecting the service.", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 46 + }, + "hiddenSeries": false, + "id": 361, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.3", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "lines": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum by (namespace)\n (\n (\n sum by(namespace, pod, container) (avg_over_time(kube_pod_container_resource_requests{resource=\"memory\",unit=\"byte\",node=~\"$node\", namespace=~\"$namespace\"}[$__rate_interval]))\n -\n sum by(namespace, pod, container) (avg_over_time(container_memory_working_set_bytes:without_kmem{node=~\"$node\", container!=\"POD\", namespace=~\"$namespace\"}[$__rate_interval]))\n ) > 0\n )", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{ namespace }}", + "refId": "A" + }, + { + "expr": "sum\n (\n (\n sum by(namespace, pod, container) (avg_over_time(kube_pod_container_resource_requests{resource=\"memory\",unit=\"byte\",node=~\"$node\", namespace=~\"$namespace\"}[$__rate_interval]))\n -\n sum by(namespace, pod, container) (avg_over_time(container_memory_working_set_bytes:without_kmem{node=~\"$node\", container!=\"POD\", namespace=~\"$namespace\"}[$__rate_interval]))\n ) > 0\n )", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Over-requested by namespace", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "description": "This graph shows the requested Memory resources higher than the actual Memory consumption. In other words, it shows Memory resources that need to be \"reserved\" for the service to run smoothly.", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 46 + }, + "hiddenSeries": false, + "id": 387, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.3", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "lines": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum by (namespace)\n (\n (\n (\n sum by(namespace, pod, container) (avg_over_time(container_memory_working_set_bytes:without_kmem{node=~\"$node\", container!=\"POD\", namespace=~\"$namespace\"}[$__rate_interval]))\n -\n sum by(namespace, pod, container) (avg_over_time(kube_pod_container_resource_requests{resource=\"memory\",unit=\"byte\",node=~\"$node\", namespace=~\"$namespace\"}[$__rate_interval]))\n ) or sum by(namespace, pod, container) (avg_over_time(container_memory_working_set_bytes:without_kmem{node=~\"$node\", container!=\"POD\", namespace=~\"$namespace\"}[$__rate_interval]))\n )\n > 0\n )", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{ namespace }}", + "refId": "A" + }, + { + "expr": "sum\n (\n (\n (\n sum by(namespace, pod, container) (avg_over_time(container_memory_working_set_bytes:without_kmem{node=~\"$node\", container!=\"POD\", namespace=~\"$namespace\"}[$__rate_interval]))\n -\n sum by(namespace, pod, container) (avg_over_time(kube_pod_container_resource_requests{resource=\"memory\",unit=\"byte\",node=~\"$node\", namespace=~\"$namespace\"}[$__rate_interval]))\n ) or sum by(namespace, pod, container) (avg_over_time(container_memory_working_set_bytes:without_kmem{node=~\"$node\", container!=\"POD\", namespace=~\"$namespace\"}[$__rate_interval]))\n )\n > 0\n )", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Under-requested by namespace", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "collapsed": true, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 53 + }, + "id": 43, + "panels": [ + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "description": "The Working set bytes metric is the actual memory used by the container, as it includes active file memory. When its value approaches the limit, the container can be killed by the OOMKiller. This value can be higher than the sum RSS and Cache since not all active file memory is Cache.", + "fill": 1, + "gridPos": { + "h": 9, + "w": 6, + "x": 0, + "y": 59 + }, + "id": 44, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": "namespace", + "repeatDirection": "h", + "seriesOverrides": [ + { + "alias": "Working set bytes without kmem", + "color": "rgb(0, 0, 0)", + "dashes": true, + "fill": 0, + "linewidth": 2, + "stack": false + }, + { + "alias": "Kmem", + "color": "rgb(255, 0, 0)", + "dashes": true, + "fill": 0, + "linewidth": 2, + "stack": false + }, + { + "alias": "VPA Target", + "color": "#447ebc", + "dashes": true, + "fill": 0, + "lines": false, + "linewidth": 2, + "stack": false + }, + { + "alias": "Requests", + "color": "#f4d598", + "dashes": true, + "fill": 0, + "lines": false, + "linewidth": 2, + "stack": false + }, + { + "alias": "Limits", + "color": "#c15c17", + "dashes": true, + "fill": 0, + "lines": false, + "linewidth": 2, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum by (namespace) (avg_over_time(container_memory_rss{node=~\"$node\", namespace=\"$namespace\", container!=\"POD\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "RSS", + "refId": "A" + }, + { + "expr": "sum by (namespace) (avg_over_time(container_memory_cache{node=~\"$node\", namespace=\"$namespace\", container!=\"POD\"}[$__rate_interval]))", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "Cache", + "refId": "B" + }, + { + "expr": "sum by (namespace) (avg_over_time(container_memory_swap{node=~\"$node\", namespace=\"$namespace\", container!=\"POD\"}[$__rate_interval]))", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "Swap", + "refId": "C" + }, + { + "expr": "sum by (namespace) (avg_over_time(container_memory_working_set_bytes:without_kmem{node=~\"$node\", namespace=\"$namespace\", container!=\"POD\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Working set bytes without kmem", + "refId": "D" + }, + { + "expr": "sum by(namespace) (avg_over_time(vpa_target_recommendation{container!=\"POD\",namespace=\"$namespace\", resource=\"memory\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "VPA Target", + "refId": "E" + }, + { + "expr": "sum by(namespace) (avg_over_time(kube_pod_container_resource_requests{resource=\"memory\",unit=\"byte\",node=~\"$node\", container!=\"POD\", namespace=\"$namespace\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Requests", + "refId": "F" + }, + { + "expr": "sum by(namespace) (avg_over_time(kube_pod_container_resource_limits{resource=\"memory\",unit=\"byte\",node=~\"$node\", container!=\"POD\", namespace=\"$namespace\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Limits", + "refId": "G" + }, + { + "expr": "sum by (namespace) (avg_over_time(container_memory:kmem{node=~\"$node\", namespace=\"$namespace\", container!=\"POD\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Kmem", + "refId": "H" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "$namespace", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "title": "Namespaces Memory", + "type": "row" + }, + { + "collapsed": false, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 54 + }, + "id": 77, + "panels": [], + "title": "Network", + "type": "row" + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "description": "This graph shows Network Receive (except for the hostNetwork Pods)", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 55 + }, + "hiddenSeries": false, + "id": 79, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 2, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.3", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum by (namespace) (rate(container_network_receive_bytes_total{node=~\"$node\", namespace=~\"$namespace\"}[$__rate_interval])) \n- \n(\n sum by (namespace) (\n sum by (namespace, pod) (rate(container_network_receive_bytes_total{node=~\"$node\", namespace=~\"$namespace\"}[$__rate_interval]))\n * \n sum by (namespace, pod) (kube_pod_info{host_network=\"true\",namespace=~\"$namespace\"})\n )\n)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{ namespace }}", + "refId": "A" + }, + { + "expr": "sum (\n sum by (namespace) (rate(container_network_receive_bytes_total{node=~\"$node\", namespace=~\"$namespace\"}[$__rate_interval])) \n - \n (\n sum by (namespace) (\n sum by (namespace, pod) (rate(container_network_receive_bytes_total{node=~\"$node\", namespace=~\"$namespace\"}[$__rate_interval]))\n * \n sum by (namespace, pod) (kube_pod_info{host_network=\"true\",namespace=~\"$namespace\"})\n )\n )\n)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Receive", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "description": "This graph shows Network Transmit (except for the hostNetwork Pods)", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 55 + }, + "hiddenSeries": false, + "id": 276, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 2, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.3", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum by (namespace) (rate(container_network_transmit_bytes_total{node=~\"$node\", namespace=~\"$namespace\"}[$__rate_interval])) \n- \n(\n sum by (namespace) (\n sum by (namespace, pod) (rate(container_network_transmit_bytes_total{node=~\"$node\", namespace=~\"$namespace\"}[$__rate_interval]))\n * \n sum by (namespace, pod) (kube_pod_info{host_network=\"true\",namespace=~\"$namespace\"})\n )\n)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{ namespace }}", + "refId": "A" + }, + { + "expr": "sum (\n sum by (namespace) (rate(container_network_transmit_bytes_total{node=~\"$node\", namespace=~\"$namespace\"}[$__rate_interval])) \n - \n (\n sum by (namespace) (\n sum by (namespace, pod) (rate(container_network_transmit_bytes_total{node=~\"$node\", namespace=~\"$namespace\"}[$__rate_interval]))\n * \n sum by (namespace, pod) (kube_pod_info{host_network=\"true\",namespace=~\"$namespace\"})\n )\n )\n)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Transmit", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "collapsed": false, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 63 + }, + "id": 154, + "panels": [], + "title": "IOPS", + "type": "row" + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 64 + }, + "hiddenSeries": false, + "id": 156, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.3", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum by (namespace) (rate(container_fs_reads_total{node=~\"$node\", namespace=~\"$namespace\", container!=\"POD\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{ namespace }}", + "refId": "A" + }, + { + "expr": "sum (rate(container_fs_reads_total{node=~\"$node\", namespace=~\"$namespace\", container!=\"POD\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Read", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "iops", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 64 + }, + "hiddenSeries": false, + "id": 277, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.3", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum by (namespace) (rate(container_fs_writes_total{node=~\"$node\", namespace=~\"$namespace\", container!=\"POD\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{ namespace }}", + "refId": "A" + }, + { + "expr": "sum (rate(container_fs_writes_total{node=~\"$node\", namespace=~\"$namespace\", container!=\"POD\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Write", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "iops", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "collapsed": false, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 72 + }, + "id": 518, + "panels": [], + "title": "PVC", + "type": "row" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "description": "This graph does not show any localstorage-related information due to incorrectly calculating the occupied space on localstorage disks", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 73 + }, + "hiddenSeries": false, + "id": 519, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.3", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "/Total/", + "fill": 0, + "linewidth": 2, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "(sum by (namespace) (\n (\n sum by (namespace, persistentvolumeclaim) (kubelet_volume_stats_capacity_bytes{node=~\"$node\"})\n * on (namespace, persistentvolumeclaim)\n sum by (namespace, persistentvolume, persistentvolumeclaim) (\n label_replace(\n max_over_time(kube_persistentvolumeclaim_info{namespace=~\"$namespace\"}[$__rate_interval]),\n \"persistentvolume\", \"$1\", \"volumename\", \"(.*)\")\n + on (persistentvolume) group_left() max by (persistentvolume) (kube_persistentvolume_is_local == 0)\n )\n )\n or on(namespace, persistentvolumeclaim) (\n sum by (persistentvolume) (\n max_over_time(kube_persistentvolume_capacity_bytes[$__rate_interval])\n )\n * on(persistentvolume) group_left(namespace, persistentvolumeclaim)\n sum by (namespace, persistentvolume, persistentvolumeclaim) (\n label_replace(\n max_over_time(kube_persistentvolumeclaim_info{namespace=~\"$namespace\"}[$__rate_interval]),\n \"persistentvolume\", \"$1\", \"volumename\", \"(.*)\")\n + on (persistentvolume) group_left() max by (persistentvolume) (kube_persistentvolume_is_local == 0)\n )\n )\n) and on (namespace) (kube_namespace_created * scalar(count (kube_node_info) == bool count (kube_node_info{node=~\"$node\"})) > 0))\nor sum by (namespace) (\n sum by (namespace, persistentvolumeclaim) (kubelet_volume_stats_capacity_bytes{node=~\"$node\"})\n * on (namespace, persistentvolumeclaim)\n sum by (namespace, persistentvolume, persistentvolumeclaim) (\n label_replace(\n max_over_time(kube_persistentvolumeclaim_info{namespace=~\"$namespace\"}[$__rate_interval]),\n \"persistentvolume\", \"$1\", \"volumename\", \"(.*)\")\n + on (persistentvolume) group_left() max by (persistentvolume) (kube_persistentvolume_is_local == 0)\n )\n)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Provisioned {{ namespace }}", + "refId": "A" + }, + { + "expr": "sum(\n(sum by (namespace) (\n (\n sum by (namespace, persistentvolumeclaim) (kubelet_volume_stats_capacity_bytes{node=~\"$node\"})\n * on (namespace, persistentvolumeclaim)\n sum by (namespace, persistentvolume, persistentvolumeclaim) (\n label_replace(\n max_over_time(kube_persistentvolumeclaim_info{namespace=~\"$namespace\"}[$__rate_interval]),\n \"persistentvolume\", \"$1\", \"volumename\", \"(.*)\")\n + on (persistentvolume) group_left() max by (persistentvolume) (kube_persistentvolume_is_local == 0)\n )\n )\n or on(namespace, persistentvolumeclaim) (\n sum by (persistentvolume) (\n max_over_time(kube_persistentvolume_capacity_bytes[$__rate_interval])\n )\n * on(persistentvolume) group_left(namespace, persistentvolumeclaim)\n sum by (namespace, persistentvolume, persistentvolumeclaim) (\n label_replace(\n max_over_time(kube_persistentvolumeclaim_info{namespace=~\"$namespace\"}[$__rate_interval]),\n \"persistentvolume\", \"$1\", \"volumename\", \"(.*)\")\n + on (persistentvolume) group_left() max by (persistentvolume) (kube_persistentvolume_is_local == 0)\n )\n )\n) and on (namespace) (kube_namespace_created * scalar(count (kube_node_info) == bool count (kube_node_info{node=~\"$node\"})) > 0))\nor sum by (namespace) (\n sum by (namespace, persistentvolumeclaim) (kubelet_volume_stats_capacity_bytes{node=~\"$node\"})\n * on (namespace, persistentvolumeclaim)\n sum by (namespace, persistentvolume, persistentvolumeclaim) (\n label_replace(\n max_over_time(kube_persistentvolumeclaim_info{namespace=~\"$namespace\"}[$__rate_interval]),\n \"persistentvolume\", \"$1\", \"volumename\", \"(.*)\")\n + on (persistentvolume) group_left() max by (persistentvolume) (kube_persistentvolume_is_local == 0)\n )\n))", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "PVC Provisioned (except local storage classes)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "description": "This graph does not show any localstorage-related information due to incorrectly calculating the occupied space on localstorage disks", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 73 + }, + "hiddenSeries": false, + "id": 520, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.3", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "/Total/", + "fill": 0, + "linewidth": 2, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum by (namespace) (\n sum by (namespace, persistentvolumeclaim) (\n max_over_time(kubelet_volume_stats_capacity_bytes{node=~\"$node\", namespace=~\"$namespace\"}[$__rate_interval]) - max_over_time(kubelet_volume_stats_available_bytes{node=~\"$node\", namespace=~\"$namespace\"}[$__rate_interval])\n )\n * on (namespace, persistentvolumeclaim) group_left(persistentvolume)\n\tsum by (namespace, persistentvolume, persistentvolumeclaim) (\n\t\tlabel_replace(\n\t\t\tmax_over_time(kube_persistentvolumeclaim_info{namespace=~\"$namespace\"}[$__rate_interval]),\n\t\t\t\"persistentvolume\", \"$1\", \"volumename\", \"(.*)\")\n\t\t\t+ on (persistentvolume) group_left() max by (persistentvolume) (kube_persistentvolume_is_local == 0)\n\t)\n)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Usage {{ namespace }}", + "refId": "A" + }, + { + "expr": "sum(\n sum by (namespace) (\n sum by (namespace, persistentvolumeclaim) (\n max_over_time(kubelet_volume_stats_capacity_bytes{node=~\"$node\", namespace=~\"$namespace\"}[$__rate_interval]) - max_over_time(kubelet_volume_stats_available_bytes{node=~\"$node\", namespace=~\"$namespace\"}[$__rate_interval])\n )\n \t* on (namespace, persistentvolumeclaim) group_left(persistentvolume)\n\t\tsum by (namespace, persistentvolume, persistentvolumeclaim) (\n\t\t\tlabel_replace(\n\t\t\t\tmax_over_time(kube_persistentvolumeclaim_info{namespace=~\"$namespace\"}[$__rate_interval]), \n\t\t\t\t\"persistentvolume\", \"$1\", \"volumename\", \"(.*)\")\n\t\t\t\t+ on (persistentvolume) group_left() max by (persistentvolume) (kube_persistentvolume_is_local == 0)\n\t\t)\n )\n)", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "PVC Used (except local storage classes)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "description": "This graph does not show any localstorage-related information due to incorrectly calculating the occupied space on localstorage disks", + "fill": 1, + "gridPos": { + "h": 8, + "w": 24, + "x": 0, + "y": 80 + }, + "id": 521, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "8.2.3", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "/Total/", + "fill": 0, + "linewidth": 2, + "stack": false + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum by (namespace) (\n sum by (namespace, persistentvolumeclaim) (\n max_over_time(kubelet_volume_stats_capacity_bytes{node=~\"$node\", namespace=~\"$namespace\"}[$__rate_interval]) - max_over_time(kubelet_volume_stats_available_bytes{node=~\"$node\", namespace=~\"$namespace\"}[$__rate_interval])\n )\n * on (namespace, persistentvolumeclaim)\n\tsum by (namespace, persistentvolumeclaim) (\n\t\tlabel_replace(\n\t\t\tmax_over_time(\n\t\t\t\tkube_persistentvolumeclaim_info{namespace=~\"$namespace\"}[$__rate_interval]),\n\t\t\t\t\"persistentvolume\", \"$1\", \"volumename\", \"(.*)\")\n\t\t\t\t+ on (persistentvolume) group_left() max by (persistentvolume) (kube_persistentvolume_is_local == 0)\n\t)\n)\n/\nsum by (namespace) (\n sum by (namespace, persistentvolumeclaim) (\n max_over_time(kubelet_volume_stats_capacity_bytes{node=~\"$node\", namespace=~\"$namespace\"}[$__rate_interval])\n )\n * on (namespace, persistentvolumeclaim)\n\tsum by (namespace, persistentvolumeclaim) (\n\t\tlabel_replace(\n\t\t\tmax_over_time(\n\t\t\t\tkube_persistentvolumeclaim_info{namespace=~\"$namespace\"}[$__rate_interval]),\n\t\t\t\t\"persistentvolume\", \"$1\", \"volumename\", \"(.*)\")\n\t\t\t\t+ on (persistentvolume) group_left() max by (persistentvolume) (kube_persistentvolume_is_local == 0)\n\t)\n)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Usage {{ namespace }}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "PVC Used in % (except local storage classes)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "percentunit", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "refresh": "30s", + "schemaVersion": 32, + "style": "dark", + "tags": [ + "main" + ], + "templating": { + "list": [ + { + "current": { + "selected": false, + "text": "default", + "value": "default" + }, + "description": null, + "error": null, + "hide": 0, + "includeAll": false, + "label": "Prometheus", + "multi": false, + "name": "ds_prometheus", + "options": [], + "query": "prometheus", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + }, + { + "allValue": ".*", + "current": { + "selected": true, + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": "$ds_prometheus", + "definition": "label_values(kubernetes_build_info, node)", + "description": null, + "error": null, + "hide": 0, + "includeAll": true, + "label": "Node", + "multi": true, + "name": "node", + "options": [], + "query": { + "query": "label_values(kubernetes_build_info, node)", + "refId": "main-node-Variable-Query" + }, + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": "", + "current": { + "selected": true, + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": "$ds_prometheus", + "definition": "label_values(kube_pod_info{node=~\"$node\"}, namespace)", + "description": null, + "error": null, + "hide": 0, + "includeAll": true, + "label": "Namespace", + "multi": true, + "name": "namespace", + "options": [], + "query": { + "query": "label_values(kube_pod_info{node=~\"$node\"}, namespace)", + "refId": "main-namespace-Variable-Query" + }, + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + } + ] + }, + "time": { + "from": "now-3h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "", + "title": "Namespaces", + "uid": "V_WjJ-Pmk", + "version": 2 +} diff --git a/dashboards/main/node.json b/dashboards/main/node.json new file mode 100644 index 00000000..747e961f --- /dev/null +++ b/dashboards/main/node.json @@ -0,0 +1,13341 @@ +{ + "annotations": { + "list": [ + { + "$$hashKey": "object:1058", + "builtIn": 1, + "datasource": "-- Grafana --", + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": false, + "gnetId": 1860, + "graphTooltip": 0, + "iteration": 1630508489644, + "panels": [ + { + "collapsed": false, + "datasource": "$ds_prometheus", + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 261, + "panels": [], + "repeat": null, + "title": "Quick CPU / Mem / Disk", + "type": "row" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "description": "Busy state of all CPU cores together", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": {}, + "mappings": [ + { + "id": 0, + "op": "=", + "text": "N/A", + "type": 1, + "value": "null" + } + ], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "rgba(50, 172, 45, 0.97)", + "value": null + }, + { + "color": "rgba(237, 129, 40, 0.89)", + "value": 85 + }, + { + "color": "rgba(245, 54, 54, 0.9)", + "value": 95 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 3, + "x": 0, + "y": 1 + }, + "id": 20, + "links": [], + "options": { + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": true, + "text": {} + }, + "pluginVersion": "7.4.2", + "targets": [ + { + "expr": "(((count(count(node_cpu_seconds_total{node=~\"$node\",job=\"node-exporter\"}) by (cpu))) - avg(sum by (mode)(rate(node_cpu_seconds_total{mode='idle',node=~\"$node\",job=\"node-exporter\"}[$__rate_interval])))) * 100) / count(count(node_cpu_seconds_total{node=~\"$node\",job=\"node-exporter\"}) by (cpu))", + "hide": false, + "intervalFactor": 1, + "legendFormat": "", + "refId": "A", + "step": 240 + } + ], + "title": "CPU Busy", + "type": "gauge" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "description": "Busy state of all CPU cores together (5 min average)", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": {}, + "mappings": [ + { + "id": 0, + "op": "=", + "text": "N/A", + "type": 1, + "value": "null" + } + ], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "rgba(50, 172, 45, 0.97)", + "value": null + }, + { + "color": "rgba(237, 129, 40, 0.89)", + "value": 85 + }, + { + "color": "rgba(245, 54, 54, 0.9)", + "value": 95 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 3, + "x": 3, + "y": 1 + }, + "id": 155, + "links": [], + "options": { + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": true, + "text": {} + }, + "pluginVersion": "7.4.2", + "targets": [ + { + "expr": "avg(node_load5{node=~\"$node\",job=\"node-exporter\"}) / count(count(node_cpu_seconds_total{node=~\"$node\",job=\"node-exporter\"}) by (cpu)) * 100", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "refId": "A", + "step": 240 + } + ], + "title": "Sys Load (5m avg)", + "type": "gauge" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "description": "Busy state of all CPU cores together (15 min average)", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": {}, + "mappings": [ + { + "id": 0, + "op": "=", + "text": "N/A", + "type": 1, + "value": "null" + } + ], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "rgba(50, 172, 45, 0.97)", + "value": null + }, + { + "color": "rgba(237, 129, 40, 0.89)", + "value": 85 + }, + { + "color": "rgba(245, 54, 54, 0.9)", + "value": 95 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 3, + "x": 6, + "y": 1 + }, + "id": 19, + "links": [], + "options": { + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": true, + "text": {} + }, + "pluginVersion": "7.4.2", + "targets": [ + { + "expr": "avg(node_load15{node=~\"$node\",job=\"node-exporter\"}) / count(count(node_cpu_seconds_total{node=~\"$node\",job=\"node-exporter\"}) by (cpu)) * 100", + "hide": false, + "intervalFactor": 1, + "refId": "A", + "step": 240 + } + ], + "title": "Sys Load (15m avg)", + "type": "gauge" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "description": "Non available RAM memory", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": {}, + "decimals": 0, + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "rgba(50, 172, 45, 0.97)", + "value": null + }, + { + "color": "rgba(237, 129, 40, 0.89)", + "value": 80 + }, + { + "color": "rgba(245, 54, 54, 0.9)", + "value": 90 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 3, + "x": 9, + "y": 1 + }, + "hideTimeOverride": false, + "id": 16, + "links": [], + "options": { + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": true, + "text": {} + }, + "pluginVersion": "7.4.2", + "targets": [ + { + "expr": "((node_memory_MemTotal_bytes{node=~\"$node\",job=\"node-exporter\"} - node_memory_MemFree_bytes{node=~\"$node\",job=\"node-exporter\"}) / (node_memory_MemTotal_bytes{node=~\"$node\",job=\"node-exporter\"} )) * 100", + "format": "time_series", + "hide": true, + "intervalFactor": 1, + "refId": "A", + "step": 240 + }, + { + "expr": "100 - ((node_memory_MemAvailable_bytes{node=~\"$node\",job=\"node-exporter\"} * 100) / node_memory_MemTotal_bytes{node=~\"$node\",job=\"node-exporter\"})", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "refId": "B", + "step": 240 + } + ], + "title": "RAM Used", + "type": "gauge" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "description": "Used Swap", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": {}, + "mappings": [ + { + "id": 0, + "op": "=", + "text": "N/A", + "type": 1, + "value": "null" + } + ], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "rgba(50, 172, 45, 0.97)", + "value": null + }, + { + "color": "rgba(237, 129, 40, 0.89)", + "value": 10 + }, + { + "color": "rgba(245, 54, 54, 0.9)", + "value": 25 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 3, + "x": 12, + "y": 1 + }, + "id": 21, + "links": [], + "options": { + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": true, + "text": {} + }, + "pluginVersion": "7.4.2", + "targets": [ + { + "expr": "((node_memory_SwapTotal_bytes{node=~\"$node\",job=\"node-exporter\"} - node_memory_SwapFree_bytes{node=~\"$node\",job=\"node-exporter\"}) / (node_memory_SwapTotal_bytes{node=~\"$node\",job=\"node-exporter\"} )) * 100", + "intervalFactor": 1, + "refId": "A", + "step": 240 + } + ], + "title": "SWAP Used", + "type": "gauge" + }, + { + "cacheTimeout": null, + "datasource": "$ds_prometheus", + "description": "Used Root FS", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": {}, + "mappings": [ + { + "id": 0, + "op": "=", + "text": "N/A", + "type": 1, + "value": "null" + } + ], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "rgba(50, 172, 45, 0.97)", + "value": null + }, + { + "color": "rgba(237, 129, 40, 0.89)", + "value": 80 + }, + { + "color": "rgba(245, 54, 54, 0.9)", + "value": 90 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 3, + "x": 15, + "y": 1 + }, + "id": 154, + "links": [], + "options": { + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": true, + "text": {} + }, + "pluginVersion": "7.4.2", + "targets": [ + { + "expr": "100 - ((node_filesystem_avail_bytes{node=~\"$node\",job=\"node-exporter\",mountpoint=\"/\",fstype!=\"rootfs\"} * 100) / node_filesystem_size_bytes{node=~\"$node\",job=\"node-exporter\",mountpoint=\"/\",fstype!=\"rootfs\"})", + "format": "time_series", + "intervalFactor": 1, + "refId": "A", + "step": 240 + } + ], + "title": "Root FS Used", + "type": "gauge" + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorValue": false, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "datasource": "$ds_prometheus", + "description": "Total number of CPU cores", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "format": "short", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 2, + "w": 2, + "x": 18, + "y": 1 + }, + "id": 14, + "interval": null, + "links": [], + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + }, + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "maxPerRow": 6, + "nullPointMode": "null", + "nullText": null, + "postfix": "", + "postfixFontSize": "50%", + "prefix": "", + "prefixFontSize": "50%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false + }, + "tableColumn": "", + "targets": [ + { + "expr": "count(count(node_cpu_seconds_total{node=~\"$node\",job=\"node-exporter\"}) by (cpu))", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A", + "step": 240 + } + ], + "thresholds": "", + "title": "CPU Cores", + "type": "singlestat", + "valueFontSize": "50%", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "current" + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorValue": false, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "datasource": "$ds_prometheus", + "decimals": 1, + "description": "System uptime", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "format": "s", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 2, + "w": 4, + "x": 20, + "y": 1 + }, + "hideTimeOverride": true, + "id": 15, + "interval": null, + "links": [], + "mappingType": 1, + "mappingTypes": [ + { + "$$hashKey": "object:1094", + "name": "value to text", + "value": 1 + }, + { + "$$hashKey": "object:1095", + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "nullPointMode": "null", + "nullText": null, + "postfix": "s", + "postfixFontSize": "50%", + "prefix": "", + "prefixFontSize": "50%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false + }, + "tableColumn": "", + "targets": [ + { + "expr": "node_time_seconds{node=~\"$node\",job=\"node-exporter\"} - node_boot_time_seconds{node=~\"$node\",job=\"node-exporter\"}", + "intervalFactor": 1, + "refId": "A", + "step": 240 + } + ], + "thresholds": "", + "title": "Uptime", + "type": "singlestat", + "valueFontSize": "50%", + "valueMaps": [ + { + "$$hashKey": "object:1097", + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "current" + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorValue": false, + "colors": [ + "rgba(50, 172, 45, 0.97)", + "rgba(237, 129, 40, 0.89)", + "rgba(245, 54, 54, 0.9)" + ], + "datasource": "$ds_prometheus", + "decimals": 0, + "description": "Total RootFS", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "format": "bytes", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 2, + "w": 2, + "x": 18, + "y": 3 + }, + "id": 23, + "interval": null, + "links": [], + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + }, + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "maxPerRow": 6, + "nullPointMode": "null", + "nullText": null, + "postfix": "", + "postfixFontSize": "50%", + "prefix": "", + "prefixFontSize": "50%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false + }, + "tableColumn": "", + "targets": [ + { + "expr": "node_filesystem_size_bytes{node=~\"$node\",job=\"node-exporter\",mountpoint=\"/\",fstype!=\"rootfs\"}", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "refId": "A", + "step": 240 + } + ], + "thresholds": "70,90", + "title": "RootFS Total", + "type": "singlestat", + "valueFontSize": "50%", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "current" + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorValue": false, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "datasource": "$ds_prometheus", + "decimals": 0, + "description": "Total RAM", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "format": "bytes", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 2, + "w": 2, + "x": 20, + "y": 3 + }, + "id": 75, + "interval": null, + "links": [], + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + }, + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "maxPerRow": 6, + "nullPointMode": "null", + "nullText": null, + "postfix": "", + "postfixFontSize": "70%", + "prefix": "", + "prefixFontSize": "50%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false + }, + "tableColumn": "", + "targets": [ + { + "expr": "node_memory_MemTotal_bytes{node=~\"$node\",job=\"node-exporter\"}", + "intervalFactor": 1, + "refId": "A", + "step": 240 + } + ], + "thresholds": "", + "title": "RAM Total", + "type": "singlestat", + "valueFontSize": "50%", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "current" + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorValue": false, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "datasource": "$ds_prometheus", + "decimals": 0, + "description": "Total SWAP", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "format": "bytes", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 2, + "w": 2, + "x": 22, + "y": 3 + }, + "id": 18, + "interval": null, + "links": [], + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + }, + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "maxPerRow": 6, + "nullPointMode": "null", + "nullText": null, + "postfix": "", + "postfixFontSize": "70%", + "prefix": "", + "prefixFontSize": "50%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false + }, + "tableColumn": "", + "targets": [ + { + "expr": "node_memory_SwapTotal_bytes{node=~\"$node\",job=\"node-exporter\"}", + "intervalFactor": 1, + "refId": "A", + "step": 240 + } + ], + "thresholds": "", + "title": "SWAP Total", + "type": "singlestat", + "valueFontSize": "50%", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "current" + }, + { + "collapsed": false, + "datasource": "$ds_prometheus", + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 5 + }, + "id": 263, + "panels": [], + "repeat": null, + "title": "Basic CPU / Mem / Net / Disk", + "type": "row" + }, + { + "aliasColors": { + "Busy": "#EAB839", + "Busy Iowait": "#890F02", + "Busy other": "#1F78C1", + "Idle": "#052B51", + "Idle - Waiting for something to happen": "#052B51", + "guest": "#9AC48A", + "idle": "#052B51", + "iowait": "#EAB839", + "irq": "#BF1B00", + "nice": "#C15C17", + "softirq": "#E24D42", + "steal": "#FCE2DE", + "system": "#508642", + "user": "#5195CE" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "description": "Basic CPU info", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 4, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 6 + }, + "hiddenSeries": false, + "id": 77, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": 250, + "sort": null, + "sortDesc": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": true, + "pluginVersion": "7.4.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Busy Iowait", + "color": "#890F02" + }, + { + "alias": "Idle", + "color": "#7EB26D" + }, + { + "alias": "Busy System", + "color": "#EAB839" + }, + { + "alias": "Busy User", + "color": "#0A437C" + }, + { + "alias": "Busy Other", + "color": "#6D1F62" + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum by (instance)(rate(node_cpu_seconds_total{mode=\"system\",node=~\"$node\",job=\"node-exporter\"}[$__rate_interval])) * 100", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "Busy System", + "refId": "A", + "step": 240 + }, + { + "expr": "sum by (instance)(rate(node_cpu_seconds_total{mode='user',node=~\"$node\",job=\"node-exporter\"}[$__rate_interval])) * 100", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "Busy User", + "refId": "B", + "step": 240 + }, + { + "expr": "sum by (instance)(rate(node_cpu_seconds_total{mode='iowait',node=~\"$node\",job=\"node-exporter\"}[$__rate_interval])) * 100", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Busy Iowait", + "refId": "C", + "step": 240 + }, + { + "expr": "sum by (instance)(rate(node_cpu_seconds_total{mode=~\".*irq\",node=~\"$node\",job=\"node-exporter\"}[$__rate_interval])) * 100", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Busy IRQs", + "refId": "D", + "step": 240 + }, + { + "expr": "sum (rate(node_cpu_seconds_total{mode!='idle',mode!='user',mode!='system',mode!='iowait',mode!='irq',mode!='softirq',node=~\"$node\",job=\"node-exporter\"}[$__rate_interval])) * 100", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Busy Other", + "refId": "E", + "step": 240 + }, + { + "expr": "sum by (mode)(rate(node_cpu_seconds_total{mode='idle',node=~\"$node\",job=\"node-exporter\"}[$__rate_interval])) * 100", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Idle", + "refId": "F", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "CPU Basic", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:123", + "format": "short", + "label": "", + "logBase": 1, + "max": "100", + "min": "0", + "show": true + }, + { + "$$hashKey": "object:124", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "Apps": "#629E51", + "Buffers": "#614D93", + "Cache": "#6D1F62", + "Cached": "#511749", + "Committed": "#508642", + "Free": "#0A437C", + "Hardware Corrupted - Amount of RAM that the kernel identified as corrupted / not working": "#CFFAFF", + "Inactive": "#584477", + "PageTables": "#0A50A1", + "Page_Tables": "#0A50A1", + "RAM_Free": "#E0F9D7", + "SWAP Used": "#BF1B00", + "Slab": "#806EB7", + "Slab_Cache": "#E0752D", + "Swap": "#BF1B00", + "Swap Used": "#BF1B00", + "Swap_Cache": "#C15C17", + "Swap_Free": "#2F575E", + "Unused": "#EAB839" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "description": "Basic memory usage", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 4, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 6 + }, + "hiddenSeries": false, + "id": 78, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": 350, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "RAM Total", + "color": "#E0F9D7", + "fill": 0, + "stack": false + }, + { + "alias": "RAM Cache + Buffer", + "color": "#052B51" + }, + { + "alias": "RAM Free", + "color": "#7EB26D" + }, + { + "alias": "Avaliable", + "color": "#DEDAF7", + "fill": 0, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": true, + "targets": [ + { + "expr": "node_memory_MemTotal_bytes{node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "RAM Total", + "refId": "A", + "step": 240 + }, + { + "expr": "node_memory_MemTotal_bytes{node=~\"$node\",job=\"node-exporter\"} - node_memory_MemFree_bytes{node=~\"$node\",job=\"node-exporter\"} - (node_memory_Cached_bytes{node=~\"$node\",job=\"node-exporter\"} + node_memory_Buffers_bytes{node=~\"$node\",job=\"node-exporter\"})", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "RAM Used", + "refId": "B", + "step": 240 + }, + { + "expr": "node_memory_Cached_bytes{node=~\"$node\",job=\"node-exporter\"} + node_memory_Buffers_bytes{node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "RAM Cache + Buffer", + "refId": "C", + "step": 240 + }, + { + "expr": "node_memory_MemFree_bytes{node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "RAM Free", + "refId": "D", + "step": 240 + }, + { + "expr": "(node_memory_SwapTotal_bytes{node=~\"$node\",job=\"node-exporter\"} - node_memory_SwapFree_bytes{node=~\"$node\",job=\"node-exporter\"})", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "SWAP Used", + "refId": "E", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Memory Basic", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "Recv_bytes_eth2": "#7EB26D", + "Recv_bytes_lo": "#0A50A1", + "Recv_drop_eth2": "#6ED0E0", + "Recv_drop_lo": "#E0F9D7", + "Recv_errs_eth2": "#BF1B00", + "Recv_errs_lo": "#CCA300", + "Trans_bytes_eth2": "#7EB26D", + "Trans_bytes_lo": "#0A50A1", + "Trans_drop_eth2": "#6ED0E0", + "Trans_drop_lo": "#E0F9D7", + "Trans_errs_eth2": "#BF1B00", + "Trans_errs_lo": "#CCA300", + "recv_bytes_lo": "#0A50A1", + "recv_drop_eth0": "#99440A", + "recv_drop_lo": "#967302", + "recv_errs_eth0": "#BF1B00", + "recv_errs_lo": "#890F02", + "trans_bytes_eth0": "#7EB26D", + "trans_bytes_lo": "#0A50A1", + "trans_drop_eth0": "#99440A", + "trans_drop_lo": "#967302", + "trans_errs_eth0": "#BF1B00", + "trans_errs_lo": "#890F02" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "description": "Basic network info per interface", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 4, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 13 + }, + "hiddenSeries": false, + "id": 74, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sort": "current", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "/.*trans.*/", + "transform": "negative-Y" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "rate(node_network_receive_bytes_total{node=~\"$node\",job=\"node-exporter\"}[$__rate_interval])*8", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "recv {{device}}", + "refId": "A", + "step": 240 + }, + { + "expr": "rate(node_network_transmit_bytes_total{node=~\"$node\",job=\"node-exporter\"}[$__rate_interval])*8", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "trans {{device}} ", + "refId": "B", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Network Traffic Basic", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "pps", + "label": "", + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 3, + "description": "Disk space used of all filesystems mounted", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 4, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 13 + }, + "height": "", + "hiddenSeries": false, + "id": 152, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sort": "current", + "sortDesc": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "100 - ((node_filesystem_avail_bytes{node=~\"$node\",job=\"node-exporter\",device!~'rootfs'} * 100) / node_filesystem_size_bytes{node=~\"$node\",job=\"node-exporter\",device!~'rootfs'})", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{mountpoint}}", + "refId": "A", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Disk Space Used Basic", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "percent", + "label": null, + "logBase": 1, + "max": "100", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "collapsed": true, + "datasource": "$ds_prometheus", + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 20 + }, + "id": 265, + "panels": [ + { + "aliasColors": { + "Idle - Waiting for something to happen": "#052B51", + "guest": "#9AC48A", + "idle": "#052B51", + "iowait": "#EAB839", + "irq": "#BF1B00", + "nice": "#C15C17", + "softirq": "#E24D42", + "steal": "#FCE2DE", + "system": "#508642", + "user": "#5195CE" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "description": "", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 4, + "fillGradient": 0, + "gridPos": { + "h": 12, + "w": 12, + "x": 0, + "y": 7 + }, + "hiddenSeries": false, + "id": 3, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sideWidth": 250, + "sort": null, + "sortDesc": null, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": true, + "pluginVersion": "7.4.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum by (mode)(rate(node_cpu_seconds_total{mode=\"system\",node=~\"$node\",job=\"node-exporter\"}[$__rate_interval])) * 100", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "System - Processes executing in kernel mode", + "refId": "A", + "step": 240 + }, + { + "expr": "sum by (mode)(rate(node_cpu_seconds_total{mode='user',node=~\"$node\",job=\"node-exporter\"}[$__rate_interval])) * 100", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "User - Normal processes executing in user mode", + "refId": "B", + "step": 240 + }, + { + "expr": "sum by (mode)(rate(node_cpu_seconds_total{mode='nice',node=~\"$node\",job=\"node-exporter\"}[$__rate_interval])) * 100", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Nice - Niced processes executing in user mode", + "refId": "C", + "step": 240 + }, + { + "expr": "sum by (mode)(rate(node_cpu_seconds_total{mode='idle',node=~\"$node\",job=\"node-exporter\"}[$__rate_interval])) * 100", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Idle - Waiting for something to happen", + "refId": "D", + "step": 240 + }, + { + "expr": "sum by (mode)(rate(node_cpu_seconds_total{mode='iowait',node=~\"$node\",job=\"node-exporter\"}[$__rate_interval])) * 100", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Iowait - Waiting for I/O to complete", + "refId": "E", + "step": 240 + }, + { + "expr": "sum by (mode)(rate(node_cpu_seconds_total{mode='irq',node=~\"$node\",job=\"node-exporter\"}[$__rate_interval])) * 100", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Irq - Servicing interrupts", + "refId": "F", + "step": 240 + }, + { + "expr": "sum by (mode)(rate(node_cpu_seconds_total{mode='softirq',node=~\"$node\",job=\"node-exporter\"}[$__rate_interval])) * 100", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Softirq - Servicing softirqs", + "refId": "G", + "step": 240 + }, + { + "expr": "sum by (mode)(rate(node_cpu_seconds_total{mode='steal',node=~\"$node\",job=\"node-exporter\"}[$__rate_interval])) * 100", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Steal - Time spent in other operating systems when running in a virtualized environment", + "refId": "H", + "step": 240 + }, + { + "expr": "sum by (mode)(rate(node_cpu_seconds_total{mode='guest',node=~\"$node\",job=\"node-exporter\"}[$__rate_interval])) * 100", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Guest - Time spent running a virtual CPU for a guest operating system", + "refId": "I", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "CPU", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "percentage", + "logBase": 1, + "max": "100", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "Apps": "#629E51", + "Buffers": "#614D93", + "Cache": "#6D1F62", + "Cached": "#511749", + "Committed": "#508642", + "Free": "#0A437C", + "Hardware Corrupted - Amount of RAM that the kernel identified as corrupted / not working": "#CFFAFF", + "Inactive": "#584477", + "PageTables": "#0A50A1", + "Page_Tables": "#0A50A1", + "RAM_Free": "#E0F9D7", + "Slab": "#806EB7", + "Slab_Cache": "#E0752D", + "Swap": "#BF1B00", + "Swap - Swap memory usage": "#BF1B00", + "Swap_Cache": "#C15C17", + "Swap_Free": "#2F575E", + "Unused": "#EAB839", + "Unused - Free memory unassigned": "#052B51" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "description": "", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 4, + "fillGradient": 0, + "gridPos": { + "h": 12, + "w": 12, + "x": 12, + "y": 7 + }, + "hiddenSeries": false, + "id": 24, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sideWidth": 350, + "sort": null, + "sortDesc": null, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "/.*Hardware Corrupted - *./", + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": true, + "targets": [ + { + "expr": "node_memory_MemTotal_bytes{node=~\"$node\",job=\"node-exporter\"} - node_memory_MemFree_bytes{node=~\"$node\",job=\"node-exporter\"} - node_memory_Buffers_bytes{node=~\"$node\",job=\"node-exporter\"} - node_memory_Cached_bytes{node=~\"$node\",job=\"node-exporter\"} - node_memory_Slab_bytes{node=~\"$node\",job=\"node-exporter\"} - node_memory_PageTables_bytes{node=~\"$node\",job=\"node-exporter\"} - node_memory_SwapCached_bytes{node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "Apps - Memory used by user-space applications", + "refId": "A", + "step": 240 + }, + { + "expr": "node_memory_PageTables_bytes{node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "PageTables - Memory used to map between virtual and physical memory addresses", + "refId": "B", + "step": 240 + }, + { + "expr": "node_memory_SwapCached_bytes{node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "SwapCache - Memory that keeps track of pages that have been fetched from swap but not yet been modified", + "refId": "C", + "step": 240 + }, + { + "expr": "node_memory_Slab_bytes{node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "Slab - Memory used by the kernel to cache data structures for its own use (caches like inode, dentry, etc)", + "refId": "D", + "step": 240 + }, + { + "expr": "node_memory_Cached_bytes{node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "Cache - Parked file data (file content) cache", + "refId": "E", + "step": 240 + }, + { + "expr": "node_memory_Buffers_bytes{node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "Buffers - Block device (e.g. harddisk) cache", + "refId": "F", + "step": 240 + }, + { + "expr": "node_memory_MemFree_bytes{node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "Unused - Free memory unassigned", + "refId": "G", + "step": 240 + }, + { + "expr": "(node_memory_SwapTotal_bytes{node=~\"$node\",job=\"node-exporter\"} - node_memory_SwapFree_bytes{node=~\"$node\",job=\"node-exporter\"})", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "Swap - Swap space used", + "refId": "H", + "step": 240 + }, + { + "expr": "node_memory_HardwareCorrupted_bytes{node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "Hardware Corrupted - Amount of RAM that the kernel identified as corrupted / not working", + "refId": "I", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Memory Stack", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": "bytes", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "receive_packets_eth0": "#7EB26D", + "receive_packets_lo": "#E24D42", + "transmit_packets_eth0": "#7EB26D", + "transmit_packets_lo": "#E24D42" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 4, + "fillGradient": 0, + "gridPos": { + "h": 12, + "w": 12, + "x": 0, + "y": 19 + }, + "hiddenSeries": false, + "id": 84, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "$$hashKey": "object:5871", + "alias": "/.*Trans.*/", + "transform": "negative-Y" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "rate(node_network_receive_bytes_total{node=~\"$node\",job=\"node-exporter\"}[$__rate_interval])*8", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{device}} - Receive", + "refId": "A", + "step": 240 + }, + { + "expr": "rate(node_network_transmit_bytes_total{node=~\"$node\",job=\"node-exporter\"}[$__rate_interval])*8", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{device}} - Transmit", + "refId": "B", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Network Traffic", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:5884", + "format": "bps", + "label": "bits out (-) / in (+)", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "$$hashKey": "object:5885", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 3, + "description": "", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 4, + "fillGradient": 0, + "gridPos": { + "h": 12, + "w": 12, + "x": 12, + "y": 19 + }, + "height": "", + "hiddenSeries": false, + "id": 156, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sort": "current", + "sortDesc": false, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "node_filesystem_size_bytes{node=~\"$node\",job=\"node-exporter\",device!~'rootfs'} - node_filesystem_avail_bytes{node=~\"$node\",job=\"node-exporter\",device!~'rootfs'}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{mountpoint}}", + "refId": "A", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Disk Space Used", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": "bytes", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "description": "", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 12, + "w": 12, + "x": 0, + "y": 31 + }, + "hiddenSeries": false, + "id": 229, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "hideZero": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "/.*Read.*/", + "transform": "negative-Y" + }, + { + "alias": "/.*sda_.*/", + "color": "#7EB26D" + }, + { + "alias": "/.*sdb_.*/", + "color": "#EAB839" + }, + { + "alias": "/.*sdc_.*/", + "color": "#6ED0E0" + }, + { + "alias": "/.*sdd_.*/", + "color": "#EF843C" + }, + { + "alias": "/.*sde_.*/", + "color": "#E24D42" + }, + { + "alias": "/.*sda1.*/", + "color": "#584477" + }, + { + "alias": "/.*sda2_.*/", + "color": "#BA43A9" + }, + { + "alias": "/.*sda3_.*/", + "color": "#F4D598" + }, + { + "alias": "/.*sdb1.*/", + "color": "#0A50A1" + }, + { + "alias": "/.*sdb2.*/", + "color": "#BF1B00" + }, + { + "alias": "/.*sdb2.*/", + "color": "#BF1B00" + }, + { + "alias": "/.*sdb3.*/", + "color": "#E0752D" + }, + { + "alias": "/.*sdc1.*/", + "color": "#962D82" + }, + { + "alias": "/.*sdc2.*/", + "color": "#614D93" + }, + { + "alias": "/.*sdc3.*/", + "color": "#9AC48A" + }, + { + "alias": "/.*sdd1.*/", + "color": "#65C5DB" + }, + { + "alias": "/.*sdd2.*/", + "color": "#F9934E" + }, + { + "alias": "/.*sdd3.*/", + "color": "#EA6460" + }, + { + "alias": "/.*sde1.*/", + "color": "#E0F9D7" + }, + { + "alias": "/.*sdd2.*/", + "color": "#FCEACA" + }, + { + "alias": "/.*sde3.*/", + "color": "#F9E2D2" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "rate(node_disk_reads_completed_total{node=~\"$node\",job=\"node-exporter\",device=~\"$diskdevices\"}[$__rate_interval])", + "intervalFactor": 1, + "legendFormat": "{{device}} - Reads completed", + "refId": "A", + "step": 240 + }, + { + "expr": "rate(node_disk_writes_completed_total{node=~\"$node\",job=\"node-exporter\",device=~\"$diskdevices\"}[$__rate_interval])", + "intervalFactor": 1, + "legendFormat": "{{device}} - Writes completed", + "refId": "B", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Disk IOps", + "tooltip": { + "shared": false, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "iops", + "label": "IO read (-) / write (+)", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "io time": "#890F02" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 3, + "description": "", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 4, + "fillGradient": 0, + "gridPos": { + "h": 12, + "w": 12, + "x": 12, + "y": 31 + }, + "hiddenSeries": false, + "id": 42, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sort": null, + "sortDesc": null, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "/.*read*./", + "transform": "negative-Y" + }, + { + "alias": "/.*sda.*/", + "color": "#7EB26D" + }, + { + "alias": "/.*sdb.*/", + "color": "#EAB839" + }, + { + "alias": "/.*sdc.*/", + "color": "#6ED0E0" + }, + { + "alias": "/.*sdd.*/", + "color": "#EF843C" + }, + { + "alias": "/.*sde.*/", + "color": "#E24D42" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "rate(node_disk_read_bytes_total{node=~\"$node\",job=\"node-exporter\",device=~\"$diskdevices\"}[$__rate_interval])", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "{{device}} - Successfully read bytes", + "refId": "A", + "step": 240 + }, + { + "expr": "rate(node_disk_written_bytes_total{node=~\"$node\",job=\"node-exporter\",device=~\"$diskdevices\"}[$__rate_interval])", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "{{device}} - Successfully written bytes", + "refId": "B", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "I/O Usage Read / Write", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": false, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:965", + "format": "Bps", + "label": "bytes read (-) / write (+)", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "$$hashKey": "object:966", + "format": "ms", + "label": "", + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "io time": "#890F02" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 3, + "description": "", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 4, + "fillGradient": 0, + "gridPos": { + "h": 12, + "w": 12, + "x": 0, + "y": 43 + }, + "hiddenSeries": false, + "id": 127, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sort": null, + "sortDesc": null, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "rate(node_disk_io_time_seconds_total{node=~\"$node\",job=\"node-exporter\",device=~\"$diskdevices\"} [$__rate_interval])", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "{{device}}", + "refId": "A", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "I/O Utilization", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": false, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:1041", + "format": "percentunit", + "label": "%util", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "$$hashKey": "object:1042", + "format": "s", + "label": "", + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "repeat": null, + "title": "CPU / Memory / Net / Disk", + "type": "row" + }, + { + "collapsed": true, + "datasource": "$ds_prometheus", + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 21 + }, + "id": 266, + "panels": [ + { + "aliasColors": { + "Apps": "#629E51", + "Buffers": "#614D93", + "Cache": "#6D1F62", + "Cached": "#511749", + "Committed": "#508642", + "Free": "#0A437C", + "Hardware Corrupted - Amount of RAM that the kernel identified as corrupted / not working": "#CFFAFF", + "Inactive": "#584477", + "PageTables": "#0A50A1", + "Page_Tables": "#0A50A1", + "RAM_Free": "#E0F9D7", + "Slab": "#806EB7", + "Slab_Cache": "#E0752D", + "Swap": "#BF1B00", + "Swap_Cache": "#C15C17", + "Swap_Free": "#2F575E", + "Unused": "#EAB839" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 8 + }, + "hiddenSeries": false, + "id": 136, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sideWidth": 350, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 2, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": true, + "targets": [ + { + "expr": "node_memory_Inactive_bytes{node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Inactive - Memory which has been less recently used. It is more eligible to be reclaimed for other purposes", + "refId": "A", + "step": 240 + }, + { + "expr": "node_memory_Active_bytes{node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Active - Memory that has been used more recently and usually not reclaimed unless absolutely necessary", + "refId": "B", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Memory Active / Inactive", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": "bytes", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "Apps": "#629E51", + "Buffers": "#614D93", + "Cache": "#6D1F62", + "Cached": "#511749", + "Committed": "#508642", + "Free": "#0A437C", + "Hardware Corrupted - Amount of RAM that the kernel identified as corrupted / not working": "#CFFAFF", + "Inactive": "#584477", + "PageTables": "#0A50A1", + "Page_Tables": "#0A50A1", + "RAM_Free": "#E0F9D7", + "Slab": "#806EB7", + "Slab_Cache": "#E0752D", + "Swap": "#BF1B00", + "Swap_Cache": "#C15C17", + "Swap_Free": "#2F575E", + "Unused": "#EAB839" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 8 + }, + "hiddenSeries": false, + "id": 135, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sideWidth": 350, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "/.*Committed_AS - *./" + }, + { + "alias": "/.*CommitLimit - *./", + "color": "#BF1B00", + "fill": 0 + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "node_memory_Committed_AS_bytes{node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Committed_AS - Amount of memory presently allocated on the system", + "refId": "A", + "step": 240 + }, + { + "expr": "node_memory_CommitLimit_bytes{node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "CommitLimit - Amount of memory currently available to be allocated on the system", + "refId": "B", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Memory Commited", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": "bytes", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "Apps": "#629E51", + "Buffers": "#614D93", + "Cache": "#6D1F62", + "Cached": "#511749", + "Committed": "#508642", + "Free": "#0A437C", + "Hardware Corrupted - Amount of RAM that the kernel identified as corrupted / not working": "#CFFAFF", + "Inactive": "#584477", + "PageTables": "#0A50A1", + "Page_Tables": "#0A50A1", + "RAM_Free": "#E0F9D7", + "Slab": "#806EB7", + "Slab_Cache": "#E0752D", + "Swap": "#BF1B00", + "Swap_Cache": "#C15C17", + "Swap_Free": "#2F575E", + "Unused": "#EAB839" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 18 + }, + "hiddenSeries": false, + "id": 191, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sideWidth": 350, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": true, + "targets": [ + { + "expr": "node_memory_Inactive_file_bytes{node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "Inactive_file - File-backed memory on inactive LRU list", + "refId": "A", + "step": 240 + }, + { + "expr": "node_memory_Inactive_anon_bytes{node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "Inactive_anon - Anonymous and swap cache on inactive LRU list, including tmpfs (shmem)", + "refId": "B", + "step": 240 + }, + { + "expr": "node_memory_Active_file_bytes{node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "Active_file - File-backed memory on active LRU list", + "refId": "C", + "step": 240 + }, + { + "expr": "node_memory_Active_anon_bytes{node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "Active_anon - Anonymous and swap cache on active least-recently-used (LRU) list, including tmpfs", + "refId": "D", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Memory Active / Inactive Detail", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": "bytes", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "Active": "#99440A", + "Buffers": "#58140C", + "Cache": "#6D1F62", + "Cached": "#511749", + "Committed": "#508642", + "Dirty": "#6ED0E0", + "Free": "#B7DBAB", + "Inactive": "#EA6460", + "Mapped": "#052B51", + "PageTables": "#0A50A1", + "Page_Tables": "#0A50A1", + "Slab_Cache": "#EAB839", + "Swap": "#BF1B00", + "Swap_Cache": "#C15C17", + "Total": "#511749", + "Total RAM": "#052B51", + "Total RAM + Swap": "#052B51", + "Total Swap": "#614D93", + "VmallocUsed": "#EA6460" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 18 + }, + "hiddenSeries": false, + "id": 130, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 2, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "node_memory_Writeback_bytes{node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Writeback - Memory which is actively being written back to disk", + "refId": "A", + "step": 240 + }, + { + "expr": "node_memory_WritebackTmp_bytes{node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "WritebackTmp - Memory used by FUSE for temporary writeback buffers", + "refId": "B", + "step": 240 + }, + { + "expr": "node_memory_Dirty_bytes{node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Dirty - Memory which is waiting to get written back to the disk", + "refId": "C", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Memory Writeback and Dirty", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": "bytes", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "Apps": "#629E51", + "Buffers": "#614D93", + "Cache": "#6D1F62", + "Cached": "#511749", + "Committed": "#508642", + "Free": "#0A437C", + "Hardware Corrupted - Amount of RAM that the kernel identified as corrupted / not working": "#CFFAFF", + "Inactive": "#584477", + "PageTables": "#0A50A1", + "Page_Tables": "#0A50A1", + "RAM_Free": "#E0F9D7", + "Slab": "#806EB7", + "Slab_Cache": "#E0752D", + "Swap": "#BF1B00", + "Swap_Cache": "#C15C17", + "Swap_Free": "#2F575E", + "Unused": "#EAB839" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 28 + }, + "hiddenSeries": false, + "id": 138, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sideWidth": 350, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "$$hashKey": "object:4131", + "alias": "ShmemHugePages - Memory used by shared memory (shmem) and tmpfs allocated with huge pages", + "fill": 0 + }, + { + "$$hashKey": "object:4138", + "alias": "ShmemHugePages - Memory used by shared memory (shmem) and tmpfs allocated with huge pages", + "fill": 0 + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "node_memory_Mapped_bytes{node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Mapped - Used memory in mapped pages files which have been mmaped, such as libraries", + "refId": "A", + "step": 240 + }, + { + "expr": "node_memory_Shmem_bytes{node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Shmem - Used shared memory (shared between several processes, thus including RAM disks)", + "refId": "B", + "step": 240 + }, + { + "expr": "node_memory_ShmemHugePages_bytes{node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "ShmemHugePages - Memory used by shared memory (shmem) and tmpfs allocated with huge pages", + "refId": "C", + "step": 240 + }, + { + "expr": "node_memory_ShmemPmdMapped_bytes{node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "ShmemPmdMapped - Ammount of shared (shmem/tmpfs) memory backed by huge pages", + "refId": "D", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Memory Shared and Mapped", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:4106", + "format": "bytes", + "label": "bytes", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "$$hashKey": "object:4107", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "Active": "#99440A", + "Buffers": "#58140C", + "Cache": "#6D1F62", + "Cached": "#511749", + "Committed": "#508642", + "Dirty": "#6ED0E0", + "Free": "#B7DBAB", + "Inactive": "#EA6460", + "Mapped": "#052B51", + "PageTables": "#0A50A1", + "Page_Tables": "#0A50A1", + "Slab_Cache": "#EAB839", + "Swap": "#BF1B00", + "Swap_Cache": "#C15C17", + "Total": "#511749", + "Total RAM": "#052B51", + "Total RAM + Swap": "#052B51", + "Total Swap": "#614D93", + "VmallocUsed": "#EA6460" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 28 + }, + "hiddenSeries": false, + "id": 131, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 2, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": true, + "targets": [ + { + "expr": "node_memory_SUnreclaim_bytes{node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "SUnreclaim - Part of Slab, that cannot be reclaimed on memory pressure", + "refId": "A", + "step": 240 + }, + { + "expr": "node_memory_SReclaimable_bytes{node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "SReclaimable - Part of Slab, that might be reclaimed, such as caches", + "refId": "B", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Memory Slab", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": "bytes", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "Active": "#99440A", + "Buffers": "#58140C", + "Cache": "#6D1F62", + "Cached": "#511749", + "Committed": "#508642", + "Dirty": "#6ED0E0", + "Free": "#B7DBAB", + "Inactive": "#EA6460", + "Mapped": "#052B51", + "PageTables": "#0A50A1", + "Page_Tables": "#0A50A1", + "Slab_Cache": "#EAB839", + "Swap": "#BF1B00", + "Swap_Cache": "#C15C17", + "Total": "#511749", + "Total RAM": "#052B51", + "Total RAM + Swap": "#052B51", + "VmallocUsed": "#EA6460" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 38 + }, + "hiddenSeries": false, + "id": 70, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "node_memory_VmallocChunk_bytes{node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "VmallocChunk - Largest contigious block of vmalloc area which is free", + "refId": "A", + "step": 240 + }, + { + "expr": "node_memory_VmallocTotal_bytes{node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "VmallocTotal - Total size of vmalloc memory area", + "refId": "B", + "step": 240 + }, + { + "expr": "node_memory_VmallocUsed_bytes{node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "VmallocUsed - Amount of vmalloc area which is used", + "refId": "C", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Memory Vmalloc", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": "bytes", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "Apps": "#629E51", + "Buffers": "#614D93", + "Cache": "#6D1F62", + "Cached": "#511749", + "Committed": "#508642", + "Free": "#0A437C", + "Hardware Corrupted - Amount of RAM that the kernel identified as corrupted / not working": "#CFFAFF", + "Inactive": "#584477", + "PageTables": "#0A50A1", + "Page_Tables": "#0A50A1", + "RAM_Free": "#E0F9D7", + "Slab": "#806EB7", + "Slab_Cache": "#E0752D", + "Swap": "#BF1B00", + "Swap_Cache": "#C15C17", + "Swap_Free": "#2F575E", + "Unused": "#EAB839" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 38 + }, + "hiddenSeries": false, + "id": 159, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sideWidth": 350, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "node_memory_Bounce_bytes{node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Bounce - Memory used for block device bounce buffers", + "refId": "A", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Memory Bounce", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": "bytes", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "Active": "#99440A", + "Buffers": "#58140C", + "Cache": "#6D1F62", + "Cached": "#511749", + "Committed": "#508642", + "Dirty": "#6ED0E0", + "Free": "#B7DBAB", + "Inactive": "#EA6460", + "Mapped": "#052B51", + "PageTables": "#0A50A1", + "Page_Tables": "#0A50A1", + "Slab_Cache": "#EAB839", + "Swap": "#BF1B00", + "Swap_Cache": "#C15C17", + "Total": "#511749", + "Total RAM": "#052B51", + "Total RAM + Swap": "#052B51", + "VmallocUsed": "#EA6460" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 48 + }, + "hiddenSeries": false, + "id": 129, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "/.*Inactive *./", + "transform": "negative-Y" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "node_memory_AnonHugePages_bytes{node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "AnonHugePages - Memory in anonymous huge pages", + "refId": "A", + "step": 240 + }, + { + "expr": "node_memory_AnonPages_bytes{node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "AnonPages - Memory in user pages not backed by files", + "refId": "B", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Memory Anonymous", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": "bytes", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "Apps": "#629E51", + "Buffers": "#614D93", + "Cache": "#6D1F62", + "Cached": "#511749", + "Committed": "#508642", + "Free": "#0A437C", + "Hardware Corrupted - Amount of RAM that the kernel identified as corrupted / not working": "#CFFAFF", + "Inactive": "#584477", + "PageTables": "#0A50A1", + "Page_Tables": "#0A50A1", + "RAM_Free": "#E0F9D7", + "Slab": "#806EB7", + "Slab_Cache": "#E0752D", + "Swap": "#BF1B00", + "Swap_Cache": "#C15C17", + "Swap_Free": "#2F575E", + "Unused": "#EAB839" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 48 + }, + "hiddenSeries": false, + "id": 160, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sideWidth": 350, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 2, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "node_memory_KernelStack_bytes{node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "KernelStack - Kernel memory stack. This is not reclaimable", + "refId": "A", + "step": 240 + }, + { + "expr": "node_memory_Percpu_bytes{node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "PerCPU - Per CPU memory allocated dynamically by loadable modules", + "refId": "B", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Memory Kernel / CPU", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": "bytes", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "Active": "#99440A", + "Buffers": "#58140C", + "Cache": "#6D1F62", + "Cached": "#511749", + "Committed": "#508642", + "Dirty": "#6ED0E0", + "Free": "#B7DBAB", + "Inactive": "#EA6460", + "Mapped": "#052B51", + "PageTables": "#0A50A1", + "Page_Tables": "#0A50A1", + "Slab_Cache": "#EAB839", + "Swap": "#BF1B00", + "Swap_Cache": "#C15C17", + "Total": "#511749", + "Total RAM": "#806EB7", + "Total RAM + Swap": "#806EB7", + "VmallocUsed": "#EA6460" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 58 + }, + "hiddenSeries": false, + "id": 140, + "legend": { + "alignAsTable": true, + "avg": false, + "current": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "node_memory_HugePages_Free{node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "HugePages_Free - Huge pages in the pool that are not yet allocated", + "refId": "A", + "step": 240 + }, + { + "expr": "node_memory_HugePages_Rsvd{node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "HugePages_Rsvd - Huge pages for which a commitment to allocate from the pool has been made, but no allocation has yet been made", + "refId": "B", + "step": 240 + }, + { + "expr": "node_memory_HugePages_Surp{node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "HugePages_Surp - Huge pages in the pool above the value in /proc/sys/vm/nr_hugepages", + "refId": "C", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Memory HugePages Counter", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "pages", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": "", + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "Active": "#99440A", + "Buffers": "#58140C", + "Cache": "#6D1F62", + "Cached": "#511749", + "Committed": "#508642", + "Dirty": "#6ED0E0", + "Free": "#B7DBAB", + "Inactive": "#EA6460", + "Mapped": "#052B51", + "PageTables": "#0A50A1", + "Page_Tables": "#0A50A1", + "Slab_Cache": "#EAB839", + "Swap": "#BF1B00", + "Swap_Cache": "#C15C17", + "Total": "#511749", + "Total RAM": "#806EB7", + "Total RAM + Swap": "#806EB7", + "VmallocUsed": "#EA6460" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 58 + }, + "hiddenSeries": false, + "id": 71, + "legend": { + "alignAsTable": true, + "avg": false, + "current": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 2, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "node_memory_HugePages_Total{node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "HugePages - Total size of the pool of huge pages", + "refId": "A", + "step": 240 + }, + { + "expr": "node_memory_Hugepagesize_bytes{node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Hugepagesize - Huge Page size", + "refId": "B", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Memory HugePages Size", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": "bytes", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": "", + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "Active": "#99440A", + "Buffers": "#58140C", + "Cache": "#6D1F62", + "Cached": "#511749", + "Committed": "#508642", + "Dirty": "#6ED0E0", + "Free": "#B7DBAB", + "Inactive": "#EA6460", + "Mapped": "#052B51", + "PageTables": "#0A50A1", + "Page_Tables": "#0A50A1", + "Slab_Cache": "#EAB839", + "Swap": "#BF1B00", + "Swap_Cache": "#C15C17", + "Total": "#511749", + "Total RAM": "#052B51", + "Total RAM + Swap": "#052B51", + "VmallocUsed": "#EA6460" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 68 + }, + "hiddenSeries": false, + "id": 128, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "node_memory_DirectMap1G_bytes{node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "DirectMap1G - Amount of pages mapped as this size", + "refId": "A", + "step": 240 + }, + { + "expr": "node_memory_DirectMap2M_bytes{node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "DirectMap2M - Amount of pages mapped as this size", + "refId": "B", + "step": 240 + }, + { + "expr": "node_memory_DirectMap4k_bytes{node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "DirectMap4K - Amount of pages mapped as this size", + "refId": "C", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Memory DirectMap", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": "bytes", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "Apps": "#629E51", + "Buffers": "#614D93", + "Cache": "#6D1F62", + "Cached": "#511749", + "Committed": "#508642", + "Free": "#0A437C", + "Hardware Corrupted - Amount of RAM that the kernel identified as corrupted / not working": "#CFFAFF", + "Inactive": "#584477", + "PageTables": "#0A50A1", + "Page_Tables": "#0A50A1", + "RAM_Free": "#E0F9D7", + "Slab": "#806EB7", + "Slab_Cache": "#E0752D", + "Swap": "#BF1B00", + "Swap_Cache": "#C15C17", + "Swap_Free": "#2F575E", + "Unused": "#EAB839" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 68 + }, + "hiddenSeries": false, + "id": 137, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sideWidth": 350, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "node_memory_Unevictable_bytes{node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Unevictable - Amount of unevictable memory that can't be swapped out for a variety of reasons", + "refId": "A", + "step": 240 + }, + { + "expr": "node_memory_Mlocked_bytes{node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "MLocked - Size of pages locked to memory using the mlock() system call", + "refId": "B", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Memory Unevictable and MLocked", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": "bytes", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "Active": "#99440A", + "Buffers": "#58140C", + "Cache": "#6D1F62", + "Cached": "#511749", + "Committed": "#508642", + "Dirty": "#6ED0E0", + "Free": "#B7DBAB", + "Inactive": "#EA6460", + "Mapped": "#052B51", + "PageTables": "#0A50A1", + "Page_Tables": "#0A50A1", + "Slab_Cache": "#EAB839", + "Swap": "#BF1B00", + "Swap_Cache": "#C15C17", + "Total": "#511749", + "Total RAM": "#052B51", + "Total RAM + Swap": "#052B51", + "Total Swap": "#614D93", + "VmallocUsed": "#EA6460" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 78 + }, + "hiddenSeries": false, + "id": 132, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "node_memory_NFS_Unstable_bytes{node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "NFS Unstable - Memory in NFS pages sent to the server, but not yet commited to the storage", + "refId": "A", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Memory NFS", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": "bytes", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "repeat": null, + "title": "Memory Meminfo", + "type": "row" + }, + { + "collapsed": true, + "datasource": "$ds_prometheus", + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 22 + }, + "id": 267, + "panels": [ + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 9 + }, + "hiddenSeries": false, + "id": 176, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "/.*out/", + "transform": "negative-Y" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "rate(node_vmstat_pgpgin{node=~\"$node\",job=\"node-exporter\"}[$__rate_interval])", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Pagesin - Page in operations", + "refId": "A", + "step": 240 + }, + { + "expr": "rate(node_vmstat_pgpgout{node=~\"$node\",job=\"node-exporter\"}[$__rate_interval])", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Pagesout - Page out operations", + "refId": "B", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Memory Pages In / Out", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "pages out (-) / in (+)", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 9 + }, + "hiddenSeries": false, + "id": 22, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "/.*out/", + "transform": "negative-Y" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "rate(node_vmstat_pswpin{node=~\"$node\",job=\"node-exporter\"}[$__rate_interval])", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Pswpin - Pages swapped in", + "refId": "A", + "step": 240 + }, + { + "expr": "rate(node_vmstat_pswpout{node=~\"$node\",job=\"node-exporter\"}[$__rate_interval])", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Pswpout - Pages swapped out", + "refId": "B", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Memory Pages Swap In / Out", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "pages out (-) / in (+)", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "Apps": "#629E51", + "Buffers": "#614D93", + "Cache": "#6D1F62", + "Cached": "#511749", + "Committed": "#508642", + "Free": "#0A437C", + "Hardware Corrupted - Amount of RAM that the kernel identified as corrupted / not working": "#CFFAFF", + "Inactive": "#584477", + "PageTables": "#0A50A1", + "Page_Tables": "#0A50A1", + "RAM_Free": "#E0F9D7", + "Slab": "#806EB7", + "Slab_Cache": "#E0752D", + "Swap": "#BF1B00", + "Swap_Cache": "#C15C17", + "Swap_Free": "#2F575E", + "Unused": "#EAB839" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 19 + }, + "hiddenSeries": false, + "id": 175, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sideWidth": 350, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "$$hashKey": "object:6118", + "alias": "Pgfault - Page major and minor fault operations", + "fill": 0, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": true, + "targets": [ + { + "expr": "rate(node_vmstat_pgfault{node=~\"$node\",job=\"node-exporter\"}[$__rate_interval])", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Pgfault - Page major and minor fault operations", + "refId": "A", + "step": 240 + }, + { + "expr": "rate(node_vmstat_pgmajfault{node=~\"$node\",job=\"node-exporter\"}[$__rate_interval])", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Pgmajfault - Major page fault operations", + "refId": "B", + "step": 240 + }, + { + "expr": "rate(node_vmstat_pgfault{node=~\"$node\",job=\"node-exporter\"}[$__rate_interval]) - rate(node_vmstat_pgmajfault{node=~\"$node\",job=\"node-exporter\"}[$__rate_interval])", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Pgminfault - Minor page fault operations", + "refId": "C", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Memory Page Faults", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:6133", + "format": "short", + "label": "faults", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "$$hashKey": "object:6134", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "Active": "#99440A", + "Buffers": "#58140C", + "Cache": "#6D1F62", + "Cached": "#511749", + "Committed": "#508642", + "Dirty": "#6ED0E0", + "Free": "#B7DBAB", + "Inactive": "#EA6460", + "Mapped": "#052B51", + "PageTables": "#0A50A1", + "Page_Tables": "#0A50A1", + "Slab_Cache": "#EAB839", + "Swap": "#BF1B00", + "Swap_Cache": "#C15C17", + "Total": "#511749", + "Total RAM": "#052B51", + "Total RAM + Swap": "#052B51", + "Total Swap": "#614D93", + "VmallocUsed": "#EA6460" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 2, + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 19 + }, + "hiddenSeries": false, + "id": 307, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "rate(node_vmstat_oom_kill{node=~\"$node\",job=\"node-exporter\"}[$__rate_interval])", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "oom killer invocations ", + "refId": "A", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "OOM Killer", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:5373", + "format": "short", + "label": "counter", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "$$hashKey": "object:5374", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "repeat": null, + "title": "Memory Vmstat", + "type": "row" + }, + { + "collapsed": true, + "datasource": "$ds_prometheus", + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 23 + }, + "id": 293, + "panels": [ + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "description": "", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 10 + }, + "hiddenSeries": false, + "id": 260, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "/.*Variation*./", + "color": "#890F02" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "node_timex_estimated_error_seconds{node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "Estimated error in seconds", + "refId": "A", + "step": 240 + }, + { + "expr": "node_timex_offset_seconds{node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "Time offset in between local system and reference clock", + "refId": "B", + "step": 240 + }, + { + "expr": "node_timex_maxerror_seconds{node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "Maximum error in seconds", + "refId": "C", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Time Syncronized Drift", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "s", + "label": "seconds", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": "counter", + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "description": "", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 10 + }, + "hiddenSeries": false, + "id": 291, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "node_timex_loop_time_constant{node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Phase-locked loop time adjust", + "refId": "A", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Time PLL Adjust", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "counter", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "description": "", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 20 + }, + "hiddenSeries": false, + "id": 168, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "/.*Variation*./", + "color": "#890F02" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "node_timex_sync_status{node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Is clock synchronized to a reliable server (1 = yes, 0 = no)", + "refId": "A", + "step": 240 + }, + { + "expr": "node_timex_frequency_adjustment_ratio{node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Local clock frequency adjustment", + "refId": "B", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Time Syncronized Status", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "counter", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "description": "", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 20 + }, + "hiddenSeries": false, + "id": 294, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "node_timex_tick_seconds{node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Seconds between clock ticks", + "refId": "A", + "step": 240 + }, + { + "expr": "node_timex_tai_offset_seconds{node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "International Atomic Time (TAI) offset", + "refId": "B", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Time Misc", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "s", + "label": "seconds", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "title": "System Timesync", + "type": "row" + }, + { + "collapsed": true, + "datasource": "$ds_prometheus", + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 24 + }, + "id": 312, + "panels": [ + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 11 + }, + "hiddenSeries": false, + "id": 62, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "node_procs_blocked{node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Processes blocked waiting for I/O to complete", + "refId": "A", + "step": 240 + }, + { + "expr": "node_procs_running{node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Processes in runnable state", + "refId": "B", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Processes Status", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:6500", + "format": "short", + "label": "counter", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "$$hashKey": "object:6501", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 11 + }, + "hiddenSeries": false, + "id": 315, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": true, + "targets": [ + { + "expr": "node_processes_state{node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{ state }}", + "refId": "A", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Processes State", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:6500", + "format": "short", + "label": "counter", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "$$hashKey": "object:6501", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 21 + }, + "hiddenSeries": false, + "id": 148, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "rate(node_forks_total{node=~\"$node\",job=\"node-exporter\"}[$__rate_interval])", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "Processes forks second", + "refId": "A", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Processes Forks", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:6640", + "format": "short", + "label": "forks / sec", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "$$hashKey": "object:6641", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 21 + }, + "hiddenSeries": false, + "id": 149, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "/.*Max.*/", + "fill": 0 + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "process_virtual_memory_bytes{node=~\"$node\",job=\"node-exporter\"}", + "hide": false, + "intervalFactor": 1, + "legendFormat": "Processes virtual memory size in bytes", + "refId": "A", + "step": 240 + }, + { + "expr": "process_resident_memory_max_bytes{node=~\"$node\",job=\"node-exporter\"}", + "hide": false, + "intervalFactor": 1, + "legendFormat": "Maximum amount of virtual memory available in bytes", + "refId": "B", + "step": 240 + }, + { + "expr": "process_virtual_memory_bytes{node=~\"$node\",job=\"node-exporter\"}", + "hide": false, + "intervalFactor": 1, + "legendFormat": "Processes virtual memory size in bytes", + "refId": "C", + "step": 240 + }, + { + "expr": "process_virtual_memory_max_bytes{node=~\"$node\",job=\"node-exporter\"}", + "hide": false, + "intervalFactor": 1, + "legendFormat": "Maximum amount of virtual memory available in bytes", + "refId": "D", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Processes Memory", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "decbytes", + "label": "bytes", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 31 + }, + "hiddenSeries": false, + "id": 313, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "$$hashKey": "object:709", + "alias": "PIDs limit", + "color": "#F2495C", + "fill": 0 + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "node_processes_pids{node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Number of PIDs", + "refId": "A", + "step": 240 + }, + { + "expr": "node_processes_max_processes{node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "PIDs limit", + "refId": "B", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "PIDs Number and Limit", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:6500", + "format": "short", + "label": "counter", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "$$hashKey": "object:6501", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 31 + }, + "hiddenSeries": false, + "id": 314, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "$$hashKey": "object:709", + "alias": "Threads limit", + "color": "#F2495C", + "fill": 0 + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "node_processes_threads{node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Allocated threads", + "refId": "A", + "step": 240 + }, + { + "expr": "node_processes_max_threads{node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Threads limit", + "refId": "B", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Threads Number and Limit", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:6500", + "format": "short", + "label": "counter", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "$$hashKey": "object:6501", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "title": "System Processes", + "type": "row" + }, + { + "collapsed": true, + "datasource": "$ds_prometheus", + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 25 + }, + "id": 269, + "panels": [ + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 26 + }, + "hiddenSeries": false, + "id": 8, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "rate(node_context_switches_total{node=~\"$node\",job=\"node-exporter\"}[$__rate_interval])", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Context switches", + "refId": "A", + "step": 240 + }, + { + "expr": "rate(node_intr_total{node=~\"$node\",job=\"node-exporter\"}[$__rate_interval])", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "Interrupts", + "refId": "B", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Context Switches / Interrupts", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "counter", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 26 + }, + "hiddenSeries": false, + "id": 7, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "node_load1{node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Load 1m", + "refId": "A", + "step": 240 + }, + { + "expr": "node_load5{node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Load 5m", + "refId": "B", + "step": 240 + }, + { + "expr": "node_load15{node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Load 15m", + "refId": "C", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "System Load", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:6261", + "format": "short", + "label": "counter", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "$$hashKey": "object:6262", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 36 + }, + "hiddenSeries": false, + "id": 308, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "rate(process_cpu_seconds_total{node=~\"$node\",job=\"node-exporter\"}[$__rate_interval])", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Time spent", + "refId": "A", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "CPU time spent in user and system contexts", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:4860", + "format": "s", + "label": "seconds", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "$$hashKey": "object:4861", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 46 + }, + "hiddenSeries": false, + "id": 151, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "node_entropy_available_bits{node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Entropy available to random number generators", + "refId": "A", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Entropy", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:6568", + "format": "short", + "label": "counter", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "$$hashKey": "object:6569", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 56 + }, + "hiddenSeries": false, + "id": 64, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "$$hashKey": "object:6323", + "alias": "/.*Max*./", + "color": "#890F02", + "fill": 0 + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "process_max_fds{node=~\"$node\",job=\"node-exporter\"}", + "intervalFactor": 1, + "legendFormat": "Maximum open file descriptors", + "refId": "A", + "step": 240 + }, + { + "expr": "process_open_fds{node=~\"$node\",job=\"node-exporter\"}", + "intervalFactor": 1, + "legendFormat": "Open file descriptors", + "refId": "B", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "File Descriptors", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:6338", + "format": "short", + "label": "counter", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "$$hashKey": "object:6339", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "repeat": null, + "title": "System Misc", + "type": "row" + }, + { + "collapsed": true, + "datasource": "$ds_prometheus", + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 26 + }, + "id": 270, + "panels": [ + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "description": "The number (after merges) of I/O requests completed per second for the device", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 28 + }, + "hiddenSeries": false, + "id": 9, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "hideZero": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + { + "$$hashKey": "object:2033", + "alias": "/.*Read.*/", + "transform": "negative-Y" + }, + { + "$$hashKey": "object:2034", + "alias": "/.*sda_.*/", + "color": "#7EB26D" + }, + { + "$$hashKey": "object:2035", + "alias": "/.*sdb_.*/", + "color": "#EAB839" + }, + { + "$$hashKey": "object:2036", + "alias": "/.*sdc_.*/", + "color": "#6ED0E0" + }, + { + "$$hashKey": "object:2037", + "alias": "/.*sdd_.*/", + "color": "#EF843C" + }, + { + "$$hashKey": "object:2038", + "alias": "/.*sde_.*/", + "color": "#E24D42" + }, + { + "$$hashKey": "object:2039", + "alias": "/.*sda1.*/", + "color": "#584477" + }, + { + "$$hashKey": "object:2040", + "alias": "/.*sda2_.*/", + "color": "#BA43A9" + }, + { + "$$hashKey": "object:2041", + "alias": "/.*sda3_.*/", + "color": "#F4D598" + }, + { + "$$hashKey": "object:2042", + "alias": "/.*sdb1.*/", + "color": "#0A50A1" + }, + { + "$$hashKey": "object:2043", + "alias": "/.*sdb2.*/", + "color": "#BF1B00" + }, + { + "$$hashKey": "object:2044", + "alias": "/.*sdb3.*/", + "color": "#E0752D" + }, + { + "$$hashKey": "object:2045", + "alias": "/.*sdc1.*/", + "color": "#962D82" + }, + { + "$$hashKey": "object:2046", + "alias": "/.*sdc2.*/", + "color": "#614D93" + }, + { + "$$hashKey": "object:2047", + "alias": "/.*sdc3.*/", + "color": "#9AC48A" + }, + { + "$$hashKey": "object:2048", + "alias": "/.*sdd1.*/", + "color": "#65C5DB" + }, + { + "$$hashKey": "object:2049", + "alias": "/.*sdd2.*/", + "color": "#F9934E" + }, + { + "$$hashKey": "object:2050", + "alias": "/.*sdd3.*/", + "color": "#EA6460" + }, + { + "$$hashKey": "object:2051", + "alias": "/.*sde1.*/", + "color": "#E0F9D7" + }, + { + "$$hashKey": "object:2052", + "alias": "/.*sdd2.*/", + "color": "#FCEACA" + }, + { + "$$hashKey": "object:2053", + "alias": "/.*sde3.*/", + "color": "#F9E2D2" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "rate(node_disk_reads_completed_total{node=~\"$node\",job=\"node-exporter\"}[$__rate_interval])", + "intervalFactor": 1, + "legendFormat": "{{device}} - Reads completed", + "refId": "A", + "step": 240 + }, + { + "expr": "rate(node_disk_writes_completed_total{node=~\"$node\",job=\"node-exporter\"}[$__rate_interval])", + "intervalFactor": 1, + "legendFormat": "{{device}} - Writes completed", + "refId": "B", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Disk IOps Completed", + "tooltip": { + "shared": false, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:2186", + "format": "iops", + "label": "IO read (-) / write (+)", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "$$hashKey": "object:2187", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "description": "The number of bytes read from or written to the device per second", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 28 + }, + "hiddenSeries": false, + "id": 33, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "hideZero": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "/.*Read.*/", + "transform": "negative-Y" + }, + { + "alias": "/.*sda_.*/", + "color": "#7EB26D" + }, + { + "alias": "/.*sdb_.*/", + "color": "#EAB839" + }, + { + "alias": "/.*sdc_.*/", + "color": "#6ED0E0" + }, + { + "alias": "/.*sdd_.*/", + "color": "#EF843C" + }, + { + "alias": "/.*sde_.*/", + "color": "#E24D42" + }, + { + "alias": "/.*sda1.*/", + "color": "#584477" + }, + { + "alias": "/.*sda2_.*/", + "color": "#BA43A9" + }, + { + "alias": "/.*sda3_.*/", + "color": "#F4D598" + }, + { + "alias": "/.*sdb1.*/", + "color": "#0A50A1" + }, + { + "alias": "/.*sdb2.*/", + "color": "#BF1B00" + }, + { + "alias": "/.*sdb3.*/", + "color": "#E0752D" + }, + { + "alias": "/.*sdc1.*/", + "color": "#962D82" + }, + { + "alias": "/.*sdc2.*/", + "color": "#614D93" + }, + { + "alias": "/.*sdc3.*/", + "color": "#9AC48A" + }, + { + "alias": "/.*sdd1.*/", + "color": "#65C5DB" + }, + { + "alias": "/.*sdd2.*/", + "color": "#F9934E" + }, + { + "alias": "/.*sdd3.*/", + "color": "#EA6460" + }, + { + "alias": "/.*sde1.*/", + "color": "#E0F9D7" + }, + { + "alias": "/.*sdd2.*/", + "color": "#FCEACA" + }, + { + "alias": "/.*sde3.*/", + "color": "#F9E2D2" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "rate(node_disk_read_bytes_total{node=~\"$node\",job=\"node-exporter\"}[$__rate_interval])", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{device}} - Read bytes", + "refId": "A", + "step": 240 + }, + { + "expr": "rate(node_disk_written_bytes_total{node=~\"$node\",job=\"node-exporter\"}[$__rate_interval])", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{device}} - Written bytes", + "refId": "B", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Disk R/W Data", + "tooltip": { + "shared": false, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:369", + "format": "Bps", + "label": "bytes read (-) / write (+)", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "$$hashKey": "object:370", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "description": "The average time for requests issued to the device to be served. This includes the time spent by the requests in queue and the time spent servicing them.", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 3, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 38 + }, + "hiddenSeries": false, + "id": 37, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "hideZero": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "/.*Read.*/", + "transform": "negative-Y" + }, + { + "alias": "/.*sda_.*/", + "color": "#7EB26D" + }, + { + "alias": "/.*sdb_.*/", + "color": "#EAB839" + }, + { + "alias": "/.*sdc_.*/", + "color": "#6ED0E0" + }, + { + "alias": "/.*sdd_.*/", + "color": "#EF843C" + }, + { + "alias": "/.*sde_.*/", + "color": "#E24D42" + }, + { + "alias": "/.*sda1.*/", + "color": "#584477" + }, + { + "alias": "/.*sda2_.*/", + "color": "#BA43A9" + }, + { + "alias": "/.*sda3_.*/", + "color": "#F4D598" + }, + { + "alias": "/.*sdb1.*/", + "color": "#0A50A1" + }, + { + "alias": "/.*sdb2.*/", + "color": "#BF1B00" + }, + { + "alias": "/.*sdb3.*/", + "color": "#E0752D" + }, + { + "alias": "/.*sdc1.*/", + "color": "#962D82" + }, + { + "alias": "/.*sdc2.*/", + "color": "#614D93" + }, + { + "alias": "/.*sdc3.*/", + "color": "#9AC48A" + }, + { + "alias": "/.*sdd1.*/", + "color": "#65C5DB" + }, + { + "alias": "/.*sdd2.*/", + "color": "#F9934E" + }, + { + "alias": "/.*sdd3.*/", + "color": "#EA6460" + }, + { + "alias": "/.*sde1.*/", + "color": "#E0F9D7" + }, + { + "alias": "/.*sdd2.*/", + "color": "#FCEACA" + }, + { + "alias": "/.*sde3.*/", + "color": "#F9E2D2" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "rate(node_disk_read_time_seconds_total{node=~\"$node\",job=\"node-exporter\"}[$__rate_interval]) / rate(node_disk_reads_completed_total{node=~\"$node\",job=\"node-exporter\"}[$__rate_interval])", + "hide": false, + "intervalFactor": 1, + "legendFormat": "{{device}} - r_await", + "refId": "A", + "step": 240 + }, + { + "expr": "rate(node_disk_write_time_seconds_total{node=~\"$node\",job=\"node-exporter\"}[$__rate_interval]) / rate(node_disk_writes_completed_total{node=~\"$node\",job=\"node-exporter\"}[$__rate_interval])", + "hide": false, + "intervalFactor": 1, + "legendFormat": "{{device}} - w_await", + "refId": "B", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Disk Average Wait Time", + "tooltip": { + "shared": false, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:441", + "format": "s", + "label": "time. read (-) / write (+)", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "$$hashKey": "object:442", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "description": "The average queue length of the requests that were issued to the device", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 38 + }, + "hiddenSeries": false, + "id": 35, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "hideZero": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "/.*sda_.*/", + "color": "#7EB26D" + }, + { + "alias": "/.*sdb_.*/", + "color": "#EAB839" + }, + { + "alias": "/.*sdc_.*/", + "color": "#6ED0E0" + }, + { + "alias": "/.*sdd_.*/", + "color": "#EF843C" + }, + { + "alias": "/.*sde_.*/", + "color": "#E24D42" + }, + { + "alias": "/.*sda1.*/", + "color": "#584477" + }, + { + "alias": "/.*sda2_.*/", + "color": "#BA43A9" + }, + { + "alias": "/.*sda3_.*/", + "color": "#F4D598" + }, + { + "alias": "/.*sdb1.*/", + "color": "#0A50A1" + }, + { + "alias": "/.*sdb2.*/", + "color": "#BF1B00" + }, + { + "alias": "/.*sdb3.*/", + "color": "#E0752D" + }, + { + "alias": "/.*sdc1.*/", + "color": "#962D82" + }, + { + "alias": "/.*sdc2.*/", + "color": "#614D93" + }, + { + "alias": "/.*sdc3.*/", + "color": "#9AC48A" + }, + { + "alias": "/.*sdd1.*/", + "color": "#65C5DB" + }, + { + "alias": "/.*sdd2.*/", + "color": "#F9934E" + }, + { + "alias": "/.*sdd3.*/", + "color": "#EA6460" + }, + { + "alias": "/.*sde1.*/", + "color": "#E0F9D7" + }, + { + "alias": "/.*sdd2.*/", + "color": "#FCEACA" + }, + { + "alias": "/.*sde3.*/", + "color": "#F9E2D2" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "rate(node_disk_io_time_weighted_seconds_total{node=~\"$node\",job=\"node-exporter\"}[$__rate_interval])", + "intervalFactor": 1, + "legendFormat": "{{device}}", + "refId": "A", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Average Queue Size", + "tooltip": { + "shared": false, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:513", + "format": "none", + "label": "aqu-sz", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "$$hashKey": "object:514", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "description": "The number of read and write requests merged per second that were queued to the device", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 48 + }, + "hiddenSeries": false, + "id": 133, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "hideZero": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "/.*Read.*/", + "transform": "negative-Y" + }, + { + "alias": "/.*sda_.*/", + "color": "#7EB26D" + }, + { + "alias": "/.*sdb_.*/", + "color": "#EAB839" + }, + { + "alias": "/.*sdc_.*/", + "color": "#6ED0E0" + }, + { + "alias": "/.*sdd_.*/", + "color": "#EF843C" + }, + { + "alias": "/.*sde_.*/", + "color": "#E24D42" + }, + { + "alias": "/.*sda1.*/", + "color": "#584477" + }, + { + "alias": "/.*sda2_.*/", + "color": "#BA43A9" + }, + { + "alias": "/.*sda3_.*/", + "color": "#F4D598" + }, + { + "alias": "/.*sdb1.*/", + "color": "#0A50A1" + }, + { + "alias": "/.*sdb2.*/", + "color": "#BF1B00" + }, + { + "alias": "/.*sdb3.*/", + "color": "#E0752D" + }, + { + "alias": "/.*sdc1.*/", + "color": "#962D82" + }, + { + "alias": "/.*sdc2.*/", + "color": "#614D93" + }, + { + "alias": "/.*sdc3.*/", + "color": "#9AC48A" + }, + { + "alias": "/.*sdd1.*/", + "color": "#65C5DB" + }, + { + "alias": "/.*sdd2.*/", + "color": "#F9934E" + }, + { + "alias": "/.*sdd3.*/", + "color": "#EA6460" + }, + { + "alias": "/.*sde1.*/", + "color": "#E0F9D7" + }, + { + "alias": "/.*sdd2.*/", + "color": "#FCEACA" + }, + { + "alias": "/.*sde3.*/", + "color": "#F9E2D2" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "rate(node_disk_reads_merged_total{node=~\"$node\",job=\"node-exporter\"}[$__rate_interval])", + "intervalFactor": 1, + "legendFormat": "{{device}} - Read merged", + "refId": "A", + "step": 240 + }, + { + "expr": "rate(node_disk_writes_merged_total{node=~\"$node\",job=\"node-exporter\"}[$__rate_interval])", + "intervalFactor": 1, + "legendFormat": "{{device}} - Write merged", + "refId": "B", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Disk R/W Merged", + "tooltip": { + "shared": false, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:585", + "format": "iops", + "label": "I/Os", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "$$hashKey": "object:586", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "description": "Percentage of elapsed time during which I/O requests were issued to the device (bandwidth utilization for the device). Device saturation occurs when this value is close to 100% for devices serving requests serially. But for devices serving requests in parallel, such as RAID arrays and modern SSDs, this number does not reflect their performance limits.", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 3, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 48 + }, + "hiddenSeries": false, + "id": 36, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "hideZero": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "/.*sda_.*/", + "color": "#7EB26D" + }, + { + "alias": "/.*sdb_.*/", + "color": "#EAB839" + }, + { + "alias": "/.*sdc_.*/", + "color": "#6ED0E0" + }, + { + "alias": "/.*sdd_.*/", + "color": "#EF843C" + }, + { + "alias": "/.*sde_.*/", + "color": "#E24D42" + }, + { + "alias": "/.*sda1.*/", + "color": "#584477" + }, + { + "alias": "/.*sda2_.*/", + "color": "#BA43A9" + }, + { + "alias": "/.*sda3_.*/", + "color": "#F4D598" + }, + { + "alias": "/.*sdb1.*/", + "color": "#0A50A1" + }, + { + "alias": "/.*sdb2.*/", + "color": "#BF1B00" + }, + { + "alias": "/.*sdb3.*/", + "color": "#E0752D" + }, + { + "alias": "/.*sdc1.*/", + "color": "#962D82" + }, + { + "alias": "/.*sdc2.*/", + "color": "#614D93" + }, + { + "alias": "/.*sdc3.*/", + "color": "#9AC48A" + }, + { + "alias": "/.*sdd1.*/", + "color": "#65C5DB" + }, + { + "alias": "/.*sdd2.*/", + "color": "#F9934E" + }, + { + "alias": "/.*sdd3.*/", + "color": "#EA6460" + }, + { + "alias": "/.*sde1.*/", + "color": "#E0F9D7" + }, + { + "alias": "/.*sdd2.*/", + "color": "#FCEACA" + }, + { + "alias": "/.*sde3.*/", + "color": "#F9E2D2" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "rate(node_disk_io_time_seconds_total{node=~\"$node\",job=\"node-exporter\"}[$__rate_interval])", + "intervalFactor": 1, + "legendFormat": "{{device}} - IO", + "refId": "A", + "step": 240 + }, + { + "expr": "rate(node_disk_discard_time_seconds_total{node=~\"$node\",job=\"node-exporter\"}[$__rate_interval])", + "intervalFactor": 1, + "legendFormat": "{{device}} - discard", + "refId": "B", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Time Spent Doing I/Os", + "tooltip": { + "shared": false, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:657", + "format": "percentunit", + "label": "%util", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "$$hashKey": "object:658", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "description": "The number of outstanding requests at the instant the sample was taken. Incremented as requests are given to appropriate struct request_queue and decremented as they finish.", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 58 + }, + "hiddenSeries": false, + "id": 34, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "hideZero": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "/.*sda_.*/", + "color": "#7EB26D" + }, + { + "alias": "/.*sdb_.*/", + "color": "#EAB839" + }, + { + "alias": "/.*sdc_.*/", + "color": "#6ED0E0" + }, + { + "alias": "/.*sdd_.*/", + "color": "#EF843C" + }, + { + "alias": "/.*sde_.*/", + "color": "#E24D42" + }, + { + "alias": "/.*sda1.*/", + "color": "#584477" + }, + { + "alias": "/.*sda2_.*/", + "color": "#BA43A9" + }, + { + "alias": "/.*sda3_.*/", + "color": "#F4D598" + }, + { + "alias": "/.*sdb1.*/", + "color": "#0A50A1" + }, + { + "alias": "/.*sdb2.*/", + "color": "#BF1B00" + }, + { + "alias": "/.*sdb3.*/", + "color": "#E0752D" + }, + { + "alias": "/.*sdc1.*/", + "color": "#962D82" + }, + { + "alias": "/.*sdc2.*/", + "color": "#614D93" + }, + { + "alias": "/.*sdc3.*/", + "color": "#9AC48A" + }, + { + "alias": "/.*sdd1.*/", + "color": "#65C5DB" + }, + { + "alias": "/.*sdd2.*/", + "color": "#F9934E" + }, + { + "alias": "/.*sdd3.*/", + "color": "#EA6460" + }, + { + "alias": "/.*sde1.*/", + "color": "#E0F9D7" + }, + { + "alias": "/.*sdd2.*/", + "color": "#FCEACA" + }, + { + "alias": "/.*sde3.*/", + "color": "#F9E2D2" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "rate(node_disk_io_now{node=~\"$node\",job=\"node-exporter\"}[$__rate_interval])", + "intervalFactor": 1, + "legendFormat": "{{device}} - IO now", + "refId": "A", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Instantaneous Queue Size", + "tooltip": { + "shared": false, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:729", + "format": "iops", + "label": "I/Os", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "$$hashKey": "object:730", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "description": "", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 58 + }, + "hiddenSeries": false, + "id": 301, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "hideZero": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 6, + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "$$hashKey": "object:2034", + "alias": "/.*sda_.*/", + "color": "#7EB26D" + }, + { + "$$hashKey": "object:2035", + "alias": "/.*sdb_.*/", + "color": "#EAB839" + }, + { + "$$hashKey": "object:2036", + "alias": "/.*sdc_.*/", + "color": "#6ED0E0" + }, + { + "$$hashKey": "object:2037", + "alias": "/.*sdd_.*/", + "color": "#EF843C" + }, + { + "$$hashKey": "object:2038", + "alias": "/.*sde_.*/", + "color": "#E24D42" + }, + { + "$$hashKey": "object:2039", + "alias": "/.*sda1.*/", + "color": "#584477" + }, + { + "$$hashKey": "object:2040", + "alias": "/.*sda2_.*/", + "color": "#BA43A9" + }, + { + "$$hashKey": "object:2041", + "alias": "/.*sda3_.*/", + "color": "#F4D598" + }, + { + "$$hashKey": "object:2042", + "alias": "/.*sdb1.*/", + "color": "#0A50A1" + }, + { + "$$hashKey": "object:2043", + "alias": "/.*sdb2.*/", + "color": "#BF1B00" + }, + { + "$$hashKey": "object:2044", + "alias": "/.*sdb3.*/", + "color": "#E0752D" + }, + { + "$$hashKey": "object:2045", + "alias": "/.*sdc1.*/", + "color": "#962D82" + }, + { + "$$hashKey": "object:2046", + "alias": "/.*sdc2.*/", + "color": "#614D93" + }, + { + "$$hashKey": "object:2047", + "alias": "/.*sdc3.*/", + "color": "#9AC48A" + }, + { + "$$hashKey": "object:2048", + "alias": "/.*sdd1.*/", + "color": "#65C5DB" + }, + { + "$$hashKey": "object:2049", + "alias": "/.*sdd2.*/", + "color": "#F9934E" + }, + { + "$$hashKey": "object:2050", + "alias": "/.*sdd3.*/", + "color": "#EA6460" + }, + { + "$$hashKey": "object:2051", + "alias": "/.*sde1.*/", + "color": "#E0F9D7" + }, + { + "$$hashKey": "object:2052", + "alias": "/.*sdd2.*/", + "color": "#FCEACA" + }, + { + "$$hashKey": "object:2053", + "alias": "/.*sde3.*/", + "color": "#F9E2D2" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "rate(node_disk_discards_completed_total{node=~\"$node\",job=\"node-exporter\"}[$__rate_interval])", + "intervalFactor": 1, + "legendFormat": "{{device}} - Discards completed", + "refId": "A", + "step": 240 + }, + { + "expr": "rate(node_disk_discards_merged_total{node=~\"$node\",job=\"node-exporter\"}[$__rate_interval])", + "intervalFactor": 1, + "legendFormat": "{{device}} - Discards merged", + "refId": "B", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Disk IOps Discards completed / merged", + "tooltip": { + "shared": false, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:2186", + "format": "iops", + "label": "IOs", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "$$hashKey": "object:2187", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "repeat": null, + "title": "Storage Disk", + "type": "row" + }, + { + "collapsed": true, + "datasource": "$ds_prometheus", + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 27 + }, + "id": 271, + "panels": [ + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 3, + "description": "", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 14 + }, + "hiddenSeries": false, + "id": 43, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "node_filesystem_avail_bytes{node=~\"$node\",job=\"node-exporter\",device!~'rootfs'}", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "{{mountpoint}} - Available", + "metric": "", + "refId": "A", + "step": 240 + }, + { + "expr": "node_filesystem_free_bytes{node=~\"$node\",job=\"node-exporter\",device!~'rootfs'}", + "format": "time_series", + "hide": true, + "intervalFactor": 1, + "legendFormat": "{{mountpoint}} - Free", + "refId": "B", + "step": 240 + }, + { + "expr": "node_filesystem_size_bytes{node=~\"$node\",job=\"node-exporter\",device!~'rootfs'}", + "format": "time_series", + "hide": true, + "intervalFactor": 1, + "legendFormat": "{{mountpoint}} - Size", + "refId": "C", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Filesystem space available", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:3826", + "format": "bytes", + "label": "bytes", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "$$hashKey": "object:3827", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "description": "", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 14 + }, + "hiddenSeries": false, + "id": 41, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "hideZero": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "node_filesystem_files_free{node=~\"$node\",job=\"node-exporter\",device!~'rootfs'}", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "{{mountpoint}} - Free file nodes", + "refId": "A", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "File Nodes Free", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:3894", + "format": "short", + "label": "file nodes", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "$$hashKey": "object:3895", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "description": "", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 24 + }, + "hiddenSeries": false, + "id": 28, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "node_filefd_maximum{node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Max open files", + "refId": "A", + "step": 240 + }, + { + "expr": "node_filefd_allocated{node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Open files", + "refId": "B", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "File Descriptor", + "tooltip": { + "shared": false, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "files", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "description": "", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 24 + }, + "hiddenSeries": false, + "id": 219, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "hideZero": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "node_filesystem_files{node=~\"$node\",job=\"node-exporter\",device!~'rootfs'}", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "{{mountpoint}} - File nodes total", + "refId": "A", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "File Nodes Size", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "file Nodes", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "/ ReadOnly": "#890F02" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": null, + "description": "", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 34 + }, + "hiddenSeries": false, + "id": 44, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "hideEmpty": true, + "hideZero": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": true, + "targets": [ + { + "expr": "node_filesystem_readonly{node=~\"$node\",job=\"node-exporter\",device!~'rootfs'}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{mountpoint}} - ReadOnly", + "refId": "A", + "step": 240 + }, + { + "expr": "node_filesystem_device_error{node=~\"$node\",job=\"node-exporter\",device!~'rootfs',fstype!~'tmpfs'}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{mountpoint}} - Device error", + "refId": "B", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Filesystem in ReadOnly / Error", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:3670", + "format": "short", + "label": "counter", + "logBase": 1, + "max": "1", + "min": "0", + "show": true + }, + { + "$$hashKey": "object:3671", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "repeat": null, + "title": "Storage Filesystem", + "type": "row" + }, + { + "collapsed": true, + "datasource": "$ds_prometheus", + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 28 + }, + "id": 272, + "panels": [ + { + "aliasColors": { + "receive_packets_eth0": "#7EB26D", + "receive_packets_lo": "#E24D42", + "transmit_packets_eth0": "#7EB26D", + "transmit_packets_lo": "#E24D42" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 100 + }, + "hiddenSeries": false, + "id": 60, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sideWidth": 300, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "/.*Trans.*/", + "transform": "negative-Y" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "rate(node_network_receive_packets_total{node=~\"$node\",job=\"node-exporter\"}[$__rate_interval])", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{device}} - Receive", + "refId": "A", + "step": 240 + }, + { + "expr": "rate(node_network_transmit_packets_total{node=~\"$node\",job=\"node-exporter\"}[$__rate_interval])", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{device}} - Transmit", + "refId": "B", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Network Traffic by Packets", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "pps", + "label": "packets out (-) / in (+)", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 100 + }, + "hiddenSeries": false, + "id": 142, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "hideEmpty": false, + "hideZero": false, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sideWidth": 300, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "/.*Trans.*/", + "transform": "negative-Y" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "rate(node_network_receive_errs_total{node=~\"$node\",job=\"node-exporter\"}[$__rate_interval])", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{device}} - Receive errors", + "refId": "A", + "step": 240 + }, + { + "expr": "rate(node_network_transmit_errs_total{node=~\"$node\",job=\"node-exporter\"}[$__rate_interval])", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{device}} - Rransmit errors", + "refId": "B", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Network Traffic Errors", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "pps", + "label": "packets out (-) / in (+)", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 110 + }, + "hiddenSeries": false, + "id": 143, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "hideEmpty": false, + "hideZero": false, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sideWidth": 300, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "/.*Trans.*/", + "transform": "negative-Y" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "rate(node_network_receive_drop_total{node=~\"$node\",job=\"node-exporter\"}[$__rate_interval])", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{device}} - Receive drop", + "refId": "A", + "step": 240 + }, + { + "expr": "rate(node_network_transmit_drop_total{node=~\"$node\",job=\"node-exporter\"}[$__rate_interval])", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{device}} - Transmit drop", + "refId": "B", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Network Traffic Drop", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "pps", + "label": "packets out (-) / in (+)", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 110 + }, + "hiddenSeries": false, + "id": 141, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "hideEmpty": false, + "hideZero": false, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sideWidth": 300, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "/.*Trans.*/", + "transform": "negative-Y" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "rate(node_network_receive_compressed_total{node=~\"$node\",job=\"node-exporter\"}[$__rate_interval])", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{device}} - Receive compressed", + "refId": "A", + "step": 240 + }, + { + "expr": "rate(node_network_transmit_compressed_total{node=~\"$node\",job=\"node-exporter\"}[$__rate_interval])", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{device}} - Transmit compressed", + "refId": "B", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Network Traffic Compressed", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "pps", + "label": "packets out (-) / in (+)", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 120 + }, + "hiddenSeries": false, + "id": 146, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "hideEmpty": false, + "hideZero": false, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sideWidth": 300, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "/.*Trans.*/", + "transform": "negative-Y" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "rate(node_network_receive_multicast_total{node=~\"$node\",job=\"node-exporter\"}[$__rate_interval])", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{device}} - Receive multicast", + "refId": "A", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Network Traffic Multicast", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "pps", + "label": "packets out (-) / in (+)", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 120 + }, + "hiddenSeries": false, + "id": 144, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "hideEmpty": false, + "hideZero": false, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sideWidth": 300, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "/.*Trans.*/", + "transform": "negative-Y" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "rate(node_network_receive_fifo_total{node=~\"$node\",job=\"node-exporter\"}[$__rate_interval])", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{device}} - Receive fifo", + "refId": "A", + "step": 240 + }, + { + "expr": "rate(node_network_transmit_fifo_total{node=~\"$node\",job=\"node-exporter\"}[$__rate_interval])", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{device}} - Transmit fifo", + "refId": "B", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Network Traffic Fifo", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "pps", + "label": "packets out (-) / in (+)", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 130 + }, + "hiddenSeries": false, + "id": 145, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "hideEmpty": false, + "hideZero": false, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sideWidth": 300, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "$$hashKey": "object:576", + "alias": "/.*Trans.*/", + "transform": "negative-Y" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "rate(node_network_receive_frame_total{node=~\"$node\",job=\"node-exporter\"}[$__rate_interval])", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "{{device}} - Receive frame", + "refId": "A", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Network Traffic Frame", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:589", + "format": "pps", + "label": "packets out (-) / in (+)", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "$$hashKey": "object:590", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 130 + }, + "hiddenSeries": false, + "id": 231, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "hideEmpty": false, + "hideZero": false, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sideWidth": 300, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "rate(node_network_transmit_carrier_total{node=~\"$node\",job=\"node-exporter\"}[$__rate_interval])", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{device}} - Statistic transmit_carrier", + "refId": "A", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Network Traffic Carrier", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "counter", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 140 + }, + "hiddenSeries": false, + "id": 232, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "hideEmpty": false, + "hideZero": false, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sideWidth": 300, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "/.*Trans.*/", + "transform": "negative-Y" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "rate(node_network_transmit_colls_total{node=~\"$node\",job=\"node-exporter\"}[$__rate_interval])", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{device}} - Transmit colls", + "refId": "A", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Network Traffic Colls", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "counter", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 140 + }, + "hiddenSeries": false, + "id": 61, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "$$hashKey": "object:663", + "alias": "NF conntrack limit", + "color": "#890F02", + "fill": 0 + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "node_nf_conntrack_entries{node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "NF conntrack entries", + "refId": "A", + "step": 240 + }, + { + "expr": "node_nf_conntrack_entries_limit{node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "NF conntrack limit", + "refId": "B", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "NF Contrack", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:678", + "format": "short", + "label": "entries", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "$$hashKey": "object:679", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 150 + }, + "hiddenSeries": false, + "id": 230, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "node_arp_entries{node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{ device }} - ARP entries", + "refId": "A", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "ARP Entries", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "Entries", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 150 + }, + "hiddenSeries": false, + "id": 288, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.2", + "pointradius": 1, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "node_network_mtu_bytes{node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{ device }} - Bytes", + "refId": "A", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "MTU", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 0, + "format": "bytes", + "label": "bytes", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 160 + }, + "hiddenSeries": false, + "id": 280, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.2", + "pointradius": 1, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "node_network_speed_bytes{node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{ device }} - Speed", + "refId": "A", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Speed", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 0, + "format": "bytes", + "label": "bytes", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 160 + }, + "hiddenSeries": false, + "id": 289, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.2", + "pointradius": 1, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "node_network_transmit_queue_length{node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{ device }} - Interface transmit queue length", + "refId": "A", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Queue Length", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 0, + "format": "none", + "label": "packets", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 170 + }, + "hiddenSeries": false, + "id": 309, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "hideEmpty": false, + "hideZero": false, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sideWidth": 300, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "node_network_up{operstate=\"up\",node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{interface}} - Operational state UP", + "refId": "A", + "step": 240 + }, + { + "expr": "node_network_carrier{node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "instant": false, + "legendFormat": "{{device}} - Physical link state", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Network Operational Status", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "counter", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "repeat": null, + "title": "Network Traffic", + "type": "row" + }, + { + "collapsed": true, + "datasource": "$ds_prometheus", + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 29 + }, + "id": 273, + "panels": [ + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 101 + }, + "hiddenSeries": false, + "id": 63, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "hideEmpty": false, + "hideZero": false, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sideWidth": 300, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "node_sockstat_TCP_alloc{node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "TCP_alloc - Allocated sockets", + "refId": "A", + "step": 240 + }, + { + "expr": "node_sockstat_TCP_inuse{node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "TCP_inuse - Tcp sockets currently in use", + "refId": "B", + "step": 240 + }, + { + "expr": "node_sockstat_TCP_mem{node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "hide": true, + "intervalFactor": 1, + "legendFormat": "TCP_mem - Used memory for tcp", + "refId": "C", + "step": 240 + }, + { + "expr": "node_sockstat_TCP_orphan{node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "TCP_orphan - Orphan sockets", + "refId": "D", + "step": 240 + }, + { + "expr": "node_sockstat_TCP_tw{node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "TCP_tw - Sockets wating close", + "refId": "E", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Sockstat TCP", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "counter", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 101 + }, + "hiddenSeries": false, + "id": 124, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "hideEmpty": false, + "hideZero": false, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sideWidth": 300, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "node_sockstat_UDPLITE_inuse{node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "UDPLITE_inuse - Udplite sockets currently in use", + "refId": "A", + "step": 240 + }, + { + "expr": "node_sockstat_UDP_inuse{node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "UDP_inuse - Udp sockets currently in use", + "refId": "B", + "step": 240 + }, + { + "expr": "node_sockstat_UDP_mem{node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "UDP_mem - Used memory for udp", + "refId": "C", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Sockstat UDP", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "counter", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 111 + }, + "hiddenSeries": false, + "id": 126, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "hideEmpty": false, + "hideZero": false, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sideWidth": 300, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "node_sockstat_sockets_used{node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Sockets_used - Sockets currently in use", + "refId": "A", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Sockstat Used", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "sockets", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 111 + }, + "hiddenSeries": false, + "id": 220, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "hideEmpty": false, + "hideZero": false, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sideWidth": 300, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "node_sockstat_TCP_mem_bytes{node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "mem_bytes - TCP sockets in that state", + "refId": "A", + "step": 240 + }, + { + "expr": "node_sockstat_UDP_mem_bytes{node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "mem_bytes - UDP sockets in that state", + "refId": "B", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Sockstat Memory Size", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": "bytes", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 121 + }, + "hiddenSeries": false, + "id": 125, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "hideEmpty": false, + "hideZero": false, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sideWidth": 300, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "node_sockstat_FRAG_inuse{node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "FRAG_inuse - Frag sockets currently in use", + "refId": "A", + "step": 240 + }, + { + "expr": "node_sockstat_FRAG_memory{node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "FRAG_memory - Used memory for frag", + "refId": "B", + "step": 240 + }, + { + "expr": "node_sockstat_RAW_inuse{node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "RAW_inuse - Raw sockets currently in use", + "refId": "C", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Sockstat FRAG / RAW", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:1572", + "format": "short", + "label": "counter", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "$$hashKey": "object:1573", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "repeat": null, + "title": "Network Sockstat", + "type": "row" + }, + { + "collapsed": true, + "datasource": "$ds_prometheus", + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 30 + }, + "id": 274, + "panels": [ + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 47 + }, + "height": "", + "hiddenSeries": false, + "id": 221, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "hideEmpty": false, + "hideZero": false, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sideWidth": 300, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 12, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "$$hashKey": "object:1876", + "alias": "/.*Out.*/", + "transform": "negative-Y" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "rate(node_netstat_IpExt_InOctets{node=~\"$node\",job=\"node-exporter\"}[$__rate_interval])", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "InOctets - Received octets", + "refId": "A", + "step": 240 + }, + { + "expr": "rate(node_netstat_IpExt_OutOctets{node=~\"$node\",job=\"node-exporter\"}[$__rate_interval])", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "OutOctets - Sent octets", + "refId": "B", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Netstat IP In / Out Octets", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:1889", + "format": "short", + "label": "octects out (-) / in (+)", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "$$hashKey": "object:1890", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 47 + }, + "height": "", + "hiddenSeries": false, + "id": 81, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "hideEmpty": false, + "hideZero": false, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sideWidth": 300, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "node_netstat_Ip_Forwarding{node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Forwarding - IP forwarding", + "refId": "A", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Netstat IP Forwarding", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:1957", + "format": "short", + "label": "counter", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "$$hashKey": "object:1958", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": null, + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 57 + }, + "height": "", + "hiddenSeries": false, + "id": 115, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "hideZero": false, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 12, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "/.*Out.*/", + "transform": "negative-Y" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "rate(node_netstat_Icmp_InMsgs{node=~\"$node\",job=\"node-exporter\"}[$__rate_interval])", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "InMsgs - Messages which the entity received. Note that this counter includes all those counted by icmpInErrors", + "refId": "A", + "step": 240 + }, + { + "expr": "rate(node_netstat_Icmp_OutMsgs{node=~\"$node\",job=\"node-exporter\"}[$__rate_interval])", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "OutMsgs - Messages which this entity attempted to send. Note that this counter includes all those counted by icmpOutErrors", + "refId": "B", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "ICMP In / Out", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "messages out (-) / in (+)", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": null, + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 57 + }, + "height": "", + "hiddenSeries": false, + "id": 50, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "hideZero": false, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 12, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "/.*Out.*/", + "transform": "negative-Y" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "rate(node_netstat_Icmp_InErrors{node=~\"$node\",job=\"node-exporter\"}[$__rate_interval])", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "InErrors - Messages which the entity received but determined as having ICMP-specific errors (bad ICMP checksums, bad length, etc.)", + "refId": "A", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "ICMP Errors", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "messages out (-) / in (+)", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": null, + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 67 + }, + "height": "", + "hiddenSeries": false, + "id": 55, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "hideZero": false, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 12, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "/.*Out.*/", + "transform": "negative-Y" + }, + { + "alias": "/.*Snd.*/", + "transform": "negative-Y" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "rate(node_netstat_Udp_InDatagrams{node=~\"$node\",job=\"node-exporter\"}[$__rate_interval])", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "InDatagrams - Datagrams received", + "refId": "A", + "step": 240 + }, + { + "expr": "rate(node_netstat_Udp_OutDatagrams{node=~\"$node\",job=\"node-exporter\"}[$__rate_interval])", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "OutDatagrams - Datagrams sent", + "refId": "B", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "UDP In / Out", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "datagrams out (-) / in (+)", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 67 + }, + "height": "", + "hiddenSeries": false, + "id": 109, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "hideZero": false, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 12, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "rate(node_netstat_Udp_InErrors{node=~\"$node\",job=\"node-exporter\"}[$__rate_interval])", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "InErrors - UDP Datagrams that could not be delivered to an application", + "refId": "A", + "step": 240 + }, + { + "expr": "rate(node_netstat_Udp_NoPorts{node=~\"$node\",job=\"node-exporter\"}[$__rate_interval])", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "NoPorts - UDP Datagrams received on a port with no listener", + "refId": "B", + "step": 240 + }, + { + "expr": "rate(node_netstat_UdpLite_InErrors{node=~\"$node\",job=\"node-exporter\"}[$__rate_interval])", + "legendFormat": "InErrors Lite - UDPLite Datagrams that could not be delivered to an application", + "refId": "C" + }, + { + "expr": "rate(node_netstat_Udp_RcvbufErrors{node=~\"$node\",job=\"node-exporter\"}[$__rate_interval])", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "RcvbufErrors - UDP buffer errors received", + "refId": "D", + "step": 240 + }, + { + "expr": "rate(node_netstat_Udp_SndbufErrors{node=~\"$node\",job=\"node-exporter\"}[$__rate_interval])", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "SndbufErrors - UDP buffer errors send", + "refId": "E", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "UDP Errors", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:4232", + "format": "short", + "label": "datagrams", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "$$hashKey": "object:4233", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": null, + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 77 + }, + "height": "", + "hiddenSeries": false, + "id": 299, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "hideZero": false, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 12, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "/.*Out.*/", + "transform": "negative-Y" + }, + { + "alias": "/.*Snd.*/", + "transform": "negative-Y" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "rate(node_netstat_Tcp_InSegs{node=~\"$node\",job=\"node-exporter\"}[$__rate_interval])", + "format": "time_series", + "instant": false, + "intervalFactor": 1, + "legendFormat": "InSegs - Segments received, including those received in error. This count includes segments received on currently established connections", + "refId": "A", + "step": 240 + }, + { + "expr": "rate(node_netstat_Tcp_OutSegs{node=~\"$node\",job=\"node-exporter\"}[$__rate_interval])", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "OutSegs - Segments sent, including those on current connections but excluding those containing only retransmitted octets", + "refId": "B", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "TCP In / Out", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "datagrams out (-) / in (+)", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "description": "", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 77 + }, + "height": "", + "hiddenSeries": false, + "id": 104, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "hideEmpty": false, + "hideZero": false, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 12, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "rate(node_netstat_TcpExt_ListenOverflows{node=~\"$node\",job=\"node-exporter\"}[$__rate_interval])", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "ListenOverflows - Times the listen queue of a socket overflowed", + "refId": "A", + "step": 240 + }, + { + "expr": "rate(node_netstat_TcpExt_ListenDrops{node=~\"$node\",job=\"node-exporter\"}[$__rate_interval])", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "ListenDrops - SYNs to LISTEN sockets ignored", + "refId": "B", + "step": 240 + }, + { + "expr": "rate(node_netstat_TcpExt_TCPSynRetrans{node=~\"$node\",job=\"node-exporter\"}[$__rate_interval])", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "TCPSynRetrans - SYN-SYN/ACK retransmits to break down retransmissions in SYN, fast/timeout retransmits", + "refId": "C", + "step": 240 + }, + { + "expr": "rate(node_netstat_Tcp_RetransSegs{node=~\"$node\",job=\"node-exporter\"}[$__rate_interval])", + "legendFormat": "RetransSegs - Segments retransmitted - that is, the number of TCP segments transmitted containing one or more previously transmitted octets", + "refId": "D" + }, + { + "expr": "rate(node_netstat_Tcp_InErrs{node=~\"$node\",job=\"node-exporter\"}[$__rate_interval])", + "legendFormat": "InErrs - Segments received in error (e.g., bad TCP checksums)", + "refId": "E" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "TCP Errors", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "counter", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 87 + }, + "height": "", + "hiddenSeries": false, + "id": 85, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "hideZero": false, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 12, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "$$hashKey": "object:454", + "alias": "/.*MaxConn *./", + "color": "#890F02", + "fill": 0 + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "node_netstat_Tcp_CurrEstab{node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "CurrEstab - TCP connections for which the current state is either ESTABLISHED or CLOSE- WAIT", + "refId": "A", + "step": 240 + }, + { + "expr": "node_netstat_Tcp_MaxConn{node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "MaxConn - Limit on the total number of TCP connections the entity can support (Dinamic is \"-1\")", + "refId": "B", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "TCP Connections", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:469", + "format": "short", + "label": "connections", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "$$hashKey": "object:470", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "description": "", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 87 + }, + "height": "", + "hiddenSeries": false, + "id": 91, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "hideEmpty": false, + "hideZero": false, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 12, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "/.*Sent.*/", + "transform": "negative-Y" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "rate(node_netstat_TcpExt_SyncookiesFailed{node=~\"$node\",job=\"node-exporter\"}[$__rate_interval])", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "SyncookiesFailed - Invalid SYN cookies received", + "refId": "A", + "step": 240 + }, + { + "expr": "rate(node_netstat_TcpExt_SyncookiesRecv{node=~\"$node\",job=\"node-exporter\"}[$__rate_interval])", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "SyncookiesRecv - SYN cookies received", + "refId": "B", + "step": 240 + }, + { + "expr": "rate(node_netstat_TcpExt_SyncookiesSent{node=~\"$node\",job=\"node-exporter\"}[$__rate_interval])", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "SyncookiesSent - SYN cookies sent", + "refId": "C", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "TCP SynCookie", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "counter out (-) / in (+)", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 97 + }, + "height": "", + "hiddenSeries": false, + "id": 82, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "hideZero": false, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 12, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "rate(node_netstat_Tcp_ActiveOpens{node=~\"$node\",job=\"node-exporter\"}[$__rate_interval])", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "ActiveOpens - TCP connections that have made a direct transition to the SYN-SENT state from the CLOSED state", + "refId": "A", + "step": 240 + }, + { + "expr": "rate(node_netstat_Tcp_PassiveOpens{node=~\"$node\",job=\"node-exporter\"}[$__rate_interval])", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "PassiveOpens - TCP connections that have made a direct transition to the SYN-RCVD state from the LISTEN state", + "refId": "B", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "TCP Direct Transition", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "connections", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 97 + }, + "height": "", + "hiddenSeries": false, + "id": 100, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "hideZero": false, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "minSpan": 2, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "rate(node_netstat_TcpExt_TW{node=~\"$node\"}[$__rate_interval])", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "TW - TCP sockets finished time wait in fast timer", + "refId": "O", + "step": 600 + }, + { + "expr": "rate(node_netstat_TcpExt_TWKilled{node=~\"$node\"}[$__rate_interval])", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "TWKilled - TCP sockets finished time wait in slow timer", + "refId": "P", + "step": 600 + }, + { + "expr": "rate(node_netstat_TcpExt_TWRecycled{node=~\"$node\"}[$__rate_interval])", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "TWRecycled - Time wait sockets recycled by time stamp", + "refId": "Q", + "step": 600 + }, + { + "expr": "rate(node_netstat_TcpExt_TCPTimeWaitOverflow{node=~\"$node\"}[$__rate_interval])", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "TCPTimeWaitOverflow - Occurences of time wait bucket overflow", + "refId": "A", + "step": 600 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "TCP TimeWait", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "Counter", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "repeat": null, + "title": "Network Netstat", + "type": "row" + }, + { + "collapsed": true, + "datasource": "$ds_prometheus", + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 31 + }, + "id": 279, + "panels": [ + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "description": "", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 18 + }, + "hiddenSeries": false, + "id": 40, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "show": true, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": true, + "targets": [ + { + "expr": "node_scrape_collector_duration_seconds{node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "{{collector}} - Scrape duration", + "refId": "A", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Node Exporter Scrape Time", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "s", + "label": "seconds", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "description": "", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 18 + }, + "hiddenSeries": false, + "id": 157, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "$$hashKey": "object:1969", + "alias": "/.*error.*/", + "color": "#F2495C", + "transform": "negative-Y" + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": true, + "targets": [ + { + "expr": "node_scrape_collector_success{node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "{{collector}} - Scrape success", + "refId": "A", + "step": 240 + }, + { + "expr": "node_textfile_scrape_error{node=~\"$node\",job=\"node-exporter\"}", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "{{collector}} - Scrape textfile error (1 = true)", + "refId": "B", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Node Exporter Scrape", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:1484", + "format": "short", + "label": "counter", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "$$hashKey": "object:1485", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "repeat": null, + "title": "Node Exporter", + "type": "row" + } + ], + "refresh": "30s", + "schemaVersion": 27, + "style": "dark", + "tags": [ + "nodes" + ], + "templating": { + "list": [ + { + "current": { + "selected": false, + "text": "default", + "value": "default" + }, + "description": null, + "error": null, + "hide": 0, + "includeAll": false, + "label": "datasource", + "multi": false, + "name": "ds_prometheus", + "options": [], + "query": "prometheus", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + }, + { + "allValue": null, + "current": { + "selected": false, + "text": "dev-master-0", + "value": "dev-master-0" + }, + "datasource": "$ds_prometheus", + "definition": "", + "description": null, + "error": null, + "hide": 0, + "includeAll": false, + "label": "Node:", + "multi": false, + "name": "node", + "options": [], + "query": { + "query": "label_values(up{job=\"node-exporter\"}, node)", + "refId": "main-node-Variable-Query" + }, + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "current": { + "selected": false, + "text": "[a-z]+|nvme[0-9]+n[0-9]+", + "value": "[a-z]+|nvme[0-9]+n[0-9]+" + }, + "description": null, + "error": null, + "hide": 2, + "includeAll": false, + "label": null, + "multi": false, + "name": "diskdevices", + "options": [ + { + "selected": true, + "text": "[a-z]+|nvme[0-9]+n[0-9]+", + "value": "[a-z]+|nvme[0-9]+n[0-9]+" + } + ], + "query": "[a-z]+|nvme[0-9]+n[0-9]+", + "skipUrlSync": false, + "type": "custom" + } + ] + }, + "time": { + "from": "now-3h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "browser", + "title": "Node", + "uid": "rYdddlPWk", + "version": 4 +} diff --git a/dashboards/main/nodes.json b/dashboards/main/nodes.json new file mode 100644 index 00000000..1d46aaec --- /dev/null +++ b/dashboards/main/nodes.json @@ -0,0 +1,1942 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "target": { + "limit": 100, + "matchAny": false, + "tags": [], + "type": "dashboard" + }, + "type": "dashboard" + } + ] + }, + "description": "Dashboard to get an overview of one server", + "editable": false, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": 20, + "iteration": 1660228454568, + "links": [], + "liveNow": false, + "panels": [ + { + "datasource": { + "uid": "$ds_prometheus" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "displayMode": "auto", + "filterable": false, + "inspect": false, + "minWidth": 130 + }, + "decimals": 2, + "displayName": "", + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Time" + }, + "properties": [ + { + "id": "displayName", + "value": "Time" + }, + { + "id": "custom.align" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "node" + }, + "properties": [ + { + "id": "displayName", + "value": "Node name" + }, + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "links", + "value": [ + { + "targetBlank": true, + "title": "Node Details", + "url": "/d/rYdddlPWk/node-metrics-detailed?var-ds_prometheus=${ds_prometheus}&var-node=${__data.fields[\"node\"]}&${__url_time_range}" + } + ] + }, + { + "id": "custom.align" + }, + { + "id": "custom.minWidth", + "value": 400 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #B" + }, + "properties": [ + { + "id": "displayName", + "value": "Cores" + }, + { + "id": "unit", + "value": "short" + }, + { + "id": "custom.align" + }, + { + "id": "decimals", + "value": 0 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #C" + }, + "properties": [ + { + "id": "displayName", + "value": "Load Average" + }, + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #F" + }, + "properties": [ + { + "id": "displayName", + "value": "CPU Usage" + }, + { + "id": "unit", + "value": "percent" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #G" + }, + "properties": [ + { + "id": "displayName", + "value": "Memory Total" + }, + { + "id": "unit", + "value": "bytes" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "" + }, + "properties": [ + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #H" + }, + "properties": [ + { + "id": "displayName", + "value": "Memory RSS" + }, + { + "id": "unit", + "value": "bytes" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #J" + }, + "properties": [ + { + "id": "displayName", + "value": "Memory Cached + Buffer" + }, + { + "id": "unit", + "value": "bytes" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #K" + }, + "properties": [ + { + "id": "displayName", + "value": "RX Network" + }, + { + "id": "unit", + "value": "Bps" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #L" + }, + "properties": [ + { + "id": "displayName", + "value": "TX Network" + }, + { + "id": "unit", + "value": "Bps" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #M" + }, + "properties": [ + { + "id": "displayName", + "value": "Read bytes" + }, + { + "id": "unit", + "value": "bytes" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #N" + }, + "properties": [ + { + "id": "displayName", + "value": "Write bytes" + }, + { + "id": "unit", + "value": "bytes" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align" + } + ] + } + ] + }, + "gridPos": { + "h": 9, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 12, + "links": [], + "options": { + "footer": { + "fields": "", + "reducer": [ + "sum" + ], + "show": false + }, + "showHeader": true + }, + "pluginVersion": "8.5.2", + "targets": [ + { + "expr": "kube_node_info{node=~\"$node\"}", + "format": "table", + "instant": true, + "intervalFactor": 1, + "legendFormat": "Node name", + "refId": "A" + }, + { + "expr": "count by (node) (node_cpu_seconds_total{node=~\"$node\", mode=\"idle\"})", + "format": "table", + "instant": true, + "intervalFactor": 1, + "legendFormat": "Cores", + "refId": "B" + }, + { + "expr": "sum by (node) (avg_over_time(node_load1{node=~\"$node\"}[$__range]))", + "format": "table", + "instant": true, + "intervalFactor": 1, + "legendFormat": "Load Average", + "refId": "C" + }, + { + "expr": "100 - (avg by (node) (rate(node_cpu_seconds_total{node=~\"$node\", mode=\"idle\"}[$__rate_interval])) * 100 )", + "format": "table", + "instant": true, + "intervalFactor": 1, + "legendFormat": "CPU Usage", + "refId": "F" + }, + { + "expr": "sum by (node) (avg_over_time(node_memory_MemTotal_bytes{node=~\"$node\"}[$__range]))", + "format": "table", + "instant": true, + "intervalFactor": 1, + "legendFormat": "Memory", + "refId": "G" + }, + { + "expr": "sum by (node) \n (\n avg_over_time(node_memory_MemTotal_bytes{node=~\"$node\"}[$__range])\n -\n avg_over_time(node_memory_MemFree_bytes{node=~\"$node\"}[$__range])\n -\n avg_over_time(node_memory_Buffers_bytes{node=~\"$node\"}[$__range])\n -\n avg_over_time(node_memory_Cached_bytes{node=~\"$node\"}[$__range])\n )", + "format": "table", + "instant": true, + "intervalFactor": 1, + "legendFormat": "Memory RSS", + "refId": "H" + }, + { + "expr": "sum by (node) (avg_over_time(node_memory_Cached_bytes{node=~\"$node\"}[$__range]) + avg_over_time(node_memory_Buffers_bytes{node=~\"$node\"}[$__range]))", + "format": "table", + "instant": true, + "intervalFactor": 1, + "legendFormat": "Memory cached + bufeer", + "refId": "J" + }, + { + "expr": "sum by (node) (rate(node_network_receive_bytes_total{node=~\"$node\", device!~\"lo\"}[$__range]))", + "format": "table", + "instant": true, + "intervalFactor": 1, + "legendFormat": "RX Network", + "refId": "K" + }, + { + "expr": "sum by (node) (rate(node_network_transmit_bytes_total{node=~\"$node\", device!~\"lo\"}[$__range]))", + "format": "table", + "instant": true, + "intervalFactor": 1, + "legendFormat": "TX Network", + "refId": "L" + }, + { + "expr": "sum by (node) (rate(node_disk_read_bytes_total{node=~\"$node\"}[$__range]))", + "format": "table", + "instant": true, + "intervalFactor": 1, + "legendFormat": "Read bytes", + "refId": "M" + }, + { + "expr": "sum by (node) (rate(node_disk_written_bytes_total{node=~\"$node\"}[$__range]))", + "format": "table", + "instant": true, + "intervalFactor": 1, + "legendFormat": "Write bytes", + "refId": "N" + } + ], + "title": "Average", + "transformations": [ + { + "id": "merge", + "options": { + "reducers": [] + } + }, + { + "id": "filterFieldsByName", + "options": { + "include": { + "names": [ + "node", + "Value #B", + "Value #C", + "Value #F", + "Value #G", + "Value #H", + "Value #J", + "Value #K", + "Value #L", + "Value #M", + "Value #N" + ] + } + } + } + ], + "type": "table" + }, + { + "alerting": {}, + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "unit": "short" + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 7, + "w": 24, + "x": 0, + "y": 9 + }, + "hiddenSeries": false, + "id": 39, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.5.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "editorMode": "code", + "expr": "count(kube_node_info)", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "Total", + "range": true, + "refId": "A", + "step": 50 + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Count", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "", + "logBase": 1, + "max": 100, + "min": 0, + "show": true + }, + { + "format": "short", + "logBase": 1, + "show": true + } + ], + "yaxis": { + "align": false + } + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 16 + }, + "id": 27, + "title": "CPU", + "type": "row" + }, + { + "alerting": {}, + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "uid": "$ds_prometheus" + }, + "editable": true, + "error": false, + "fill": 1, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 7, + "w": 24, + "x": 0, + "y": 17 + }, + "hiddenSeries": false, + "id": 3, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.5.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "100 - (avg by (node) (rate(node_cpu_seconds_total{node=~\"$node\", mode=\"idle\"}[$__rate_interval])) * 100 )", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "{{ node }}", + "refId": "A", + "step": 50 + } + ], + "thresholds": [], + "timeRegions": [], + "title": "CPU Usage", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "percent", + "label": "", + "logBase": 1, + "max": 100, + "min": 0, + "show": true + }, + { + "format": "short", + "logBase": 1, + "show": true + } + ], + "yaxis": { + "align": false + } + }, + { + "alerting": {}, + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "uid": "$ds_prometheus" + }, + "editable": true, + "error": false, + "fill": 1, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 24 + }, + "hiddenSeries": false, + "id": 9, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.5.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "sum by (node) (avg_over_time(node_load1{node=~\"$node\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{ node }}", + "refId": "A", + "step": 20, + "target": "" + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Load Average", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "logBase": 1, + "show": true + }, + { + "format": "short", + "logBase": 1, + "show": true + } + ], + "yaxis": { + "align": false + } + }, + { + "alerting": {}, + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "uid": "$ds_prometheus" + }, + "description": "This graph shows the load as a percentage of the number of cores on the node", + "editable": true, + "error": false, + "fill": 1, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 24 + }, + "hiddenSeries": false, + "id": 13, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.5.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "sum by (node) (avg_over_time(node_load1{node=~\"$node\"}[$__rate_interval])) / count by (node) (node_cpu_seconds_total{node=~\"$node\", mode=\"idle\"}) * 100", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{ node }}", + "refId": "A", + "step": 20, + "target": "" + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Load Average %", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "percent", + "logBase": 1, + "show": true + }, + { + "format": "short", + "logBase": 1, + "show": true + } + ], + "yaxis": { + "align": false + } + }, + { + "collapsed": true, + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 31 + }, + "id": 17, + "panels": [ + { + "alerting": {}, + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "uid": "$ds_prometheus" + }, + "editable": true, + "error": false, + "fill": 1, + "grid": {}, + "gridPos": { + "h": 7, + "w": 6, + "x": 0, + "y": 25 + }, + "id": 28, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": "node", + "repeatDirection": "h", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "sum by (mode) (rate(node_cpu_seconds_total{node=~\"$node\"}[$__rate_interval])) * 100", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "{{ mode }}", + "refId": "A", + "step": 50 + } + ], + "thresholds": [], + "timeRegions": [], + "title": "$node", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "percent", + "label": "cpu usage", + "logBase": 1, + "min": 0, + "show": true + }, + { + "format": "short", + "logBase": 1, + "show": true + } + ], + "yaxis": { + "align": false + } + } + ], + "title": "CPU Usage", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 32 + }, + "id": 25, + "title": "Memory", + "type": "row" + }, + { + "alerting": {}, + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "uid": "$ds_prometheus" + }, + "editable": true, + "error": false, + "fill": 1, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 33 + }, + "hiddenSeries": false, + "id": 4, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.5.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": true, + "targets": [ + { + "expr": "sum by (node) \n (\n avg_over_time(node_memory_MemTotal_bytes{node=~\"$node\"}[$__rate_interval])\n -\n avg_over_time(node_memory_MemFree_bytes{node=~\"$node\"}[$__rate_interval])\n -\n avg_over_time(node_memory_Buffers_bytes{node=~\"$node\"}[$__rate_interval])\n -\n avg_over_time(node_memory_Cached_bytes{node=~\"$node\"}[$__rate_interval])\n )", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "{{ node }}", + "metric": "", + "refId": "C", + "step": 10 + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Memory RSS", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "logBase": 1, + "min": "0", + "show": true + }, + { + "format": "short", + "logBase": 1, + "show": true + } + ], + "yaxis": { + "align": false + } + }, + { + "alerting": {}, + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "uid": "$ds_prometheus" + }, + "editable": true, + "error": false, + "fill": 1, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 33 + }, + "hiddenSeries": false, + "id": 14, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.5.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "sum by (node) \n (\n avg_over_time(node_memory_MemTotal_bytes{node=~\"$node\"}[$__rate_interval])\n -\n avg_over_time(node_memory_MemFree_bytes{node=~\"$node\"}[$__rate_interval])\n -\n avg_over_time(node_memory_Buffers_bytes{node=~\"$node\"}[$__rate_interval])\n -\n avg_over_time(node_memory_Cached_bytes{node=~\"$node\"}[$__rate_interval])\n )\n/\nsum by (node) (avg_over_time(node_memory_MemTotal_bytes{node=~\"$node\"}[$__rate_interval]))\n* 100", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "{{ node }}", + "metric": "", + "refId": "C", + "step": 10 + }, + { + "expr": "sum by (node) (avg_over_time(node_load1{node=~\"$node\"}[$__rate_interval])) / count by (node) (node_cpu_seconds_total{node=~\"$node\", mode=\"idle\"}) * 100", + "format": "time_series", + "hide": true, + "intervalFactor": 1, + "refId": "A" + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Memory RSS %", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "percent", + "logBase": 1, + "min": "0", + "show": true + }, + { + "format": "short", + "logBase": 1, + "show": true + } + ], + "yaxis": { + "align": false + } + }, + { + "collapsed": true, + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 40 + }, + "id": 19, + "panels": [ + { + "alerting": {}, + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "uid": "$ds_prometheus" + }, + "editable": true, + "error": false, + "fill": 1, + "grid": {}, + "gridPos": { + "h": 7, + "w": 6, + "x": 0, + "y": 34 + }, + "id": 38, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": "node", + "repeatDirection": "h", + "seriesOverrides": [ + { + "alias": "Total", + "lines": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": true, + "targets": [ + { + "expr": "sum by (node) (avg_over_time(node_memory_MemTotal_bytes{node=\"$node\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A" + }, + { + "expr": "sum by (node) (avg_over_time(node_memory_MemFree_bytes{node=\"$node\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Free", + "refId": "B" + }, + { + "expr": "sum by (node) \n (\n avg_over_time(node_memory_MemTotal_bytes{node=\"$node\"}[$__rate_interval])\n -\n avg_over_time(node_memory_MemFree_bytes{node=\"$node\"}[$__rate_interval])\n -\n avg_over_time(node_memory_Buffers_bytes{node=\"$node\"}[$__rate_interval])\n -\n avg_over_time(node_memory_Cached_bytes{node=\"$node\"}[$__rate_interval])\n )", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "RSS", + "metric": "", + "refId": "C", + "step": 10 + }, + { + "expr": "sum by (node) (avg_over_time(node_memory_Cached_bytes{node=\"$node\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Cached", + "refId": "D" + }, + { + "expr": "sum by (node) (avg_over_time(node_memory_Buffers_bytes{node=\"$node\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Buffered", + "refId": "E" + } + ], + "thresholds": [], + "timeRegions": [], + "title": "$node", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "logBase": 1, + "min": "0", + "show": true + }, + { + "format": "short", + "logBase": 1, + "show": true + } + ], + "yaxis": { + "align": false + } + } + ], + "title": "Memory Usage", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 41 + }, + "id": 23, + "title": "Disk", + "type": "row" + }, + { + "alerting": {}, + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "uid": "$ds_prometheus" + }, + "editable": true, + "error": false, + "fill": 1, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 42 + }, + "hiddenSeries": false, + "id": 6, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.5.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "read", + "yaxis": 1 + }, + { + "alias": "{node=\"$node\"}", + "yaxis": 2 + }, + { + "alias": "io time", + "yaxis": 2 + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "sum by (node) (rate(node_disk_read_bytes_total{node=~\"$node\"}[$__rate_interval]))", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "{{ node }} read bytes", + "refId": "A", + "step": 20, + "target": "" + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Disk read bytes", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "logBase": 1, + "show": true + }, + { + "format": "ms", + "logBase": 1, + "show": true + } + ], + "yaxis": { + "align": false + } + }, + { + "alerting": {}, + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "uid": "$ds_prometheus" + }, + "editable": true, + "error": false, + "fill": 1, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 42 + }, + "hiddenSeries": false, + "id": 15, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.5.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "read", + "yaxis": 1 + }, + { + "alias": "{node=\"$node\"}", + "yaxis": 2 + }, + { + "alias": "io time", + "yaxis": 2 + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "sum by (node) (rate(node_disk_written_bytes_total{node=~\"$node\"}[$__rate_interval]))", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "{{ node }} written bytes", + "refId": "A", + "step": 20, + "target": "" + }, + { + "expr": "", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "", + "refId": "B", + "step": 20 + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Disk written bytes", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "logBase": 1, + "show": true + }, + { + "format": "ms", + "logBase": 1, + "show": true + } + ], + "yaxis": { + "align": false + } + }, + { + "collapsed": false, + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 50 + }, + "id": 21, + "panels": [], + "title": "Network", + "type": "row" + }, + { + "alerting": {}, + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "uid": "$ds_prometheus" + }, + "editable": true, + "error": false, + "fill": 1, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 51 + }, + "hiddenSeries": false, + "id": 8, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.5.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "transmitted ", + "yaxis": 2 + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "sum by (node) (rate(node_network_receive_bytes_total{node=~\"$node\",device!~\"lo\"}[$__rate_interval]))", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "{{ node }}", + "refId": "A", + "step": 10, + "target": "" + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Network received", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "show": true + } + ], + "yaxis": { + "align": false + } + }, + { + "alerting": {}, + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "uid": "$ds_prometheus" + }, + "editable": true, + "error": false, + "fill": 1, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 51 + }, + "hiddenSeries": false, + "id": 10, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.5.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "transmitted ", + "yaxis": 2 + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "sum by (node) (rate(node_network_transmit_bytes_total{node=~\"$node\",device!~\"lo\"}[$__rate_interval]))", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "{{ node }}", + "refId": "B", + "step": 10, + "target": "" + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Network transmitted", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "show": true + } + ], + "yaxis": { + "align": false + } + } + ], + "refresh": "30s", + "schemaVersion": 36, + "style": "dark", + "tags": [ + "nodes" + ], + "templating": { + "list": [ + { + "current": { + "selected": false, + "text": "default", + "value": "default" + }, + "hide": 0, + "includeAll": false, + "label": "Prometheus", + "multi": false, + "name": "ds_prometheus", + "options": [], + "query": "prometheus", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + }, + { + "allValue": ".*", + "current": { + "selected": false, + "text": "All", + "value": "$__all" + }, + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "definition": "", + "hide": 0, + "includeAll": true, + "label": "Node", + "multi": true, + "name": "node", + "options": [], + "query": { + "query": "label_values(up{job=\"node-exporter\"}, node)", + "refId": "main-node-Variable-Query" + }, + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + } + ] + }, + "time": { + "from": "now-3h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "browser", + "title": "Nodes", + "uid": "HB3tuvkmk1", + "version": 1, + "weekStart": "" +} diff --git a/dashboards/main/ntp.json b/dashboards/main/ntp.json new file mode 100644 index 00000000..5a79e6b0 --- /dev/null +++ b/dashboards/main/ntp.json @@ -0,0 +1,1271 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": "-- Grafana --", + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "description": "Dashboard for chrony or OpenNTPD.", + "editable": false, + "gnetId": 7496, + "graphTooltip": 0, + "iteration": 1557844573805, + "links": [], + "panels": [ + { + "cacheTimeout": null, + "colorBackground": false, + "colorValue": true, + "colors": [ + "#299c46", + "rgba(237, 129, 40, 0.89)", + "#d44a3a" + ], + "datasource": "$ds_prometheus", + "format": "short", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 3, + "w": 8, + "x": 0, + "y": 0 + }, + "id": 21, + "interval": null, + "links": [], + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + }, + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "nullPointMode": "connected", + "nullText": null, + "postfix": "", + "postfixFontSize": "50%", + "prefix": "", + "prefixFontSize": "50%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false + }, + "tableColumn": "", + "targets": [ + { + "expr": "count (node_timex_sync_status{node=~\"$node\"}==0)\nor vector(0)", + "format": "time_series", + "instant": true, + "intervalFactor": 1, + "refId": "A" + } + ], + "thresholds": "1,1", + "title": "Unsynced clocks", + "type": "singlestat", + "valueFontSize": "80%", + "valueMaps": [], + "valueName": "current" + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorPrefix": false, + "colorValue": true, + "colors": [ + "#299c46", + "rgba(237, 129, 40, 0.89)", + "#d44a3a" + ], + "datasource": "$ds_prometheus", + "description": "Aggregate NTPD health including stratum, leap flag, sane freshness, root distance being less than collector.ntp.max-distance and causality violation being less than collector.ntp.local-offset-tolerance.\n\nCausality violation is lower bound estimate of clock error done using SNTP, it's calculated as positive portion of abs(node_ntp_offset) - node_ntp_rtt / 2.", + "format": "none", + "gauge": { + "maxValue": 15, + "minValue": 0, + "show": false, + "thresholdLabels": true, + "thresholdMarkers": true + }, + "gridPos": { + "h": 3, + "w": 8, + "x": 8, + "y": 0 + }, + "id": 11, + "interval": null, + "links": [], + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + }, + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "nullPointMode": "connected", + "nullText": null, + "postfix": "", + "postfixFontSize": "50%", + "prefix": "", + "prefixFontSize": "50%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": true, + "lineColor": "rgb(31, 120, 193)", + "show": false + }, + "tableColumn": "key", + "targets": [ + { + "alias": "Reference ID", + "expr": "count (node_ntp_sanity{node=~\"$node\"}==0)\nor vector(0)", + "format": "time_series", + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "hide": false, + "instant": false, + "intervalFactor": 1, + "measurement": "chrony", + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT \"reference_id\" FROM (SELECT \"reference_id\", \"system_time\" FROM \"chrony\" WHERE $timeFilter)", + "rawQuery": true, + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "stratum" + ], + "type": "field" + } + ] + ], + "tags": [] + } + ], + "thresholds": "1,1", + "title": "Insane nodes", + "type": "singlestat", + "valueFontSize": "100%", + "valueMaps": [], + "valueName": "current" + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorValue": true, + "colors": [ + "#299c46", + "rgba(237, 129, 40, 0.89)", + "#d44a3a" + ], + "datasource": "$ds_prometheus", + "description": "The stratum indicates how many hops away from a computer with an attached reference clock we are. Such a computer is a stratum-1 computer, so the computer in the example is two hops away (i.e. foo.example.net is a stratum-2 and is synchronised from a stratum-1)", + "format": "none", + "gauge": { + "maxValue": 15, + "minValue": 0, + "show": false, + "thresholdLabels": true, + "thresholdMarkers": true + }, + "gridPos": { + "h": 3, + "w": 8, + "x": 16, + "y": 0 + }, + "id": 8, + "interval": null, + "links": [], + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + }, + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "nullPointMode": "connected", + "nullText": null, + "postfix": "", + "postfixFontSize": "50%", + "prefix": "", + "prefixFontSize": "50%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false + }, + "tableColumn": "__name__", + "targets": [ + { + "alias": "Stratum", + "expr": "count (node_ntp_stratum{node=~\"$node\"}==16)\nor vector(0)", + "format": "time_series", + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "hide": false, + "instant": true, + "intervalFactor": 1, + "legendFormat": "", + "measurement": "chrony", + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT \"stratum\" FROM (SELECT \"stratum\", \"system_time\" FROM \"chrony\" WHERE $timeFilter)", + "rawQuery": true, + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "stratum" + ], + "type": "field" + } + ] + ], + "tags": [] + } + ], + "thresholds": "16,16", + "title": "Stratum 16 nodes", + "type": "singlestat", + "valueFontSize": "100%", + "valueMaps": [], + "valueName": "current" + }, + { + "columns": [], + "datasource": "$ds_prometheus", + "fontSize": "100%", + "gridPos": { + "h": 8, + "w": 24, + "x": 0, + "y": 3 + }, + "id": 24, + "links": [], + "pageSize": null, + "scroll": true, + "showHeader": true, + "sort": { + "col": 3, + "desc": true + }, + "styles": [ + { + "alias": "Time", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "pattern": "Time", + "type": "hidden" + }, + { + "alias": "Node", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "decimals": 2, + "mappingType": 1, + "pattern": "node", + "thresholds": [], + "type": "string", + "unit": "short" + }, + { + "alias": "Sync status", + "colorMode": "value", + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 0, + "link": false, + "mappingType": 1, + "pattern": "Value #A", + "thresholds": [ + "1", + "1" + ], + "type": "number", + "unit": "short" + }, + { + "alias": "Sanity", + "colorMode": "value", + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 0, + "mappingType": 1, + "pattern": "Value #B", + "thresholds": [ + "1", + "1" + ], + "type": "number", + "unit": "short", + "valueMaps": [ + { + "text": "", + "value": "" + } + ] + }, + { + "alias": "Stratum", + "colorMode": null, + "colors": [ + "rgba(50, 172, 45, 0.97)", + "rgba(237, 129, 40, 0.89)", + "rgba(245, 54, 54, 0.9)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 0, + "mappingType": 1, + "pattern": "Value #C", + "thresholds": [ + "0", + "16" + ], + "type": "number", + "unit": "short" + }, + { + "alias": "Offset", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "Value #D", + "thresholds": [], + "type": "number", + "unit": "s" + }, + { + "alias": "RTT", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "Value #E", + "thresholds": [], + "type": "number", + "unit": "s" + }, + { + "alias": "Root dispersion", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "Value #F", + "thresholds": [], + "type": "number", + "unit": "s" + }, + { + "alias": "Root delay", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "Value #G", + "thresholds": [], + "type": "number", + "unit": "s" + }, + { + "alias": "Last clock adj", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "Value #H", + "thresholds": [], + "type": "number", + "unit": "s" + } + ], + "targets": [ + { + "expr": "max by (node) (min_over_time(node_timex_sync_status{node=~\"$node\"}[$__range]))", + "format": "table", + "instant": true, + "intervalFactor": 1, + "legendFormat": "Sync status", + "refId": "A" + }, + { + "expr": "max by (node) (min_over_time(node_ntp_sanity{node=~\"$node\"}[$__range]))", + "format": "table", + "instant": true, + "intervalFactor": 1, + "legendFormat": "Sanity", + "refId": "B" + }, + { + "expr": "max by (node) (max_over_time(node_ntp_stratum{node=~\"$node\"}[$__range]))", + "format": "table", + "instant": true, + "intervalFactor": 1, + "legendFormat": "Stratum", + "refId": "C" + }, + { + "expr": "max by (node) (max_over_time(node_ntp_offset_seconds:abs{node=~\"$node\"}[$__range]))", + "format": "table", + "instant": true, + "intervalFactor": 1, + "legendFormat": "Offset", + "refId": "D" + }, + { + "expr": "max by (node) (max_over_time(node_ntp_rtt_seconds{node=~\"$node\"}[$__range]))", + "format": "table", + "instant": true, + "intervalFactor": 1, + "legendFormat": "RTT", + "refId": "E" + }, + { + "expr": "max by (node) (max_over_time(node_ntp_root_dispersion_seconds{node=~\"$node\"}[$__range]))", + "format": "table", + "instant": true, + "intervalFactor": 1, + "legendFormat": "Root dispersion", + "refId": "F" + }, + { + "expr": "max by (node) (max_over_time(node_ntp_root_delay_seconds{node=~\"$node\"}[$__range]))", + "format": "table", + "instant": true, + "intervalFactor": 1, + "legendFormat": "Root delay", + "refId": "G" + }, + { + "expr": "max by (node) (node_time_seconds{node=~\"$node\"} - node_ntp_reference_timestamp_seconds{node=~\"$node\"})", + "format": "table", + "instant": true, + "intervalFactor": 1, + "legendFormat": "Last click adjustment", + "refId": "H" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Panel Title", + "transform": "table", + "type": "table" + }, + { + "aliasColors": { + "Frequency": "#70dbed", + "Residual Frequency": "#eab839", + "Skew (estimated error bound on the frequency)": "#962d82", + "Skew (estimated error)": "rgb(168, 48, 28)" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 3, + "description": "RTT (round-trip time) from node_exporter collector to local NTPD. This value is used in sanity check as part of causality violation estimate.", + "fill": 1, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 11 + }, + "id": 2, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "hideEmpty": true, + "max": true, + "min": true, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pointradius": 1, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "alias": "Frequency", + "expr": "max_over_time(node_ntp_rtt_seconds{node=~\"$node\"}[$__rate_interval])", + "format": "time_series", + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "none" + ], + "type": "fill" + } + ], + "intervalFactor": 1, + "legendFormat": "{{node}}", + "measurement": "chrony", + "orderByTime": "ASC", + "policy": "default", + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "frequency" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [] + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Max RTT", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": null, + "format": "s", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "decimals": null, + "format": "short", + "label": "", + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": null, + "description": "Offset - This is the estimated local offset to the ntp sources on the last clock update.", + "fill": 1, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 11 + }, + "id": 4, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "hideEmpty": true, + "max": true, + "min": true, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "alias": "Last Offset", + "expr": "(max_over_time(node_ntp_offset_seconds{node=~\"$node\"}[$__rate_interval]) > 0)\nor\n(min_over_time(node_ntp_offset_seconds{node=~\"$node\"}[$__rate_interval]) < 0)", + "format": "time_series", + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "none" + ], + "type": "fill" + } + ], + "instant": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "{{node}}", + "measurement": "chrony", + "orderByTime": "ASC", + "policy": "default", + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "last_offset" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [] + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Max offset", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "Frequency": "#70dbed", + "Residual Frequency": "#eab839", + "Skew (estimated error bound on the frequency)": "#962d82", + "Skew (estimated error)": "rgb(168, 48, 28)" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": 3, + "description": "RTT (round-trip time) from node_exporter collector to local NTPD. This value is used in sanity check as part of causality violation estimate.", + "fill": 1, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 20 + }, + "id": 25, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "hideEmpty": true, + "max": true, + "min": true, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pointradius": 1, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "alias": "Frequency", + "expr": "max_over_time(node_ntp_root_dispersion_seconds{node=~\"$node\"}[$__rate_interval])", + "format": "time_series", + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "none" + ], + "type": "fill" + } + ], + "intervalFactor": 1, + "legendFormat": "{{node}}", + "measurement": "chrony", + "orderByTime": "ASC", + "policy": "default", + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "frequency" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [] + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Max root dispersion", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": null, + "format": "s", + "label": "", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "decimals": null, + "format": "short", + "label": "", + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "decimals": null, + "description": "Offset - This is the estimated local offset to the ntp sources on the last clock update.", + "fill": 1, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 20 + }, + "id": 26, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "hideEmpty": true, + "max": true, + "min": true, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "alias": "Last Offset", + "expr": "(max_over_time(node_ntp_root_delay_seconds{node=~\"$node\"}[$__rate_interval]) > 0)\nor\n(min_over_time(node_ntp_root_delay_seconds{node=~\"$node\"}[$__rate_interval]) < 0)", + "format": "time_series", + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "none" + ], + "type": "fill" + } + ], + "instant": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "{{node}}", + "measurement": "chrony", + "orderByTime": "ASC", + "policy": "default", + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "last_offset" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [] + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Max root delay", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "description": "Reference Time. This field show time when the last adjustment was made, but implementation details vary from \"local wall-clock time\" to \"Reference Time field in incoming SNTP packet\".\n\nrepresent some estimate of \"freshness\" of synchronization.", + "fill": 1, + "gridPos": { + "h": 6, + "w": 24, + "x": 0, + "y": 29 + }, + "id": 15, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": true, + "min": true, + "rightSide": true, + "show": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pointradius": 0.5, + "points": true, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "node_time_seconds - node_ntp_reference_timestamp_seconds{node=~\"$node\"}", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "{{node}}", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Last Clock Adjustment", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": null, + "format": "s", + "label": "Duration", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": "", + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "refresh": "30s", + "schemaVersion": 18, + "style": "dark", + "tags": [ + "nodes" + ], + "templating": { + "list": [ + { + "current": { + "text": "trickster", + "value": "trickster" + }, + "hide": 0, + "includeAll": false, + "label": "Prometheus", + "multi": false, + "name": "ds_prometheus", + "options": [], + "query": "prometheus", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + }, + { + "allValue": null, + "current": { + "text": "All", + "value": "$__all" + }, + "datasource": "$ds_prometheus", + "definition": "label_values(node_ntp_sanity, node)", + "hide": 0, + "includeAll": true, + "label": "Node", + "multi": true, + "name": "node", + "options": [], + "query": "label_values(node_ntp_sanity, node)", + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + } + ] + }, + "time": { + "from": "now-3h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "", + "title": "NTP", + "uid": "38sNyU7iz", + "version": 2 +} diff --git a/dashboards/main/pod.json b/dashboards/main/pod.json new file mode 100644 index 00000000..36c172b8 --- /dev/null +++ b/dashboards/main/pod.json @@ -0,0 +1,4473 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": "-- Grafana --", + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "target": { + "limit": 100, + "matchAny": false, + "tags": [], + "type": "dashboard" + }, + "type": "dashboard" + } + ] + }, + "editable": false, + "fiscalYearStartMonth": 0, + "gnetId": null, + "graphTooltip": 1, + "iteration": 1640791001978, + "links": [], + "liveNow": false, + "panels": [ + { + "datasource": null, + "description": "Note that this table shows the average values for the entire period selected in the dashboard. Consequently, it may contain information about Pods or namespaces that were changed or deleted during the selected period.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": null, + "displayMode": "auto", + "filterable": false, + "minWidth": 75 + }, + "decimals": 2, + "displayName": "", + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Time" + }, + "properties": [ + { + "id": "displayName", + "value": "Time" + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 120 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "container" + }, + "properties": [ + { + "id": "displayName", + "value": "Container Name" + }, + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 150 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #A" + }, + "properties": [ + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #B" + }, + "properties": [ + { + "id": "displayName", + "value": "VPA Mode" + }, + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "mappings", + "value": [ + { + "options": { + "0": { + "text": "Off" + }, + "1": { + "text": "Initial" + }, + "2": { + "text": "Auto" + }, + "3": { + "text": "Recreate" + }, + "5": { + "text": "-" + } + }, + "type": "value" + } + ] + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #C" + }, + "properties": [ + { + "id": "displayName", + "value": "CPU" + }, + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #D" + }, + "properties": [ + { + "id": "displayName", + "value": "Req CPU" + }, + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #E" + }, + "properties": [ + { + "id": "displayName", + "value": "VPA CPU" + }, + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #F" + }, + "properties": [ + { + "id": "displayName", + "value": "Over-req CPU" + }, + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #G" + }, + "properties": [ + { + "id": "displayName", + "value": "Under-req CPU" + }, + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #H" + }, + "properties": [ + { + "id": "displayName", + "value": "Throttling cores" + }, + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #I" + }, + "properties": [ + { + "id": "displayName", + "value": "Memory" + }, + { + "id": "unit", + "value": "bytes" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #J" + }, + "properties": [ + { + "id": "displayName", + "value": "Req Memory" + }, + { + "id": "unit", + "value": "bytes" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #K" + }, + "properties": [ + { + "id": "displayName", + "value": "VPA Memory" + }, + { + "id": "unit", + "value": "bytes" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #L" + }, + "properties": [ + { + "id": "displayName", + "value": "Over-req Memory" + }, + { + "id": "unit", + "value": "bytes" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #M" + }, + "properties": [ + { + "id": "displayName", + "value": "Under-req Memory" + }, + { + "id": "unit", + "value": "bytes" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #N" + }, + "properties": [ + { + "id": "displayName", + "value": "RX Network (Pod)" + }, + { + "id": "unit", + "value": "Bps" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "mappings", + "value": [ + { + "type": "value", + "options": { + "-1": { + "text": "hostNet", + "index": 0 + } + } + } + ] + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #O" + }, + "properties": [ + { + "id": "displayName", + "value": "TX Network (Pod)" + }, + { + "id": "unit", + "value": "Bps" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "mappings", + "value": [ + { + "type": "value", + "options": { + "-1": { + "text": "hostNet", + "index": 0 + } + } + } + ] + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #P" + }, + "properties": [ + { + "id": "displayName", + "value": "Read IOPS" + }, + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #Q" + }, + "properties": [ + { + "id": "displayName", + "value": "Write IOPS" + }, + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #R" + }, + "properties": [ + { + "id": "displayName", + "value": "Pod Restarts" + }, + { + "id": "unit", + "value": "short" + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "node" + }, + "properties": [ + { + "id": "displayName", + "value": "Node" + }, + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + }, + { + "id": "custom.minWidth", + "value": 200 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #T" + }, + "properties": [ + { + "id": "displayName", + "value": "OOM killed" + }, + { + "id": "unit", + "value": "short" + }, + { + "id": "custom.align", + "value": null + } + ] + } + ] + }, + "gridPos": { + "h": 9, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 141, + "links": [], + "options": { + "showHeader": true + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "kube_pod_container_info{namespace=\"$namespace\", pod=\"$pod\", container=~\"$container\"}", + "format": "table", + "hide": false, + "instant": true, + "interval": "", + "intervalFactor": 1, + "legendFormat": "Container Name", + "refId": "A" + }, + { + "expr": "max by (pod, node) (avg_over_time(kube_pod_info{namespace=\"$namespace\", pod=\"$pod\"}[$__range]))", + "format": "table", + "instant": true, + "intervalFactor": 1, + "legendFormat": "Node", + "refId": "S" + }, + { + "expr": "sum by (pod) (avg_over_time(kube_controller_pod{namespace=\"$namespace\", pod=\"$pod\"}[$__range]) * on (controller_type, controller_name) group_left() sum by (controller_type, controller_name) (avg_over_time(vpa_target_recommendation{namespace=\"$namespace\", update_mode=\"Off\"}[$__range]))) * 0\nor\nsum by (pod) (avg_over_time(kube_controller_pod{namespace=\"$namespace\", pod=\"$pod\"}[$__range]) * on (controller_type, controller_name) group_left() sum by (controller_type, controller_name) (avg_over_time(vpa_target_recommendation{namespace=\"$namespace\", update_mode=\"Initial\"}[$__range]))) * 0 + 1\nor\nsum by (pod) (avg_over_time(kube_controller_pod{namespace=\"$namespace\", pod=\"$pod\"}[$__range]) * on (controller_type, controller_name) group_left() sum by (controller_type, controller_name) (avg_over_time(vpa_target_recommendation{namespace=\"$namespace\", update_mode=\"Auto\"}[$__range]))) * 0 + 2\nor\nsum by (pod) (avg_over_time(kube_controller_pod{namespace=\"$namespace\", pod=\"$pod\"}[$__range]) * on (controller_type, controller_name) group_left() sum by (controller_type, controller_name) (avg_over_time(vpa_target_recommendation{namespace=\"$namespace\", update_mode=\"Recreate\"}[$__range]))) * 0 + 3\nor\nsum by (pod) (avg_over_time(kube_controller_pod{namespace=\"$namespace\", pod=\"$pod\"}[$__range])) * 0 + 5", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "legendFormat": "VPA Mode", + "refId": "B" + }, + { + "expr": "sum by (container) (rate(container_cpu_usage_seconds_total{namespace=\"$namespace\", pod=\"$pod\", container!=\"POD\", container=~\"$container\"}[$__range]))\nor\nsum by (container) (avg_over_time(kube_pod_container_info{namespace=\"$namespace\", pod=\"$pod\", container=~\"$container\"}[$__range]) * 0)", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "legendFormat": "CPU", + "refId": "C" + }, + { + "expr": "sum by (container) (avg_over_time(kube_pod_container_resource_requests{resource=\"cpu\",unit=\"core\",namespace=\"$namespace\", pod=\"$pod\", container=~\"$container\"}[$__range]))\nor\nsum by (container) (avg_over_time(kube_pod_container_info{namespace=\"$namespace\", pod=\"$pod\", container=~\"$container\"}[$__range]) * 0)", + "format": "table", + "instant": true, + "intervalFactor": 1, + "legendFormat": "Req CPU", + "refId": "D" + }, + { + "expr": "sum by (container) (\n sum by (controller_type, controller_name, pod) (avg_over_time(kube_controller_pod{namespace=\"$namespace\", pod=\"$pod\"}[$__range]))\n * on (controller_type, controller_name) group_right() \n sum by (controller_type, controller_name, container) (\n avg_over_time(vpa_target_recommendation{namespace=\"$namespace\", container=~\"$container\", resource=\"cpu\"}[$__range])))\nor\nsum by (container) (avg_over_time(kube_pod_container_info{namespace=\"$namespace\", pod=\"$pod\", container=~\"$container\"}[$__range]) * 0)", + "format": "table", + "instant": true, + "intervalFactor": 1, + "legendFormat": "VPA CPU", + "refId": "E" + }, + { + "expr": "(\n sum by (container) (avg_over_time(kube_pod_container_resource_requests{resource=\"cpu\",unit=\"core\",namespace=\"$namespace\", pod=\"$pod\", container=~\"$container\"}[$__range]))\n -\n sum by (container) (rate(container_cpu_usage_seconds_total{namespace=\"$namespace\", pod=\"$pod\", container=~\"$container\"}[$__range]))\n) > 0\nor\nsum by (container) (avg_over_time(kube_pod_container_info{namespace=\"$namespace\", pod=\"$pod\", container=~\"$container\"}[$__range]) * 0)", + "format": "table", + "instant": true, + "intervalFactor": 1, + "legendFormat": "Over-req CPU", + "refId": "F" + }, + { + "expr": "(\n (\n sum by (container) (rate(container_cpu_usage_seconds_total{namespace=\"$namespace\", pod=\"$pod\", container=~\"$container\"}[$__range]))\n -\n sum by (container) (avg_over_time(kube_pod_container_resource_requests{resource=\"cpu\",unit=\"core\",namespace=\"$namespace\", pod=\"$pod\", container=~\"$container\"}[$__range]))\n ) or sum by (container) (rate(container_cpu_usage_seconds_total{namespace=\"$namespace\", pod=\"$pod\", container=~\"$container\"}[$__range]))\n) > 0\nor\nsum by (container) (avg_over_time(kube_pod_container_info{namespace=\"$namespace\", pod=\"$pod\", container=~\"$container\"}[$__range]) * 0)", + "format": "table", + "instant": true, + "intervalFactor": 1, + "legendFormat": "Under-req CPU", + "refId": "G" + }, + { + "expr": "(\n (\n sum by (container) (rate(container_cpu_cfs_throttled_periods_total{namespace=\"$namespace\", pod=\"$pod\", container=~\"$container\"}[$__range])) \n / \n sum by (container) (rate(container_cpu_cfs_periods_total{namespace=\"$namespace\", pod=\"$pod\", container=~\"$container\"}[$__range]))\n )\n * sum by (container) (avg_over_time(kube_pod_container_resource_limits{resource=\"cpu\",unit=\"core\",namespace=\"$namespace\", pod=\"$pod\", container=~\"$container\"}[$__range]))\n)\nor\nsum by (container) (avg_over_time(kube_pod_container_info{namespace=\"$namespace\", pod=\"$pod\", container=~\"$container\"}[$__range]) * 0)", + "format": "table", + "instant": true, + "intervalFactor": 1, + "legendFormat": "Thottling cores", + "refId": "H" + }, + { + "expr": "sum by (container) (avg_over_time(container_memory_working_set_bytes:without_kmem{namespace=\"$namespace\", pod=\"$pod\", container!=\"POD\", container=~\"$container\"}[$__range]))\nor\nsum by (container) (avg_over_time(kube_pod_container_info{namespace=\"$namespace\", pod=\"$pod\", container=~\"$container\"}[$__range]) * 0)", + "format": "table", + "instant": true, + "intervalFactor": 1, + "legendFormat": "Memory", + "refId": "I" + }, + { + "expr": "sum by (container) (avg_over_time(kube_pod_container_resource_requests{resource=\"memory\",unit=\"byte\",namespace=\"$namespace\", pod=\"$pod\", container=~\"$container\"}[$__range]))\nor\nsum by (container) (avg_over_time(kube_pod_container_info{namespace=\"$namespace\", pod=\"$pod\", container=~\"$container\"}[$__range]) * 0)", + "format": "table", + "instant": true, + "intervalFactor": 1, + "legendFormat": "Req Memory", + "refId": "J" + }, + { + "expr": "sum by (container) (\n sum by (controller_type, controller_name, pod) (avg_over_time(kube_controller_pod{namespace=\"$namespace\", pod=\"$pod\"}[$__range]))\n * on (controller_type, controller_name) group_right() \n sum by (controller_type, controller_name, container) (\n avg_over_time(vpa_target_recommendation{namespace=\"$namespace\", container=~\"$container\", resource=\"memory\"}[$__range])))\nor\nsum by (container) (avg_over_time(kube_pod_container_info{namespace=\"$namespace\", pod=\"$pod\", container=~\"$container\"}[$__range]) * 0)", + "format": "table", + "instant": true, + "intervalFactor": 1, + "legendFormat": "VPA Memory", + "refId": "K" + }, + { + "expr": "(\n sum by (container) (avg_over_time(kube_pod_container_resource_requests{resource=\"memory\",unit=\"byte\",namespace=\"$namespace\", pod=\"$pod\", container=~\"$container\"}[$__range]))\n -\n sum by (container) (avg_over_time(container_memory_working_set_bytes:without_kmem{namespace=\"$namespace\", pod=\"$pod\", container=~\"$container\"}[$__range]))\n) > 0\nor\nsum by (container) (avg_over_time(kube_pod_container_info{namespace=\"$namespace\", pod=\"$pod\", container=~\"$container\"}[$__range]) * 0)", + "format": "table", + "instant": true, + "intervalFactor": 1, + "legendFormat": "Over-req Memory", + "refId": "L" + }, + { + "expr": "(\n (\n sum by (container) (avg_over_time(container_memory_working_set_bytes:without_kmem{namespace=\"$namespace\", pod=\"$pod\", container=~\"$container\"}[$__range]))\n -\n sum by (container) (avg_over_time(kube_pod_container_resource_requests{resource=\"memory\",unit=\"byte\",namespace=\"$namespace\", pod=\"$pod\", container=~\"$container\"}[$__range]))\n ) or sum by (container) (avg_over_time(container_memory_working_set_bytes:without_kmem{namespace=\"$namespace\", pod=\"$pod\", container=~\"$container\"}[$__range]))\n) > 0\nor\nsum by (container) (avg_over_time(kube_pod_container_info{namespace=\"$namespace\", pod=\"$pod\", container=~\"$container\"}[$__range]) * 0)", + "format": "table", + "instant": true, + "intervalFactor": 1, + "legendFormat": "Under-req Memory", + "refId": "M" + }, + { + "expr": "(\n # Show data rate for the Pod if it had hostNetwork: false during the selected period.\n max_over_time(kube_pod_info{host_network=\"false\", namespace=\"$namespace\", pod=\"$pod\"}[$__range])\n * on(pod)\n sum by (pod) (rate(container_network_receive_bytes_total{namespace=\"$namespace\", pod=\"$pod\"}[$__range]))\n) or (\n # Else return -1 if the Pod had hostNetwork: true during the selecte period.\n max_over_time(kube_pod_info{host_network=\"true\", namespace=\"$namespace\", pod=\"$pod\"}[$__range]) * -1\n)", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "legendFormat": "RX Network", + "refId": "N" + }, + { + "expr": "(\n # Show data rate for the Pod if it had hostNetwork: false during the selected period.\n max_over_time(kube_pod_info{host_network=\"false\", namespace=\"$namespace\", pod=\"$pod\"}[$__range])\n * on(pod)\n sum by (pod) (rate(container_network_transmit_bytes_total{namespace=\"$namespace\", pod=\"$pod\"}[$__range]))\n) or (\n # Else return -1 if the Pod had hostNetwork: true during the selecte period.\n max_over_time(kube_pod_info{host_network=\"true\", namespace=\"$namespace\", pod=\"$pod\"}[$__range]) * -1\n)", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "legendFormat": "TX Network", + "refId": "O" + }, + { + "expr": "sum by(container) (rate(container_fs_reads_total{namespace=\"$namespace\", pod=\"$pod\", container!=\"POD\"}[$__range]))", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "legendFormat": "Read IOPS", + "refId": "P" + }, + { + "expr": "sum by(container) (rate(container_fs_writes_total{namespace=\"$namespace\", pod=\"$pod\", container!=\"POD\"}[$__range]))", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "legendFormat": "Write IOPS", + "refId": "Q" + }, + { + "expr": "sum by (container) (increase(kube_pod_container_status_restarts_total{namespace=\"$namespace\", pod=\"$pod\"}[$__range]))", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "legendFormat": "Pod Restart count", + "refId": "R" + }, + { + "expr": "sum by (container) (label_replace(increase(klog_pod_oomkill{namespace=\"$namespace\", pod_name=\"$pod\"}[$__range]), \"container\", \"$1\", \"container_name\", \"(.+)\"))", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "legendFormat": "OOM killed", + "refId": "T" + }, + { + "expr": "sum by (container) (avg_over_time(container_memory:kmem{namespace=\"$namespace\", pod=\"$pod\", container!=\"POD\", container=~\"$container\"}[$__range]))\nor\nsum by (container) (avg_over_time(kube_pod_container_info{namespace=\"$namespace\", pod=\"$pod\", container=~\"$container\"}[$__range]) * 0)", + "format": "table", + "instant": true, + "intervalFactor": 1, + "legendFormat": "Memory", + "refId": "U" + } + ], + "title": "Containers", + "transformations": [ + { + "id": "merge", + "options": { + "reducers": [] + } + }, + { + "id": "filterFieldsByName", + "options": { + "include": { + "names": [ + "container", + "node", + "Value #B", + "Value #C", + "Value #D", + "Value #E", + "Value #F", + "Value #G", + "Value #H", + "Value #I", + "Value #J", + "Value #K", + "Value #L", + "Value #M", + "Value #N", + "Value #O", + "Value #P", + "Value #Q", + "Value #R" + ] + } + } + }, + { + "id": "sortBy", + "options": { + "fields": {}, + "sort": [ + { + "field": "container" + } + ] + } + } + ], + "type": "table" + }, + { + "cards": { + "cardHSpacing": 2, + "cardMinWidth": 5, + "cardRound": null, + "cardVSpacing": 2 + }, + "color": { + "cardColor": "#b4ff00", + "colorScale": "sqrt", + "colorScheme": "interpolateGnYlRd", + "defaultColor": "#757575", + "exponent": 0.5, + "mode": "discrete", + "thresholds": [ + { + "color": "#9ac48a", + "tooltip": "ready", + "value": "0" + }, + { + "color": "#f4d598", + "tooltip": "running", + "value": "1" + }, + { + "color": "#890f02", + "tooltip": "terminated/Error", + "value": "2" + }, + { + "color": "#e24d42", + "tooltip": "terminated/Completed", + "value": "3" + }, + { + "color": "#f29191", + "tooltip": "terminated/ContainerCannotRun", + "value": "4" + }, + { + "color": "#fce2de", + "tooltip": "terminated/OOMKilled", + "value": "5" + }, + { + "color": "#1f78c1", + "tooltip": "waiting/ContainerCreating", + "value": "6" + }, + { + "color": "#64b0c8", + "tooltip": "waiting/CrashLoopBackOff", + "value": "7" + }, + { + "color": "#65c5db", + "tooltip": "waiting/CreateContainerConfigError", + "value": "8" + }, + { + "color": "#badff4", + "tooltip": "waiting/ErrImagePull", + "value": "9" + }, + { + "color": "#cffaff", + "tooltip": "waiting/ImagePullBackOff", + "value": "10" + } + ] + }, + "datasource": "$ds_prometheus", + "gridPos": { + "h": 8, + "w": 24, + "x": 0, + "y": 9 + }, + "highlightCards": true, + "id": 47, + "legend": { + "show": true + }, + "links": [], + "nullPointMode": "as empty", + "pageSize": 15, + "seriesFilterIndex": -1, + "statusmap": { + "ConfigVersion": "v1" + }, + "targets": [ + { + "expr": "(min_over_time(kube_pod_container_status_ready{namespace=\"$namespace\", pod=\"$pod\"}[$__rate_interval]) == 1) * 0", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "{{ container }}", + "refId": "A" + }, + { + "expr": "(min_over_time(kube_pod_container_status_running{namespace=\"$namespace\", pod=\"$pod\"}[$__rate_interval]) == 1) * 1", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{ container }}", + "refId": "B" + }, + { + "expr": "(max_over_time(kube_pod_container_status_terminated_reason{namespace=\"$namespace\", pod=\"$pod\", reason=\"Error\"}[$__rate_interval]) == 1) * 2", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{ container }}", + "refId": "C" + }, + { + "expr": "(max_over_time(kube_pod_container_status_terminated_reason{namespace=\"$namespace\", pod=\"$pod\", reason=\"Completed\"}[$__rate_interval]) == 1) * 3", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{ container }}", + "refId": "D" + }, + { + "expr": "(max_over_time(kube_pod_container_status_terminated_reason{namespace=\"$namespace\", pod=\"$pod\", reason=\"ContainerCannotRun\"}[$__rate_interval]) == 1) * 4", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{ container }}", + "refId": "E" + }, + { + "expr": "(max_over_time(kube_pod_container_status_terminated_reason{namespace=\"$namespace\", pod=\"$pod\", reason=\"OOMKilled\"}[$__rate_interval]) == 1) * 5", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{ container }}", + "refId": "F" + }, + { + "expr": "(max_over_time(kube_pod_container_status_waiting_reason{namespace=\"$namespace\", pod=\"$pod\", reason=\"ContainerCreating\"}[$__rate_interval]) == 1) * 6", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{ container }}", + "refId": "G" + }, + { + "expr": "(max_over_time(kube_pod_container_status_waiting_reason{namespace=\"$namespace\", pod=\"$pod\", reason=\"CrashLoopBackOff\"}[$__rate_interval]) == 1) * 7", + "format": "time_series", + "instant": false, + "intervalFactor": 1, + "legendFormat": "{{ container }}", + "refId": "H" + }, + { + "expr": "(max_over_time(kube_pod_container_status_waiting_reason{namespace=\"$namespace\", pod=\"$pod\", reason=\"CreateContainerConfigError\"}[$__rate_interval]) == 1) * 8", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{ container }}", + "refId": "I" + }, + { + "expr": "(max_over_time(kube_pod_container_status_waiting_reason{namespace=\"$namespace\", pod=\"$pod\", reason=\"ErrImagePull\"}[$__rate_interval]) == 1) * 9", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{ container }}", + "refId": "J" + }, + { + "expr": "(max_over_time(kube_pod_container_status_waiting_reason{namespace=\"$namespace\", pod=\"$pod\", reason=\"ImagePullBackOff\"}[$__rate_interval]) == 1) * 10", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{ container }}", + "refId": "K" + } + ], + "title": "Status", + "tooltip": { + "extraInfo": "", + "freezeOnClick": true, + "items": [], + "show": true, + "showExtraInfo": false, + "showItems": false + }, + "type": "flant-statusmap-panel", + "useMax": true, + "usingPagination": false, + "xAxis": { + "show": true + }, + "yAxis": { + "maxWidth": -1, + "minWidth": -1, + "show": true + }, + "yAxisSort": "metrics", + "yLabel": { + "delimiter": "", + "labelTemplate": "", + "usingSplitLabel": false + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "description": "The number of container restarts", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 12, + "x": 0, + "y": 17 + }, + "hiddenSeries": false, + "id": 166, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum by (container) (increase(kube_pod_container_status_restarts_total{namespace=\"$namespace\", pod=\"$pod\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{ container }}", + "refId": "A" + }, + { + "expr": "sum (increase(kube_pod_container_status_restarts_total{namespace=\"$namespace\", pod=\"$pod\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Containers restarts", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 0, + "format": "short", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "description": "The number of container OOM kills", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 12, + "x": 12, + "y": 17 + }, + "hiddenSeries": false, + "id": 167, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum by (container) (increase(oom_kills:normalized{namespace=\"$namespace\", pod=\"$pod\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{ container }}", + "refId": "A" + }, + { + "expr": "sum (increase(oom_kills:normalized{namespace=\"$namespace\", pod=\"$pod\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "OOM Killed Processes", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 0, + "format": "short", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "collapsed": false, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 21 + }, + "id": 14, + "panels": [], + "title": "CPU", + "type": "row" + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 22 + }, + "hiddenSeries": false, + "id": 2, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": true, + "targets": [ + { + "expr": "sum by(container) (rate(container_cpu_usage_seconds_total{container!=\"POD\", pod=\"$pod\", namespace=\"$namespace\"}[$__rate_interval]))", + "format": "time_series", + "instant": false, + "intervalFactor": 1, + "legendFormat": "{{ container }}", + "refId": "A" + }, + { + "expr": "sum (rate(container_cpu_usage_seconds_total{container!=\"POD\", pod=\"$pod\", namespace=\"$namespace\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Usage by container", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "cores", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "description": "The total value may not equal the sum of system and user times because of the kernel's cgroup accounting peculiarities. Read more here: https://www.kernel.org/doc/Documentation/cgroup-v1/cpuacct.txt", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 22 + }, + "hiddenSeries": false, + "id": 3, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "/Total.*/", + "bars": false, + "stack": false + }, + { + "alias": "System", + "color": "#e24d42" + }, + { + "alias": "User", + "color": "#1f78c1" + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": true, + "targets": [ + { + "expr": "sum by(pod) (rate(container_cpu_system_seconds_total{container!=\"POD\", pod=\"$pod\", namespace=\"$namespace\"}[$__rate_interval]))", + "format": "time_series", + "instant": false, + "intervalFactor": 1, + "legendFormat": "System", + "refId": "A" + }, + { + "expr": "sum by(pod) (rate(container_cpu_user_seconds_total{container!=\"POD\", pod=\"$pod\", namespace=\"$namespace\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "User", + "refId": "B" + }, + { + "expr": "sum by(pod) (rate(container_cpu_usage_seconds_total{container!=\"POD\", pod=\"$pod\", namespace=\"$namespace\"}[$__rate_interval]))", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "D" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Usage by state", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "cores", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "description": "This graph shows the requested CPU resources higher than the actual CPU consumption. In other words, it shows CPU resources that can be \"freed\" without affecting the service.", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 31 + }, + "hiddenSeries": false, + "id": 76, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": true, + "targets": [ + { + "expr": "sum by (namespace, pod, container)\n (\n (\n sum by(namespace, pod, container) (avg_over_time(kube_pod_container_resource_requests{resource=\"cpu\",unit=\"core\",namespace=\"$namespace\", pod=\"$pod\", container=~\"$container\"}[$__rate_interval]))\n -\n sum by(namespace, pod, container) (rate(container_cpu_usage_seconds_total{container!=\"POD\", namespace=\"$namespace\", pod=\"$pod\", container=~\"$container\"}[$__rate_interval]))\n ) > 0\n )", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "{{ container }}", + "refId": "C" + }, + { + "expr": "sum\n (\n (\n sum by(namespace, pod, container) (avg_over_time(kube_pod_container_resource_requests{resource=\"cpu\",unit=\"core\",namespace=\"$namespace\", pod=\"$pod\", container=~\"$container\"}[$__rate_interval]))\n -\n sum by(namespace, pod, container) (rate(container_cpu_usage_seconds_total{container!=\"POD\", namespace=\"$namespace\", pod=\"$pod\", container=~\"$container\"}[$__rate_interval]))\n ) > 0\n )", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Over-requested by container", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "cores", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "decimals": null, + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "description": "This graph shows the requested CPU resources lower than the actual CPU consumption. In other words, it shows CPU resources that need to be \"reserved\" for the service to run smoothly.", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 31 + }, + "hiddenSeries": false, + "id": 123, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": true, + "targets": [ + { + "expr": "sum by (namespace, pod, container)\n (\n (\n (\n sum by(namespace, pod, container) (rate(container_cpu_usage_seconds_total{namespace=\"$namespace\", pod=\"$pod\", container=~\"$container\"}[$__rate_interval]))\n -\n sum by(namespace, pod, container) (avg_over_time(kube_pod_container_resource_requests{resource=\"cpu\",unit=\"core\",namespace=\"$namespace\", pod=\"$pod\", container=~\"$container\"}[$__rate_interval]))\n ) or sum by(namespace, pod, container) (rate(container_cpu_usage_seconds_total{namespace=\"$namespace\", pod=\"$pod\", container=~\"$container\"}[$__rate_interval]))\n ) > 0\n )", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "{{ container }}", + "refId": "C" + }, + { + "expr": "sum\n (\n (\n (\n sum by(namespace, pod, container) (rate(container_cpu_usage_seconds_total{namespace=\"$namespace\", pod=\"$pod\", container=~\"$container\"}[$__rate_interval]))\n -\n sum by(namespace, pod, container) (avg_over_time(kube_pod_container_resource_requests{resource=\"cpu\",unit=\"core\",namespace=\"$namespace\", pod=\"$pod\", container=~\"$container\"}[$__rate_interval]))\n ) or sum by(namespace, pod, container) (rate(container_cpu_usage_seconds_total{namespace=\"$namespace\", pod=\"$pod\", container=~\"$container\"}[$__rate_interval]))\n ) > 0\n )", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Under-requested by container", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "cores", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "decimals": null, + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "description": "The absence of data on the graph means that container resources are not set", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 24, + "x": 0, + "y": 39 + }, + "hiddenSeries": false, + "id": 36, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": true, + "min": false, + "rightSide": true, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "(sum by (pod, container) (rate(container_cpu_cfs_throttled_periods_total{namespace=\"$namespace\", container=~\"$container\", pod=\"$pod\"}[$__rate_interval])) / sum by (container, pod) (rate(container_cpu_cfs_periods_total{namespace=\"$namespace\", container=~\"$container\", pod=\"$pod\"}[$__rate_interval]))) * sum by (pod, container) (kube_pod_container_resource_limits{resource=\"cpu\",unit=\"core\",namespace=\"$namespace\", pod=\"$pod\", container=~\"$container\"})", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{ container }}", + "refId": "A" + }, + { + "expr": "sum by (pod) ((sum by (pod, container) (rate(container_cpu_cfs_throttled_periods_total{namespace=\"$namespace\", container=~\"$container\", pod=\"$pod\"}[$__rate_interval])) / sum by (container, pod) (rate(container_cpu_cfs_periods_total{namespace=\"$namespace\", container=~\"$container\", pod=\"$pod\"}[$__rate_interval]))) * sum by (pod, container) (kube_pod_container_resource_limits{resource=\"cpu\",unit=\"core\",namespace=\"$namespace\", pod=\"$pod\", container=~\"$container\"}))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Throttling", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "cores", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "collapsed": true, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 45 + }, + "id": 95, + "panels": [ + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "description": "The total value may not equal the sum of system and user times because of the kernel's cgroup accounting peculiarities. Read more here: https://www.kernel.org/doc/Documentation/cgroup-v1/cpuacct.txt", + "fill": 0, + "gridPos": { + "h": 9, + "w": 8, + "x": 0, + "y": 46 + }, + "id": 102, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": "container", + "repeatDirection": "h", + "seriesOverrides": [ + { + "alias": "Usage", + "color": "#629e51" + }, + { + "alias": "Requests", + "color": "#f4d598" + }, + { + "alias": "Limits", + "color": "#c15c17" + }, + { + "alias": "VPA Target", + "color": "#447ebc" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "sum by(container) (rate(container_cpu_usage_seconds_total{namespace=\"$namespace\", pod=\"$pod\", container!=\"POD\", container=\"$container\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Usage", + "refId": "D" + }, + { + "expr": "sum by(container) (avg_over_time(kube_pod_container_resource_requests{resource=\"cpu\",unit=\"core\",namespace=\"$namespace\", pod=\"$pod\", container=\"$container\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Requests", + "refId": "C" + }, + { + "expr": "sum by(container) (avg_over_time(kube_pod_container_resource_limits{resource=\"cpu\",unit=\"core\",namespace=\"$namespace\", pod=\"$pod\", container=\"$container\"}[$__rate_interval]) )", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Limits", + "refId": "E" + }, + { + "expr": "sum by (container) (\n sum by (controller_type, controller_name, pod) (kube_controller_pod{namespace=\"$namespace\", pod=\"$pod\"})\n * on (controller_type, controller_name) group_right() \n sum by (controller_type, controller_name, container) (\n avg_over_time(vpa_target_recommendation{namespace=\"$namespace\", container=~\"$container\", resource=\"cpu\"}[$__rate_interval])\n )\n)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "VPA Target", + "refId": "F" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "$container", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "cores", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "title": "Containers CPU", + "type": "row" + }, + { + "collapsed": true, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 46 + }, + "id": 5, + "panels": [ + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "description": "The total value may not equal the sum of system and user times because of the kernel's cgroup accounting peculiarities. Read more here: https://www.kernel.org/doc/Documentation/cgroup-v1/cpuacct.txt", + "fill": 1, + "gridPos": { + "h": 9, + "w": 8, + "x": 0, + "y": 47 + }, + "id": 7, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": "container", + "repeatDirection": "h", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + }, + { + "alias": "System", + "color": "#e24d42" + }, + { + "alias": "User", + "color": "#1f78c1" + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum by(container) (rate(container_cpu_system_seconds_total{container!=\"POD\", pod=\"$pod\", namespace=\"$namespace\", container=\"$container\"}[$__rate_interval]))", + "format": "time_series", + "instant": false, + "intervalFactor": 1, + "legendFormat": "System", + "refId": "A" + }, + { + "expr": "sum by(container) (rate(container_cpu_user_seconds_total{container!=\"POD\", pod=\"$pod\", namespace=\"$namespace\", container=\"$container\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "User", + "refId": "B" + }, + { + "expr": "sum by(container) (rate(container_cpu_usage_seconds_total{container!=\"POD\", pod=\"$pod\", namespace=\"$namespace\", container=\"$container\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "D" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "$container", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "cores", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "repeat": null, + "title": "Containers CPU by state", + "type": "row" + }, + { + "collapsed": false, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 47 + }, + "id": 12, + "panels": [], + "title": "Memory", + "type": "row" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 48 + }, + "hiddenSeries": false, + "id": 6, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "lines": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum by(container) (avg_over_time(container_memory_working_set_bytes:without_kmem{container!=\"POD\", pod=\"$pod\", namespace=\"$namespace\"}[$__rate_interval]))", + "format": "time_series", + "instant": false, + "intervalFactor": 1, + "legendFormat": "{{ container }}", + "refId": "A" + }, + { + "expr": "sum (avg_over_time(container_memory_working_set_bytes:without_kmem{container!=\"POD\", pod=\"$pod\", namespace=\"$namespace\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Usage by container", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "description": "The Working set bytes metric is the actual memory used by the container, as it includes active file memory. When its value approaches the limit, the container can be killed by the OOMKiller. This value can be higher than the sum RSS and Cache since not all active file memory is Cache.", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 48 + }, + "hiddenSeries": false, + "id": 8, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Working set bytes without kmem", + "color": "rgb(0, 0, 0)", + "dashes": true, + "fill": 0, + "linewidth": 2, + "stack": false + }, + { + "alias": "Kmem", + "color": "rgb(255, 0, 0)", + "dashes": true, + "fill": 0, + "linewidth": 2, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum by(pod) (avg_over_time(container_memory_rss{namespace=\"$namespace\", pod=\"$pod\", container!=\"POD\"}[$__rate_interval]))", + "format": "time_series", + "instant": false, + "intervalFactor": 1, + "legendFormat": "RSS", + "refId": "A" + }, + { + "expr": "sum by(pod) (avg_over_time(container_memory_cache{namespace=\"$namespace\", pod=\"$pod\", container!=\"POD\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Cache", + "refId": "B" + }, + { + "expr": "sum by(pod) (avg_over_time(container_memory_swap{namespace=\"$namespace\", pod=\"$pod\", container!=\"POD\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Swap", + "refId": "C" + }, + { + "expr": "sum by(pod) (avg_over_time(container_memory_working_set_bytes:without_kmem{namespace=\"$namespace\", pod=\"$pod\", container!=\"POD\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Working set bytes without kmem", + "refId": "D" + }, + { + "expr": "sum by(pod) (avg_over_time(container_memory:kmem{namespace=\"$namespace\", pod=\"$pod\", container!=\"POD\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Kmem", + "refId": "E" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Usage by state", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "description": "This graph shows the requested Memory resources higher than the actual Memory consumption. In other words, it shows Memory resources that can be \"freed\" without affecting the service.", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 57 + }, + "hiddenSeries": false, + "id": 106, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "lines": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum by (container)\n (\n (\n sum by (namespace, pod, container) (avg_over_time(kube_pod_container_resource_requests{resource=\"memory\",unit=\"byte\",namespace=\"$namespace\", pod=\"$pod\", container=~\"$container\"}[$__rate_interval]))\n -\n sum by (namespace, pod, container) (avg_over_time(container_memory_working_set_bytes:without_kmem{namespace=\"$namespace\", pod=\"$pod\", container=~\"$container\", container!=\"POD\"}[$__rate_interval]))\n ) > 0\n )", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "{{ container }}", + "refId": "C" + }, + { + "expr": "sum\n (\n (\n sum by (namespace, pod, container) (avg_over_time(kube_pod_container_resource_requests{resource=\"memory\",unit=\"byte\",namespace=\"$namespace\", pod=\"$pod\", container=~\"$container\"}[$__rate_interval]))\n -\n sum by (namespace, pod, container) (avg_over_time(container_memory_working_set_bytes:without_kmem{namespace=\"$namespace\", pod=\"$pod\", container=~\"$container\", container!=\"POD\"}[$__rate_interval]))\n ) > 0\n )", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Over-requested by container", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": null, + "format": "bytes", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "decimals": null, + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "description": "This graph shows the requested Memory resources higher than the actual Memory consumption. In other words, it shows Memory resources that need to be \"reserved\" for the service to run smoothly.", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 57 + }, + "hiddenSeries": false, + "id": 136, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "lines": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum by (container)\n (\n (\n (\n sum by (namespace, pod, container) (avg_over_time(container_memory_working_set_bytes:without_kmem{namespace=\"$namespace\", pod=\"$pod\", container=~\"$container\"}[$__rate_interval]))\n -\n sum by (namespace, pod, container) (avg_over_time(kube_pod_container_resource_requests{resource=\"memory\",unit=\"byte\",namespace=\"$namespace\", pod=\"$pod\", container=~\"$container\", container!=\"POD\"}[$__rate_interval]))\n ) or sum by (namespace, pod, container) (avg_over_time(container_memory_working_set_bytes:without_kmem{namespace=\"$namespace\", pod=\"$pod\", container=~\"$container\", container!=\"POD\"}[$__rate_interval]))\n ) > 0\n )", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "{{ container }}", + "refId": "C" + }, + { + "expr": "sum\n (\n (\n (\n sum by (namespace, pod, container) (avg_over_time(container_memory_working_set_bytes:without_kmem{namespace=\"$namespace\", pod=\"$pod\", container=~\"$container\"}[$__rate_interval]))\n -\n sum by (namespace, pod, container) (avg_over_time(kube_pod_container_resource_requests{resource=\"memory\",unit=\"byte\",namespace=\"$namespace\", pod=\"$pod\", container=~\"$container\", container!=\"POD\"}[$__rate_interval]))\n ) or sum by (namespace, pod, container) (avg_over_time(container_memory_working_set_bytes:without_kmem{namespace=\"$namespace\", pod=\"$pod\", container=~\"$container\", container!=\"POD\"}[$__rate_interval]))\n ) > 0\n )", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Under-requested by container", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": null, + "format": "bytes", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "decimals": null, + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "collapsed": true, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 65 + }, + "id": 16, + "panels": [ + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "description": "The Working set bytes metric is the actual memory used by the container, as it includes active file memory. When its value approaches the limit, the container can be killed by the OOMKiller. This value can be higher than the sum RSS and Cache since not all active file memory is Cache.", + "fill": 1, + "gridPos": { + "h": 9, + "w": 8, + "x": 0, + "y": 66 + }, + "id": 19, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": "container", + "repeatDirection": "h", + "seriesOverrides": [ + { + "alias": "Working set bytes without kmem", + "color": "rgb(0, 0, 0)", + "dashes": true, + "fill": 0, + "linewidth": 2, + "stack": false + }, + { + "alias": "Kmem", + "color": "rgb(255, 0, 0)", + "dashes": true, + "fill": 0, + "linewidth": 2, + "stack": false + }, + { + "alias": "Limits", + "color": "#c15c17", + "dashes": true, + "fill": 0, + "lines": false, + "linewidth": 2, + "stack": false + }, + { + "alias": "Requests", + "color": "#f4d598", + "dashes": true, + "fill": 0, + "lines": false, + "linewidth": 2, + "stack": false + }, + { + "alias": "VPA Target", + "color": "#447ebc", + "dashes": true, + "fill": 0, + "lines": false, + "linewidth": 2, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum by(container) (avg_over_time(container_memory_rss{namespace=\"$namespace\", pod=\"$pod\", container!=\"POD\", container=\"$container\"}[$__rate_interval]))", + "format": "time_series", + "instant": false, + "intervalFactor": 1, + "legendFormat": "RSS", + "refId": "A" + }, + { + "expr": "sum by(container) (avg_over_time(container_memory_cache{namespace=\"$namespace\", pod=\"$pod\", container!=\"POD\", container=\"$container\"}[$__rate_interval]))", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "Cache", + "refId": "B" + }, + { + "expr": "sum by(container) (avg_over_time(container_memory_swap{namespace=\"$namespace\", pod=\"$pod\", container!=\"POD\", container=\"$container\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Swap", + "refId": "C" + }, + { + "expr": "sum by(container) (avg_over_time(container_memory_working_set_bytes:without_kmem{namespace=\"$namespace\", pod=\"$pod\", container!=\"POD\", container=\"$container\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Working set bytes without kmem", + "refId": "D" + }, + { + "expr": "sum by(container) (avg_over_time(kube_pod_container_resource_limits{resource=\"memory\",unit=\"byte\",namespace=\"$namespace\", pod=\"$pod\", container!=\"POD\", container=\"$container\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Limits", + "refId": "E" + }, + { + "expr": "sum by(container) (avg_over_time(kube_pod_container_resource_requests{resource=\"memory\",unit=\"byte\",namespace=\"$namespace\", pod=\"$pod\", container!=\"POD\", container=\"$container\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Requests", + "refId": "F" + }, + { + "expr": "sum by (container) (\n sum by (controller_type, controller_name, pod) (kube_controller_pod{namespace=\"$namespace\", pod=\"$pod\"})\n * on (controller_type, controller_name) group_right() \n sum by (controller_type, controller_name, container) (\n avg_over_time(vpa_target_recommendation{namespace=\"$namespace\", container=~\"$container\", resource=\"memory\"}[$__rate_interval])\n )\n)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "VPA Target", + "refId": "G" + }, + { + "expr": "sum by(container) (avg_over_time(container_memory:kmem{namespace=\"$namespace\", pod=\"$pod\", container!=\"POD\", container=\"$container\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Kmem", + "refId": "H" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "$container", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "title": "Containers Memory", + "type": "row" + }, + { + "collapsed": false, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 66 + }, + "id": 25, + "panels": [], + "title": "Network", + "type": "row" + }, + { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisPlacement": "auto", + "axisLabel": "", + "barAlignment": 0, + "drawStyle": "bars", + "fillOpacity": 100, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 0, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [ + { + "options": { + "-1": { + "color": "transparent", + "index": 0, + "text": "Network graph for Pod with hostNetwork: true is meaningless" + } + }, + "type": "value" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "Bps" + }, + "overrides": [ + { + "matcher": { + "id": "byFrameRefID", + "options": "B" + }, + "properties": [ + { + "id": "min", + "value": 0 + }, + { + "id": "max", + "value": 0 + }, + { + "id": "custom.axisPlacement", + "value": "hidden" + }, + { + "id": "color", + "value": { + "mode": "fixed", + "fixedColor": "transparent" + } + } + ] + } + ] + }, + "datasource": { + "uid": "${ds_prometheus}", + "type": "prometheus" + }, + "description": "This graph shows Network Receive (except for the hostNetwork Pods)", + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 67 + }, + "id": 27, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean" + ], + "displayMode": "table", + "placement": "right" + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "8.5.13", + "targets": [ + { + "expr": "# Select Pods with hostNetwork: false.\nkube_pod_info{host_network=\"false\",namespace=\"$namespace\", pod=\"$pod\"}\n* on(pod)\n# Sum data rate for all interfaces in the Pod.\nsum by(pod) (rate(container_network_receive_bytes_total{pod=\"$pod\", namespace=\"$namespace\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{ pod }}", + "refId": "A" + }, + { + "expr": "# Return -1 for Pods with 'hostNetwork: true' to use in value mappings.\nkube_pod_info{host_network=\"true\",namespace=\"$namespace\", pod=\"$pod\"}\n*\n-1", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{pod}}", + "refId": "B" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Receive", + "transformations": [], + "type": "timeseries" + }, + { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisPlacement": "auto", + "axisLabel": "", + "barAlignment": 0, + "drawStyle": "bars", + "fillOpacity": 100, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 0, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [ + { + "options": { + "-1": { + "color": "transparent", + "index": 0, + "text": "no traffic available for hostNetwork: true" + } + }, + "type": "value" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "Bps" + }, + "overrides": [ + { + "matcher": { + "id": "byFrameRefID", + "options": "B" + }, + "properties": [ + { + "id": "min", + "value": 0 + }, + { + "id": "max", + "value": 0 + }, + { + "id": "custom.axisPlacement", + "value": "hidden" + }, + { + "id": "color", + "value": { + "mode": "fixed", + "fixedColor": "transparent" + } + } + ] + } + ] + }, + "datasource": { + "uid": "${ds_prometheus}", + "type": "prometheus" + }, + "description": "This graph shows Network Transmit (except for the hostNetwork Pods)", + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 67 + }, + "id": 62, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean" + ], + "displayMode": "table", + "placement": "right" + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "8.5.13", + "targets": [ + { + "expr": "# Select Pods with hostNetwork: false.\nkube_pod_info{host_network=\"false\",namespace=\"$namespace\", pod=\"$pod\"}\n* on(pod)\n# Sum data rate for all interfaces in the Pod.\nsum by(pod) (rate(container_network_transmit_bytes_total{pod=\"$pod\", namespace=\"$namespace\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{ pod }}", + "refId": "A" + }, + { + "expr": "# Return -1 for Pods with 'hostNetwork: true' to use in value mappings.\nkube_pod_info{host_network=\"true\",namespace=\"$namespace\", pod=\"$pod\"}\n*\n-1", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{pod}}", + "refId": "B" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Transmit", + "transformations": [], + "type": "timeseries" + }, + { + "collapsed": false, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 74 + }, + "id": 30, + "panels": [], + "title": "IOPS", + "type": "row" + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 75 + }, + "hiddenSeries": false, + "id": 32, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum by(container) (rate(container_fs_reads_total{container!=\"POD\", pod=\"$pod\", namespace=\"$namespace\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{ container }}", + "refId": "A" + }, + { + "expr": "sum (rate(container_fs_reads_total{container!=\"POD\", pod=\"$pod\", namespace=\"$namespace\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Read", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "iops", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 75 + }, + "hiddenSeries": false, + "id": 63, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "bars": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum by(container) (rate(container_fs_writes_total{container!=\"POD\", pod=\"$pod\", namespace=\"$namespace\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{ container }}", + "refId": "A" + }, + { + "expr": "sum (rate(container_fs_writes_total{container!=\"POD\", pod=\"$pod\", namespace=\"$namespace\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Write", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "iops", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "collapsed": false, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 83 + }, + "id": 150, + "panels": [], + "title": "PVC", + "type": "row" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "description": "This graph does not show any localstorage-related information due to incorrectly calculating the occupied space on localstorage disks", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 84 + }, + "hiddenSeries": false, + "id": 148, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "/Total/", + "fill": 0, + "linewidth": 2, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "avg_over_time(kubelet_volume_stats_capacity_bytes{namespace=\"$namespace\"}[$__rate_interval])\n* \non (namespace, persistentvolumeclaim) group_left (pod) \n(\n avg_over_time(kube_pod_spec_volumes_persistentvolumeclaims_info{namespace=\"$namespace\", pod=\"$pod\"}[$__rate_interval])\n * on (namespace, persistentvolumeclaim) group_right(pod) \n max by (namespace, persistentvolumeclaim) (\n label_replace(\n max_over_time(kube_persistentvolumeclaim_info{namespace=\"$namespace\"}[$__rate_interval]),\n \"persistentvolume\", \"$1\", \"volumename\", \"(.*)\")\n + on (persistentvolume) group_left() max by (persistentvolume) (kube_persistentvolume_is_local == 0))\n * on (namespace, persistentvolumeclaim) group_right (pod)\n avg_over_time(kube_persistentvolumeclaim_status_phase{namespace=\"$namespace\", phase=\"Bound\"}[$__rate_interval])\n)\n", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Provisioned {{ persistentvolumeclaim }}", + "refId": "A" + }, + { + "expr": "sum (\n avg_over_time(kubelet_volume_stats_capacity_bytes{namespace=\"$namespace\"}[$__rate_interval])\n * \n on (namespace, persistentvolumeclaim) group_left (pod) \n (\n avg_over_time(kube_pod_spec_volumes_persistentvolumeclaims_info{namespace=\"$namespace\", pod=\"$pod\"}[$__rate_interval])\n * on (namespace, persistentvolumeclaim) group_right(pod) \n max by (namespace, persistentvolumeclaim) (\n label_replace(\n max_over_time(kube_persistentvolumeclaim_info{namespace=\"$namespace\"}[$__rate_interval]),\n \"persistentvolume\", \"$1\", \"volumename\", \"(.*)\")\n + on (persistentvolume) group_left() max by (persistentvolume) (kube_persistentvolume_is_local == 0))\n * on (namespace, persistentvolumeclaim) group_right (pod)\n avg_over_time(kube_persistentvolumeclaim_status_phase{namespace=\"$namespace\", phase=\"Bound\"}[$__rate_interval])\n )\n)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "PVC Provisioned (except local storage classes)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "description": "This graph does not show any localstorage-related information due to incorrectly calculating the occupied space on localstorage disks", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 84 + }, + "hiddenSeries": false, + "id": 151, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "/Total/", + "fill": 0, + "linewidth": 2, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "(avg_over_time(kubelet_volume_stats_capacity_bytes{namespace=\"$namespace\"}[$__rate_interval]) - avg_over_time(kubelet_volume_stats_available_bytes{namespace=\"$namespace\"}[$__rate_interval]))\n* \non (namespace, persistentvolumeclaim) group_left (pod) \n(\n avg_over_time(kube_pod_spec_volumes_persistentvolumeclaims_info{namespace=\"$namespace\", pod=\"$pod\"}[$__rate_interval])\n * on (namespace, persistentvolumeclaim) group_right(pod) \n max by (namespace, persistentvolumeclaim) (\n label_replace(\n max_over_time(kube_persistentvolumeclaim_info{namespace=\"$namespace\"}[$__rate_interval]),\n \"persistentvolume\", \"$1\", \"volumename\", \"(.*)\")\n + on (persistentvolume) group_left() max by (persistentvolume) (kube_persistentvolume_is_local == 0))\n * on (namespace, persistentvolumeclaim) group_right (pod)\n avg_over_time(kube_persistentvolumeclaim_status_phase{namespace=\"$namespace\", phase=\"Bound\"}[$__rate_interval])\n)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Usage {{ persistentvolumeclaim }}", + "refId": "A" + }, + { + "expr": "sum (\n (avg_over_time(kubelet_volume_stats_capacity_bytes{namespace=\"$namespace\"}[$__rate_interval]) - avg_over_time(kubelet_volume_stats_available_bytes{namespace=\"$namespace\"}[$__rate_interval]))\n * \n on (namespace, persistentvolumeclaim) group_left (pod) \n (\n avg_over_time(kube_pod_spec_volumes_persistentvolumeclaims_info{namespace=\"$namespace\", pod=\"$pod\"}[$__rate_interval])\n * on (namespace, persistentvolumeclaim) group_right(pod) \n max by (namespace, persistentvolumeclaim) (\n label_replace(\n max_over_time(kube_persistentvolumeclaim_info{namespace=\"$namespace\"}[$__rate_interval]),\n \"persistentvolume\", \"$1\", \"volumename\", \"(.*)\")\n + on (persistentvolume) group_left() max by (persistentvolume) (kube_persistentvolume_is_local == 0))\n * on (namespace, persistentvolumeclaim) group_right (pod)\n avg_over_time(kube_persistentvolumeclaim_status_phase{namespace=\"$namespace\", phase=\"Bound\"}[$__rate_interval])\n )\n)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Total", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "PVC Usage (except local storage classes)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "description": "This graph does not show any localstorage-related information due to incorrectly calculating the occupied space on localstorage disks", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 24, + "x": 0, + "y": 92 + }, + "hiddenSeries": false, + "id": 152, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "(avg_over_time(kubelet_volume_stats_capacity_bytes{namespace=\"$namespace\"}[$__rate_interval]) - avg_over_time(kubelet_volume_stats_available_bytes{namespace=\"$namespace\"}[$__rate_interval]))\n* \non (namespace, persistentvolumeclaim) group_left (pod) \n(\n avg_over_time(kube_pod_spec_volumes_persistentvolumeclaims_info{namespace=\"$namespace\", pod=\"$pod\"}[$__rate_interval])\n * on (namespace, persistentvolumeclaim) group_right(pod) \n max by (namespace, persistentvolumeclaim) (\n label_replace(\n max_over_time(kube_persistentvolumeclaim_info{namespace=\"$namespace\"}[$__rate_interval]),\n \"persistentvolume\", \"$1\", \"volumename\", \"(.*)\")\n + on (persistentvolume) group_left() max by (persistentvolume) (kube_persistentvolume_is_local == 0))\n * on (namespace, persistentvolumeclaim) group_right (pod)\n avg_over_time(kube_persistentvolumeclaim_status_phase{namespace=\"$namespace\", phase=\"Bound\"}[$__rate_interval])\n)\n/\n(\n avg_over_time(kubelet_volume_stats_capacity_bytes{namespace=\"$namespace\"}[$__rate_interval])\n * \n on (namespace, persistentvolumeclaim) group_left (pod) \n (\n avg_over_time(kube_pod_spec_volumes_persistentvolumeclaims_info{namespace=\"$namespace\", pod=\"$pod\"}[$__rate_interval])\n * on (namespace, persistentvolumeclaim) group_right(pod) \n max by (namespace, persistentvolumeclaim) (\n label_replace(\n max_over_time(kube_persistentvolumeclaim_info{namespace=\"$namespace\"}[$__rate_interval]),\n \"persistentvolume\", \"$1\", \"volumename\", \"(.*)\")\n + on (persistentvolume) group_left() max by (persistentvolume) (kube_persistentvolume_is_local == 0))\n * on (namespace, persistentvolumeclaim) group_right (pod)\n avg_over_time(kube_persistentvolumeclaim_status_phase{namespace=\"$namespace\", phase=\"Bound\"}[$__rate_interval])\n )\n)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Usage {{ persistentvolumeclaim }}", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "PVC Usage in % (except local storage classes)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "percentunit", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "collapsed": true, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 100 + }, + "id": 156, + "panels": [ + { + "datasource": "$ds_prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": null, + "displayMode": "auto" + }, + "decimals": 2, + "displayName": "", + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Time" + }, + "properties": [ + { + "id": "displayName", + "value": "Time" + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "persistentvolumeclaim" + }, + "properties": [ + { + "id": "displayName", + "value": "Name" + }, + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "storageclass" + }, + "properties": [ + { + "id": "displayName", + "value": "StorageClass" + }, + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #B" + }, + "properties": [ + { + "id": "displayName", + "value": "Requested" + }, + { + "id": "unit", + "value": "bytes" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #C" + }, + "properties": [ + { + "id": "displayName", + "value": "Provisioned" + }, + { + "id": "unit", + "value": "bytes" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #D" + }, + "properties": [ + { + "id": "displayName", + "value": "Capacity" + }, + { + "id": "unit", + "value": "bytes" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #E" + }, + "properties": [ + { + "id": "displayName", + "value": "Used bytes" + }, + { + "id": "unit", + "value": "bytes" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #F" + }, + "properties": [ + { + "id": "displayName", + "value": "Used inodes" + }, + { + "id": "unit", + "value": "short" + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #G" + }, + "properties": [ + { + "id": "displayName", + "value": "Used bytes (%)" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #H" + }, + "properties": [ + { + "id": "displayName", + "value": "Used inodes (%)" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + } + ] + }, + "gridPos": { + "h": 9, + "w": 24, + "x": 0, + "y": 101 + }, + "id": 154, + "links": [], + "options": { + "showHeader": true + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "expr": "max by (namespace, persistentvolumeclaim, storageclass) (\n kube_persistentvolumeclaim_info{namespace=\"$namespace\"}\n) \nand on (namespace, persistentvolumeclaim) \nmax by (namespace, persistentvolumeclaim) (\n kube_pod_spec_volumes_persistentvolumeclaims_info{namespace=\"$namespace\", pod=~\"$pod\"}\n)", + "format": "table", + "instant": true, + "intervalFactor": 1, + "legendFormat": "Name, storageclass", + "refId": "A" + }, + { + "expr": "max by (namespace, persistentvolumeclaim, storageclass) (\n avg_over_time(kube_persistentvolumeclaim_resource_requests_storage_bytes{namespace=\"$namespace\"}[$__range])\n) \nand on (namespace, persistentvolumeclaim) \nmax by (namespace, persistentvolumeclaim) (\n kube_pod_spec_volumes_persistentvolumeclaims_info{namespace=\"$namespace\", pod=~\"$pod\"}\n)", + "format": "table", + "instant": true, + "intervalFactor": 1, + "legendFormat": "Requested (pvc)", + "refId": "B" + }, + { + "expr": "max by (namespace, persistentvolumeclaim, storageclass) (\n label_replace(\n kube_persistentvolumeclaim_info{namespace=\"$namespace\"},\n \"persistentvolume\", \"$1\", \"volumename\", \"(.*)\") \n * on (persistentvolume) group_left() \n kube_persistentvolume_capacity_bytes\n) \nand on (namespace, persistentvolumeclaim) \nmax by (namespace, persistentvolumeclaim) (\n kube_pod_spec_volumes_persistentvolumeclaims_info{namespace=\"$namespace\", pod=~\"$pod\"}\n)", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "legendFormat": "Provisioned (pv)", + "refId": "C" + }, + { + "expr": "max by (namespace, persistentvolumeclaim, storageclass) (\n avg_over_time(kubelet_volume_stats_capacity_bytes{namespace=\"$namespace\"}[$__range])\n) \nand on (namespace, persistentvolumeclaim) \nmax by (namespace, persistentvolumeclaim) (\n kube_pod_spec_volumes_persistentvolumeclaims_info{namespace=\"$namespace\", pod=~\"$pod\"}\n)", + "format": "table", + "instant": true, + "intervalFactor": 1, + "legendFormat": "Capcity (real)", + "refId": "D" + }, + { + "expr": "max by (namespace, persistentvolumeclaim, storageclass) (\n avg_over_time(kubelet_volume_stats_capacity_bytes{namespace=\"$namespace\"}[$__range]) - avg_over_time(kubelet_volume_stats_available_bytes{namespace=\"$namespace\"}[$__range])\n) \nand on (namespace, persistentvolumeclaim) \nmax by (namespace, persistentvolumeclaim) (\n kube_pod_spec_volumes_persistentvolumeclaims_info{namespace=\"$namespace\", pod=~\"$pod\"}\n)", + "format": "table", + "instant": true, + "intervalFactor": 1, + "legendFormat": "Used bytes", + "refId": "E" + }, + { + "expr": "max by (namespace, persistentvolumeclaim, storageclass) (\n avg_over_time(kubelet_volume_stats_inodes_used{namespace=\"$namespace\"}[$__range])\n) \nand on (namespace, persistentvolumeclaim) \nmax by (namespace, persistentvolumeclaim) (\n kube_pod_spec_volumes_persistentvolumeclaims_info{namespace=\"$namespace\", pod=~\"$pod\"}\n)", + "format": "table", + "instant": true, + "intervalFactor": 1, + "legendFormat": "Used inodes", + "refId": "F" + }, + { + "expr": "max by (namespace, persistentvolumeclaim, storageclass) (\n (avg_over_time(kubelet_volume_stats_capacity_bytes{namespace=\"$namespace\"}[$__range]) - avg_over_time(kubelet_volume_stats_available_bytes{namespace=\"$namespace\"}[$__range]))\n /\n avg_over_time(kubelet_volume_stats_capacity_bytes{namespace=\"$namespace\"}[$__range])\n) \nand on (namespace, persistentvolumeclaim) \nmax by (namespace, persistentvolumeclaim) (\n kube_pod_spec_volumes_persistentvolumeclaims_info{namespace=\"$namespace\", pod=~\"$pod\"}\n)", + "format": "table", + "instant": true, + "intervalFactor": 1, + "legendFormat": "Used bytes %", + "refId": "G" + }, + { + "expr": "max by (namespace, persistentvolumeclaim, storageclass) (\n avg_over_time(kubelet_volume_stats_inodes_used{namespace=\"$namespace\"}[$__range])\n /\n avg_over_time(kubelet_volume_stats_inodes{namespace=\"$namespace\"}[$__range])\n) \nand on (namespace, persistentvolumeclaim) \nmax by (namespace, persistentvolumeclaim) (\n kube_pod_spec_volumes_persistentvolumeclaims_info{namespace=\"$namespace\", pod=~\"$pod\"}\n)", + "format": "table", + "instant": true, + "intervalFactor": 1, + "legendFormat": "Used inodes %", + "refId": "H" + }, + { + "expr": "max by (namespace, persistentvolumeclaim, pod) (\n kube_pod_spec_volumes_persistentvolumeclaims_info{namespace=\"$namespace\", pod=~\"$pod\"}\n)", + "format": "table", + "instant": true, + "intervalFactor": 1, + "legendFormat": "pod", + "refId": "I" + } + ], + "title": "Overview", + "transformations": [ + { + "id": "merge", + "options": { + "reducers": [] + } + }, + { + "id": "filterFieldsByName", + "options": { + "include": { + "names": [ + "persistentvolumeclaim", + "storageclass", + "Value #B", + "Value #C", + "Value #D", + "Value #E", + "Value #F", + "Value #G", + "Value #H" + ] + } + } + } + ], + "type": "table" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$ds_prometheus", + "description": "This graph does not show any localstorage-related information due to incorrectly calculating the occupied space on localstorage disks", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 24, + "x": 0, + "y": 110 + }, + "hiddenSeries": false, + "id": 157, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": "persistentvolumeclaim", + "repeatDirection": "h", + "seriesOverrides": [ + { + "alias": "/Total/", + "fill": 0, + "linewidth": 2, + "stack": false + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "max by (namespace, persistentvolumeclaim, storageclass) (\n label_replace(\n kube_persistentvolumeclaim_info{namespace=\"$namespace\"},\n \"persistentvolume\", \"$1\", \"volumename\", \"(.*)\") \n * on (persistentvolume) group_left() \n avg_over_time(kube_persistentvolume_capacity_bytes[$__rate_interval])\n) \nand on (namespace, persistentvolumeclaim) \nmax by (namespace, persistentvolumeclaim) (\n kube_pod_spec_volumes_persistentvolumeclaims_info{namespace=\"$namespace\", persistentvolumeclaim=\"$persistentvolumeclaim\", pod=~\"$pod\"}\n)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Provisioned", + "refId": "A" + }, + { + "expr": "max by (namespace, persistentvolumeclaim, storageclass) (\n avg_over_time(kubelet_volume_stats_capacity_bytes{namespace=\"$namespace\"}[$__rate_interval])\n) \nand on (namespace, persistentvolumeclaim) \nmax by (namespace, persistentvolumeclaim) (\n kube_pod_spec_volumes_persistentvolumeclaims_info{namespace=\"$namespace\", persistentvolumeclaim=\"$persistentvolumeclaim\", pod=~\"$pod\"}\n)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Capacity", + "refId": "B" + }, + { + "expr": "max by (namespace, persistentvolumeclaim, storageclass) (\n avg_over_time(kubelet_volume_stats_capacity_bytes{namespace=\"$namespace\"}[$__rate_interval]) - avg_over_time(kubelet_volume_stats_available_bytes{namespace=\"$namespace\"}[$__rate_interval])\n) \nand on (namespace, persistentvolumeclaim) \nmax by (namespace, persistentvolumeclaim) (\n kube_pod_spec_volumes_persistentvolumeclaims_info{namespace=\"$namespace\", pod=~\"$pod\"}\n)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Used", + "refId": "C" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "$persistentvolumeclaim", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "title": "PVC Detailed", + "type": "row" + } + ], + "refresh": "30s", + "schemaVersion": 32, + "style": "dark", + "tags": [ + "main" + ], + "templating": { + "list": [ + { + "current": { + "selected": false, + "text": "default", + "value": "default" + }, + "description": null, + "error": null, + "hide": 0, + "includeAll": false, + "label": "Prometheus", + "multi": false, + "name": "ds_prometheus", + "options": [], + "query": "prometheus", + "queryValue": "", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + }, + { + "allValue": null, + "current": { + "selected": false, + "text": "candi-dashboard-stage", + "value": "candi-dashboard-stage" + }, + "datasource": "$ds_prometheus", + "definition": "", + "description": null, + "error": null, + "hide": 0, + "includeAll": false, + "label": "Namespace", + "multi": false, + "name": "namespace", + "options": [], + "query": { + "query": "label_values(kube_pod_info, namespace)", + "refId": "main-namespace-Variable-Query" + }, + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "current": { + "selected": false, + "text": "postgres-0", + "value": "postgres-0" + }, + "datasource": "$ds_prometheus", + "definition": "", + "description": null, + "error": null, + "hide": 0, + "includeAll": false, + "label": "Pod", + "multi": false, + "name": "pod", + "options": [], + "query": { + "query": "label_values(kube_pod_info{namespace=\"$namespace\"}, pod)", + "refId": "main-pod-Variable-Query" + }, + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": "", + "current": { + "selected": true, + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": "$ds_prometheus", + "definition": "", + "description": null, + "error": null, + "hide": 2, + "includeAll": true, + "label": "Container", + "multi": true, + "name": "container", + "options": [], + "query": { + "query": "label_values(kube_pod_container_info{namespace=~\"$namespace\", pod=~\"$pod\"}, container)", + "refId": "main-container-Variable-Query" + }, + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": ".*", + "current": { + "selected": true, + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": "$ds_prometheus", + "definition": "label_values(kube_pod_spec_volumes_persistentvolumeclaims_info{namespace=\"$namespace\", pod=\"$pod\"}, persistentvolumeclaim)", + "description": null, + "error": null, + "hide": 2, + "includeAll": true, + "label": "PersistentVolumeClaim", + "multi": true, + "name": "persistentvolumeclaim", + "options": [], + "query": { + "query": "label_values(kube_pod_spec_volumes_persistentvolumeclaims_info{namespace=\"$namespace\", pod=\"$pod\"}, persistentvolumeclaim)", + "refId": "main-persistentvolumeclaim-Variable-Query" + }, + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "current": { + "selected": false, + "text": "No controller", + "value": "No controller" + }, + "datasource": "$ds_prometheus", + "definition": "label_values(kube_controller_pod{namespace=~\"$namespace\"}, controller_type)", + "description": null, + "error": null, + "hide": 2, + "includeAll": false, + "label": "Controller Type", + "multi": false, + "name": "controller_type", + "options": [], + "query": { + "query": "label_values(kube_controller_pod{namespace=~\"$namespace\"}, controller_type)", + "refId": "main-controller_type-Variable-Query" + }, + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "current": { + "selected": false, + "text": "", + "value": "" + }, + "datasource": "$ds_prometheus", + "definition": "label_values(kube_controller_pod{namespace=~\"$namespace\"}, controller_name)", + "description": null, + "error": null, + "hide": 2, + "includeAll": false, + "label": "Controller Name", + "multi": false, + "name": "controller_name", + "options": [], + "query": { + "query": "label_values(kube_controller_pod{namespace=~\"$namespace\"}, controller_name)", + "refId": "main-controller_name-Variable-Query" + }, + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "datasource": "$ds_prometheus", + "description": null, + "error": null, + "filters": [], + "hide": 0, + "label": null, + "name": "Filters", + "skipUrlSync": false, + "type": "adhoc" + } + ] + }, + "time": { + "from": "now-3h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "", + "title": "Namespace / Controller / Pod", + "uid": "m41rB4yiz1", + "version": 2 +} diff --git a/dashboards/main/volumes.json b/dashboards/main/volumes.json new file mode 100644 index 00000000..5a0d4b42 --- /dev/null +++ b/dashboards/main/volumes.json @@ -0,0 +1,492 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "target": { + "limit": 100, + "matchAny": false, + "tags": [], + "type": "dashboard" + }, + "type": "dashboard" + } + ] + }, + "editable": false, + "fiscalYearStartMonth": 0, + "graphTooltip": 1, + "id": 51, + "links": [], + "liveNow": false, + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "continuous-GrYlRd" + }, + "decimals": 2, + "mappings": [], + "max": 1, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 0.8 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 26, + "w": 12, + "x": 0, + "y": 0 + }, + "id": 2, + "options": { + "displayMode": "gradient", + "minVizHeight": 10, + "minVizWidth": 0, + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showUnfilled": true, + "valueMode": "color" + }, + "pluginVersion": "10.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "editorMode": "code", + "expr": "sort_desc(kubelet_volume_stats_used_bytes{namespace=~\"$namespace\"} / kubelet_volume_stats_capacity_bytes{namespace=~\"$namespace\"})", + "legendFormat": "{{persistentvolumeclaim}}", + "range": true, + "refId": "A" + } + ], + "title": "Persistent Volume Usage", + "type": "bargauge" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "continuous-GrYlRd" + }, + "decimals": 2, + "mappings": [], + "max": 1, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 26, + "w": 12, + "x": 12, + "y": 0 + }, + "id": 4, + "options": { + "displayMode": "basic", + "minVizHeight": 10, + "minVizWidth": 0, + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showUnfilled": true, + "valueMode": "color" + }, + "pluginVersion": "10.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "editorMode": "code", + "expr": "sort_desc(kubelet_volume_stats_inodes_used{namespace=~\"$namespace\"} / kubelet_volume_stats_inodes{namespace=~\"$namespace\"})", + "legendFormat": "{{persistentvolumeclaim}}", + "range": true, + "refId": "A" + } + ], + "title": "Persistent Volume Inodes Usage", + "type": "bargauge" + }, + { + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 26 + }, + "id": 14, + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 0, + "mappings": [], + "max": 1, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 24, + "x": 0, + "y": 19 + }, + "id": 16, + "options": { + "legend": { + "calcs": [], + "displayMode": "table", + "placement": "right", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "editorMode": "code", + "expr": "kube_persistentvolume_status_phase{phase=\"Bound\"} == 1", + "legendFormat": "{{phase}} - {{persistentvolume}}", + "range": true, + "refId": "A" + } + ], + "title": "Persistent Volume Status by Phase", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 0, + "mappings": [], + "max": 1, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "__systemRef": "hideSeriesFrom", + "matcher": { + "id": "byNames", + "options": { + "mode": "exclude", + "names": [ + "Bound - vmselect-cachedir-vmselect-vmcluster-longterm-0" + ], + "prefix": "All except:", + "readOnly": true + } + }, + "properties": [ + { + "id": "custom.hideFrom", + "value": { + "legend": false, + "tooltip": false, + "viz": true + } + } + ] + } + ] + }, + "gridPos": { + "h": 9, + "w": 24, + "x": 0, + "y": 28 + }, + "id": 12, + "options": { + "legend": { + "calcs": [], + "displayMode": "table", + "placement": "right", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "editorMode": "code", + "expr": "kube_persistentvolumeclaim_status_phase{phase=\"Pending\"} == 1", + "legendFormat": "{{phase}} - {{persistentvolumeclaim}} ", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "editorMode": "code", + "expr": "kube_persistentvolumeclaim_status_phase{phase=\"Lost\"} == 1", + "hide": false, + "legendFormat": "{{phase}} - {{persistentvolumeclaim}}", + "range": true, + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "editorMode": "code", + "expr": "kube_persistentvolumeclaim_status_phase{phase=\"Bound\"} == 1", + "hide": false, + "legendFormat": "{{phase}} - {{persistentvolumeclaim}}", + "range": true, + "refId": "C" + } + ], + "title": "Persistent Volume Claim Status by Phase", + "type": "timeseries" + } + ], + "title": "kube-state", + "type": "row" + } + ], + "refresh": "30s", + "schemaVersion": 38, + "style": "dark", + "tags": [], + "templating": { + "list": [ + { + "current": { + "selected": false, + "text": "vm", + "value": "7de66667-64e8-4685-b5b4-2c3d573910bc" + }, + "hide": 0, + "includeAll": false, + "label": "Prometheus", + "multi": false, + "name": "ds_prometheus", + "options": [], + "query": "prometheus", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + }, + { + "current": { + "selected": true, + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "prometheus", + "uid": "$ds_prometheus" + }, + "definition": "label_values(kubelet_volume_stats_capacity_bytes, namespace)", + "hide": 0, + "includeAll": true, + "multi": true, + "name": "namespace", + "options": [], + "query": { + "query": "label_values(kubelet_volume_stats_capacity_bytes, namespace)", + "refId": "StandardVariableQuery" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "type": "query" + } + ] + }, + "time": { + "from": "now-3h", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "Volumes", + "uid": "AxpMCRd4z", + "version": 260, + "weekStart": "" +} diff --git a/dashboards/victoria-metrics/backupmanager.json b/dashboards/victoria-metrics/backupmanager.json new file mode 100644 index 00000000..71e44416 --- /dev/null +++ b/dashboards/victoria-metrics/backupmanager.json @@ -0,0 +1,1756 @@ +{ + "__inputs": [], + "__elements": {}, + "__requires": [ + { + "type": "panel", + "id": "barchart", + "name": "Bar chart", + "version": "" + }, + { + "type": "grafana", + "id": "grafana", + "name": "Grafana", + "version": "9.0.4" + }, + { + "type": "datasource", + "id": "prometheus", + "name": "Prometheus", + "version": "1.0.0" + }, + { + "type": "panel", + "id": "stat", + "name": "Stat", + "version": "" + }, + { + "type": "panel", + "id": "table", + "name": "Table", + "version": "" + }, + { + "type": "panel", + "id": "timeseries", + "name": "Time series", + "version": "" + } + ], + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "target": { + "limit": 100, + "matchAny": false, + "tags": [], + "type": "dashboard" + }, + "type": "dashboard" + } + ] + }, + "description": "Overview for VictoriaMetrics backupmanager v1.85.3 or higher", + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": null, + "links": [], + "liveNow": false, + "panels": [ + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 10, + "panels": [], + "title": "Stats", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 3, + "x": 0, + "y": 1 + }, + "id": 32, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "9.0.4", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": false, + "expr": "count(vm_app_version{job=~\"$job\", instance=~\"$instance\", version=~\"^vmbackupmanager.+\" })", + "instant": true, + "legendFormat": "__auto", + "range": false, + "refId": "A" + } + ], + "title": "Instances", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Status of last backup operation.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "0": { + "index": 0, + "text": "Success" + } + }, + "type": "value" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 4, + "x": 3, + "y": 1 + }, + "id": 2, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "9.0.4", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "sum(vm_backup_last_run_failed)", + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "Last backup status", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Number of backups stored in remote storage.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 3, + "x": 7, + "y": 1 + }, + "id": 6, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "9.0.4", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "sum(vm_backups_stored{job=~\"$job\", instance=~\"$instance\"})", + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "Total backups stored", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Space used in remote storage.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "decbytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 3, + "x": 10, + "y": 1 + }, + "id": 27, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "9.0.4", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "sum(vm_backups_size_bytes{job=~\"$job\", instance=~\"$instance\"})", + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "Backups size", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "0": { + "index": 0, + "text": "No errors" + } + }, + "type": "value" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 1 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 3, + "x": 13, + "y": 1 + }, + "id": 7, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "9.0.4", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "sum(increase(vm_backup_errors_total{job=~\"$job\", instance=~\"$instance\"}[1h]))", + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "Backups errors ", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Status of last retention run.\n\nRetention is a process of removing old backups from remote storage.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "0": { + "index": 0, + "text": "Success" + } + }, + "type": "value" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 4, + "x": 16, + "y": 1 + }, + "id": 5, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "9.0.4", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "sum(vm_retention_last_run_failed)", + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "Last retention status", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "0": { + "index": 0, + "text": "No errors" + } + }, + "type": "value" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 1 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 4, + "x": 20, + "y": 1 + }, + "id": 8, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "9.0.4", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "sum(increase(vm_retention_errors_total{job=~\"$job\", instance=~\"$instance\"}[1h]))", + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "Retention errors", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "displayMode": "auto", + "inspect": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "name" + }, + "properties": [ + { + "id": "custom.width", + "value": 148 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "value" + }, + "properties": [ + { + "id": "custom.width", + "value": 101 + } + ] + } + ] + }, + "gridPos": { + "h": 6, + "w": 12, + "x": 0, + "y": 6 + }, + "id": 22, + "options": { + "footer": { + "fields": "", + "reducer": [ + "sum" + ], + "show": false + }, + "showHeader": true, + "sortBy": [ + { + "desc": false, + "displayName": "name" + } + ] + }, + "pluginVersion": "9.0.4", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": false, + "expr": "sum(flag{job=~\"$job\", instance=~\"$instance\",name=~\"disableDaily|disableHourly|disableWeekly|disableMonthly\"}) by (name, value, instance)", + "format": "table", + "instant": true, + "legendFormat": "", + "range": false, + "refId": "A" + } + ], + "title": "Backups configuration", + "transformations": [ + { + "id": "groupBy", + "options": { + "fields": { + "instance": { + "aggregations": [ + "uniqueValues" + ], + "operation": "aggregate" + }, + "name": { + "aggregations": [], + "operation": "groupby" + }, + "value": { + "aggregations": [], + "operation": "groupby" + } + } + } + } + ], + "type": "table" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "displayMode": "auto", + "inspect": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "value" + }, + "properties": [ + { + "id": "custom.width", + "value": 100 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "name" + }, + "properties": [ + { + "id": "custom.width", + "value": 150 + } + ] + } + ] + }, + "gridPos": { + "h": 6, + "w": 12, + "x": 12, + "y": 6 + }, + "id": 21, + "options": { + "footer": { + "fields": "", + "reducer": [ + "sum" + ], + "show": false + }, + "showHeader": true, + "sortBy": [ + { + "desc": false, + "displayName": "name" + } + ] + }, + "pluginVersion": "9.0.4", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": false, + "expr": "sum(flag{job=~\"$job\", instance=~\"$instance\",name=~\"keep(.*)\", is_set=\"true\"}) by (name, value, instance)", + "format": "table", + "instant": true, + "legendFormat": "", + "range": false, + "refId": "A" + } + ], + "title": "Retention configuration", + "transformations": [ + { + "id": "groupBy", + "options": { + "fields": { + "instance": { + "aggregations": [ + "uniqueValues" + ], + "operation": "aggregate" + }, + "name": { + "aggregations": [], + "operation": "groupby" + }, + "value": { + "aggregations": [], + "operation": "groupby" + } + } + } + } + ], + "type": "table" + }, + { + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 12 + }, + "id": 12, + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Max duration of backup run. Lower better.\n\nEach backup starts with data upload during `latest` backup. Subsequent backups (`hourly`, `daily`, `weekly`, `monthly`) are copying date by using server-side copy. ", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "fillOpacity": 80, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineWidth": 1, + "scaleDistribution": { + "type": "linear" + } + }, + "links": [ + { + "targetBlank": true, + "title": "Drilldown", + "url": "/d/gF-lxRdVz?viewPanel=36&var-ds=$ds&var-instance=$instance&var-job=$job&${__url_time_range}" + } + ], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 13 + }, + "id": 23, + "interval": "1h", + "options": { + "barRadius": 0, + "barWidth": 0.97, + "groupWidth": 0.7, + "legend": { + "calcs": [ + "max", + "min", + "mean" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": false + }, + "orientation": "auto", + "showValue": "auto", + "stacking": "none", + "tooltip": { + "mode": "single", + "sort": "none" + }, + "xTickLabelRotation": 0, + "xTickLabelSpacing": 100 + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "max(increase(vm_backup_duration_seconds_total{job=~\"$job\", instance=~\"$instance\"})) by (type) > 0", + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "Max backup duration", + "type": "barchart" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 13 + }, + "id": 16, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "sum(increase(vm_backup_errors_total{job=~\"$job\", instance=~\"$instance\"})[$__interval]) by (instance) > 0", + "legendFormat": "{{instance}}", + "range": true, + "refId": "A" + } + ], + "title": "Backup errors", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "decbytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 21 + }, + "id": 29, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "vm_backups_size_bytes{job=~\"$job\", instance=~\"$instance\"}", + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "Backups size", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "displayMode": "auto", + "inspect": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "decbytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 21 + }, + "id": 28, + "options": { + "footer": { + "fields": "", + "reducer": [ + "sum" + ], + "show": false + }, + "showHeader": true, + "sortBy": [ + { + "desc": true, + "displayName": "backup" + } + ] + }, + "pluginVersion": "9.0.4", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": false, + "expr": "topk(10, sum(vm_backups_size_bytes{job=~\"$job\", instance=~\"$instance\"}) by (backup, job, type))", + "format": "table", + "instant": true, + "legendFormat": "__auto", + "range": false, + "refId": "A" + } + ], + "title": "Top 10 backups by size", + "transformations": [ + { + "id": "groupBy", + "options": { + "fields": { + "Value": { + "aggregations": [], + "operation": "groupby" + }, + "backup": { + "aggregations": [], + "operation": "groupby" + }, + "job": { + "aggregations": [], + "operation": "groupby" + }, + "type": { + "aggregations": [], + "operation": "groupby" + } + } + } + } + ], + "type": "table" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "fillOpacity": 80, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineWidth": 1, + "scaleDistribution": { + "type": "linear" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 29 + }, + "id": 30, + "interval": "1d", + "options": { + "barRadius": 0, + "barWidth": 0.97, + "groupWidth": 0.85, + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "orientation": "auto", + "showValue": "auto", + "stacking": "normal", + "tooltip": { + "mode": "single", + "sort": "none" + }, + "xTickLabelRotation": 0, + "xTickLabelSpacing": 100 + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "sum(increase(vm_backups_total{job=~\"$job\", instance=~\"$instance\"}[24h])) by (type) > 0", + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "Backup runs", + "type": "barchart" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "binBps" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 29 + }, + "id": 31, + "options": { + "legend": { + "calcs": [ + "max", + "mean" + ], + "displayMode": "table", + "placement": "right", + "showLegend": false + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "sum(rollup_rate(vm_backups_uploaded_bytes_total[$__rate_interval])) by (rollup)", + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "Backups upload speed", + "type": "timeseries" + } + ], + "title": "Backups", + "type": "row" + }, + { + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 13 + }, + "id": 18, + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Max duration of retention run. Lower better.\n\nRetention is a process of removing old backups from remote storage.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "fillOpacity": 80, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineWidth": 1, + "scaleDistribution": { + "type": "linear" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 38 + }, + "id": 26, + "interval": "1h", + "options": { + "barRadius": 0, + "barWidth": 0.97, + "groupWidth": 0.7, + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "orientation": "auto", + "showValue": "auto", + "stacking": "none", + "tooltip": { + "mode": "single", + "sort": "none" + }, + "xTickLabelRotation": 0, + "xTickLabelSpacing": 0 + }, + "pluginVersion": "9.0.4", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "max(increase(vm_retention_duration_seconds_total{job=~\"$job\", instance=~\"$instance\"})) > 0", + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "Max retention duration", + "type": "barchart" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 38 + }, + "id": 25, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "sum(increase(vm_retention_errors_total{job=~\"$job\", instance=~\"$instance\"})[$__interval]) by (instance) > 0", + "legendFormat": "{{instance}}", + "range": true, + "refId": "A" + } + ], + "title": "Retention errors", + "type": "timeseries" + } + ], + "title": "Retention", + "type": "row" + }, + { + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 14 + }, + "id": 34, + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Duration of backup run. Lower better.\n\nEach backup starts with data upload during `latest` backup. Subsequent backups (`hourly`, `daily`, `weekly`, `monthly`) are copying date by using server-side copy.\n", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "fillOpacity": 80, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineWidth": 1, + "scaleDistribution": { + "type": "linear" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 11, + "w": 24, + "x": 0, + "y": 39 + }, + "id": 36, + "interval": "1h", + "options": { + "barRadius": 0, + "barWidth": 0.97, + "groupWidth": 0.7, + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "orientation": "auto", + "showValue": "auto", + "stacking": "none", + "tooltip": { + "mode": "single", + "sort": "none" + }, + "xTickLabelRotation": 0, + "xTickLabelSpacing": 100 + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "increase(vm_backup_duration_seconds_total{job=~\"$job\", instance=~\"$instance\"}) > 0", + "legendFormat": "{{instance}} - {{type}}", + "range": true, + "refId": "A" + } + ], + "title": "Backup duration per instance", + "type": "barchart" + } + ], + "title": "Drilldown", + "type": "row" + } + ], + "refresh": "1m", + "schemaVersion": 36, + "style": "dark", + "tags": [], + "templating": { + "list": [ + { + "current": { + "selected": true, + "text": "VictoriaMetrics", + "value": "VictoriaMetrics" + }, + "hide": 0, + "includeAll": false, + "multi": false, + "name": "ds", + "options": [], + "query": "prometheus", + "queryValue": "", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + }, + { + "allValue": ".*", + "current": {}, + "datasource": { + "uid": "$ds" + }, + "definition": "label_values(vm_app_version{version=~\"^vmbackupmanager.*\"}, job)", + "hide": 0, + "includeAll": true, + "multi": true, + "name": "job", + "options": [], + "query": { + "query": "label_values(vm_app_version{version=~\"^vmbackupmanager.*\"}, job)", + "refId": "StandardVariableQuery" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": ".*", + "current": {}, + "datasource": { + "uid": "$ds" + }, + "definition": "label_values(vm_app_version{job=~\"$job\"}, instance)", + "hide": 0, + "includeAll": true, + "multi": true, + "name": "instance", + "options": [], + "query": { + "query": "label_values(vm_app_version{job=~\"$job\"}, instance)", + "refId": "VictoriaMetrics-instance-Variable-Query" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "filters": [], + "hide": 0, + "name": "adhoc", + "skipUrlSync": false, + "type": "adhoc" + } + ] + }, + "time": { + "from": "now-7d", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "VictoriaMetrics - backupmanager", + "uid": "gF-lxRdVz", + "version": 1, + "weekStart": "" +} \ No newline at end of file diff --git a/dashboards/victoria-metrics/operator.json b/dashboards/victoria-metrics/operator.json new file mode 100644 index 00000000..4f9cc6c7 --- /dev/null +++ b/dashboards/victoria-metrics/operator.json @@ -0,0 +1,1362 @@ +{ + "__inputs": [], + "__elements": {}, + "__requires": [ + { + "type": "grafana", + "id": "grafana", + "name": "Grafana", + "version": "9.2.2" + }, + { + "type": "panel", + "id": "graph", + "name": "Graph (old)", + "version": "" + }, + { + "type": "datasource", + "id": "prometheus", + "name": "Prometheus", + "version": "1.0.0" + }, + { + "type": "panel", + "id": "stat", + "name": "Stat", + "version": "" + }, + { + "type": "panel", + "id": "text", + "name": "Text", + "version": "" + } + ], + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "target": { + "limit": 100, + "matchAny": false, + "tags": [], + "type": "dashboard" + }, + "type": "dashboard" + } + ] + }, + "description": "Overview for operator VictoriaMetrics v0.25.0 or higher", + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": null, + "links": [], + "liveNow": false, + "panels": [ + { + "collapsed": false, + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 8, + "panels": [], + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "refId": "A" + } + ], + "title": "Overview", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "gridPos": { + "h": 3, + "w": 4, + "x": 0, + "y": 1 + }, + "id": 24, + "options": { + "code": { + "language": "plaintext", + "showLineNumbers": false, + "showMiniMap": false + }, + "content": "
$version
", + "mode": "markdown" + }, + "pluginVersion": "9.2.2", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "refId": "A" + } + ], + "title": "Version", + "type": "text" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Number of objects at kubernetes cluster per each controller", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 20, + "x": 4, + "y": 1 + }, + "id": 14, + "options": { + "colorMode": "none", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "9.2.2", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "max(operator_controller_objects_count{job=~\"$job\",instance=~\"$instance\"}) by (controller)", + "legendFormat": "{{controller}}", + "range": true, + "refId": "A" + } + ], + "title": "CRD Objects count by controller", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 4, + "x": 0, + "y": 4 + }, + "id": 22, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "9.2.2", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": false, + "expr": "vm_app_uptime_seconds{job=~\"$job\",instance=~\"$instance\"}", + "format": "table", + "instant": true, + "interval": "", + "legendFormat": "{{instance}}", + "range": false, + "refId": "A" + } + ], + "title": "Uptime", + "type": "stat" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 13, + "w": 12, + "x": 0, + "y": 8 + }, + "hiddenSeries": false, + "id": 12, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "9.2.2", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "sum(rate(controller_runtime_reconcile_total{job=~\"$job\",instance=~\"$instance\",result=~\"requeue_after|requeue|success\"}[$__rate_interval])) by(controller)", + "legendFormat": "{{controller}}", + "range": true, + "refId": "A" + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Reconciliation rate by controller", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "logBase": 1, + "show": true + }, + { + "format": "short", + "logBase": 1, + "show": true + } + ], + "yaxis": { + "align": false + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 13, + "w": 12, + "x": 12, + "y": 8 + }, + "hiddenSeries": false, + "id": 16, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "9.2.2", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "sum(rate(operator_log_messages_total{job=~\"$job\",instance=~\"$instance\"}[$__rate_interval])) by (level)", + "legendFormat": "{{label_name}}", + "range": true, + "refId": "A" + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Log message rate", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "logBase": 1, + "show": true + }, + { + "format": "short", + "logBase": 1, + "show": true + } + ], + "yaxis": { + "align": false + } + }, + { + "collapsed": false, + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 21 + }, + "id": 6, + "panels": [], + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "refId": "A" + } + ], + "title": "Troubleshooting", + "type": "row" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Non zero metrics indicates about error with CR object definition (typos or incorrect values) or errors with kubernetes API connection.", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 22 + }, + "hiddenSeries": false, + "id": 10, + "legend": { + "alignAsTable": true, + "avg": false, + "current": true, + "max": true, + "min": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.3.2", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": false, + "expr": "sum(rate(controller_runtime_reconcile_errors_total{job=~\"$job\",instance=~\"$instance\"}[$__rate_interval])) by(controller) > 0 ", + "instant": false, + "legendFormat": "{{controller}}", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "sum(rate(controller_runtime_reconcile_total{job=~\"$job\",instance=~\"$instance\",result=\"error\"}[$__rate_interval])) by(controller) > 0", + "hide": false, + "legendFormat": "{{label_name}}", + "range": true, + "refId": "B" + } + ], + "thresholds": [], + "timeRegions": [], + "title": "reconcile errors by controller", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "logBase": 1, + "show": true + }, + { + "format": "short", + "logBase": 1, + "show": true + } + ], + "yaxis": { + "align": false + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Operator limits number of reconcilation events to 5 events per 2 seconds.\n For now, this limit is applied only for vmalert and vmagent controllers.\n It should reduce load at kubernetes cluster and increase operator performance.", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 22 + }, + "hiddenSeries": false, + "id": 18, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.3.2", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "sum(rate(operator_reconcile_throttled_events_total[$__rate_interval])) by(controller)", + "legendFormat": "{{controller}}", + "range": true, + "refId": "A" + } + ], + "thresholds": [], + "timeRegions": [], + "title": "throttled reconcilation events", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "logBase": 1, + "show": true + }, + { + "format": "short", + "logBase": 1, + "show": true + } + ], + "yaxis": { + "align": false + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Number of objects waiting in the queue for reconciliation. Non-zero values indicate that operator cannot process CR objects changes with the given resources.", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 11, + "w": 12, + "x": 0, + "y": 30 + }, + "hiddenSeries": false, + "id": 20, + "legend": { + "alignAsTable": true, + "avg": false, + "current": true, + "max": true, + "min": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.3.2", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "max(workqueue_depth{job=~\"$job\",instance=~\"$instance\"}) by (name)", + "legendFormat": "{{label_name}}", + "range": true, + "refId": "A" + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Wokring queue depth", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "logBase": 1, + "show": true + }, + { + "format": "short", + "logBase": 1, + "show": true + } + ], + "yaxis": { + "align": false + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": " For controllers with StatefulSet it's ok to see latency greater then 3 seconds. It could be vmalertmanager,vmcluster or vmagent in statefulMode.\n\n For other controllers, latency greater then 1 second may indicate issues with kubernetes cluster or operator's performance.\n ", + "fieldConfig": { + "defaults": { + "unit": "s" + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 11, + "w": 12, + "x": 12, + "y": 30 + }, + "hiddenSeries": false, + "id": 26, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": false, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.3.2", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "histogram_quantile(0.99,sum(rate(controller_runtime_reconcile_time_seconds_bucket[$__rate_interval])) by(le,controller) )", + "legendFormat": "q.99 {{controller}}", + "range": true, + "refId": "A" + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Reconcilation latency by controller", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "s", + "logBase": 1, + "show": true + }, + { + "format": "short", + "logBase": 1, + "show": true + } + ], + "yaxis": { + "align": false + } + }, + { + "collapsed": false, + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 41 + }, + "id": 4, + "panels": [], + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "refId": "A" + } + ], + "title": "resources", + "type": "row" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "fieldConfig": { + "defaults": { + "unit": "bytes" + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 42 + }, + "hiddenSeries": false, + "id": 28, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.3.2", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "sum(go_memstats_sys_bytes{job=~\"$job\", instance=~\"$instance\"}) ", + "legendFormat": "requested from system", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "sum(go_memstats_heap_inuse_bytes{job=~\"$job\", instance=~\"$instance\"}) ", + "hide": false, + "legendFormat": "heap inuse", + "range": true, + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "sum(go_memstats_stack_inuse_bytes{job=~\"$job\", instance=~\"$instance\"})", + "hide": false, + "legendFormat": "stack inuse", + "range": true, + "refId": "C" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "sum(process_resident_memory_bytes{job=~\"$job\", instance=~\"$instance\"})", + "hide": false, + "legendFormat": "resident", + "range": true, + "refId": "D" + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Memory usage ($instance)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "logBase": 1, + "show": true + }, + { + "format": "short", + "logBase": 1, + "show": true + } + ], + "yaxis": { + "align": false + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 42 + }, + "hiddenSeries": false, + "id": 30, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.3.2", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "rate(process_cpu_seconds_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])", + "legendFormat": "CPU cores used", + "range": true, + "refId": "A" + } + ], + "thresholds": [], + "timeRegions": [], + "title": "CPU ($instance)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "logBase": 1, + "show": true + }, + { + "format": "short", + "logBase": 1, + "show": true + } + ], + "yaxis": { + "align": false + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 50 + }, + "hiddenSeries": false, + "id": 32, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.3.2", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "sum(go_goroutines{job=~\"$job\", instance=~\"$instance\"})", + "legendFormat": "goroutines", + "range": true, + "refId": "A" + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Goroutines ($instance)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "logBase": 1, + "show": true + }, + { + "format": "short", + "logBase": 1, + "show": true + } + ], + "yaxis": { + "align": false + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "fieldConfig": { + "defaults": { + "unit": "s" + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 50 + }, + "hiddenSeries": false, + "id": 34, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.3.2", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "sum(rate(go_gc_duration_seconds_sum{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval]))\n/\nsum(rate(go_gc_duration_seconds_count{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval]))", + "legendFormat": "avg gc duration", + "range": true, + "refId": "A" + } + ], + "thresholds": [], + "timeRegions": [], + "title": "GC duration ($instance)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "s", + "logBase": 1, + "show": true + }, + { + "format": "short", + "logBase": 1, + "show": true + } + ], + "yaxis": { + "align": false + } + } + ], + "refresh": "", + "schemaVersion": 37, + "style": "dark", + "tags": [ + "operator", + "VictoriaMetrics" + ], + "templating": { + "list": [ + { + "current": { + "selected": false, + "text": "cloud-c15", + "value": "cloud-c15" + }, + "hide": 0, + "includeAll": false, + "multi": false, + "name": "ds", + "options": [], + "query": "prometheus", + "queryValue": "", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + }, + { + "current": {}, + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "definition": "label_values(operator_log_messages_total,job)", + "hide": 0, + "includeAll": false, + "multi": false, + "name": "job", + "options": [], + "query": { + "query": "label_values(operator_log_messages_total,job)", + "refId": "StandardVariableQuery" + }, + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "current": {}, + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "definition": "label_values(operator_log_messages_total{job=~\"$job\"},instance)", + "hide": 0, + "includeAll": true, + "multi": false, + "name": "instance", + "options": [], + "query": { + "query": "label_values(operator_log_messages_total{job=~\"$job\"},instance)", + "refId": "StandardVariableQuery" + }, + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "current": {}, + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "definition": "label_values(vm_app_version{job=\"$job\", instance=\"$instance\"}, version)", + "hide": 2, + "includeAll": false, + "multi": false, + "name": "version", + "options": [], + "query": { + "query": "label_values(vm_app_version{job=\"$job\", instance=\"$instance\"}, version)", + "refId": "StandardVariableQuery" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 2, + "type": "query" + } + ] + }, + "time": { + "from": "now-15m", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "VictoriaMetrics - operator", + "uid": "1H179hunk", + "version": 1, + "weekStart": "" +} \ No newline at end of file diff --git a/dashboards/victoria-metrics/victoriametrics-cluster.json b/dashboards/victoria-metrics/victoriametrics-cluster.json new file mode 100644 index 00000000..6abd17a6 --- /dev/null +++ b/dashboards/victoria-metrics/victoriametrics-cluster.json @@ -0,0 +1,9066 @@ +{ + "__inputs": [], + "__elements": {}, + "__requires": [ + { + "type": "grafana", + "id": "grafana", + "name": "Grafana", + "version": "9.2.7" + }, + { + "type": "datasource", + "id": "prometheus", + "name": "Prometheus", + "version": "1.0.0" + }, + { + "type": "panel", + "id": "stat", + "name": "Stat", + "version": "" + }, + { + "type": "panel", + "id": "table", + "name": "Table", + "version": "" + }, + { + "type": "panel", + "id": "text", + "name": "Text", + "version": "" + }, + { + "type": "panel", + "id": "timeseries", + "name": "Time series", + "version": "" + } + ], + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "target": { + "limit": 100, + "matchAny": false, + "tags": [], + "type": "dashboard" + }, + "type": "dashboard" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "enable": true, + "expr": "sum(ALERTS{job=~\"$job\", instance=~\"$instance\", alertgroup=\"vmcluster\",alertstate=\"firing\",show_at=\"dashboard\"}) by(alertname)", + "iconColor": "red", + "name": "alerts", + "titleFormat": "{{alertname}}" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "enable": true, + "expr": "sum(vm_app_version{job=~\"$job\", instance=~\"$instance\"}) by(version) unless (sum(vm_app_version{job=~\"$job\", instance=~\"$instance\"} offset 20m) by(version))", + "hide": true, + "iconColor": "dark-blue", + "name": "version change", + "textFormat": "{{version}}", + "titleFormat": "Version change" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "enable": true, + "expr": "sum(changes(vm_app_start_timestamp{job=~\"$job\", instance=~\"$instance\"})) by(job)", + "hide": true, + "iconColor": "dark-yellow", + "name": "restarts", + "textFormat": "{{job}} restarted" + } + ] + }, + "description": "Overview for cluster VictoriaMetrics v1.86.0 or higher", + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 1, + "id": null, + "links": [ + { + "icon": "doc", + "tags": [], + "targetBlank": true, + "title": "Cluster Wiki", + "type": "link", + "url": "https://github.com/VictoriaMetrics/VictoriaMetrics/wiki/Cluster-VictoriaMetrics" + }, + { + "icon": "external link", + "tags": [], + "targetBlank": true, + "title": "Found a bug?", + "type": "link", + "url": "https://github.com/VictoriaMetrics/VictoriaMetrics/issues" + }, + { + "icon": "external link", + "tags": [], + "targetBlank": true, + "title": "New releases", + "type": "link", + "url": "https://github.com/VictoriaMetrics/VictoriaMetrics/releases" + } + ], + "liveNow": false, + "panels": [ + { + "collapsed": false, + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 137, + "panels": [], + "title": "Stats", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "How many datapoints are in storage", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 1 + }, + "id": 131, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "9.2.7", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "exemplar": true, + "expr": "sum(vm_rows{job=~\"$job_storage\", type!~\"indexdb.*\"})", + "format": "time_series", + "instant": true, + "interval": "", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "title": "Total datapoints", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Shows the datapoints ingestion rate, including replication factor.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 6, + "x": 6, + "y": 1 + }, + "id": 124, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "9.2.7", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": false, + "expr": "sum(rate(vm_vminsert_metrics_read_total{job=~\"$job_storage\", instance=~\"$instance\"}[$__rate_interval])) ", + "format": "time_series", + "instant": true, + "interval": "", + "intervalFactor": 1, + "legendFormat": "", + "range": false, + "refId": "A" + } + ], + "title": "Ingestion rate", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Shows the rate of HTTP read requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "req/s" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 6, + "x": 12, + "y": 1 + }, + "id": 130, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "9.2.7", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(rate(vm_http_requests_total{job=~\"$job\", instance=~\"$instance\", path=~\"/select/.*\"}[$__rate_interval]))", + "format": "time_series", + "instant": true, + "interval": "", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "title": "Read requests", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Total number of available CPUs for all VM components. ", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 6, + "x": 18, + "y": 1 + }, + "id": 126, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "9.2.7", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(vm_available_cpu_cores{job=~\"$job\", instance=~\"$instance\"})", + "format": "time_series", + "instant": true, + "interval": "", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "title": "Available CPU", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Shows the number of active time series with new data points inserted during the last hour. High value may result in ingestion slowdown. \n\nSee more details here https://docs.victoriametrics.com/FAQ.html#what-is-an-active-time-series", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 4 + }, + "id": 34, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "9.2.7", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(max_over_time(vm_cache_entries{job=~\"$job\", instance=~\"$instance\", type=\"storage/hour_metric_ids\"}[1h]))", + "format": "time_series", + "instant": true, + "interval": "", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "title": "Active series", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Total amount of used disk space", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 6, + "x": 6, + "y": 4 + }, + "id": 35, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "9.2.7", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "exemplar": false, + "expr": "sum(vm_data_size_bytes{job=~\"$job_storage\"})", + "format": "time_series", + "instant": true, + "interval": "", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "title": "Disk space usage", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Average disk usage per datapoint.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "decimals": 2, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 6, + "x": 12, + "y": 4 + }, + "id": 112, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "9.2.7", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "exemplar": true, + "expr": "sum(vm_data_size_bytes{job=~\"$job_storage\"}) / sum(vm_rows{job=~\"$job_storage\", type!~\"indexdb.*\"})", + "format": "time_series", + "instant": true, + "interval": "", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "title": "Bytes per point", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Total size of available memory for all VM components.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 6, + "x": 18, + "y": 4 + }, + "id": 128, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "9.2.7", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(vm_available_memory_bytes{job=~\"$job\", instance=~\"$instance\"})", + "format": "time_series", + "instant": true, + "interval": "", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "title": "Available memory", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "displayMode": "auto", + "inspect": false, + "minWidth": 50 + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Time" + }, + "properties": [ + { + "id": "custom.hidden", + "value": true + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value" + }, + "properties": [ + { + "id": "displayName", + "value": "Count" + } + ] + } + ] + }, + "gridPos": { + "h": 5, + "w": 8, + "x": 0, + "y": 7 + }, + "id": 149, + "options": { + "footer": { + "fields": "", + "reducer": [ + "sum" + ], + "show": false + }, + "showHeader": true, + "sortBy": [ + { + "desc": true, + "displayName": "Count" + } + ] + }, + "pluginVersion": "9.2.7", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": false, + "expr": "sum(vm_app_version{job=~\"$job\", instance=~\"$instance\"}) by(job, short_version)", + "format": "table", + "instant": true, + "range": false, + "refId": "A" + } + ], + "type": "table" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMin": 0, + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "stepAfter", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 0, + "links": [], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 16, + "x": 8, + "y": 7 + }, + "id": 62, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "right", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "sum(min_over_time(up{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by (job)", + "format": "time_series", + "instant": false, + "legendFormat": "{{job}}", + "refId": "A" + } + ], + "title": "Uptime ($job)", + "type": "timeseries" + }, + { + "collapsed": false, + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 12 + }, + "id": 10, + "panels": [], + "title": "Overview", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "How many datapoints are inserted into cluster per second by protocol before the replication.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineStyle": { + "fill": "solid" + }, + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 13 + }, + "id": 2, + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(rate(vm_rows_inserted_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by (type) > 0 ", + "interval": "", + "legendFormat": "{{type}}", + "range": true, + "refId": "A" + } + ], + "title": "Datapoints ingestion rate ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "* `*` - unsupported query path\n* `/write` - insert into VM\n* `/metrics` - query VM system metrics\n* `/query` - query instant values\n* `/query_range` - query over a range of time\n* `/series` - match a certain label set\n* `/label/{}/values` - query a list of label values (variables mostly)", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 13 + }, + "id": 6, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "sum(rate(vm_http_requests_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by (path) > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{path}}", + "range": true, + "refId": "A" + } + ], + "title": "Requests rate ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Shows the number of active time series with new data points inserted during the last hour across all storage nodes. High value may result in ingestion slowdown. \n\nSee following link for details:", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 21 + }, + "id": 12, + "links": [ + { + "targetBlank": true, + "title": "troubleshooting", + "url": "https://github.com/VictoriaMetrics/VictoriaMetrics/blob/master/README.md#troubleshooting" + } + ], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "expr": "sum(vm_cache_entries{job=~\"$job\", instance=~\"$instance\", type=\"storage/hour_metric_ids\"})", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Active time series", + "refId": "A" + } + ], + "title": "Active time series ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "The less time it takes is better.\n* `*` - unsupported query path\n* `/write` - insert into VM\n* `/metrics` - query VM system metrics\n* `/query` - query instant values\n* `/query_range` - query over a range of time\n* `/series` - match a certain label set\n* `/label/{}/values` - query a list of label values (variables mostly)", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 21 + }, + "id": 8, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "max(vm_request_duration_seconds{job=~\"$job\", instance=~\"$instance\", quantile=\"0.99\"}) by (path) > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{path}}", + "range": true, + "refId": "A" + } + ], + "title": "Query duration 0.99 quantile ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "* `*` - unsupported query path\n* `/write` - insert into VM\n* `/metrics` - query VM system metrics\n* `/query` - query instant values\n* `/query_range` - query over a range of time\n* `/series` - match a certain label set\n* `/label/{}/values` - query a list of label values (variables mostly)", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 29 + }, + "id": 52, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "sum(rate(vm_http_request_errors_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by (job, path) > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{path}} ({{job}})", + "range": true, + "refId": "A" + } + ], + "title": "Requests error rate ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Shows the rate of logging the messages by their level. Unexpected spike in rate is a good reason to check logs.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "bars", + "fillOpacity": 100, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [ + { + "targetBlank": true, + "title": "Drilldown", + "url": "/d/oS7Bi_0Wz?viewPanel=203&var-job=${__field.labels.job}&var-ds=$ds&var-instance=$instance&${__url_time_range}" + } + ], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 29 + }, + "id": 104, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(rate(vm_log_messages_total{job=~\"$job\",instance=~\"$instance\", level!=\"info\"}[$__rate_interval])) by (job, level) > 0", + "format": "time_series", + "hide": false, + "interval": "5m", + "intervalFactor": 1, + "legendFormat": "{{job}} - {{level}}", + "range": true, + "refId": "A" + } + ], + "title": "Logging rate", + "type": "timeseries" + }, + { + "collapsed": true, + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 37 + }, + "id": 46, + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Percentage of used RSS memory (resident).\nThe RSS memory shows the amount of memory recently accessed by the application. It includes anonymous memory and data from recently accessed files (aka page cache).\nThe application's performance will significantly degrade when memory usage is close to 100%.\n\nClick on the line and choose Drilldown to show memory usage per instance", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [ + { + "targetBlank": true, + "title": "Drilldown", + "url": "/d/oS7Bi_0Wz?viewPanel=189&var-job=${__field.labels.job}&var-ds=$ds&var-instance=$instance&${__url_time_range}" + } + ], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 38 + }, + "id": 66, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": true, + "expr": "max(\n max_over_time(process_resident_memory_bytes{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])\n /\n vm_available_memory_bytes{job=~\"$job\", instance=~\"$instance\"}\n) by(job)", + "interval": "", + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "RSS memory % usage ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Share for memory allocated by the process itself. When memory usage reaches 100% it will be likely OOM-killed.\nSafe memory usage % considered to be below 80%\n\nClick on the line and choose Drilldown to show memory usage per instance", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [ + { + "targetBlank": true, + "title": "Drilldown", + "url": "/d/oS7Bi_0Wz?viewPanel=190&var-job=${__field.labels.job}&var-ds=$ds&var-instance=$instance&${__url_time_range}" + } + ], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 38 + }, + "id": 138, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": true, + "expr": "max(\n max_over_time(process_resident_memory_anon_bytes{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])\n /\n vm_available_memory_bytes{job=~\"$job\", instance=~\"$instance\"}\n) by(job)", + "interval": "", + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "RSS anonymous memory % usage ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [ + { + "targetBlank": true, + "title": "Drilldown", + "url": "/d/oS7Bi_0Wz?viewPanel=192&var-job=${__field.labels.job}&var-ds=$ds&var-instance=$instance&${__url_time_range}" + } + ], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 46 + }, + "id": 64, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": true, + "expr": "max(\n rate(process_cpu_seconds_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])\n /\n vm_available_cpu_cores{job=~\"$job\", instance=~\"$instance\"}\n) by(job)", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "CPU ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Shows the number of bytes read/write from the storage layer.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "Bps" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": "/read .*/" + }, + "properties": [ + { + "id": "custom.transform", + "value": "negative-Y" + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 46 + }, + "id": 122, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(rate(process_io_storage_read_bytes_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by(job) > 0", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "read {{job}}", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "sum(rate(process_io_storage_written_bytes_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by(job) > 0", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "write {{job}}", + "range": true, + "refId": "B" + } + ], + "title": "Disk writes/reads ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Shows the percentage of open file descriptors compared to the limit set in the OS.\nReaching the limit of open files can cause various issues and must be prevented.\n\nSee how to change limits here https://medium.com/@muhammadtriwibowo/set-permanently-ulimit-n-open-files-in-ubuntu-4d61064429a", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 2, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": "/max.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#C4162A", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 54 + }, + "id": 117, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": true, + "expr": "max(\n max_over_time(process_open_fds{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])\n /\n process_max_fds{job=~\"$job\", instance=~\"$instance\"}\n) by(job)", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "{{job}}", + "range": true, + "refId": "A" + } + ], + "title": "Open FDs usage % ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Shows the number of read/write syscalls such as read, pread, write, pwrite.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": "/read .*/" + }, + "properties": [ + { + "id": "custom.transform", + "value": "negative-Y" + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 54 + }, + "id": 204, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(rate(process_io_read_syscalls_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by(job) > 0", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "read {{job}}", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "sum(rate(process_io_write_syscalls_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by(job) > 0", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "write {{job}}", + "range": true, + "refId": "B" + } + ], + "title": "Disk write/read calls ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 0, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 62 + }, + "id": 68, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(max_over_time(go_goroutines{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by(job)", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "Goroutines ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 62 + }, + "id": 119, + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(max_over_time(vm_tcplistener_conns{job=~\"$job\", instance=~\"$instance\"}[$__interval])) by(job)", + "interval": "", + "legendFormat": "{{job}}", + "range": true, + "refId": "A" + } + ], + "title": "TCP connections ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 0, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 70 + }, + "id": 70, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(max_over_time(process_num_threads{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by(job)", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "Threads ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 70 + }, + "id": 120, + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(rate(vm_tcplistener_accepts_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by(job)", + "interval": "", + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "TCP connections rate ($instance)", + "type": "timeseries" + } + ], + "title": "Resource usage ($job)", + "type": "row" + }, + { + "collapsed": true, + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 38 + }, + "id": 106, + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Shows the rate and total number of new series created over last 24h.\n\nHigh churn rate tightly connected with database performance and may result in unexpected OOM's or slow queries. It is recommended to always keep an eye on this metric to avoid unexpected cardinality \"explosions\".\n\nThe higher churn rate is, the more resources required to handle it. Consider to keep the churn rate as low as possible.\n\nTo investigate stats about most expensive series use `api/v1/status/tsdb` handler. More details here https://docs.victoriametrics.com/Cluster-VictoriaMetrics.html#url-format\n\nGood references to read:\n* https://www.robustperception.io/cardinality-is-key\n* https://valyala.medium.com/high-cardinality-tsdb-benchmarks-victoriametrics-vs-timescaledb-vs-influxdb-13e6ee64dd6b", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "new series over 24h" + }, + "properties": [ + { + "id": "custom.axisPlacement", + "value": "right" + }, + { + "id": "custom.axisSoftMin", + "value": 0 + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 31 + }, + "id": 102, + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "exemplar": true, + "expr": "sum(rate(vm_new_timeseries_created_total{job=~\"$job_storage\", instance=~\"$instance\"}[$__rate_interval]))", + "interval": "", + "legendFormat": "churn rate", + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "exemplar": true, + "expr": "sum(increase(vm_new_timeseries_created_total{job=~\"$job_storage\", instance=~\"$instance\"}[24h]))", + "hide": false, + "interval": "", + "legendFormat": "new series over 24h", + "refId": "B" + } + ], + "title": "Churn rate ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "The percentage of slow inserts comparing to total insertion rate during the last 5 minutes. \n\nThe less value is better. If percentage remains high (>10%) during extended periods of time, then it is likely more RAM is needed for optimal handling of the current number of active time series. \n\nIn general, VictoriaMetrics requires ~1KB or RAM per active time series, so it should be easy calculating the required amounts of RAM for the current workload according to capacity planning docs. But the resulting number may be far from the real number because the required amounts of memory depends on many other factors such as the number of labels per time series and the length of label values. See also https://github.com/VictoriaMetrics/VictoriaMetrics/issues/3976#issuecomment-1476883183", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "line+area" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "transparent" + }, + { + "color": "red", + "value": 0.1 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 31 + }, + "id": 108, + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "max(\n rate(vm_slow_row_inserts_total{job=~\"$job_storage\"}[$__rate_interval]) \n / rate(vm_rows_added_to_storage_total{job=~\"$job_storage\"}[$__rate_interval])\n)", + "interval": "", + "legendFormat": "slow inserts", + "range": true, + "refId": "A" + } + ], + "title": "Slow inserts", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "The value is above 0 when the vmstorage at the given `addr` communicates to the given vminsert node that it cannot accept new data because it is in the read-only mode.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 39 + }, + "id": 142, + "links": [ + { + "targetBlank": true, + "title": "Readonly mode", + "url": "https://docs.victoriametrics.com/Cluster-VictoriaMetrics.html#readonly-mode" + } + ], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(vm_rpc_vmstorage_is_read_only{job=~\"$job_insert\", instance=~\"$instance\"}) by(instance, addr) > 0", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "{{instance}} => {{addr}}", + "range": true, + "refId": "A" + } + ], + "title": "Storage in readonly status for vminsert ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Slow queries according to `search.logSlowQueryDuration` flag, which is `5s` by default.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 39 + }, + "id": 107, + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "expr": "sum(rate(vm_slow_queries_total{job=~\"$job_select\", instance=~\"$instance\"}[$__rate_interval]))", + "interval": "", + "legendFormat": "slow queries rate", + "refId": "A" + } + ], + "title": "Slow queries rate ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Merge assist happens when vmstorage can't keep up with merging parts. This is usually a sign of overload for vmstorage.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "bars", + "fillOpacity": 100, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 47 + }, + "id": 170, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(increase(vm_assisted_merges_total{job=~\"$job_storage\", instance=~\"$instance\"}[$__rate_interval])) by(type) > 0", + "format": "time_series", + "interval": "5m", + "intervalFactor": 1, + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "Assisted merges ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "VictoriaMetrics limits the number of labels per each metric with `-maxLabelsPerTimeseries` command-line flag.\n\nThis prevents from ingesting metrics with too many labels. The value of `maxLabelsPerTimeseries` must be adjusted for your workload.\n\nWhen limit is exceeded (graph is > 0) - extra labels are dropped, which could result in unexpected identical time series.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 2, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 47 + }, + "id": 116, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "exemplar": true, + "expr": "sum(increase(vm_metrics_with_dropped_labels_total{job=~\"$job_insert\", instance=~\"$instance\"}[$__rate_interval]))", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "metrics with dropped labels", + "refId": "A" + } + ], + "title": "Labels limit exceeded ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Shows the percentage of used cache size from the allowed size by type. \nValues close to 100% show the maximum potential utilization.\nValues close to 0% show that cache is underutilized.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 55 + }, + "id": 144, + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": true, + "expr": "max(\n vm_cache_size_bytes{job=~\"$job\", instance=~\"$instance\"} \n /\n vm_cache_size_max_bytes{job=~\"$job\", instance=~\"$instance\"}\n) by(type)", + "interval": "", + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "Cache usage % by type ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Shows cache miss ratio. Lower is better.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "max": 1, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 55 + }, + "id": 58, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": true, + "expr": "max(\n rate(vm_cache_misses_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])\n /\n rate(vm_cache_requests_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])\n) by(type)", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "Cache miss ratio ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "displayMode": "auto", + "inspect": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Value" + }, + "properties": [ + { + "id": "custom.hidden", + "value": true + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Time" + }, + "properties": [ + { + "id": "custom.hidden", + "value": true + } + ] + } + ] + }, + "gridPos": { + "h": 7, + "w": 24, + "x": 0, + "y": 64 + }, + "id": 183, + "options": { + "footer": { + "fields": "", + "reducer": [ + "sum" + ], + "show": false + }, + "showHeader": true, + "sortBy": [ + { + "desc": true, + "displayName": "job" + } + ] + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": false, + "expr": "sum(flag{is_set=\"true\", job=~\"$job\", instance=~\"$instance\"}) by(job, instance, name, value)", + "format": "table", + "instant": true, + "legendFormat": "__auto", + "range": false, + "refId": "A" + } + ], + "title": "Non-default flags", + "transformations": [ + { + "id": "groupBy", + "options": { + "fields": { + "instance": { + "aggregations": [ + "uniqueValues" + ], + "operation": "aggregate" + }, + "job": { + "aggregations": [], + "operation": "groupby" + }, + "name": { + "aggregations": [], + "operation": "groupby" + }, + "value": { + "aggregations": [], + "operation": "groupby" + } + } + } + } + ], + "type": "table" + } + ], + "title": "Troubleshooting", + "type": "row" + }, + { + "collapsed": true, + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 39 + }, + "id": 48, + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Shows number of pushed and sent rows. \n* `Pushed rows` - rows added to internal inserter buffers before send\n* `Sent rows` - successfully transmitted rows to storage nodes\n\nPlease note, it could be that `Sent > Pushed` because of the replication factor.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 21 + }, + "id": 76, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "sum(rate(vm_rpc_rows_pushed_total{job=~\"$job\",instance=~\"$instance\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Pushed", + "range": true, + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "sum(rate(vm_rpc_rows_sent_total{job=~\"$job\",instance=~\"$instance\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Sent", + "range": true, + "refId": "E" + } + ], + "title": "Rows ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Rate of RPC errors by type:\n* `Connection` - the number of connection errors to vmstorage node\n* `Dial` - the number of dial errors to vmstorage node.\n* `Handshake` - the number of handshake errors to vmstorage node\n* `Rerouted` - errors appeared during rerouting of rows from un-healthy storage node to a healthy one.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 21 + }, + "id": 86, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "sum(rate(vm_rpc_connection_errors_total{job=~\"$job\",instance=~\"$instance\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Connection", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "expr": "sum(rate(vm_rpc_dial_errors_total{job=~\"$job\",instance=~\"$instance\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Dial", + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "expr": "sum(rate(vm_rpc_handshake_errors_total{job=~\"$job\",instance=~\"$instance\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Handshake", + "refId": "E" + } + ], + "title": "RPC errors ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "The number of rows rerouted to the vmstorage node from other nodes when they were unhealthy.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "rps" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 30 + }, + "id": 80, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(rate(vm_rpc_rows_rerouted_to_here_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by(addr) > 0", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "Rows ($instance) rerouted to ", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "The number of rows rerouted from the vmstorage node to healthy nodes when the given node was unhealthy.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "rps" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 30 + }, + "id": 78, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "exemplar": true, + "expr": "sum(rate(vm_rpc_rows_rerouted_from_here_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by(addr) > 0", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "{{addr}}", + "refId": "A" + } + ], + "title": "Rows ($instance) rerouted from", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "The number of rows or bytes that vminesrt internal buffer contains at the moment.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "bytes" + }, + "properties": [ + { + "id": "unit", + "value": "bytes" + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 38 + }, + "id": 82, + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "expr": "sum(vm_rpc_buf_pending_bytes{job=~\"$job\", instance=~\"$instance\"})", + "legendFormat": "bytes", + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "expr": "sum(vm_rpc_rows_pending{job=~\"$job\", instance=~\"$instance\"})", + "legendFormat": "rows", + "refId": "B" + } + ], + "title": "Pending", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Network usage by internal VictoriaMetrics RPC protocol", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bps" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 38 + }, + "id": 74, + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "sum(rate(vm_tcpdialer_written_bytes_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) * 8", + "legendFormat": "network usage", + "range": true, + "refId": "A" + } + ], + "title": "RPC network usage ($instance)", + "type": "timeseries" + } + ], + "title": "Interconnection ($job)", + "type": "row" + }, + { + "collapsed": true, + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 40 + }, + "id": 24, + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Shows the number of datapoints ingested into storage nodes per second. This metric doesn't show all stored datapoints since some of them may be dropped because of wrong timestamps or decode errors.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 6 + }, + "id": 100, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "sum(rate(vm_vminsert_metrics_read_total{job=~\"$job_storage\", instance=~\"$instance\"}[$__rate_interval])) ", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "ingestion rate", + "range": true, + "refId": "A" + } + ], + "title": "Ingestion rate ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Shows the approx time needed to reach 100% of disk capacity for at least one vmstorage node based on the following params:\n* free disk space;\n* row ingestion rate;\n* dedup rate;\n* compression.\n\nUse this panel for capacity planning in order to estimate the time remaining for running out of the disk space.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [ + { + "targetBlank": true, + "title": "Drilldown", + "url": "/d/oS7Bi_0Wz?viewPanel=196&${__url_time_range}&${__all_variables}" + } + ], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 6 + }, + "id": 113, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "min(vm_free_disk_space_bytes{job=~\"$job_storage\", instance=~\"$instance\"} \n/ \nignoring(path) (\n (\n rate(vm_rows_added_to_storage_total{job=~\"$job_storage\", instance=~\"$instance\"}[1d])\n - \n ignoring(type) rate(vm_deduplicated_samples_total{job=~\"$job_storage\", instance=~\"$instance\", type=\"merge\"}[1d])\n ) * scalar(\n sum(vm_data_size_bytes{job=~\"$job_storage\", instance=~\"$instance\", type!~\"indexdb.*\"})\n / \n sum(vm_rows{job=~\"$job_storage\", instance=~\"$instance\", type!~\"indexdb.*\"})\n )\n))", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "min ETA", + "range": true, + "refId": "A" + } + ], + "title": "Storage full ETA ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "line" + } + }, + "links": [ + { + "targetBlank": true, + "title": "Drilldown", + "url": "/d/oS7Bi_0Wz?viewPanel=192&var-job=$job_storage&var-ds=$ds&var-instance=$instance&${__url_time_range}" + } + ], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 0.9 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 14 + }, + "id": 151, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": false, + "expr": "max(\n rate(process_cpu_seconds_total{job=~\"$job_storage\", instance=~\"$instance\"}[$__rate_interval])\n /\n process_cpu_cores_available{job=~\"$job_storage\", instance=~\"$instance\"}\n)", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "max", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": false, + "expr": "min(\n rate(process_cpu_seconds_total{job=~\"$job_storage\", instance=~\"$instance\"}[$__rate_interval])\n /\n process_cpu_cores_available{job=~\"$job_storage\", instance=~\"$instance\"}\n)", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "min", + "range": true, + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": false, + "expr": "quantile(0.5,\n rate(process_cpu_seconds_total{job=~\"$job_storage\", instance=~\"$instance\"}[$__rate_interval])\n /\n process_cpu_cores_available{job=~\"$job_storage\", instance=~\"$instance\"}\n)", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "median", + "range": true, + "refId": "C" + } + ], + "title": "CPU usage % ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Percentage of used memory (resident).\nThe application's performance will significantly degrade when memory usage is close to 100%.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "line" + } + }, + "links": [ + { + "targetBlank": true, + "title": "Drilldown", + "url": "/d/oS7Bi_0Wz?viewPanel=189&var-job=$job_storage&var-ds=$ds&var-instance=$instance&${__url_time_range}" + } + ], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 0.9 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 14 + }, + "id": 167, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": true, + "expr": "max(\n max_over_time(process_resident_memory_bytes{job=~\"$job_storage\", instance=~\"$instance\"}[$__rate_interval])\n /\n vm_available_memory_bytes{job=~\"$job_storage\", instance=~\"$instance\"}\n)", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "max", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": true, + "expr": "min(\n max_over_time(process_resident_memory_bytes{job=~\"$job_storage\", instance=~\"$instance\"}[$__rate_interval])\n /\n vm_available_memory_bytes{job=~\"$job_storage\", instance=~\"$instance\"}\n)", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "min", + "range": true, + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": true, + "expr": "quantile(0.5,\n max_over_time(process_resident_memory_bytes{job=~\"$job_storage\", instance=~\"$instance\"}[$__rate_interval])\n /\n vm_available_memory_bytes{job=~\"$job_storage\", instance=~\"$instance\"}\n)", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "median", + "range": true, + "refId": "C" + } + ], + "title": "Memory usage % ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Value > 0 means vmstorage is in readonly mode.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 21 + }, + "id": 141, + "links": [ + { + "targetBlank": true, + "title": "Readonly mode", + "url": "https://docs.victoriametrics.com/Cluster-VictoriaMetrics.html#readonly-mode" + } + ], + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": true, + "expr": "vm_storage_is_read_only{job=~\"$job_storage\", instance=~\"$instance\"} > 0", + "interval": "", + "legendFormat": "{{ instance }}", + "range": true, + "refId": "A" + } + ], + "title": "Readonly mode", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Shows how many ongoing insertions (not API /write calls) on disk are taking place, where:\n* `max` - equal to number of CPUs;\n* `current` - current number of goroutines busy with inserting rows into underlying storage.\n\nEvery successful API /write call results into flush on disk. The `max` is an internal limit and can't be changed. It is always equal to the number of CPUs. \n\nWhen `current` hits `max` constantly, it means storage is overloaded and requires more CPU or faster disk.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "max" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#C4162A", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 21 + }, + "id": 133, + "links": [ + { + "targetBlank": true, + "title": "Related discussion", + "url": "https://github.com/VictoriaMetrics/VictoriaMetrics/issues/632" + } + ], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": true, + "expr": "max(\n max_over_time(vm_concurrent_insert_current{job=~\"$job_storage\", \n instance=~\"$instance\"}[$__rate_interval])\n)", + "interval": "", + "legendFormat": "current", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": true, + "expr": "min(vm_concurrent_insert_capacity{job=~\"$job_storage\", instance=~\"$instance\"})", + "hide": false, + "interval": "", + "legendFormat": "max", + "range": true, + "refId": "B" + } + ], + "title": "Concurrent flushes on disk ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "The number of on-going merges in storage nodes. It is expected to have high numbers for `storage/small` metric.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 0, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 29 + }, + "id": 54, + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "sum(max_over_time(vm_active_merges{job=~\"$job_storage\", instance=~\"$instance\"}[$__rate_interval])) by(type)", + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "Active merges ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "The number of rows merged per second by storage nodes.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 0, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 29 + }, + "id": 55, + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "sum(rate(vm_rows_merged_total{job=~\"$job_storage\", instance=~\"$instance\"}[$__rate_interval])) by(type)", + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "Merge speed", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Shows the percentage of used disk space. It is recommended to have at least 20% of free disk space for the best performance.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "line" + } + }, + "links": [ + { + "targetBlank": true, + "title": "Drilldown", + "url": "/d/oS7Bi_0Wz?viewPanel=200&var-ds=$ds&var-instance=$instance&${__url_time_range}" + } + ], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 37 + }, + "id": 20, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "max(\n sum(vm_data_size_bytes{job=~\"$job\", instance=~\"$instance\"}) by(job, instance) /\n (\n sum(vm_free_disk_space_bytes{job=~\"$job\", instance=~\"$instance\"}) by(job, instance) +\n sum(vm_data_size_bytes{job=~\"$job\", instance=~\"$instance\"}) by(job, instance)\n ) \n)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "max", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "min(\n sum(vm_data_size_bytes{job=~\"$job\", instance=~\"$instance\"}) by(job, instance) /\n (\n sum(vm_free_disk_space_bytes{job=~\"$job\", instance=~\"$instance\"}) by(job, instance) +\n sum(vm_data_size_bytes{job=~\"$job\", instance=~\"$instance\"}) by(job, instance)\n ) \n)", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "min", + "range": true, + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "quantile(0.5,\n sum(vm_data_size_bytes{job=~\"$job\", instance=~\"$instance\"}) by(job, instance) /\n (\n sum(vm_free_disk_space_bytes{job=~\"$job\", instance=~\"$instance\"}) by(job, instance) +\n sum(vm_data_size_bytes{job=~\"$job\", instance=~\"$instance\"}) by(job, instance)\n ) \n)", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "median", + "range": true, + "refId": "C" + } + ], + "title": "Disk space usage % ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "The max number of data parts of LSM tree across all storage nodes.\nHigh number of parts (the hard limit is 512) is an evidence of slow merge performance - check the resource utilization.\n* `indexdb` - inverted index\n* `storage/small` - recently added parts of data ingested into storage (hot data)\n* `storage/big` - small parts gradually merged into big parts (cold data)", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 37 + }, + "id": 22, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "max(vm_parts{job=~\"$job_storage\", instance=~\"$instance\"}) by(type)", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "LSM parts max by type ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Shows the percentage of used disk space by type: datapoints or indexdb. Normally, indexdb takes much less space comparing to datapoints. But with high churn rate the size of the indexdb could grow significantly.\n\nThe sum of the % can be > 100% since panel shows max % per-job and per-instance. It means different instance can have different ratio between datapoints and indexdb size.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "line" + } + }, + "links": [ + { + "targetBlank": true, + "title": "Drilldown", + "url": "/d/oS7Bi_0Wz?viewPanel=201&var-ds=$ds&var-instance=$instance&${__url_time_range}" + } + ], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 45 + }, + "id": 202, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "max(\n sum(vm_data_size_bytes{job=~\"$job\", instance=~\"$instance\", type=~\"indexdb.*\"}) by(job, instance)\n / \n sum(vm_data_size_bytes{job=~\"$job\", instance=~\"$instance\"}) by(job, instance)\n)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "indexdb", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "max(\n sum(vm_data_size_bytes{job=~\"$job\", instance=~\"$instance\", type!~\"indexdb.*\"}) by(job, instance)\n / \n sum(vm_data_size_bytes{job=~\"$job\", instance=~\"$instance\"}) by(job, instance)\n)", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "datapoints", + "range": true, + "refId": "B" + } + ], + "title": "Disk space usage % by type ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "How many datapoints are in RAM queue waiting to be written into storage. The number of pending data points should be in the range from 0 to `2*`, since VictoriaMetrics pushes pending data to persistent storage every second. The index datapoints value in general is much lower.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "pending index entries" + }, + "properties": [ + { + "id": "unit", + "value": "none" + }, + { + "id": "decimals", + "value": 3 + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 45 + }, + "id": 14, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "sum(max_over_time(vm_pending_rows{job=~\"$job_storage\", instance=~\"$instance\", type=\"storage\"}[$__rate_interval]))", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "pending datapoints", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "sum(max_over_time(vm_pending_rows{job=~\"$job_storage\", instance=~\"$instance\", type=\"indexdb\"}[$__rate_interval]))", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "pending index entries", + "range": true, + "refId": "B" + } + ], + "title": "Pending datapoints ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Shows how many rows were ignored on insertion due to corrupted or out of retention timestamps.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 53 + }, + "id": 135, + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(increase(vm_rows_ignored_total{job=~\"$job_storage\", instance=~\"$instance\"}[1h])) by (reason)", + "interval": "", + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "Rows ignored for last 1h ($instance)", + "type": "timeseries" + } + ], + "title": "vmstorage ($instance)", + "type": "row" + }, + { + "collapsed": true, + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 41 + }, + "id": 42, + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Request rate accepted by vmselect nodes", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 98 + }, + "id": 92, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "sum(rate(vm_http_requests_total{job=~\"$job_select\", instance=~\"$instance\"}[$__rate_interval])) by (path) > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "Requests rate ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Shows the max number of concurrent selects across instances.\n* `max` limit can be configured via `search.maxConcurrentRequests` flag\n* `current` shows the current number of goroutines busy with processing requests\n\nWhen `current` hits `max` constantly, it means one or more vmselect nodes are overloaded with number of requests. If you observe that CPU for vmselects is saturated, consider adding more vmselect replicas or increase CPU resources. If CPU panel shows a plenty of free resources - try increasing `search.maxConcurrentRequests`.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 0, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "max" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#C4162A", + "mode": "fixed" + } + }, + { + "id": "custom.fillOpacity", + "value": 0 + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 98 + }, + "id": 95, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "max(max_over_time(vm_concurrent_select_current{job=~\"$job_select\", instance=~\"$instance\"}[$__rate_interval])) ", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "current", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "expr": "min(vm_concurrent_select_capacity{job=~\"$job_select\", instance=~\"$instance\"})", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "max", + "refId": "B" + } + ], + "title": "Concurrent selects ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "line" + } + }, + "links": [ + { + "targetBlank": true, + "title": "Drilldown", + "url": "/d/oS7Bi_0Wz?viewPanel=192&var-job=$job_select&var-ds=$ds&var-instance=$instance&${__url_time_range}" + } + ], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 0.9 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 106 + }, + "id": 163, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": true, + "expr": "max(\n rate(process_cpu_seconds_total{job=~\"$job_select\", instance=~\"$instance\"}[$__rate_interval])\n /\n process_cpu_cores_available{job=~\"$job_select\", instance=~\"$instance\"}\n)", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "max", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": true, + "expr": "min(\n rate(process_cpu_seconds_total{job=~\"$job_select\", instance=~\"$instance\"}[$__rate_interval])\n /\n process_cpu_cores_available{job=~\"$job_select\", instance=~\"$instance\"}\n)", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "min", + "range": true, + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": true, + "expr": "quantile(0.5,\n rate(process_cpu_seconds_total{job=~\"$job_select\", instance=~\"$instance\"}[$__rate_interval])\n /\n process_cpu_cores_available{job=~\"$job_select\", instance=~\"$instance\"}\n)", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "median", + "range": true, + "refId": "C" + } + ], + "title": "CPU usage % ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "line" + } + }, + "links": [ + { + "targetBlank": true, + "title": "Drilldown", + "url": "/d/oS7Bi_0Wz?viewPanel=189&var-job=$job_select&var-ds=$ds&var-instance=$instance&${__url_time_range}" + } + ], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 0.9 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 106 + }, + "id": 165, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": true, + "expr": "max(\n max_over_time(process_resident_memory_bytes{job=~\"$job_select\", instance=~\"$instance\"}[$__rate_interval])\n /\n vm_available_memory_bytes{job=~\"$job_select\", instance=~\"$instance\"}\n)", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "max", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": true, + "expr": "min(\n max_over_time(process_resident_memory_bytes{job=~\"$job_select\", instance=~\"$instance\"}[$__rate_interval])\n /\n vm_available_memory_bytes{job=~\"$job_select\", instance=~\"$instance\"}\n)", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "min", + "range": true, + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": true, + "expr": "quantile(0.5,\n max_over_time(process_resident_memory_bytes{job=~\"$job_select\", instance=~\"$instance\"}[$__rate_interval])\n /\n vm_available_memory_bytes{job=~\"$job_select\", instance=~\"$instance\"}\n)", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "median", + "range": true, + "refId": "C" + } + ], + "title": "Memory usage % ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "99th percentile of the number of time series read per query.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 2, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 114 + }, + "id": 178, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "sum(histogram_quantile(0.99, sum(rate(vm_series_read_per_query_bucket{job=~\"$job_select\", instance=~\"$instance\"}[$__rate_interval])) by (instance, vmrange)))", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "series", + "range": true, + "refId": "A" + } + ], + "title": "Series read per query ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "99th percentile of number of raw datapoints read per queried time series.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 2, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 114 + }, + "id": 180, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "sum(histogram_quantile(0.99, sum(rate(vm_rows_read_per_series_bucket{job=~\"$job_select\", instance=~\"$instance\"}[$__rate_interval])) by (instance, vmrange)))", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "datapoints", + "range": true, + "refId": "A" + } + ], + "title": "Datapoints read per series ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "99th percentile of number of raw datapoints read per query.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 2, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 122 + }, + "id": 179, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "sum(histogram_quantile(0.99, sum(rate(vm_rows_read_per_query_bucket{job=~\"$job_select\", instance=~\"$instance\"}[$__rate_interval])) by (instance, vmrange)))", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "datapoints", + "range": true, + "refId": "A" + } + ], + "title": "Datapoints read per query ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "99th percentile of number of raw datapoints scanner per query.\n\nThis number can exceed number of DatapointsReadPerQuery if `step` query arg passed to [/api/v1/query_range](https://prometheus.io/docs/prometheus/latest/querying/api/#range-queries) is smaller than the lookbehind window set in square brackets of [rollup function](https://docs.victoriametrics.com/MetricsQL.html#rollup-functions). For example, if `increase(some_metric[1h])` is executed with the `step=5m`, then the same raw samples on a hour time range are scanned `1h/5m=12` times. See [this article](https://valyala.medium.com/how-to-optimize-promql-and-metricsql-queries-85a1b75bf986) for details.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 2, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 122 + }, + "id": 181, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "sum(histogram_quantile(0.99, sum(rate(vm_rows_scanned_per_query_bucket{job=~\"$job_select\", instance=~\"$instance\"}[$__rate_interval])) by (instance, vmrange)))", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "datapoints", + "range": true, + "refId": "A" + } + ], + "title": "Datapoints scanned per query ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bps" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": "/read.*/" + }, + "properties": [ + { + "id": "custom.transform", + "value": "negative-Y" + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 24, + "x": 0, + "y": 130 + }, + "id": 93, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "sum(rate(vm_tcplistener_read_bytes_total{job=~\"$job_select\", instance=~\"$instance\"}[$__rate_interval])) * 8 > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "read", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "sum(rate(vm_tcplistener_written_bytes_total{job=~\"$job_select\", instance=~\"$instance\"}[$__rate_interval])) * 8 > 0", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "write ", + "range": true, + "refId": "B" + } + ], + "title": "Network usage ($instance)", + "type": "timeseries" + } + ], + "title": "vmselect ($instance)", + "type": "row" + }, + { + "collapsed": true, + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 42 + }, + "id": 40, + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "* `*` - unsupported query path\n* `/write` - insert into VM\n* `/metrics` - query VM system metrics\n* `/query` - query instant values\n* `/query_range` - query over a range of time\n* `/series` - match a certain label set\n* `/label/{}/values` - query a list of label values (variables mostly)", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 24 + }, + "id": 97, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "sum(rate(vm_http_requests_total{job=~\"$job_insert\", instance=~\"$instance\"}[$__rate_interval])) by (path) > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "Requests rate ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Shows the max number of ongoing insertions.\n* `max` - equal to number of CPU * 2 by default. May be configured with `maxConcurrentInserts` flag;\n* `current` - current number of goroutines busy with processing requests.\n\n`-maxConcurrentInserts` limits the number of insert requests which may be actively processed at any given point in time. All the other insert requests are queued for up to `-insert.maxQueueDuration` in the hope they will get a chance to be processed. This queue is used mostly for absorbing spikes for incoming insert request rate.\n\nWhen `current` hits `max` constantly, it means vminsert node is overloaded and requires more CPU or higher limits.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 0, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "max" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#C4162A", + "mode": "fixed" + } + }, + { + "id": "custom.fillOpacity", + "value": 0 + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 24 + }, + "id": 99, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "max(max_over_time(vm_concurrent_insert_current{job=~\"$job_insert\", instance=~\"$instance\"}[$__rate_interval]))", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "current", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "exemplar": true, + "expr": "min(vm_concurrent_insert_capacity{job=~\"$job_insert\", instance=~\"$instance\"})", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "max", + "refId": "B" + } + ], + "title": "Concurrent inserts ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "line" + } + }, + "links": [ + { + "targetBlank": true, + "title": "Drilldown", + "url": "/d/oS7Bi_0Wz?viewPanel=192&var-job=$job_insert&var-ds=$ds&var-instance=$instance&${__url_time_range}" + } + ], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 0.9 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 32 + }, + "id": 185, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": true, + "expr": "max(\n rate(process_cpu_seconds_total{job=~\"$job_insert\", instance=~\"$instance\"}[$__rate_interval])\n /\n process_cpu_cores_available{job=~\"$job_insert\", instance=~\"$instance\"}\n)", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "max", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": true, + "expr": "min(\n rate(process_cpu_seconds_total{job=~\"$job_insert\", instance=~\"$instance\"}[$__rate_interval])\n /\n process_cpu_cores_available{job=~\"$job_insert\", instance=~\"$instance\"}\n)", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "min", + "range": true, + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": true, + "expr": "quantile(0.5,\n rate(process_cpu_seconds_total{job=~\"$job_insert\", instance=~\"$instance\"}[$__rate_interval])\n /\n process_cpu_cores_available{job=~\"$job_insert\", instance=~\"$instance\"}\n)", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "median", + "range": true, + "refId": "C" + } + ], + "title": "CPU usage % ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "line" + } + }, + "links": [ + { + "targetBlank": true, + "title": "Drilldown", + "url": "/d/oS7Bi_0Wz?viewPanel=189&var-job=$job_insert&var-ds=$ds&var-instance=$instance&${__url_time_range}" + } + ], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 0.9 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 32 + }, + "id": 187, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": true, + "expr": "max(\n max_over_time(process_resident_memory_bytes{job=~\"$job_insert\", instance=~\"$instance\"}[$__rate_interval])\n /\n vm_available_memory_bytes{job=~\"$job_insert\", instance=~\"$instance\"}\n)", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "max", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": true, + "expr": "min(\n max_over_time(process_resident_memory_bytes{job=~\"$job_insert\", instance=~\"$instance\"}[$__rate_interval])\n /\n vm_available_memory_bytes{job=~\"$job_insert\", instance=~\"$instance\"}\n)", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "min", + "range": true, + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": true, + "expr": "quantile(0.5,\n max_over_time(process_resident_memory_bytes{job=~\"$job_insert\", instance=~\"$instance\"}[$__rate_interval])\n /\n vm_available_memory_bytes{job=~\"$job_insert\", instance=~\"$instance\"}\n)", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "median", + "range": true, + "refId": "C" + } + ], + "title": "Memory usage % ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bps" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 40 + }, + "id": 90, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(rate(vm_tcplistener_read_bytes_total{job=~\"$job_insert\", instance=~\"$instance\"}[$__rate_interval])) * 8 > 0", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "read", + "range": true, + "refId": "A" + } + ], + "title": "Network usage ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 2, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 40 + }, + "id": 88, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "max(histogram_quantile(0.99, sum(increase(vm_rows_per_insert_bucket{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by (instance, vmrange)))", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "max", + "range": true, + "refId": "A" + } + ], + "title": "Rows per insert ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Shows the saturation level of connection between vminsert and vmstorage components. If the threshold of 0.9sec is reached, then the connection is saturated by more than 90% and vminsert won't be able to keep up. This usually means that more vminsert or vmstorage nodes must be added to the cluster in order to increase the total number of vminsert -> vmstorage links.\n", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "line+area" + } + }, + "decimals": 0, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "transparent" + }, + { + "color": "red", + "value": 0.9 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 48 + }, + "id": 139, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": true, + "expr": "max(rate(vm_rpc_send_duration_seconds_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by(addr)", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "Storage connection saturation ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Shows when vmstorage node is unreachable for vminsert.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 0, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 48 + }, + "id": 114, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "vm_rpc_vmstorage_is_reachable{job=~\"$job\", instance=~\"$instance\"} != 1", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "{{instance}} => {{addr}}", + "range": true, + "refId": "A" + } + ], + "title": "Storage reachability ($instance)", + "type": "timeseries" + } + ], + "title": "vminsert ($instance)", + "type": "row" + }, + { + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 43 + }, + "id": 194, + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "gridPos": { + "h": 2, + "w": 24, + "x": 0, + "y": 84 + }, + "id": 198, + "options": { + "code": { + "language": "plaintext", + "showLineNumbers": false, + "showMiniMap": false + }, + "content": "Drilldown row is used by other panels on the dashboard to show more detailed metrics per-instance.", + "mode": "markdown" + }, + "pluginVersion": "9.2.7", + "transparent": true, + "type": "text" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Shows the used memory (resident).\nThe application's performance will significantly degrade when memory usage is close to 100%.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "decbytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 86 + }, + "id": 189, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": true, + "expr": "max_over_time(process_resident_memory_bytes{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])", + "interval": "", + "legendFormat": "{{instance}} ({{job}})", + "range": true, + "refId": "A" + } + ], + "title": "RSS memory usage ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "RSS share for memory allocated by the process itself. This share cannot be freed by the OS, so it must be taken into account by OOM killer.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "decbytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 86 + }, + "id": 190, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": true, + "expr": "max_over_time(process_resident_memory_anon_bytes{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])", + "interval": "", + "legendFormat": "{{instance}} ({{job}})", + "range": true, + "refId": "A" + } + ], + "title": "RSS anonymous memory usage ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 94 + }, + "id": 192, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": false, + "expr": "sum(rate(process_cpu_seconds_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by(job, instance)", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "{{instance}} ({{job}})", + "range": true, + "refId": "A" + } + ], + "title": "CPU usage ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Shows the approx time needed to reach 100% of disk capacity based on the following params:\n* free disk space;\n* row ingestion rate;\n* dedup rate;\n* compression.\n\nUse this panel for capacity planning in order to estimate the time remaining for running out of the disk space.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 94 + }, + "id": 196, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "vm_free_disk_space_bytes{job=~\"$job_storage\", instance=~\"$instance\"} \n/ \nignoring(path) (\n (\n rate(vm_rows_added_to_storage_total{job=~\"$job_storage\", instance=~\"$instance\"}[1d])\n - \n ignoring(type) rate(vm_deduplicated_samples_total{job=~\"$job_storage\", instance=~\"$instance\", type=\"merge\"}[1d])\n ) * scalar(\n sum(vm_data_size_bytes{job=~\"$job_storage\", instance=~\"$instance\", type!~\"indexdb.*\"})\n / \n sum(vm_rows{job=~\"$job_storage\", instance=~\"$instance\", type!~\"indexdb.*\"})\n )\n)", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "{{instance}}", + "range": true, + "refId": "A" + } + ], + "title": "Storage full ETA ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Shows the percentage of used disk space. It is recommended to have at least 20% of free disk space for the best performance.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "line" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "decbytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 101 + }, + "id": 200, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "sum(vm_data_size_bytes{job=~\"$job\", instance=~\"$instance\"}) by(job, instance)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "", + "range": true, + "refId": "A" + } + ], + "title": "Disk space usage ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "line" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "decbytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 101 + }, + "id": 201, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "sum(vm_data_size_bytes{job=~\"$job\", instance=~\"$instance\", type=~\"indexdb.*\"}) by(job, instance)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{job}}:{{instance}} (indexdb)", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "sum(vm_data_size_bytes{job=~\"$job\", instance=~\"$instance\", type!~\"indexdb.*\"}) by(job, instance)", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "{{job}}:{{instance}} (datapoints)", + "range": true, + "refId": "B" + } + ], + "title": "Disk space usage by type ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Shows the rate of logging the messages by their level. Unexpected spike in rate is a good reason to check logs.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "bars", + "fillOpacity": 100, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 109 + }, + "id": 203, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(rate(vm_log_messages_total{job=~\"$job\",instance=~\"$instance\", level!=\"info\"}[$__rate_interval])) by (job, instance, level, location) > 0", + "format": "time_series", + "hide": false, + "interval": "5m", + "intervalFactor": 1, + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "Logging rate", + "type": "timeseries" + } + ], + "title": "Drilldown", + "type": "row" + } + ], + "refresh": false, + "schemaVersion": 37, + "style": "dark", + "tags": [], + "templating": { + "list": [ + { + "current": { + "selected": true, + "text": "VictoriaMetrics", + "value": "VictoriaMetrics" + }, + "hide": 0, + "includeAll": false, + "multi": false, + "name": "ds", + "options": [], + "query": "prometheus", + "queryValue": "", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + }, + { + "current": {}, + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "definition": "label_values(vm_app_version{version=~\"^vm(insert|select|storage).*\"}, job)", + "hide": 0, + "includeAll": true, + "multi": true, + "name": "job", + "options": [], + "query": { + "query": "label_values(vm_app_version{version=~\"^vm(insert|select|storage).*\"}, job)", + "refId": "VictoriaMetrics-job-Variable-Query" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "current": {}, + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "definition": "label_values(vm_app_version{job=~\"$job\", version=~\"^vminsert.*\"}, job)", + "hide": 2, + "includeAll": true, + "multi": true, + "name": "job_insert", + "options": [], + "query": { + "query": "label_values(vm_app_version{job=~\"$job\", version=~\"^vminsert.*\"}, job)", + "refId": "StandardVariableQuery" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "current": {}, + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "definition": "label_values(vm_app_version{job=~\"$job\", version=~\"^vmselect.*\"}, job)", + "hide": 2, + "includeAll": true, + "multi": true, + "name": "job_select", + "options": [], + "query": { + "query": "label_values(vm_app_version{job=~\"$job\", version=~\"^vmselect.*\"}, job)", + "refId": "StandardVariableQuery" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "current": {}, + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "definition": "label_values(vm_app_version{job=~\"$job\", version=~\"^vmstorage.*\"}, job)", + "hide": 2, + "includeAll": true, + "multi": true, + "name": "job_storage", + "options": [], + "query": { + "query": "label_values(vm_app_version{job=~\"$job\", version=~\"^vmstorage.*\"}, job)", + "refId": "StandardVariableQuery" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": ".*", + "current": {}, + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "definition": "label_values(vm_app_version{job=~\"$job\"}, instance)", + "hide": 0, + "includeAll": true, + "multi": true, + "name": "instance", + "options": [], + "query": { + "query": "label_values(vm_app_version{job=~\"$job\"}, instance)", + "refId": "VictoriaMetrics-instance-Variable-Query" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "filters": [], + "hide": 0, + "name": "adhoc", + "skipUrlSync": false, + "type": "adhoc" + } + ] + }, + "time": { + "from": "now-3h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "", + "title": "VictoriaMetrics - cluster", + "uid": "oS7Bi_0Wz", + "version": 1, + "weekStart": "" +} diff --git a/dashboards/victoria-metrics/victoriametrics.json b/dashboards/victoria-metrics/victoriametrics.json new file mode 100644 index 00000000..65cbd553 --- /dev/null +++ b/dashboards/victoria-metrics/victoriametrics.json @@ -0,0 +1,5587 @@ +{ + "__inputs": [], + "__elements": {}, + "__requires": [ + { + "type": "grafana", + "id": "grafana", + "name": "Grafana", + "version": "9.2.7" + }, + { + "type": "datasource", + "id": "prometheus", + "name": "Prometheus", + "version": "1.0.0" + }, + { + "type": "panel", + "id": "stat", + "name": "Stat", + "version": "" + }, + { + "type": "panel", + "id": "table", + "name": "Table", + "version": "" + }, + { + "type": "panel", + "id": "text", + "name": "Text", + "version": "" + }, + { + "type": "panel", + "id": "timeseries", + "name": "Time series", + "version": "" + } + ], + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "target": { + "limit": 100, + "matchAny": false, + "tags": [], + "type": "dashboard" + }, + "type": "dashboard" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "enable": true, + "expr": "sum(ALERTS{job=~\"$job\", instance=~\"$instance\", alertgroup=\"vmsingle\",alertstate=\"firing\",show_at=\"dashboard\"}) by(alertname)", + "iconColor": "red", + "name": "alerts", + "titleFormat": "{{alertname}}" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "enable": true, + "expr": "sum(vm_app_version{job=~\"$job\", instance=~\"$instance\"}) by(version) unless (sum(vm_app_version{job=~\"$job\", instance=~\"$instance\"} offset 20m) by(short_versionversion))", + "hide": true, + "iconColor": "dark-blue", + "name": "version", + "textFormat": "{{version}}", + "titleFormat": "Version change" + } + ] + }, + "description": "Overview for single node VictoriaMetrics v1.83.0 or higher", + "editable": true, + "fiscalYearStartMonth": 0, + "gnetId": 10229, + "graphTooltip": 1, + "id": null, + "links": [ + { + "icon": "doc", + "tags": [], + "targetBlank": true, + "title": "Single server Wiki", + "type": "link", + "url": "https://docs.victoriametrics.com/" + }, + { + "icon": "external link", + "tags": [], + "targetBlank": true, + "title": "Found a bug?", + "type": "link", + "url": "https://github.com/VictoriaMetrics/VictoriaMetrics/issues" + }, + { + "icon": "external link", + "tags": [], + "targetBlank": true, + "title": "New releases", + "tooltip": "", + "type": "link", + "url": "https://github.com/VictoriaMetrics/VictoriaMetrics/releases" + } + ], + "liveNow": false, + "panels": [ + { + "collapsed": false, + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 6, + "panels": [], + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "refId": "A" + } + ], + "title": "Stats", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "", + "gridPos": { + "h": 2, + "w": 4, + "x": 0, + "y": 1 + }, + "id": 85, + "options": { + "code": { + "language": "plaintext", + "showLineNumbers": false, + "showMiniMap": false + }, + "content": "
$version
", + "mode": "markdown" + }, + "pluginVersion": "9.2.7", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "refId": "A" + } + ], + "title": "Version", + "type": "text" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "How many datapoints are in storage", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 5, + "x": 4, + "y": 1 + }, + "id": 26, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "9.2.7", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "exemplar": false, + "expr": "sum(vm_rows{job=~\"$job\", instance=~\"$instance\", type!~\"indexdb.*\"})", + "format": "time_series", + "instant": true, + "interval": "", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "title": "Total datapoints", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Shows the datapoints ingestion rate.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 5, + "x": 9, + "y": 1 + }, + "id": 107, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "9.2.7", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": false, + "expr": "sum(rate(vm_rows_inserted_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval]))", + "format": "time_series", + "instant": true, + "interval": "", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "title": "Ingestion rate", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Shows the rate of HTTP read requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 5, + "x": 14, + "y": 1 + }, + "id": 108, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "9.2.7", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": false, + "expr": "sum(rate(vm_http_requests_total{job=~\"$job\", instance=~\"$instance\", path!~\".*(/write|/metrics)\"}[$__rate_interval]))", + "format": "time_series", + "instant": true, + "interval": "", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "title": "Read requests", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Total number of available CPUs for VM process", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 5, + "x": 19, + "y": 1 + }, + "id": 77, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "9.2.7", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "exemplar": false, + "expr": "sum(vm_available_cpu_cores{job=~\"$job\", instance=~\"$instance\"})", + "format": "time_series", + "instant": true, + "interval": "", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "title": "Available CPU", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "red", + "value": null + }, + { + "color": "green", + "value": 1800 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 4, + "x": 0, + "y": 3 + }, + "id": 87, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "9.2.7", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": false, + "expr": "vm_app_uptime_seconds{job=~\"$job\", instance=~\"$instance\"}", + "instant": true, + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "title": "Uptime", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Shows the number of active time series with new data points inserted during the last hour. High value may result in ingestion slowdown. \n\nSee more details here https://docs.victoriametrics.com/FAQ.html#what-is-an-active-time-series", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 5, + "x": 4, + "y": 3 + }, + "id": 38, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "9.2.7", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "exemplar": false, + "expr": "vm_cache_entries{job=~\"$job\", instance=~\"$instance\", type=\"storage/hour_metric_ids\"}", + "format": "time_series", + "instant": true, + "interval": "", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "title": "Active series", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Total amount of used disk space", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 5, + "x": 9, + "y": 3 + }, + "id": 81, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "9.2.7", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": false, + "expr": "sum(vm_data_size_bytes{job=~\"$job\", instance=~\"$instance\"})", + "format": "time_series", + "instant": true, + "interval": "", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "title": "Disk space usage", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Average disk usage per datapoint.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 5, + "x": 14, + "y": 3 + }, + "id": 82, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "9.2.7", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": false, + "expr": "sum(vm_data_size_bytes{job=~\"$job\", instance=~\"$instance\"}) / sum(vm_rows{job=~\"$job\", instance=~\"$instance\"})", + "format": "time_series", + "instant": true, + "interval": "", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "title": "Bytes per point", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Total size of available memory for VM process", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 5, + "x": 19, + "y": 3 + }, + "id": 78, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "9.2.7", + "targets": [ + { + "datasource": { + "uid": "$ds" + }, + "exemplar": false, + "expr": "sum(vm_available_memory_bytes{job=~\"$job\", instance=~\"$instance\"})", + "format": "time_series", + "instant": true, + "interval": "", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "title": "Available memory", + "type": "stat" + }, + { + "collapsed": false, + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 5 + }, + "id": 24, + "panels": [], + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "refId": "A" + } + ], + "title": "Overview", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "How many datapoints are inserted into storage per second", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 6 + }, + "id": 106, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "uid": "$ds" + }, + "editorMode": "code", + "expr": "sum(rate(vm_rows_inserted_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by (type) > 0", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "Datapoints ingestion rate ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "* `*` - unsupported query path\n* `/write` - insert into VM\n* `/metrics` - query VM system metrics\n* `/query` - query instant values\n* `/query_range` - query over a range of time\n* `/series` - match a certain label set\n* `/label/{}/values` - query a list of label values (variables mostly)", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 6 + }, + "id": 12, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "sum(rate(vm_http_requests_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by (path) > 0", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "{{path}}", + "range": true, + "refId": "A" + } + ], + "title": "Requests rate ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Shows the number of active time series with new data points inserted during the last hour. High value may result in ingestion slowdown. \n\nSee following link for details:", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 14 + }, + "id": 51, + "links": [ + { + "targetBlank": true, + "title": "troubleshooting", + "url": "https://github.com/VictoriaMetrics/VictoriaMetrics/blob/master/README.md#troubleshooting" + } + ], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "expr": "vm_cache_entries{job=~\"$job\", instance=~\"$instance\", type=\"storage/hour_metric_ids\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Active time series", + "refId": "A" + } + ], + "title": "Active time series ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "The less time it takes is better.\n* `*` - unsupported query path\n* `/write` - insert into VM\n* `/metrics` - query VM system metrics\n* `/query` - query instant values\n* `/query_range` - query over a range of time\n* `/series` - match a certain label set\n* `/label/{}/values` - query a list of label values (variables mostly)", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 14 + }, + "id": 22, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "max(vm_request_duration_seconds{job=~\"$job\", instance=~\"$instance\", quantile=\"0.99\"}) by (path) > 0", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "Query duration 0.99 quantile ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "* `*` - unsupported query path\n* `/write` - insert into VM\n* `/metrics` - query VM system metrics\n* `/query` - query instant values\n* `/query_range` - query over a range of time\n* `/series` - match a certain label set\n* `/label/{}/values` - query a list of label values (variables mostly)", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 22 + }, + "id": 35, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": false, + "expr": "sum(rate(vm_http_request_errors_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by (path) > 0", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "Requests error rate ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Shows the rate of logging the messages by their level. Unexpected spike in rate is a good reason to check logs.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "bars", + "fillOpacity": 100, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 22 + }, + "id": 110, + "options": { + "legend": { + "calcs": [ + "lastNotNull", + "mean", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "sum(rate(vm_log_messages_total{job=~\"$job\", instance=~\"$instance\", level!=\"info\"}[$__rate_interval])) by (level, location) > 0", + "interval": "5m", + "legendFormat": "{{level}}: {{location}}", + "range": true, + "refId": "A" + } + ], + "title": "Logging rate", + "type": "timeseries" + }, + { + "collapsed": true, + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 30 + }, + "id": 46, + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Percentage of used RSS memory (resident).\nThe RSS memory shows the amount of memory recently accessed by the application. It includes anonymous memory and data from recently accessed files (aka page cache).\nThe application's performance will significantly degrade when memory usage is close to 100%.\n\nClick on the line and choose Drilldown to show memory usage per instance", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 31 + }, + "id": 112, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": false, + "expr": "max(\n max_over_time(process_resident_memory_bytes{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])\n /\n vm_available_memory_bytes{job=~\"$job\", instance=~\"$instance\"}\n) by(instance)", + "interval": "", + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "RSS memory % usage ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 31 + }, + "id": 44, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "expr": "sum(go_memstats_sys_bytes{job=~\"$job\", instance=~\"$instance\"}) + sum(vm_cache_size_bytes{job=~\"$job\", instance=~\"$instance\"})", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "requested from system", + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "expr": "sum(go_memstats_heap_inuse_bytes{job=~\"$job\", instance=~\"$instance\"}) + sum(vm_cache_size_bytes{job=~\"$job\", instance=~\"$instance\"})", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "heap inuse", + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "expr": "sum(go_memstats_stack_inuse_bytes{job=~\"$job\", instance=~\"$instance\"})", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "stack inuse", + "refId": "C" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "expr": "sum(process_resident_memory_bytes{job=~\"$job\", instance=~\"$instance\"})", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "resident", + "refId": "D" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "exemplar": false, + "expr": "sum(process_resident_memory_anon_bytes{job=~\"$job\", instance=~\"$instance\"})", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "resident anonymous", + "refId": "E" + } + ], + "title": "Memory usage ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Share for memory allocated by the process itself. When memory usage reaches 100% it will be likely OOM-killed.\nSafe memory usage % considered to be below 80%\n\nClick on the line and choose Drilldown to show memory usage per instance", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 39 + }, + "id": 123, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": false, + "expr": "max(\n max_over_time(process_resident_memory_anon_bytes{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])\n /\n vm_available_memory_bytes{job=~\"$job\", instance=~\"$instance\"}\n) by(instance)", + "interval": "", + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "RSS anonymous memory % usage ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 39 + }, + "id": 114, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": false, + "expr": "max(\n rate(process_cpu_seconds_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])\n /\n vm_available_cpu_cores{job=~\"$job\", instance=~\"$instance\"}\n) by(instance)", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "CPU % usage ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Shows the percentage of open file descriptors compared to the limit set in the OS.\nReaching the limit of open files can cause various issues and must be prevented.\n\nSee how to change limits here https://medium.com/@muhammadtriwibowo/set-permanently-ulimit-n-open-files-in-ubuntu-4d61064429a", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 2, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "max" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#C4162A", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 47 + }, + "id": 75, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "max_over_time(process_open_fds{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])\n/\nprocess_max_fds{job=~\"$job\", instance=~\"$instance\"}", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 2, + "legendFormat": "{{instance}}", + "range": true, + "refId": "A" + } + ], + "title": "Open FDs ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Limit" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#F2495C", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 47 + }, + "id": 57, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "expr": "rate(process_cpu_seconds_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "CPU cores used", + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "exemplar": false, + "expr": "process_cpu_cores_available{job=~\"$job\", instance=~\"$instance\"}", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "Limit", + "refId": "B" + } + ], + "title": "CPU ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 0, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 55 + }, + "id": 47, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "sum(go_goroutines{job=~\"$job\", instance=~\"$instance\"}) by(instance)", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{instance}}", + "range": true, + "refId": "A" + } + ], + "title": "Goroutines ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Shows the number of bytes read/write from the storage layer.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "read" + }, + "properties": [ + { + "id": "custom.transform", + "value": "negative-Y" + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 55 + }, + "id": 76, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "expr": "sum(rate(process_io_storage_read_bytes_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval]))", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "read", + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "expr": "sum(rate(process_io_storage_written_bytes_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval]))", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "write", + "refId": "B" + } + ], + "title": "Disk writes/reads ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 0, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 63 + }, + "id": 48, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "sum(process_num_threads{job=~\"$job\", instance=~\"$instance\"}) by(instance)", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{instance}}", + "range": true, + "refId": "A" + } + ], + "title": "Threads ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Shows the number of read/write syscalls such as read, pread, write, pwrite.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "read calls" + }, + "properties": [ + { + "id": "custom.transform", + "value": "negative-Y" + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 63 + }, + "id": 124, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "sum(rate(process_io_read_syscalls_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval]))", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "read calls", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "sum(rate(process_io_write_syscalls_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval]))", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "write calls", + "range": true, + "refId": "B" + } + ], + "title": "Disk write/read calls ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 71 + }, + "id": 49, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "sum(rate(vm_tcplistener_accepts_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by(instance)", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "{{instance}}", + "range": true, + "refId": "A" + } + ], + "title": "TCP connections rate ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 71 + }, + "id": 37, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "sum(vm_tcplistener_conns{job=~\"$job\", instance=~\"$instance\"}) by(instance)", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "{{instance}}", + "range": true, + "refId": "A" + } + ], + "title": "TCP connections ($instance)", + "type": "timeseries" + } + ], + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "refId": "A" + } + ], + "title": "Resource usage", + "type": "row" + }, + { + "collapsed": true, + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 31 + }, + "id": 71, + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Shows the rate and total number of new series created over last 24h.\n\nHigh churn rate tightly connected with database performance and may result in unexpected OOM's or slow queries. It is recommended to always keep an eye on this metric to avoid unexpected cardinality \"explosions\".\n\nThe higher churn rate is, the more resources required to handle it. Consider to keep the churn rate as low as possible.\n\nGood references to read:\n* https://www.robustperception.io/cardinality-is-key\n* https://www.robustperception.io/using-tsdb-analyze-to-investigate-churn-and-cardinality", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 8 + }, + "id": 66, + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "expr": "sum(rate(vm_new_timeseries_created_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval]))", + "interval": "", + "legendFormat": "churn rate", + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "expr": "sum(increase(vm_new_timeseries_created_total{job=~\"$job\", instance=~\"$instance\"}[24h]))", + "interval": "", + "legendFormat": "new series over 24h", + "refId": "B" + } + ], + "title": "Churn rate ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "The percentage of slow inserts comparing to total insertion rate during the last 5 minutes. \n\nThe less value is better. If percentage remains high (>10%) during extended periods of time, then it is likely more RAM is needed for optimal handling of the current number of active time series. \n\nIn general, VictoriaMetrics requires ~1KB or RAM per active time series, so it should be easy calculating the required amounts of RAM for the current workload according to capacity planning docs. But the resulting number may be far from the real number because the required amounts of memory depends on many other factors such as the number of labels per time series and the length of label values. See also https://github.com/VictoriaMetrics/VictoriaMetrics/issues/3976#issuecomment-1476883183", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "line+area" + } + }, + "decimals": 2, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "transparent" + }, + { + "color": "red", + "value": 0.1 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 8 + }, + "id": 68, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "max(\n rate(vm_slow_row_inserts_total{job=~\"$job\"}[$__rate_interval]) \n / rate(vm_rows_added_to_storage_total{job=~\"$job\"}[$__rate_interval])\n)", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "slow inserts percentage", + "range": true, + "refId": "A" + } + ], + "title": "Slow inserts ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Merge assist happens when storage can't keep up with merging parts. This is usually a sign of overload for storage.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "bars", + "fillOpacity": 100, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 16 + }, + "id": 116, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": false, + "expr": "sum(increase(vm_assisted_merges_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by(type) > 0", + "format": "time_series", + "interval": "5m", + "intervalFactor": 1, + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "Assisted merges ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Slow queries rate according to `search.logSlowQueryDuration` flag, which is `5s` by default.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 16 + }, + "id": 60, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "expr": "sum(rate(vm_slow_queries_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval]))", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "slow queries rate", + "refId": "A" + } + ], + "title": "Slow queries rate ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Shows the percentage of used cache size from the allowed size by type. \nValues close to 100% show the maximum potential utilization.\nValues close to 0% show that cache is underutilized.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 24 + }, + "id": 90, + "options": { + "legend": { + "calcs": [ + "lastNotNull", + "mean", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": false, + "expr": "vm_cache_size_bytes{job=~\"$job\", instance=~\"$instance\"} / vm_cache_size_max_bytes{job=~\"$job\", instance=~\"$instance\"}", + "interval": "", + "legendFormat": "{{type}}", + "range": true, + "refId": "A" + } + ], + "title": "Cache usage % by type ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Shows cache miss ratio. Lower is better.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "max": 1, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 24 + }, + "id": 118, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": false, + "expr": "(\n rate(vm_cache_misses_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])\n /\n rate(vm_cache_requests_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])\n) > 0", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "{{type}}", + "range": true, + "refId": "A" + } + ], + "title": "Cache miss ratio ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "displayMode": "auto", + "inspect": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Value" + }, + "properties": [ + { + "id": "custom.hidden", + "value": true + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Time" + }, + "properties": [ + { + "id": "custom.hidden", + "value": true + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 33 + }, + "id": 120, + "options": { + "footer": { + "fields": "", + "reducer": [ + "sum" + ], + "show": false + }, + "showHeader": true, + "sortBy": [ + { + "desc": true, + "displayName": "job" + } + ] + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": false, + "expr": "sum(flag{is_set=\"true\", job=~\"$job\", instance=~\"$instance\"}) by(job, instance, name, value)", + "format": "table", + "instant": true, + "legendFormat": "__auto", + "range": false, + "refId": "A" + } + ], + "title": "Non-default flags", + "transformations": [ + { + "id": "groupBy", + "options": { + "fields": { + "instance": { + "aggregations": [] + }, + "job": { + "aggregations": [] + }, + "name": { + "aggregations": [], + "operation": "groupby" + }, + "value": { + "aggregations": [], + "operation": "groupby" + } + } + } + } + ], + "type": "table" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "VictoriaMetrics limits the number of labels per each metric with `-maxLabelsPerTimeseries` command-line flag.\n\nThis prevents from ingesting metrics with too many labels. The value of `maxLabelsPerTimeseries` must be adjusted for your workload.\n\nWhen limit is exceeded (graph is > 0) - extra labels are dropped, which could result in unexpected identical time series.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 2, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 33 + }, + "id": 74, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "exemplar": false, + "expr": "sum(increase(vm_metrics_with_dropped_labels_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval]))", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "limit exceeded", + "refId": "A" + } + ], + "title": "Labels limit exceeded ($instance)", + "type": "timeseries" + } + ], + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "refId": "A" + } + ], + "title": "Troubleshooting", + "type": "row" + }, + { + "collapsed": true, + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 32 + }, + "id": 14, + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "How many datapoints are inserted into storage per second", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 33 + }, + "id": 10, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "sum(rate(vm_rows_inserted_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by (type) > 0", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "{{type}}", + "range": true, + "refId": "A" + } + ], + "title": "Datapoints ingestion rate ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Shows the time needed to reach the 100% of disk capacity based on the following params:\n* free disk space;\n* row ingestion rate;\n* dedup rate;\n* compression.\n\nUse this panel for capacity planning in order to estimate the time remaining for running out of the disk space.\n\n", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 33 + }, + "id": 73, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "vm_free_disk_space_bytes{job=~\"$job\", instance=~\"$instance\"} \n/ ignoring(path) (\n (\n rate(vm_rows_added_to_storage_total{job=~\"$job\", instance=~\"$instance\"}[1d]) \n - ignoring(type) rate(vm_deduplicated_samples_total{job=~\"$job\", instance=~\"$instance\", type=\"merge\"}[1d])\n ) * scalar(\n sum(vm_data_size_bytes{job=~\"$job\", instance=~\"$instance\", type!~\"indexdb.*\"}) \n / sum(vm_rows{job=~\"$job\", instance=~\"$instance\", type!~\"indexdb.*\"})\n )\n )", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "{{instance}}", + "range": true, + "refId": "A" + } + ], + "title": "Storage full ETA ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Shows amount of on-disk space occupied by data points and the remaining disk space at `-storageDataPath`", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 41 + }, + "id": 53, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "sum(vm_data_size_bytes{job=~\"$job\", instance=~\"$instance\", type!~\"indexdb.*\"})", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "Used (datapoints)", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "expr": "vm_free_disk_space_bytes{job=~\"$job\", instance=~\"$instance\"}", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "Free", + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "sum(vm_data_size_bytes{job=~\"$job\", instance=~\"$instance\", type=~\"indexdb.*\"})", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "Used (index)", + "range": true, + "refId": "C" + } + ], + "title": "Disk space usage - datapoints ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "How many datapoints are in RAM queue waiting to be written into storage. The number of pending data points should be in the range from 0 to `2*`, since VictoriaMetrics pushes pending data to persistent storage every second.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "pending index entries" + }, + "properties": [ + { + "id": "unit", + "value": "none" + }, + { + "id": "decimals", + "value": 3 + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 41 + }, + "id": 34, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "expr": "vm_pending_rows{job=~\"$job\", instance=~\"$instance\", type=\"storage\"}", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "pending datapoints", + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "expr": "vm_pending_rows{job=~\"$job\", instance=~\"$instance\", type=\"indexdb\"}", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "pending index entries", + "refId": "B" + } + ], + "title": "Pending datapoints ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Shows how many datapoints are in the storage and what is average disk usage per datapoint.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "bytes-per-datapoint" + }, + "properties": [ + { + "id": "unit", + "value": "bytes" + }, + { + "id": "decimals", + "value": 2 + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 49 + }, + "id": 30, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "expr": "sum(vm_rows{job=~\"$job\", instance=~\"$instance\", type!~\"indexdb.*\"})", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "total datapoints", + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "sum(vm_data_size_bytes{job=~\"$job\", instance=~\"$instance\"}) \n/ sum(vm_rows{job=~\"$job\", instance=~\"$instance\", type!~\"indexdb.*\"})", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "bytes-per-datapoint", + "range": true, + "refId": "B" + } + ], + "title": "Datapoints ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "uid": "$ds" + }, + "description": "Data parts of LSM tree.\nHigh number of parts could be an evidence of slow merge performance - check the resource utilization.\n* `indexdb` - inverted index\n* `storage/small` - recently added parts of data ingested into storage(hot data)\n* `storage/big` - small parts gradually merged into big parts (cold data)", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 49 + }, + "id": 36, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "expr": "sum(vm_parts{job=~\"$job\", instance=~\"$instance\"}) by (type)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{type}}", + "refId": "A" + } + ], + "title": "LSM parts ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Shows how many rows were ignored on insertion due to corrupted or out of retention timestamps.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 57 + }, + "id": 58, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": false, + "expr": "sum(increase(vm_rows_ignored_total{job=~\"$job\", instance=~\"$instance\"}[1h])) by (reason)", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "{{reason}}", + "range": true, + "refId": "A" + } + ], + "title": "Rows ignored for last 1h ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "The number of on-going merges in storage nodes. It is expected to have high numbers for `storage/small` metric.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 0, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 57 + }, + "id": 62, + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "expr": "sum(vm_active_merges{job=~\"$job\", instance=~\"$instance\"}) by(type)", + "legendFormat": "{{type}}", + "refId": "A" + } + ], + "title": "Active merges ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Shows how many ongoing insertions (not API /write calls) on disk are taking place, where:\n* `max` - equal to number of CPUs;\n* `current` - current number of goroutines busy with inserting rows into underlying storage.\n\nEvery successful API /write call results into flush on disk. However, these two actions are separated and controlled via different concurrency limiters. The `max` on this panel can't be changed and always equal to number of CPUs. \n\nWhen `current` hits `max` constantly, it means storage is overloaded and requires more CPU.\n\n", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 0, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "max" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#C4162A", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 65 + }, + "id": 59, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "max_over_time(vm_concurrent_insert_capacity{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "max", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "expr": "sum(vm_concurrent_insert_current{job=~\"$job\", instance=~\"$instance\"})", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "current", + "refId": "B" + } + ], + "title": "Concurrent flushes on disk ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "The number of rows merged per second by storage nodes.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 0, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 65 + }, + "id": 64, + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "expr": "sum(rate(vm_rows_merged_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by(type)", + "legendFormat": "{{type}}", + "refId": "A" + } + ], + "title": "Merge speed ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "99th percentile of number of series read per query.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 2, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 73 + }, + "id": 99, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "histogram_quantile(0.99, sum(rate(vm_series_read_per_query_bucket{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by (instance, vmrange))", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "{{instance}}", + "range": true, + "refId": "A" + } + ], + "title": "Series read per query ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "99th percentile of number of raw samples read per queried series.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 2, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 73 + }, + "id": 103, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "histogram_quantile(0.99, sum(rate(vm_rows_read_per_series_bucket{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by (instance, vmrange))", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "{{instance}}", + "range": true, + "refId": "A" + } + ], + "title": "Datapoints read per series ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "99th percentile of number of raw datapoints read per query.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 2, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 81 + }, + "id": 122, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "histogram_quantile(0.99, sum(rate(vm_rows_read_per_query_bucket{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by (instance, vmrange))", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "{{instance}}", + "range": true, + "refId": "A" + } + ], + "title": "Datapoints read per query ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "99th percentile of number of raw samples scanner per query.\n\nThis number can exceed number of RowsReadPerQuery if `step` query arg passed to [/api/v1/query_range](https://prometheus.io/docs/prometheus/latest/querying/api/#range-queries) is smaller than the lookbehind window set in square brackets of [rollup function](https://docs.victoriametrics.com/MetricsQL.html#rollup-functions). For example, if `increase(some_metric[1h])` is executed with the `step=5m`, then the same raw samples on a hour time range are scanned `1h/5m=12` times. See [this article](https://valyala.medium.com/how-to-optimize-promql-and-metricsql-queries-85a1b75bf986) for details.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 2, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 81 + }, + "id": 105, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "histogram_quantile(0.99, sum(rate(vm_rows_scanned_per_query_bucket{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by (instance, vmrange))", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "{{instance}}", + "range": true, + "refId": "A" + } + ], + "title": "Datapoints scanned per query ($instance)", + "type": "timeseries" + } + ], + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "refId": "A" + } + ], + "title": "Storage", + "type": "row" + } + ], + "refresh": false, + "schemaVersion": 37, + "style": "dark", + "tags": [ + "victoriametrics", + "vmsingle" + ], + "templating": { + "list": [ + { + "current": { + "selected": false, + "text": "VictoriaMetrics", + "value": "VictoriaMetrics" + }, + "hide": 0, + "includeAll": false, + "multi": false, + "name": "ds", + "options": [], + "query": "prometheus", + "queryValue": "", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + }, + { + "current": {}, + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "definition": "label_values(vm_app_version{version=~\"victoria-metrics-.*\"}, job)", + "hide": 0, + "includeAll": false, + "multi": false, + "name": "job", + "options": [], + "query": { + "query": "label_values(vm_app_version{version=~\"victoria-metrics-.*\"}, job)", + "refId": "VictoriaMetrics-job-Variable-Query" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "current": {}, + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "definition": "label_values(vm_app_version{job=~\"$job\", instance=~\"$instance\"}, version)", + "hide": 2, + "includeAll": false, + "multi": false, + "name": "version", + "options": [], + "query": { + "query": "label_values(vm_app_version{job=~\"$job\", instance=~\"$instance\"}, version)", + "refId": "VictoriaMetrics-version-Variable-Query" + }, + "refresh": 1, + "regex": "/.*-tags-(v\\d+\\.\\d+\\.\\d+)/", + "skipUrlSync": false, + "sort": 2, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "current": {}, + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "definition": "label_values(vm_app_version{job=~\"$job\"}, instance)", + "hide": 0, + "includeAll": false, + "multi": false, + "name": "instance", + "options": [], + "query": { + "query": "label_values(vm_app_version{job=~\"$job\"}, instance)", + "refId": "VictoriaMetrics-instance-Variable-Query" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "filters": [], + "hide": 0, + "name": "adhoc", + "skipUrlSync": false, + "type": "adhoc" + } + ] + }, + "time": { + "from": "now-30m", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "", + "title": "VictoriaMetrics", + "uid": "wNf0q_kZk", + "version": 1, + "weekStart": "" +} diff --git a/dashboards/victoria-metrics/vmagent.json b/dashboards/victoria-metrics/vmagent.json new file mode 100644 index 00000000..adc0da01 --- /dev/null +++ b/dashboards/victoria-metrics/vmagent.json @@ -0,0 +1,6154 @@ +{ + "__inputs": [], + "__elements": {}, + "__requires": [ + { + "type": "grafana", + "id": "grafana", + "name": "Grafana", + "version": "9.2.7" + }, + { + "type": "datasource", + "id": "prometheus", + "name": "Prometheus", + "version": "1.0.0" + }, + { + "type": "panel", + "id": "stat", + "name": "Stat", + "version": "" + }, + { + "type": "panel", + "id": "table", + "name": "Table", + "version": "" + }, + { + "type": "panel", + "id": "text", + "name": "Text", + "version": "" + }, + { + "type": "panel", + "id": "timeseries", + "name": "Time series", + "version": "" + } + ], + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "target": { + "limit": 100, + "matchAny": false, + "tags": [], + "type": "dashboard" + }, + "type": "dashboard" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "enable": true, + "expr": "sum(vm_app_version{job=~\"$job\", instance=~\"$instance\"}) by(short_version) unless (sum(vm_app_version{job=~\"$job\", instance=~\"$instance\"} offset 20m) by(short_version))", + "hide": true, + "iconColor": "dark-blue", + "name": "version", + "textFormat": "{{short_version}}", + "titleFormat": "Version change" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "enable": true, + "expr": "sum(changes(vm_app_start_timestamp{job=~\"$job\", instance=~\"$instance\"})) by(job, instance)", + "hide": true, + "iconColor": "dark-yellow", + "name": "restarts", + "textFormat": "{{job}}:{{instance}} restarted" + } + ] + }, + "description": "Overview for VictoriaMetrics vmagent v1.80.0 or higher", + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 1, + "id": null, + "links": [ + { + "icon": "doc", + "tags": [], + "targetBlank": true, + "title": "vmagent wiki", + "tooltip": "", + "type": "link", + "url": "https://docs.victoriametrics.com/vmagent.html" + }, + { + "icon": "external link", + "tags": [], + "targetBlank": true, + "title": "Found a bug?", + "type": "link", + "url": "https://github.com/VictoriaMetrics/VictoriaMetrics/issues" + }, + { + "icon": "external link", + "tags": [], + "targetBlank": true, + "title": "New releases", + "type": "link", + "url": "https://github.com/VictoriaMetrics/VictoriaMetrics/releases" + } + ], + "liveNow": false, + "panels": [ + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 105, + "panels": [], + "title": "Stats", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Shows the rate of samples scraped from configured targets.", + "fieldConfig": { + "defaults": { + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 4, + "x": 0, + "y": 1 + }, + "id": 103, + "links": [ + { + "title": "Troubleshooting", + "url": "https://docs.victoriametrics.com/vmagent.html#troubleshooting" + } + ], + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "last" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "9.2.7", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "sum(rate(vm_promscrape_scraped_samples_sum{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval]))", + "interval": "", + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "Samples scraped/s", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Shows the rate of ingested samples", + "fieldConfig": { + "defaults": { + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 4, + "x": 4, + "y": 1 + }, + "id": 102, + "links": [ + { + "title": "Troubleshooting", + "url": "https://docs.victoriametrics.com/vmagent.html#troubleshooting" + } + ], + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "last" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "9.2.7", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "sum(rate(vmagent_rows_inserted_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval]))", + "interval": "", + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "Samples ingested/s", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Shows total number of all configured scrape targets in state \"up\".\n\nSee `http://vmagent-host:8429/targets` to get list of all targets. \n", + "fieldConfig": { + "defaults": { + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 4, + "x": 8, + "y": 1 + }, + "id": 9, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "last" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "9.2.7", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "expr": "sum(vm_promscrape_targets{job=~\"$job\", instance=~\"$instance\", status=\"up\"})", + "interval": "", + "legendFormat": "up", + "refId": "A" + } + ], + "title": "Scrape targets up", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Shows total number of all configured scrape targets in state \"down\".\n\nSee `http://vmagent-host:8429/targets` to get list of all targets. \n", + "fieldConfig": { + "defaults": { + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 1 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 4, + "x": 12, + "y": 1 + }, + "id": 72, + "links": [ + { + "title": "Troubleshooting", + "url": "https://docs.victoriametrics.com/vmagent.html#troubleshooting" + } + ], + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "last" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "9.2.7", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "expr": "sum(vm_promscrape_targets{job=~\"$job\", instance=~\"$instance\", status=\"down\"})", + "interval": "", + "legendFormat": "up", + "refId": "A" + } + ], + "title": "Scrape targets down", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Shows number of generated error messages in logs over last 30m. Non-zero value may be a sign of connectivity or missconfiguration errors.", + "fieldConfig": { + "defaults": { + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 1 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 4, + "x": 16, + "y": 1 + }, + "id": 16, + "links": [ + { + "targetBlank": true, + "title": "Troubleshooting", + "url": "https://docs.victoriametrics.com/vmagent.html#troubleshooting" + } + ], + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "last" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "9.2.7", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "expr": "sum(increase(vm_log_messages_total{job=~\"$job\", instance=~\"$instance\", level!=\"info\"}[30m]))", + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "title": "Log errors (30m)", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Persistent queue size shows size of pending samples in bytes which hasn't been flushed to remote storage yet. \nIncreasing of value might be a sign of connectivity issues. In such cases, vmagent starts to flush pending data on disk with attempt to send it later once connection is restored.", + "fieldConfig": { + "defaults": { + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 10485760 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 4, + "x": 20, + "y": 1 + }, + "id": 56, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "last" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "9.2.7", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "expr": "sum(vm_persistentqueue_bytes_pending{job=~\"$job\", instance=~\"$instance\"})", + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "title": "Persistent queue size", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "displayMode": "auto", + "inspect": false, + "minWidth": 50 + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Time" + }, + "properties": [ + { + "id": "custom.hidden", + "value": true + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value" + }, + "properties": [ + { + "id": "displayName", + "value": "Count" + } + ] + } + ] + }, + "gridPos": { + "h": 5, + "w": 8, + "x": 0, + "y": 4 + }, + "id": 101, + "options": { + "footer": { + "fields": "", + "reducer": [ + "sum" + ], + "show": false + }, + "showHeader": true + }, + "pluginVersion": "9.2.7", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": false, + "expr": "sum(vm_app_version{job=~\"$job\", instance=~\"$instance\"}) by(job, short_version)", + "format": "table", + "instant": true, + "range": false, + "refId": "A" + } + ], + "type": "table" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "stepAfter", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 0, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 16, + "x": 8, + "y": 4 + }, + "id": 13, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "right", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.2.6", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "sum(up{job=~\"$job\", instance=~\"$instance\"}) by (job)", + "format": "time_series", + "instant": false, + "interval": "", + "legendFormat": "__auto", + "refId": "A" + } + ], + "title": "Uptime", + "type": "timeseries" + }, + { + "collapsed": false, + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 9 + }, + "id": 24, + "panels": [], + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "refId": "A" + } + ], + "title": "Overview", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Shows in/out samples rate including push and pull models. \n\nThe out-rate could be different to in-rate because of replication or additional timeseries added by vmagent for every scraped target.\n\nClick on the line and choose Drilldown to show CPU usage per instance\n", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [ + { + "title": "Drilldown", + "url": "/d/G7Z9GzMGz?viewPanel=123&var-job=${__field.labels.job}&var-ds=$ds&var-instance=$instance&${__url_time_range}" + } + ], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": "/out .*/" + }, + "properties": [ + { + "id": "custom.transform", + "value": "negative-Y" + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 10 + }, + "id": 5, + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.6", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "sum(rate({__name__=~\"vmagent_rows_inserted_total|vm_promscrape_scraped_samples_sum\", job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by(job)", + "hide": false, + "interval": "", + "legendFormat": "in {{job}}", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "sum(rate(vmagent_remotewrite_block_size_rows_sum{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by(job)", + "interval": "", + "legendFormat": "out {{job}}", + "range": true, + "refId": "B" + } + ], + "title": "Samples rate ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Shows the persistent queue size of pending samples in bytes >2MB which hasn't been flushed to remote storage yet. \n\nIncreasing of value might be a sign of connectivity issues. In such cases, vmagent starts to flush pending data on disk with attempt to send it later once connection is restored.\n\nRemote write URLs are hidden by default but might be unveiled once `-remoteWrite.showURL` is set to true.\n\nClick on the line and choose Drilldown to show CPU usage per instance.\n", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [ + { + "targetBlank": true, + "title": "Drilldown", + "url": "/d/G7Z9GzMGz?viewPanel=125&var-url=${__field.labels.url}&var-ds=$ds&var-instance=$instance&var-job=$job&${__url_time_range}" + } + ], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 10 + }, + "id": 17, + "links": [ + { + "title": "Troubleshooting", + "url": "https://docs.victoriametrics.com/vmagent.html#troubleshooting" + } + ], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.6", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(vmagent_remotewrite_pending_data_bytes{job=~\"$job\", instance=~\"$instance\", url=~\"$url\"}) by (job, url) > 2e6", + "interval": "", + "legendFormat": "{{job}} => {{url}}", + "range": true, + "refId": "A" + } + ], + "title": "Persistent queue size ($instance) to ($url)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Shows the rate of logging the messages by their level. Unexpected spike in rate is a good reason to check logs.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "bars", + "fillOpacity": 100, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 18 + }, + "id": 107, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(rate(vm_log_messages_total{job=~\"$job\",instance=~\"$instance\", level!=\"info\"}[$__rate_interval])) by (job, level) > 0", + "format": "time_series", + "hide": false, + "interval": "5m", + "intervalFactor": 1, + "legendFormat": "{{job}} - {{level}}", + "range": true, + "refId": "A" + } + ], + "title": "Logging rate", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Shows rate of dropped samples from persistent queue. VMagent drops samples from queue if in-memory and on-disk queues are full and it is unable to flush them to remote storage.\nThe max size of on-disk queue is configured by `-remoteWrite.maxDiskUsagePerURL` flag.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "decbytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 18 + }, + "id": 49, + "links": [ + { + "targetBlank": true, + "title": "Troubleshooting", + "url": "https://docs.victoriametrics.com/vmagent.html#troubleshooting" + } + ], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.6", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "sum(rate(vm_persistentqueue_bytes_dropped_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by (path) > 0", + "interval": "", + "legendFormat": "{{ path }}", + "range": true, + "refId": "A" + } + ], + "title": "Persistent queue dropped rate ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Shows the rate of requests served by vmagent HTTP server.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 26 + }, + "id": 15, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.2.6", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "sum(rate(vmagent_http_requests_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by(job, path) > 0", + "interval": "", + "legendFormat": "", + "range": true, + "refId": "A" + } + ], + "title": "Requests rate ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Errors rate shows rate for multiple metrics that track possible errors in vmagent, such as network or parsing errors.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 26 + }, + "id": 69, + "links": [ + { + "targetBlank": true, + "title": "Troubleshooting", + "url": "https://docs.victoriametrics.com/vmagent.html#troubleshooting" + } + ], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.2.6", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "sum(rate(vmagent_http_request_errors_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by(job, protocol) > 0", + "interval": "", + "legendFormat": "requests:{{protocol}} ({{job}})", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "sum(rate(vm_protoparser_read_errors_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by(job, type) > 0", + "interval": "", + "legendFormat": "parse: {{type}} ({{job}})", + "range": true, + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "sum(rate(vm_ingestserver_request_errors_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by(job, type) > 0", + "interval": "", + "legendFormat": "ingest: {{type}} ({{job}})", + "range": true, + "refId": "C" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "sum(rate(vm_protoparser_unmarshal_errors_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by(job, type) > 0", + "interval": "", + "legendFormat": "unmarshal: {{type}} ({{job}})", + "range": true, + "refId": "D" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "sum(rate(vm_promscrape_dial_errors_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by(job) > 0", + "interval": "", + "legendFormat": "scrape dial ({{job}})", + "range": true, + "refId": "E" + } + ], + "title": "Errors rate ($instance)", + "type": "timeseries" + }, + { + "collapsed": true, + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 34 + }, + "id": 45, + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Click on the line and choose Drilldown to show CPU usage per instance", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [ + { + "targetBlank": true, + "title": "Drilldown", + "url": "/d/G7Z9GzMGz?viewPanel=119&var-job=${__field.labels.job}&var-ds=$ds&var-instance=$instance&${__url_time_range}" + } + ], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 11 + }, + "id": 109, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": true, + "expr": "max(\n rate(process_cpu_seconds_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])\n /\n vm_available_cpu_cores{job=~\"$job\", instance=~\"$instance\"}\n) by(job)", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "CPU ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Percentage of used RSS memory (resident).\nThe RSS memory shows the amount of memory recently accessed by the application. It includes anonymous memory and data from recently accessed files (aka page cache).\nThe application's performance will significantly degrade when memory usage is close to 100%.\n\nClick on the line and choose Drilldown to show memory usage per instance", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [ + { + "targetBlank": true, + "title": "Drilldown", + "url": "/d/G7Z9GzMGz?viewPanel=117&var-job=${__field.labels.job}&var-ds=$ds&var-instance=$instance&${__url_time_range}" + } + ], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 11 + }, + "id": 111, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": true, + "expr": "max(\n max_over_time(process_resident_memory_bytes{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])\n /\n vm_available_memory_bytes{job=~\"$job\", instance=~\"$instance\"}\n) by(job)", + "interval": "", + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "RSS memory % usage ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Shows the number of bytes read/write from the storage layer when vmagent has to buffer data on disk or read already buffered data.\n\nClick on the line and choose Drilldown to show CPU usage per instance", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [ + { + "targetBlank": true, + "title": "Drilldown", + "url": "/d/G7Z9GzMGz?viewPanel=121&var-job=${__field.labels.job}&var-ds=$ds&var-instance=$instance&${__url_time_range}" + } + ], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "read" + }, + "properties": [ + { + "id": "custom.transform", + "value": "negative-Y" + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 19 + }, + "id": 81, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.6", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "sum(rate(process_io_storage_read_bytes_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by(job) > 0", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "read {{job}}", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "sum(rate(process_io_storage_written_bytes_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by(job) > 0", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "write {{job}}", + "range": true, + "refId": "B" + } + ], + "title": "Disk writes/reads ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Network usage shows the bytes rate for data accepted by vmagent and pushed via remotewrite protocol.\nDiscrepancies are possible because of different protocols used for ingesting, scraping and writing data.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bps" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": "/out.*/" + }, + "properties": [ + { + "id": "custom.transform", + "value": "negative-Y" + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 19 + }, + "id": 7, + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.2.6", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "sum(rate(vm_tcplistener_read_bytes_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by(job) * 8 \n+ sum(rate(vm_promscrape_conn_bytes_read_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by(job) * 8", + "interval": "", + "legendFormat": "in {{job}}", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "sum(rate(vmagent_remotewrite_conn_bytes_written_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by(job) * 8", + "interval": "", + "legendFormat": "out {{job}}", + "range": true, + "refId": "B" + } + ], + "title": "Network usage ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Panel shows the percentage of open file descriptors in the OS per instance.\nReaching the limit of open files (100%) can cause various issues and must be prevented.\n\nSee how to change limits here https://medium.com/@muhammadtriwibowo/set-permanently-ulimit-n-open-files-in-ubuntu-4d61064429a", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 5, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 27 + }, + "id": 83, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.2.6", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "max(\n max_over_time(process_open_fds{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])\n /\n process_max_fds{job=~\"$job\", instance=~\"$instance\"}\n) by(job)", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "Open FDs usage % ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 0, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 27 + }, + "id": 39, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.2.6", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "sum(max_over_time(go_goroutines{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by(job)", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "Goroutines ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 0, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 35 + }, + "id": 41, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.2.6", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "sum(max_over_time(process_num_threads{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by(job)", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "Threads ($instance)", + "type": "timeseries" + } + ], + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "refId": "A" + } + ], + "title": "Resource usage", + "type": "row" + }, + { + "collapsed": true, + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 35 + }, + "id": 94, + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Shows top 5 job by the number of new series registered by vmagent over the 5min range. These jobs generate the most of the churn rate.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 4 + }, + "id": 92, + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.2.6", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": false, + "expr": "topk_max(5, sum(sum_over_time(scrape_series_added[5m])) by (job)) > 0", + "interval": "", + "legendFormat": "{{ job }}", + "range": true, + "refId": "A" + } + ], + "title": "Top 5 jobs by unique samples", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Shows top 5 instances by the number of new series registered by vmagent over the 5min range. These instances generate the most of the churn rate.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 4 + }, + "id": 95, + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.2.6", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": false, + "expr": "topk(10, sum(sum_over_time(scrape_series_added[5m])) by (instance)) > 0", + "interval": "", + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "Top 5 instances by unique samples", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Shows saturation persistent queue for writes. If the threshold of 0.9sec is reached, then persistent is saturated by more than 90% and vmagent won't be able to keep up with flushing data on disk. In this case, consider to decrease load on the vmagent or improve the disk throughput.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 2, + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "line" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "transparent" + }, + { + "color": "red", + "value": 0.9 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 12 + }, + "id": 98, + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.2.6", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": true, + "expr": "max(rate(vm_persistentqueue_write_duration_seconds_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by (job)", + "interval": "", + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "Persistent queue write saturation ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Shows saturation persistent queue for reads. If the threshold of 0.9sec is reached, then persistent is saturated by more than 90% and vmagent won't be able to keep up with reading data from the disk. In this case, consider to decrease load on the vmagent or improve the disk throughput.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 2, + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "line" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "transparent" + }, + { + "color": "red", + "value": 0.9 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 12 + }, + "id": 99, + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.6", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": true, + "expr": "max(rate(vm_persistentqueue_read_duration_seconds_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by (job)", + "interval": "", + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "Persistent queue read saturation ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Shows the rate of dropped data blocks in cases when remote storage replies with `400 Bad Request` and `409 Conflict` HTTP responses.\n\nSee https://github.com/VictoriaMetrics/VictoriaMetrics/issues/1149", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 20 + }, + "id": 79, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.6", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(rate(vmagent_remotewrite_packets_dropped_total{job=~\"$job\", instance=~\"$instance\", url=~\"$url\"}[$__rate_interval])) by(job, url) > 0", + "interval": "", + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "Data blocks dropped ($instance) to ($url)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Shows the rate of dropped samples due to relabeling. \nMetric tracks drops for `-remoteWrite.relabelConfig` configuration only.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 20 + }, + "id": 18, + "links": [ + { + "targetBlank": true, + "title": "Relabeling", + "url": "https://docs.victoriametrics.com/vmagent.html#relabeling" + } + ], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.6", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "sum(rate(vmagent_remotewrite_relabel_metrics_dropped_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by(job, url) > 0", + "interval": "", + "legendFormat": "__auto", + "range": true, + "refId": "B" + } + ], + "title": "Rows dropped by relabeling ($instance) to ($url)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Shows the rate of parsed datapoints from write or scrape requests.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 28 + }, + "id": 127, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.2.6", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(rate(vm_protoparser_rows_read_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by(job, type) > 0", + "interval": "", + "legendFormat": "{{ type }} ({{job}})", + "range": true, + "refId": "A" + } + ], + "title": "Datapoints rate ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Tracks the rate of dropped invalid rows because of errors while unmarshaling write requests. The exact errors messages will be printed in logs.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 28 + }, + "id": 50, + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.2.6", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(rate(vm_rows_invalid_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by(job, type) > 0", + "interval": "", + "legendFormat": "{{type}} ({{job}})", + "range": true, + "refId": "A" + } + ], + "title": "Invalid datapoints rate ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "displayMode": "auto", + "inspect": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Value" + }, + "properties": [ + { + "id": "custom.hidden", + "value": true + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Time" + }, + "properties": [ + { + "id": "custom.hidden", + "value": true + } + ] + } + ] + }, + "gridPos": { + "h": 7, + "w": 24, + "x": 0, + "y": 36 + }, + "id": 129, + "options": { + "footer": { + "fields": "", + "reducer": [ + "sum" + ], + "show": false + }, + "showHeader": true, + "sortBy": [ + { + "desc": true, + "displayName": "job" + } + ] + }, + "pluginVersion": "9.2.6", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": false, + "expr": "sum(flag{is_set=\"true\", job=~\"$job\", instance=~\"$instance\"}) by(job, instance, name, value)", + "format": "table", + "instant": true, + "legendFormat": "__auto", + "range": false, + "refId": "A" + } + ], + "title": "Non-default flags", + "transformations": [ + { + "id": "groupBy", + "options": { + "fields": { + "instance": { + "aggregations": [] + }, + "job": { + "aggregations": [], + "operation": "groupby" + }, + "name": { + "aggregations": [], + "operation": "groupby" + }, + "value": { + "aggregations": [], + "operation": "groupby" + } + } + } + } + ], + "type": "table" + } + ], + "targets": [ + { + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "refId": "A" + } + ], + "title": "Troubleshooting", + "type": "row" + }, + { + "collapsed": true, + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 36 + }, + "id": 28, + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 45 + }, + "id": 48, + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.2.6", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(vm_promscrape_targets{job=~\"$job\", instance=~\"$instance\", status=\"up\"}) by(job, type) > 0", + "format": "time_series", + "interval": "", + "legendFormat": "{{type}} ({{job}})", + "range": true, + "refId": "A" + } + ], + "title": "Scrape targets UP(By Type)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 45 + }, + "id": 76, + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.2.6", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(vm_promscrape_targets{job=~\"$job\", instance=~\"$instance\", status=\"down\"}) by(job, type) > 0", + "format": "time_series", + "interval": "", + "legendFormat": "{{type}} ({{job}})", + "range": true, + "refId": "A" + } + ], + "title": "Scrape targets DOWN(By Type)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 45 + }, + "id": 132, + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.2.6", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(vm_promscrape_scrape_pool_targets{job=~\"$job\", instance=~\"$instance\", status=\"up\"}) by(job, scrape_job) > 0", + "format": "time_series", + "interval": "", + "legendFormat": "{{job}}: {{scrape_job}}", + "range": true, + "refId": "A" + } + ], + "title": "Scrape targets UP(By Job)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 45 + }, + "id": 133, + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.2.6", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(vm_promscrape_scrape_pool_targets{job=~\"$job\", instance=~\"$instance\", status=\"down\"}) by(job, scrape_job) > 0", + "format": "time_series", + "interval": "", + "legendFormat": "{{job}}: {{scrape_job}}", + "range": true, + "refId": "A" + } + ], + "title": "Scrape targets DOWN(By Job)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Shows the number of scrapes per second.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 52 + }, + "id": 20, + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.2.6", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(rate(vm_promscrape_scrapes_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by(job)", + "interval": "", + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "Scrape rate ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Shows the number of datapoints scraped per second.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 52 + }, + "id": 126, + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.2.6", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(rate(vm_promscrape_scraped_samples_sum{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by(job)", + "interval": "", + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "Scraped datapoints rate ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 60 + }, + "id": 46, + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.2.6", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "max(histogram_quantile(0.99, sum(rate(vm_promscrape_scrape_response_size_bytes_bucket{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by(job, vmrange))) by(job)", + "format": "time_series", + "interval": "", + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "Scrape response size 0.99 quantile ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 60 + }, + "id": 31, + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.2.6", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "sum(rate(vm_promscrape_scrapes_failed_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by(job) > 0", + "interval": "", + "legendFormat": "scrapes failed ({{job}})", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "sum(rate(vm_promscrape_scrapes_timed_out_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by(job) > 0", + "interval": "", + "legendFormat": "timeouts ({{job}})", + "range": true, + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "sum(rate(vm_promscrape_scrapes_gunzip_failed_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by(job) > 0", + "interval": "", + "legendFormat": "gunzip fails ({{job}})", + "range": true, + "refId": "C" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "sum(rate(vm_promscrape_dial_errors_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by(job) > 0", + "interval": "", + "legendFormat": "dial fails ({{job}})", + "range": true, + "refId": "D" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "sum(rate(vm_promscrape_max_scrape_size_exceeded_errors_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by(job) > 0", + "hide": false, + "interval": "", + "legendFormat": "max scrape size exceeded ({{job}})", + "range": true, + "refId": "E" + } + ], + "title": "Scrape fails ($instance)", + "type": "timeseries" + } + ], + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "refId": "A" + } + ], + "title": "Scraping", + "type": "row" + }, + { + "collapsed": true, + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 37 + }, + "id": 71, + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Shows the rate of write requests served by ingestserver (UDP, TCP connections) and HTTP server.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 38 + }, + "id": 73, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.2.6", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(rate(vm_ingestserver_requests_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by(job, type, net) > 0", + "interval": "", + "legendFormat": "{{net}}: {{ type }} ({{job}})", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(rate(vmagent_http_requests_total{job=~\"$job\", instance=~\"$instance\", protocol!=\"\"}[$__rate_interval])) by(job, protocol) > 0", + "interval": "", + "legendFormat": "{{ protocol }}: http ({{job}})", + "range": true, + "refId": "B" + } + ], + "title": "Requests rate ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Shows the rate of rows ingested in vmagent via push protocols.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 38 + }, + "id": 131, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.2.6", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(rate(vmagent_rows_inserted_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by(job, type) > 0", + "interval": "", + "legendFormat": "{{ type }} ({{job}})", + "range": true, + "refId": "A" + } + ], + "title": "Rows rate ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Shows how many concurrent inserts are taking place.\n\nIf the number of concurrent inserts hitting the `limit` or is close to the `limit` constantly - it might be a sign of a resource shortage.\n\n If vmagent's CPU usage and remote write connection saturation are at normal level, it might be that `-maxConcurrentInserts` cmd-line flag need to be increased.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 46 + }, + "id": 130, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.2.6", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": true, + "expr": "max_over_time(vm_concurrent_insert_current{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])", + "interval": "", + "legendFormat": "{{instance}} ({{job}})", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": true, + "expr": "min(vm_concurrent_insert_capacity{job=~\"$job\", instance=~\"$instance\"}) by(job)", + "interval": "", + "legendFormat": "limit ({{job}})", + "range": true, + "refId": "B" + } + ], + "title": "Concurrent inserts ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Shows the rate of write errors in ingestserver (UDP, TCP connections) and HTTP server.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 46 + }, + "id": 77, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.2.6", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "exemplar": true, + "expr": "sum(rate(vm_ingestserver_request_errors_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by(type, net) > 0", + "interval": "", + "legendFormat": "{{ type }} ({{net}})", + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "exemplar": true, + "expr": "sum(rate(vmagent_http_request_errors_total{job=~\"$job\", instance=~\"$instance\", protocol!=\"\"}[$__rate_interval])) by(protocol) > 0", + "interval": "", + "legendFormat": "{{ protocol }} (http)", + "refId": "B" + } + ], + "title": "Error rate ($instance)", + "type": "timeseries" + } + ], + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "refId": "A" + } + ], + "title": "Ingestion", + "type": "row" + }, + { + "collapsed": true, + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 38 + }, + "id": 58, + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Shows the rate of requests to configured remote write endpoints by url and status code.\n\nRemote write URLs are hidden by default but might be unveiled once `-remoteWrite.showURL` is set to true.\n\n", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 2, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 55 + }, + "id": 60, + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.2.6", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(rate(vmagent_remotewrite_requests_total{job=~\"$job\", instance=~\"$instance\", url=~\"$url\"}[$__rate_interval])) by(job, url, status_code) > 0", + "interval": "", + "legendFormat": "", + "range": true, + "refId": "A" + } + ], + "title": "Requests rate ($instance) to ($url)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Shows the global rate for number of written bytes via remote write connections.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "decbytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 55 + }, + "id": 66, + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.2.6", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(rate(vmagent_remotewrite_conn_bytes_written_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by(job) > 0", + "interval": "", + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "Bytes write rate ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Shows requests retry rate by url. Number of retries is unlimited but protected with delays up to 1m between attempts.\n\nRemote write URLs are hidden by default but might be unveiled once `-remoteWrite.showURL` is set to true.\n\n", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 63 + }, + "id": 61, + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.6", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(rate(vmagent_remotewrite_retries_count_total{job=~\"$job\", instance=~\"$instance\", url=~\"$url\"}[$__rate_interval])) by(url) > 0", + "interval": "", + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "Retry rate ($instance) to ($url)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Shows current number of established connections to remote write endpoints.\n\n", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 63 + }, + "id": 65, + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.2.6", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(max_over_time(vmagent_remotewrite_conns{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by(job)", + "interval": "", + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "Connections ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Shows the current limit usage of unique series over an hourly period. Vmagent will start to drop series once the limit is reached.\n\nPlease note, panel will be blank if `remoteWrite.maxHourlySeries` is not set.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "line" + } + }, + "mappings": [], + "max": 100, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "transparent" + }, + { + "color": "red", + "value": 0.9 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 71 + }, + "id": 88, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.6", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": true, + "expr": "max(\n vmagent_hourly_series_limit_current_series{job=~\"$job\", instance=~\"$instance\"} \n / \n vmagent_hourly_series_limit_max_series{job=~\"$job\", instance=~\"$instance\"}\n ) by(job) * 100", + "interval": "", + "legendFormat": "{{job}}", + "range": true, + "refId": "A" + } + ], + "title": "Hourly series limit", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Shows saturation of every connection to remote storage. If the threshold of 90% is reached, then the connection is saturated (busy or slow) by more than 90%, so vmagent won't be able to keep up and can start buffering data. \n\nThis usually means that `-remoteWrite.queues` command-line flag must be increased in order to increase the number of connections per each remote storage.\n", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "line" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "transparent" + }, + { + "color": "red", + "value": 0.9 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 71 + }, + "id": 84, + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.2.6", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": true, + "expr": "max(\n rate(vmagent_remotewrite_send_duration_seconds_total{job=~\"$job\", instance=~\"$instance\", url=~\"$url\"}[$__rate_interval])\n /\n vmagent_remotewrite_queues{job=~\"$job\", instance=~\"$instance\", url=~\"$url\"}\n) by(job, url)", + "interval": "", + "legendFormat": "", + "range": true, + "refId": "A" + } + ], + "title": "Remote write connection saturation ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Shows the current limit usage of unique series over a daily period. Vmagent will start to drop series once the limit is reached.\n\nPlease note, panel will be blank if `remoteWrite.maxDailySeries` is not set.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "line" + } + }, + "mappings": [], + "max": 100, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "transparent" + }, + { + "color": "red", + "value": 0.9 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 79 + }, + "id": 90, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.6", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": true, + "expr": "max(\n vmagent_daily_series_limit_current_series{job=~\"$job\",instance=~\"$instance\"} \n / \n vmagent_daily_series_limit_max_series{job=~\"$job\",instance=~\"$instance\"}\n) by(job)", + "interval": "", + "legendFormat": "{{job}}", + "range": true, + "refId": "A" + } + ], + "title": "Daily series limit", + "type": "timeseries" + } + ], + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "refId": "A" + } + ], + "title": "Remote write", + "type": "row" + }, + { + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 39 + }, + "id": 113, + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "gridPos": { + "h": 2, + "w": 24, + "x": 0, + "y": 87 + }, + "id": 115, + "options": { + "code": { + "language": "plaintext", + "showLineNumbers": false, + "showMiniMap": false + }, + "content": "Drilldown row is used by other panels on the dashboard to show more detailed metrics per-instance.", + "mode": "markdown" + }, + "pluginVersion": "9.2.6", + "transparent": true, + "type": "text" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 89 + }, + "id": 119, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": false, + "expr": "sum(rate(process_cpu_seconds_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by(job, instance)", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "{{instance}} ({{job}})", + "range": true, + "refId": "A" + } + ], + "title": "CPU usage ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Shows the used memory (resident).\nThe application's performance will significantly degrade when memory usage is close to 100%.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "decbytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 89 + }, + "id": 117, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": true, + "expr": "max_over_time(process_resident_memory_bytes{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])", + "interval": "", + "legendFormat": "{{instance}} ({{job}})", + "range": true, + "refId": "A" + } + ], + "title": "RSS memory usage ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Shows the persistent queue size of pending samples in bytes which hasn't been flushed to remote storage yet. \n\nIncreasing of value might be a sign of connectivity issues. In such cases, vmagent starts to flush pending data on disk with attempt to send it later once connection is restored.\n\nRemote write URLs are hidden by default but might be unveiled once `-remoteWrite.showURL` is set to true.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 97 + }, + "id": 125, + "links": [ + { + "title": "Troubleshooting", + "url": "https://docs.victoriametrics.com/vmagent.html#troubleshooting" + } + ], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.6", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(vmagent_remotewrite_pending_data_bytes{job=~\"$job\", instance=~\"$instance\", url=~\"$url\"}) by (instance, url)", + "interval": "", + "legendFormat": "{{instance}} => {{url}}", + "range": true, + "refId": "A" + } + ], + "title": "Persistent queue size ($instance) to ($url)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Shows in/out samples rate including push and pull models. \n\nThe out-rate could be different to in-rate because of replication or additional timeseries added by vmagent for every scraped target.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": "/out .*/" + }, + "properties": [ + { + "id": "custom.transform", + "value": "negative-Y" + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 97 + }, + "id": 123, + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.6", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "sum(rate(vm_promscrape_scraped_samples_sum{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by(job, instance)\n+ sum(rate(vmagent_rows_inserted_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by(job, instance)", + "hide": false, + "interval": "", + "legendFormat": "in {{instance}} {{job}}", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "sum(rate(vmagent_remotewrite_block_size_rows_sum{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by(job, instance)", + "interval": "", + "legendFormat": "out {{instance}} {{job}}", + "range": true, + "refId": "B" + } + ], + "title": "Samples rate ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Shows the number of bytes read/write from the storage layer when vmagent has to buffer data on disk or read already buffered data.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "read" + }, + "properties": [ + { + "id": "custom.transform", + "value": "negative-Y" + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 105 + }, + "id": 121, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.6", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "sum(rate(process_io_storage_read_bytes_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by(job, instance)", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "read {{instance}} {{job}}", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "sum(rate(process_io_storage_written_bytes_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by(job,instance)", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "write {{instance}} {{job}}", + "range": true, + "refId": "B" + } + ], + "title": "Disk writes/reads ($instance)", + "type": "timeseries" + } + ], + "title": "Drilldown", + "type": "row" + } + ], + "refresh": "", + "schemaVersion": 37, + "style": "dark", + "tags": [ + "vmagent", + "victoriametrics" + ], + "templating": { + "list": [ + { + "current": { + "selected": true, + "text": "VictoriaMetrics", + "value": "VictoriaMetrics" + }, + "hide": 0, + "includeAll": false, + "multi": false, + "name": "ds", + "options": [], + "query": "prometheus", + "queryValue": "", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + }, + { + "allValue": "", + "current": {}, + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "definition": "label_values(vm_app_version{version=~\"^vmagent.*\"}, job)", + "hide": 0, + "includeAll": true, + "multi": true, + "name": "job", + "options": [], + "query": { + "query": "label_values(vm_app_version{version=~\"^vmagent.*\"}, job)", + "refId": "VictoriaMetrics-job-Variable-Query" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": ".*", + "current": {}, + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "definition": "label_values(vm_app_version{job=~\"$job\"}, instance)", + "hide": 0, + "includeAll": true, + "multi": true, + "name": "instance", + "options": [], + "query": { + "query": "label_values(vm_app_version{job=~\"$job\"}, instance)", + "refId": "VictoriaMetrics-instance-Variable-Query" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": ".*", + "current": {}, + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "definition": "label_values(vmagent_remotewrite_requests_total{job=~\"$job\", instance=~\"$instance\"}, url)", + "description": "The remote write URLs", + "hide": 0, + "includeAll": true, + "multi": true, + "name": "url", + "options": [], + "query": { + "query": "label_values(vmagent_remotewrite_requests_total{job=~\"$job\", instance=~\"$instance\"}, url)", + "refId": "StandardVariableQuery" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "filters": [], + "hide": 0, + "name": "adhoc", + "skipUrlSync": false, + "type": "adhoc" + } + ] + }, + "time": { + "from": "now-3h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "", + "title": "VictoriaMetrics - vmagent", + "uid": "G7Z9GzMGz", + "version": 1, + "weekStart": "" +} diff --git a/dashboards/victoria-metrics/vmalert.json b/dashboards/victoria-metrics/vmalert.json new file mode 100644 index 00000000..5a9d53e8 --- /dev/null +++ b/dashboards/victoria-metrics/vmalert.json @@ -0,0 +1,3260 @@ +{ + "__inputs": [], + "__elements": {}, + "__requires": [ + { + "type": "grafana", + "id": "grafana", + "name": "Grafana", + "version": "9.2.7" + }, + { + "type": "datasource", + "id": "prometheus", + "name": "Prometheus", + "version": "1.0.0" + }, + { + "type": "panel", + "id": "stat", + "name": "Stat", + "version": "" + }, + { + "type": "panel", + "id": "table", + "name": "Table", + "version": "" + }, + { + "type": "panel", + "id": "timeseries", + "name": "Time series", + "version": "" + } + ], + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "target": { + "limit": 100, + "matchAny": false, + "tags": [], + "type": "dashboard" + }, + "type": "dashboard" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "enable": true, + "expr": "sum(vm_app_version{job=~\"$job\", instance=~\"$instance\"}) by(short_version) unless (sum(vm_app_version{job=~\"$job\", instance=~\"$instance\"} offset 20m) by(short_version))", + "hide": true, + "iconColor": "dark-blue", + "name": "version", + "textFormat": "{{short_version}}", + "titleFormat": "Version change" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "enable": true, + "expr": "sum(changes(vm_app_start_timestamp{job=~\"$job\", instance=~\"$instance\"})) by(job, instance)", + "hide": true, + "iconColor": "dark-yellow", + "name": "restarts", + "textFormat": "{{job}}:{{instance}} restarted" + } + ] + }, + "description": "Overview for VictoriaMetrics vmalert v1.96.0 or higher", + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 1, + "id": null, + "links": [ + { + "asDropdown": false, + "icon": "external link", + "includeVars": false, + "keepTime": false, + "tags": [], + "targetBlank": true, + "title": "vmalert docs", + "tooltip": "", + "type": "link", + "url": "https://docs.victoriametrics.com/vmalert.html" + }, + { + "asDropdown": false, + "icon": "external link", + "includeVars": false, + "keepTime": false, + "tags": [], + "targetBlank": true, + "title": "Found a bug?", + "tooltip": "", + "type": "link", + "url": " https://github.com/VictoriaMetrics/VictoriaMetrics/issues" + }, + { + "asDropdown": false, + "icon": "external link", + "includeVars": false, + "keepTime": false, + "tags": [], + "targetBlank": true, + "title": "New releases", + "tooltip": "", + "type": "link", + "url": " https://github.com/VictoriaMetrics/VictoriaMetrics/releases" + } + ], + "liveNow": false, + "panels": [ + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 47, + "panels": [], + "title": "Stats", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Shows if the last configuration update was successful. \"Not Ok\" means there was an unsuccessful attempt to update the configuration due to some error. Check the log for details.", + "fieldConfig": { + "defaults": { + "mappings": [ + { + "options": { + "0": { + "color": "green", + "index": 0, + "text": "Ok" + } + }, + "type": "value" + }, + { + "options": { + "from": 1, + "result": { + "color": "red", + "index": 1, + "text": "Not Ok" + }, + "to": 999999 + }, + "type": "range" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 4, + "x": 0, + "y": 1 + }, + "id": 6, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "last" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "9.2.7", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "exemplar": false, + "expr": "count(vmalert_config_last_reload_successful{job=~\"$job\", instance=~\"$instance\"} < 1 ) or 0", + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "title": "Config update", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Shows the total number of loaded alerting rules across selected instances and groups.", + "fieldConfig": { + "defaults": { + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 5, + "x": 4, + "y": 1 + }, + "id": 9, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "last" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "9.2.7", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "exemplar": false, + "expr": "count(vmalert_alerting_rules_last_evaluation_samples{job=~\"$job\", instance=~\"$instance\", group=~\"$group\"})", + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "title": "Alerting rules", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Shows the total number of loaded recording rules across selected instances and groups.", + "fieldConfig": { + "defaults": { + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 5, + "x": 9, + "y": 1 + }, + "id": 7, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "last" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "9.2.7", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "exemplar": false, + "expr": "count(vmalert_recording_rules_last_evaluation_samples{job=~\"$job\", instance=~\"$instance\", group=~\"$group\"})", + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "title": "Recording rules", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Shows the total number of errors generated by recording/alerting rules for selected instances and groups.", + "fieldConfig": { + "defaults": { + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 1 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 5, + "x": 14, + "y": 1 + }, + "id": 8, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "last" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "9.2.7", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "exemplar": false, + "expr": "(sum(increase(vmalert_alerting_rules_errors_total{job=~\"$job\", instance=~\"$instance\", group=~\"$group\"}[$__rate_interval])) or vector(0)) + \n(sum(increase(vmalert_recording_rules_errors_total{job=~\"$job\", instance=~\"$instance\", group=~\"$group\"}[$__rate_interval])) or vector(0))", + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "title": "Errors", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Shows number of Recording Rules which produce no data.\n\n Usually it means that such rules are misconfigured, since they give no output during the evaluation.\nPlease check if rule's expression is correct and it is working as expected.", + "fieldConfig": { + "defaults": { + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 1 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 5, + "x": 19, + "y": 1 + }, + "id": 48, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "last" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "9.2.7", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": false, + "expr": "count(vmalert_recording_rules_last_evaluation_samples{job=~\"$job\", instance=~\"$instance\"} < 1) or 0", + "interval": "", + "legendFormat": "", + "range": true, + "refId": "A" + } + ], + "title": "No data errors", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "displayMode": "auto", + "inspect": false, + "minWidth": 50 + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Time" + }, + "properties": [ + { + "id": "custom.hidden", + "value": true + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value" + }, + "properties": [ + { + "id": "displayName", + "value": "Count" + } + ] + } + ] + }, + "gridPos": { + "h": 4, + "w": 9, + "x": 0, + "y": 4 + }, + "id": 45, + "options": { + "footer": { + "fields": "", + "reducer": [ + "sum" + ], + "show": false + }, + "showHeader": true + }, + "pluginVersion": "9.2.7", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": false, + "expr": "sum(vm_app_version{job=~\"$job\", instance=~\"$instance\"}) by(job, short_version)", + "format": "table", + "instant": true, + "range": false, + "refId": "A" + } + ], + "type": "table" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "stepAfter", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 0, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 15, + "x": 9, + "y": 4 + }, + "id": 4, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "right", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "asc" + } + }, + "pluginVersion": "9.2.6", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": false, + "expr": "sum(min_over_time(up{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by (job)", + "format": "time_series", + "instant": false, + "interval": "", + "legendFormat": "{{job}}", + "refId": "A" + } + ], + "title": "Uptime", + "type": "timeseries" + }, + { + "collapsed": false, + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 8 + }, + "id": 11, + "panels": [], + "targets": [ + { + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "refId": "A" + } + ], + "title": "Overview ($instance)", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Shows the number of fired alerts by job.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 9 + }, + "id": 15, + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.2.6", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": false, + "expr": "sum(increase(vmalert_alerts_fired_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by(job)", + "interval": "", + "legendFormat": "{{job}}", + "range": true, + "refId": "A" + } + ], + "title": "Alerts fired total ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Top $topk groups by evaluation duration. Shows groups that take the most of time during the evaluation across all instances.\n\nThe panel uses MetricsQL functions and may not work with Prometheus.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 9 + }, + "id": 23, + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.2.6", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": false, + "expr": "topk_max($topk, max(sum(\n rate(vmalert_iteration_duration_seconds_sum{job=~\"$job\", instance=~\"$instance\", group=~\"$group\"}[$__rate_interval])\n/\n rate(vmalert_iteration_duration_seconds_count{job=~\"$job\", instance=~\"$instance\", group=~\"$group\"}[$__rate_interval])\n) by(job, instance, group)) \nby(job, group))", + "interval": "", + "legendFormat": "{{group}} ({{job}})", + "range": true, + "refId": "A" + } + ], + "title": "Top $topk groups avg evaluation duration ($group)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Shows how many requests (executions) per second vmalert sends to the configured datasource.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 17 + }, + "id": 24, + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.2.6", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": false, + "expr": "sum(rate(vmalert_execution_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by (job)", + "interval": "", + "legendFormat": "{{job}}", + "range": true, + "refId": "A" + } + ], + "title": "Rules execution rate ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Shows the error rate while executing configured rules. Non-zero value means there are some issues with existing rules. Check the logs to get more details.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 17 + }, + "id": 25, + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.6", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": false, + "expr": "sum(rate(vmalert_execution_errors_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by(job) > 0", + "interval": "", + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "Rules execution errors ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "displayMode": "auto", + "inspect": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Value" + }, + "properties": [ + { + "id": "custom.hidden", + "value": true + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Time" + }, + "properties": [ + { + "id": "custom.hidden", + "value": true + } + ] + } + ] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 25 + }, + "id": 50, + "options": { + "footer": { + "fields": "", + "reducer": [ + "sum" + ], + "show": false + }, + "showHeader": true, + "sortBy": [ + { + "desc": true, + "displayName": "job" + } + ] + }, + "pluginVersion": "9.2.7", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": false, + "expr": "sum(flag{is_set=\"true\", job=~\"$job\", instance=~\"$instance\"}) by(job, instance, name, value)", + "format": "table", + "instant": true, + "legendFormat": "__auto", + "range": false, + "refId": "A" + } + ], + "title": "Non-default flags", + "transformations": [ + { + "id": "groupBy", + "options": { + "fields": { + "instance": { + "aggregations": [ + "uniqueValues" + ], + "operation": "aggregate" + }, + "job": { + "aggregations": [], + "operation": "groupby" + }, + "name": { + "aggregations": [], + "operation": "groupby" + }, + "value": { + "aggregations": [], + "operation": "groupby" + } + } + } + } + ], + "type": "table" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Missed evaluation means that group evaluation time takes longer than the configured evaluation interval. \nThis may result in missed alerting notifications or recording rules samples. Try increasing evaluation interval or concurrency for such groups. See https://docs.victoriametrics.com/vmalert.html#groups\n\nIf rule expressions are taking longer than expected, please see https://docs.victoriametrics.com/Troubleshooting.html#slow-queries.\"", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "bars", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 25 + }, + "id": 58, + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.6", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": false, + "expr": "sum(increase(vmalert_iteration_missed_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by(job, group) > 0", + "interval": "1m", + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "Missed evaluations ($instance)", + "type": "timeseries" + }, + { + "collapsed": true, + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 32 + }, + "id": 43, + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "The precentage of used RSS memory\n\nIf you think that usage is abnormal or unexpected, please file an issue and attach memory profile if possible.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 33 + }, + "id": 37, + "links": [ + { + "targetBlank": true, + "title": "Profiling", + "url": "https://docs.victoriametrics.com/vmagent.html#profiling" + } + ], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.2.6", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": false, + "expr": "max(\n max_over_time(process_resident_memory_bytes{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])\n /\n vm_available_memory_bytes{job=~\"$job\", instance=~\"$instance\"}\n) by(job)", + "interval": "", + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "Memory usage % ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Amount of used RSS memory\n\nIf you think that usage is abnormal or unexpected, please file an issue and attach memory profile if possible.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 33 + }, + "id": 57, + "links": [ + { + "targetBlank": true, + "title": "Profiling", + "url": "https://docs.victoriametrics.com/vmagent.html#profiling" + } + ], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.2.6", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": false, + "expr": "max(\n max_over_time(process_resident_memory_bytes{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])\n) by(job)", + "interval": "", + "legendFormat": "{{job}}", + "range": true, + "refId": "A" + } + ], + "title": "Memory usage ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Shows the CPU usage percentage per vmalert instance. \nIf you think that usage is abnormal or unexpected pls file an issue and attach CPU profile if possible.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 41 + }, + "id": 35, + "links": [ + { + "targetBlank": true, + "title": "Profiling", + "url": "https://docs.victoriametrics.com/vmagent.html#profiling" + } + ], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.2.6", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": false, + "expr": "max(\n rate(process_cpu_seconds_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval]) \n / \n vm_available_cpu_cores{job=~\"$job\", instance=~\"$instance\"}\n) by(job)", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "{{job}}", + "range": true, + "refId": "A" + } + ], + "title": "CPU usage %($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Shows the max number of CPU cores used by a `job` and the corresponding limit.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 41 + }, + "id": 56, + "links": [ + { + "targetBlank": true, + "title": "Profiling", + "url": "https://docs.victoriametrics.com/vmagent.html#profiling" + } + ], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.2.6", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": false, + "expr": "max(rate(process_cpu_seconds_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by(job)", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "{{job}}", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": false, + "expr": "min(process_cpu_cores_available{job=~\"$job\", instance=~\"$instance\"}) by(job)", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "limit ({{job}})", + "range": true, + "refId": "B" + } + ], + "title": "CPU usage ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Panel shows the percentage of open file descriptors in the OS.\nReaching the limit of open files can cause various issues and must be prevented.\n\nSee how to change limits here https://medium.com/@muhammadtriwibowo/set-permanently-ulimit-n-open-files-in-ubuntu-4d61064429a", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 3, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 49 + }, + "id": 39, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.2.6", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": false, + "expr": "max(\n max_over_time(process_open_fds{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])\n /\n process_max_fds{job=~\"$job\", instance=~\"$instance\"}\n) by(job)", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "Open FDs usage % ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 0, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 49 + }, + "id": 41, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.6", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "sum(go_goroutines{job=~\"$job\", instance=~\"$instance\"}) by(job)", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "Goroutines ($instance)", + "type": "timeseries" + } + ], + "targets": [ + { + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "refId": "A" + } + ], + "title": "Resource usage", + "type": "row" + }, + { + "collapsed": true, + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 33 + }, + "id": 17, + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Shows top $topk current active (firing) alerting rules.\n\nThe panel uses MetricsQL functions and may not work with Prometheus.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 28 + }, + "id": 14, + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.2.6", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": false, + "expr": "topk_max($topk, sum(vmalert_alerts_firing{job=~\"$job\", instance=~\"$instance\", group=~\"$group\"}) by(job, group, alertname) > 0)", + "interval": "", + "legendFormat": "{{group}}.{{alertname}} ({{job}})", + "range": true, + "refId": "A" + } + ], + "title": "Top $topk active alerts ($group)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Shows the events when rule execution resulted into an error. Check the logs for more details.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 28 + }, + "id": 13, + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.2.6", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": false, + "expr": "sum(increase(vmalert_alerting_rules_errors_total{job=~\"$job\", instance=~\"$instance\", group=~\"$group\"}[$__rate_interval])) by(job, group, alertname) > 0", + "interval": "", + "legendFormat": "{{group}}.{{alertname}} ({{job}})", + "range": true, + "refId": "A" + } + ], + "title": "Errors ($group)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Shows the current pending alerting rules per group.\nBy pending means the rule which remains active less than configured `for` parameter.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 36 + }, + "id": 20, + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Mean", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.2.6", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": false, + "expr": "sum(vmalert_alerts_pending{job=~\"$job\", instance=~\"$instance\", group=~\"$group\"}) by(job, group, alertname) > 0", + "interval": "", + "legendFormat": "{{group}}.{{alertname}} ({{job}})", + "range": true, + "refId": "A" + } + ], + "title": "Pending ($group)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Shows the error rate for the attempts to send alerts to Alertmanager. If not zero it means there issues on attempt to send notification to Alertmanager and some alerts may be not delivered properly. Check the logs for more details.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 36 + }, + "id": 32, + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.2.6", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "exemplar": false, + "expr": "sum(rate(vmalert_alerts_send_errors_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by(instance, addr) > 0", + "interval": "", + "legendFormat": "{{instance}} => {{addr}}", + "refId": "A" + } + ], + "title": "Errors rate to Alertmanager", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Shows how many alerts are sent to Alertmanager per second. Only active alerts are sent.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 44 + }, + "id": 26, + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.2.6", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": false, + "expr": "sum(rate(vmalert_alerts_sent_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by(job, addr) > 0", + "interval": "", + "legendFormat": "{{job}} => {{addr}}", + "range": true, + "refId": "A" + } + ], + "title": "Requests rate to Alertmanager by job ($group)", + "type": "timeseries" + } + ], + "targets": [ + { + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "refId": "A" + } + ], + "title": "Alerting rules ($instance)", + "type": "row" + }, + { + "collapsed": true, + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 34 + }, + "id": 28, + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Shows the top $topk recording rules which generate the most of samples. Each generated sample is basically a time series which then ingested into configured remote storage. Rules with high numbers may cause the most pressure on the remote database and become a source of too high cardinality.\n\nThe panel uses MetricsQL functions and may not work with Prometheus.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 43 + }, + "id": 31, + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.2.6", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": false, + "expr": "topk_max($topk, \n max(\n sum(vmalert_recording_rules_last_evaluation_samples{job=~\"$job\", instance=~\"$instance\", group=~\"$group\"}) by(job, instance, group, recording) > 0\n ) by(job, group, recording)\n)", + "interval": "", + "legendFormat": "{{group}}.{{recording}} ({{job}})", + "range": true, + "refId": "A" + } + ], + "title": "Top $topk rules by produced samples ($group)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Shows the rules which do not produce any samples during the evaluation. Usually it means that such rules are misconfigured, since they give no output during the evaluation.\nPlease check if rule's expression is correct and it is working as expected.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 43 + }, + "id": 33, + "options": { + "legend": { + "calcs": [ + "lastNotNull", + "max", + "mean" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "8.0.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": false, + "expr": "count(vmalert_recording_rules_last_evaluation_samples{job=~\"$job\", instance=~\"$instance\", group=~\"$group\"} < 1) by(job, group, recording)", + "interval": "", + "legendFormat": "{{group}}.{{recording}} ({{job}})", + "range": true, + "refId": "A" + } + ], + "title": "Rules with 0 produced samples ($group)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 51 + }, + "id": 30, + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.6", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "exemplar": false, + "expr": "sum(increase(vmalert_recording_rules_errors_total{job=~\"$job\", instance=~\"$instance\", group=~\"$group\"}[$__rate_interval])) by(job, group, recording) > 0", + "interval": "", + "legendFormat": "{{group}}.{{recording}} ({{job}})", + "range": true, + "refId": "A" + } + ], + "title": "Errors ($group)", + "type": "timeseries" + } + ], + "targets": [ + { + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "refId": "A" + } + ], + "title": "Recording rules ($instance)", + "type": "row" + }, + { + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 35 + }, + "id": 55, + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 9 + }, + "id": 52, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "desc" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "sum(rate(vmalert_remotewrite_sent_rows_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by(job)", + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "Datapoints send rate ($instance)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "description": "Shows the number of datapoints dropped by vmalert while sending to the configured remote write URL. vmalert performs up to 5 retries before dropping the data. Check vmalert's error logs for the specific error message.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 9 + }, + "id": 53, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "desc" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "editorMode": "code", + "expr": "sum(rate(vmalert_remotewrite_dropped_rows_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by(job) > 0", + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "Datapoints drop rate ($instance)", + "type": "timeseries" + } + ], + "title": "Remote write", + "type": "row" + } + ], + "refresh": false, + "schemaVersion": 37, + "style": "dark", + "tags": [ + "victoriametrics", + "vmalert" + ], + "templating": { + "list": [ + { + "current": { + "selected": false, + "text": "VictoriaMetrics - cluster", + "value": "VictoriaMetrics - cluster" + }, + "hide": 0, + "includeAll": false, + "multi": false, + "name": "ds", + "options": [], + "query": "prometheus", + "queryValue": "", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + }, + { + "current": {}, + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "definition": "label_values(vm_app_version{version=~\"^vmalert.*\"}, job)", + "hide": 0, + "includeAll": true, + "multi": true, + "name": "job", + "options": [], + "query": { + "query": "label_values(vm_app_version{version=~\"^vmalert.*\"}, job)", + "refId": "StandardVariableQuery" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "allValue": ".*", + "current": {}, + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "definition": "label_values(vm_app_version{job=~\"$job\"}, instance)", + "hide": 0, + "includeAll": true, + "multi": true, + "name": "instance", + "options": [], + "query": { + "query": "label_values(vm_app_version{job=~\"$job\"}, instance)", + "refId": "StandardVariableQuery" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "allValue": ".*", + "current": {}, + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "definition": "label_values(vmalert_iteration_duration_seconds{job=~\"$job\", instance=~\"$instance\"}, group)", + "hide": 0, + "includeAll": true, + "multi": true, + "name": "group", + "options": [], + "query": { + "query": "label_values(vmalert_iteration_duration_seconds{job=~\"$job\", instance=~\"$instance\"}, group)", + "refId": "StandardVariableQuery" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "current": { + "selected": false, + "text": "5", + "value": "5" + }, + "hide": 0, + "includeAll": false, + "multi": false, + "name": "topk", + "options": [ + { + "selected": true, + "text": "5", + "value": "5" + }, + { + "selected": false, + "text": "10", + "value": "10" + }, + { + "selected": false, + "text": "20", + "value": "20" + }, + { + "selected": false, + "text": "30", + "value": "30" + }, + { + "selected": false, + "text": "40", + "value": "40" + }, + { + "selected": false, + "text": "50", + "value": "50" + } + ], + "query": "5, 10, 20, 30, 40, 50", + "queryValue": "", + "skipUrlSync": false, + "type": "custom" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$ds" + }, + "filters": [], + "hide": 0, + "name": "adhoc", + "skipUrlSync": false, + "type": "adhoc" + } + ] + }, + "time": { + "from": "now-3h", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "VictoriaMetrics - vmalert", + "uid": "LzldHAVnz", + "version": 1, + "weekStart": "" +} \ No newline at end of file diff --git a/hack/download-dashboards.sh b/hack/download-dashboards.sh new file mode 100755 index 00000000..a6c0f676 --- /dev/null +++ b/hack/download-dashboards.sh @@ -0,0 +1,112 @@ +#https://github.com/deckhouse/deckhouse/blob/main/modules/340-monitoring-kubernetes-control-plane/monitoring/grafana-dashboards/kubernetes-cluster/control-plane-status.json +base=https://github.com/deckhouse/deckhouse/raw/main/ +dir="grafana-dashboards" +mkdir -p "$dir" + + + +add_ds_prometheus(){ + jq '.templating.list |= [{"current":{"selected":false,"text":"default","value":"default"},"description":null,"error":null,"hide":0,"includeAll":false,"label":"datasource","multi":false,"name":"ds_prometheus","options":[],"query":"prometheus","refresh":1,"regex":"","skipUrlSync":false,"type":"datasource"}] + .' +} + +indent() { + sed "s/^/$(head -c "$1" < /dev/zero | tr '\0' ' ')/" +} + +fix_d8() { + sed \ + -e 's|$__interval_sx3|$__rate_interval|g' \ + -e 's|$__interval_sx4|$__rate_interval|g' \ + -e 's|P0D6E4079E36703EB|$ds_prometheus|g' +} + +swap_pvc_overview() { + jq '(.panels[] | select(.title=="PVC Detailed") | .panels[] | select(.title=="Overview")) as $a | del(.panels[] | select(.title=="PVC Detailed").panels[] | select(.title=="Overview")) | ( (.panels[] | select(.title=="PVC Detailed"))) as $b | del( .panels[] | select(.title=="PVC Detailed")) | (.panels[.panels|length]=($a|.gridPos.y=$b.gridPos.y)) | (.panels[.panels|length]=($b|.gridPos.y=$a.gridPos.y))' +} + +deprectaed_remove_faq() { + jq 'del(.panels[] | select(.title == "How to find who sends requests to deprecated APIs"))| (.panels[]|select(.type == "text")).gridPos.x = 12 | (.panels[]|select(.type == "text")).gridPos.w = 12' +} + +while read url others; do + name="$(basename "$url" .json | tr _ -)" + case $url in + modules/042-kube-dns/*) + ddir=control-plane + ;; + modules/402-ingress-nginx/*) + ddir=ingress + ;; + modules/340-monitoring-kubernetes/*) + ddir=main + ;; + modules/340-monitoring-kubernetes-control-plane/*) + ddir=control-plane + ;; + esac + file="$dir/$ddir/$name.json" + echo "$file" + mkdir -p "$dir/$ddir" + curl -sSL "$base$url" -o "$file.tmp" + + case "$name" in + "deprecated-resources") + filters="add_ds_prometheus | deprectaed_remove_faq | fix_d8" + ;; + *) + filters="fix_d8" + ;; + esac + + cat "$file.tmp" | eval "$filters" > "$file" +done <<\EOT +modules/042-kube-dns/monitoring/grafana-dashboards/kubernetes-cluster/dns/dns-coredns.json +modules/402-ingress-nginx/monitoring/grafana-dashboards/kubernetes-cluster/controllers.json +modules/402-ingress-nginx/monitoring/grafana-dashboards/kubernetes-cluster/controller-detail.json +modules/402-ingress-nginx/monitoring/grafana-dashboards/ingress-nginx/namespace/namespace_detail.json +modules/402-ingress-nginx/monitoring/grafana-dashboards/ingress-nginx/namespace/namespaces.json +modules/402-ingress-nginx/monitoring/grafana-dashboards/ingress-nginx/vhost/vhost_detail.json +modules/402-ingress-nginx/monitoring/grafana-dashboards/ingress-nginx/vhost/vhosts.json +modules/340-monitoring-kubernetes-control-plane/monitoring/grafana-dashboards/kubernetes-cluster/control-plane-status.json +modules/340-monitoring-kubernetes-control-plane/monitoring/grafana-dashboards/kubernetes-cluster/kube-etcd3.json #TODO +modules/340-monitoring-kubernetes-control-plane/monitoring/grafana-dashboards/kubernetes-cluster/deprecated-resources.json +modules/340-monitoring-kubernetes/monitoring/grafana-dashboards//kubernetes-cluster/nodes/ntp.json #TODO +modules/340-monitoring-kubernetes/monitoring/grafana-dashboards//kubernetes-cluster/nodes/nodes.json +modules/340-monitoring-kubernetes/monitoring/grafana-dashboards//kubernetes-cluster/nodes/node.json +modules/340-monitoring-kubernetes/monitoring/grafana-dashboards//main/controller.json +modules/340-monitoring-kubernetes/monitoring/grafana-dashboards//main/pod.json +modules/340-monitoring-kubernetes/monitoring/grafana-dashboards//main/namespace/namespaces.json +modules/340-monitoring-kubernetes/monitoring/grafana-dashboards//main/namespace/namespace.json +modules/340-monitoring-kubernetes/monitoring/grafana-dashboards//main/capacity-planning/capacity-planning.json +EOT + + + +while read url others; do + name="$(basename "$url" .json | tr _ -)" + case $url in + *VictoriaMetrics*) + ddir=victoria-metrics + ;; + */dotdc/*) + ddir=dotdc + ;; + esac + file="$dir/$ddir/$name.json" + + mkdir -p "$dir/$ddir" + echo "$file" + curl -sSL "$url" -o "$file" +done <<\EOT + https://raw.githubusercontent.com/VictoriaMetrics/VictoriaMetrics/master/dashboards/victoriametrics.json + https://raw.githubusercontent.com/VictoriaMetrics/VictoriaMetrics/master/dashboards/vmagent.json + https://raw.githubusercontent.com/VictoriaMetrics/VictoriaMetrics/master/dashboards/victoriametrics-cluster.json + https://raw.githubusercontent.com/VictoriaMetrics/VictoriaMetrics/master/dashboards/vmalert.json + https://raw.githubusercontent.com/VictoriaMetrics/VictoriaMetrics/master/dashboards/operator.json + https://raw.githubusercontent.com/VictoriaMetrics/VictoriaMetrics/master/dashboards/backupmanager.json + https://raw.githubusercontent.com/dotdc/grafana-dashboards-kubernetes/master/dashboards/k8s-system-coredns.json + https://raw.githubusercontent.com/dotdc/grafana-dashboards-kubernetes/master/dashboards/k8s-views-global.json + https://raw.githubusercontent.com/dotdc/grafana-dashboards-kubernetes/master/dashboards/k8s-views-namespaces.json + https://raw.githubusercontent.com/dotdc/grafana-dashboards-kubernetes/master/dashboards/k8s-views-pods.json +EOT + diff --git a/hack/gen_versions_map.sh b/hack/gen_versions_map.sh new file mode 100755 index 00000000..1d9f1c5d --- /dev/null +++ b/hack/gen_versions_map.sh @@ -0,0 +1,31 @@ +#!/bin/sh +set -e +file=versions_map +charts=$(find . -mindepth 2 -maxdepth 2 -name Chart.yaml | awk 'sub("/Chart.yaml", "")') + +# +new_map=$( + for chart in $charts; do + awk '/^name:/ {chart=$2} /^version:/ {version=$2} END{printf "%s %s %s\n", chart, version, "HEAD"}' $chart/Chart.yaml + done +) + +if [ ! -f "$file" ] || [ ! -s "$file" ]; then + echo "$new_map" > "$file" + exit 0 +fi + +miss_map=$(echo "$new_map" | awk 'NR==FNR { new_map[$1 " " $2] = $3; next } { if (!($1 " " $2 in new_map)) print $1, $2, $3}' - $file) + +resolved_miss_map=$( + echo "$miss_map" | while read chart version commit; do + if [ "$commit" = HEAD ]; then + line=$(git show HEAD:"./$chart/Chart.yaml" | awk '/^version:/ {print NR; exit}') + change_commit=$(git --no-pager blame -L"$line",+1 HEAD -- "$chart/Chart.yaml" | awk '{print $1}') + commit=$(git describe --always "$change_commit~1") + fi + echo "$chart $version $commit" + done +) + +printf "%s\n" "$new_map" "$resolved_miss_map" | sort -k1,1 -k2,2 -V | awk '$1' > "$file" diff --git a/img/cozystack-logo.svg b/img/cozystack-logo.svg new file mode 100644 index 00000000..dd04b4ad --- /dev/null +++ b/img/cozystack-logo.svg @@ -0,0 +1,51 @@ + + + + + + + + diff --git a/manifests/cozystack-installer.yaml b/manifests/cozystack-installer.yaml new file mode 100644 index 00000000..8bd53d25 --- /dev/null +++ b/manifests/cozystack-installer.yaml @@ -0,0 +1,94 @@ +--- +# Source: cozy-installer/templates/cozystack.yaml +apiVersion: v1 +kind: Namespace +metadata: + name: cozy-system + labels: + pod-security.kubernetes.io/enforce: privileged +--- +# Source: cozy-installer/templates/cozystack.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: cozystack + namespace: cozy-system +--- +# Source: cozy-installer/templates/cozystack.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: cozystack + namespace: cozy-system +--- +# Source: cozy-installer/templates/cozystack.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: cozystack +subjects: +- kind: ServiceAccount + name: cozystack + namespace: cozy-system +roleRef: + kind: ClusterRole + name: cluster-admin + apiGroup: rbac.authorization.k8s.io +--- +# Source: cozy-installer/templates/cozystack.yaml +apiVersion: v1 +kind: Service +metadata: + name: cozystack + namespace: cozy-system +spec: + ports: + - name: http + port: 80 + targetPort: 8123 + selector: + app: cozystack + type: ClusterIP +--- +# Source: cozy-installer/templates/cozystack.yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: cozystack + namespace: cozy-system +spec: + replicas: 1 + selector: + matchLabels: + app: cozystack + strategy: + type: Recreate + template: + metadata: + labels: + app: cozystack + spec: + hostNetwork: true + serviceAccountName: cozystack + containers: + - name: cozystack + image: "ghcr.io/aenix-io/cozystack/installer:v0.0.1@sha256:d9edaf7fd53910c979575caf633875af2d16cc8611f79553cee8c18aade067b3" + env: + - name: KUBERNETES_SERVICE_HOST + value: localhost + - name: KUBERNETES_SERVICE_PORT + value: "7445" + - name: darkhttpd + image: "ghcr.io/aenix-io/cozystack/installer:v0.0.1@sha256:d9edaf7fd53910c979575caf633875af2d16cc8611f79553cee8c18aade067b3" + command: + - /usr/bin/darkhttpd + - /cozystack/assets + - --port + - "8123" + ports: + - name: http + containerPort: 8123 + tolerations: + - key: "node.kubernetes.io/not-ready" + operator: "Exists" + effect: "NoSchedule" diff --git a/packages/apps/Makefile b/packages/apps/Makefile new file mode 100644 index 00000000..92f68b9c --- /dev/null +++ b/packages/apps/Makefile @@ -0,0 +1,20 @@ +OUT=../../_out/repos/apps +TMP=../../_out/repos/apps/historical + +repo: + rm -rf "$(OUT)" + mkdir -p "$(OUT)" + awk '$$3 != "HEAD" {print "mkdir -p $(TMP)/" $$1 "-" $$2}' versions_map | sh -ex + awk '$$3 != "HEAD" {print "git archive " $$3 " " $$1 " | tar -xf- --strip-components=1 -C $(TMP)/" $$1 "-" $$2 }' versions_map | sh -ex + helm package -d "$(OUT)" $$(find . $(TMP) -mindepth 2 -maxdepth 2 -name Chart.yaml | awk 'sub("/Chart.yaml", "")' | sort -V) + cd "$(OUT)" && helm repo index . + rm -rf "$(TMP)" + +fix-chartnames: + find . -name Chart.yaml -maxdepth 2 | awk -F/ '{print $$2}' | while read i; do sed -i "s/^name: .*/name: $$i/" "$$i/Chart.yaml"; done + +gen-versions-map: fix-chartnames + ../../hack/gen_versions_map.sh + +check-version-map: gen-versions-map + git diff --exit-code -- versions_map diff --git a/packages/apps/http-cache/.helmignore b/packages/apps/http-cache/.helmignore new file mode 100644 index 00000000..0e8a0eb3 --- /dev/null +++ b/packages/apps/http-cache/.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/packages/apps/http-cache/Chart.yaml b/packages/apps/http-cache/Chart.yaml new file mode 100644 index 00000000..85eecbf4 --- /dev/null +++ b/packages/apps/http-cache/Chart.yaml @@ -0,0 +1,25 @@ +apiVersion: v2 +name: http-cache +description: Layer7 load balacner and caching service +icon: https://www.svgrepo.com/show/373924/nginx.svg + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +# Versions are expected to follow Semantic Versioning (https://semver.org/) +version: 0.1.0 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. Versions are not expected to +# follow Semantic Versioning. They should reflect the version the application is using. +# It is recommended to use it with quotes. +appVersion: "1.16.0" diff --git a/packages/apps/http-cache/Makefile b/packages/apps/http-cache/Makefile new file mode 100644 index 00000000..59f2d793 --- /dev/null +++ b/packages/apps/http-cache/Makefile @@ -0,0 +1,35 @@ +PUSH := 1 +LOAD := 0 +REGISTRY := ghcr.io/aenix-io/cozystack +TAG := v0.0.1 + +image: image-nginx + +image-nginx: + docker buildx build --platform linux/amd64 --build-arg ARCH=amd64 images/nginx-cache \ + --provenance false \ + --tag $(REGISTRY)/nginx-cache:$(TAG) \ + --cache-from type=registry,ref=$(REGISTRY)/nginx-cache:$(TAG) \ + --cache-to type=inline \ + --metadata-file images/nginx-cache.json \ + --push=$(PUSH) \ + --load=$(LOAD) + echo "$(REGISTRY)/nginx:$(TAG)" > images/nginx-cache.tag + +update: + tag=$$(git ls-remote --tags --sort="v:refname" https://github.com/chrislim2888/IP2Location-C-Library | awk -F'[/^]' 'END{print $$3}') && \ + sed -i "/^ARG IP2LOCATION_C_VERSION=/ s/=.*/=$$tag/" images/nginx/Dockerfile + tag=$$(git ls-remote --tags --sort="v:refname" https://github.com/ip2location/ip2proxy-c | awk -F'[/^]' 'END{print $$3}') && \ + sed -i "/^ARG IP2PROXY_C_VERSION=/ s/=.*/=$$tag/" images/nginx/Dockerfile + tag=$$(git ls-remote --tags --sort="v:refname" https://github.com/ip2location/ip2location-nginx | awk -F'[/^]' 'END{print $$3}') && \ + sed -i "/^ARG IP2LOCATION_NGINX_VERSION=/ s/=.*/=$$tag/" images/nginx/Dockerfile + tag=$$(git ls-remote --tags --sort="v:refname" https://github.com/ip2location/ip2proxy-nginx | awk -F'[/^]' 'END{print $$3}') && \ + sed -i "/^ARG IP2PROXY_NGINX_VERSION=/ s/=.*/=$$tag/" images/nginx/Dockerfile + tag=$$(git ls-remote --tags --sort="v:refname" https://github.com/nginx/nginx | awk -F'[/^]' 'END{print $$3}' | awk -F- '{print $$2}') && \ + sed -i "/^ARG NGINX_VERSION=/ s/=.*/=$$tag/" images/nginx/Dockerfile + tag=$$(git ls-remote --tags --sort="v:refname" https://github.com/nginx-modules/ngx_cache_purge | awk -F'[/^]' 'END{print $$3}') && \ + sed -i "/^ARG NGINX_CACHE_PURGE_VERSION=/ s/=.*/=$$tag/" images/nginx/Dockerfile + tag=$$(git ls-remote --tags --sort="v:refname" https://github.com/vozlt/nginx-module-vts | awk -F'[/^]' 'END{print $$3}' | sed 's/^v//') && \ + sed -i "/^ARG NGINX_VTS_VERSION=/ s/=.*/=$$tag/" images/nginx/Dockerfile + tag=$$(git ls-remote --tags --sort="v:refname" https://github.com/51Degrees/Device-Detection | awk -F'[/^]' 'END{print $$3}' | sed 's/^v//') && \ + sed -i "/^ARG FIFTYONEDEGREES_NGINX_VERSION=/ s/=.*/=$$tag/" images/nginx/Dockerfile diff --git a/packages/apps/http-cache/README.md b/packages/apps/http-cache/README.md new file mode 100644 index 00000000..90b8e7e8 --- /dev/null +++ b/packages/apps/http-cache/README.md @@ -0,0 +1,57 @@ +# Managed Nginx Caching Service + +The Nginx Caching Service is designed to optimize web traffic and enhance web application performance. This service combines custom-built Nginx instances with HAproxy for efficient caching and load balancing. + +## Deployment infromation + +The Nginx instances include the following modules and features: + +- VTS module for statistics +- Integration with ip2location +- Integration with ip2proxy +- Support for 51Degrees +- Cache purge functionality + +HAproxy plays a vital role in this setup by directing incoming traffic to specific Nginx instances based on a consistent hash calculated from the URL. Each Nginx instance includes a Persistent Volume Claim (PVC) for storing cached content, ensuring fast and reliable access to frequently used resources. + +## Deployment Details + +The deployment architecture is illustrated in the diagram below: + +``` + + ┌─────────┐ + │ metallb │ arp announce + └────┬────┘ + │ + │ + ┌───────▼───────────────────────────┐ + │ kubernetes service │ node + │ (externalTrafficPolicy: Local) │ level + └──────────┬────────────────────────┘ + │ + │ + ┌────▼────┐ ┌─────────┐ + │ haproxy │ │ haproxy │ loadbalancer + │ (active)│ │ (backup)│ layer + └────┬────┘ └─────────┘ + │ + │ balance uri whole + │ hash-type consistent + ┌──────┴──────┬──────────────┐ + ┌───▼───┐ ┌───▼───┐ ┌───▼───┐ caching + │ nginx │ │ nginx │ │ nginx │ layer + └───┬───┘ └───┬───┘ └───┬───┘ + │ │ │ + ┌────┴───────┬─────┴────┬─────────┴──┐ + │ │ │ │ + ┌───▼────┐ ┌────▼───┐ ┌───▼────┐ ┌────▼───┐ + │ origin │ │ origin │ │ origin │ │ origin │ + └────────┘ └────────┘ └────────┘ └────────┘ + +``` + +## Known issues + +VTS module shows wrong upstream resonse time +- https://github.com/vozlt/nginx-module-vts/issues/198 diff --git a/packages/apps/http-cache/images/nginx-cache.json b/packages/apps/http-cache/images/nginx-cache.json new file mode 100644 index 00000000..ea644a3c --- /dev/null +++ b/packages/apps/http-cache/images/nginx-cache.json @@ -0,0 +1,14 @@ +{ + "containerimage.config.digest": "sha256:d68641167af14b246e0332c14a7a9d9f6c0a4f813881db2de5fc53816bd35786", + "containerimage.descriptor": { + "mediaType": "application/vnd.docker.distribution.manifest.v2+json", + "digest": "sha256:241da53aba9b121d5d1829744a9ba31036cd5e5ffd6cf584da8113ddd79764f2", + "size": 1093, + "platform": { + "architecture": "amd64", + "os": "linux" + } + }, + "containerimage.digest": "sha256:241da53aba9b121d5d1829744a9ba31036cd5e5ffd6cf584da8113ddd79764f2", + "image.name": "ghcr.io/aenix-io/cozystack/nginx-cache:v0.0.1" +} \ No newline at end of file diff --git a/packages/apps/http-cache/images/nginx-cache.tag b/packages/apps/http-cache/images/nginx-cache.tag new file mode 100644 index 00000000..63b199f0 --- /dev/null +++ b/packages/apps/http-cache/images/nginx-cache.tag @@ -0,0 +1 @@ +ghcr.io/aenix-io/cozystack/nginx:v0.0.1 diff --git a/packages/apps/http-cache/images/nginx-cache/Dockerfile b/packages/apps/http-cache/images/nginx-cache/Dockerfile new file mode 100644 index 00000000..f121a3ab --- /dev/null +++ b/packages/apps/http-cache/images/nginx-cache/Dockerfile @@ -0,0 +1,178 @@ +FROM ubuntu:22.04 as stage + +ARG NGINX_VERSION=1.25.3 +ARG IP2LOCATION_C_VERSION=8.6.1 +ARG IP2PROXY_C_VERSION=4.1.2 +ARG IP2LOCATION_NGINX_VERSION=8.6.0 +ARG IP2PROXY_NGINX_VERSION=8.1.1 +ARG FIFTYONEDEGREES_NGINX_VERSION=3.2.21.1 +ARG NGINX_CACHE_PURGE_VERSION=2.5.3 +ARG NGINX_VTS_VERSION=0.2.2 + +# Install required packages for development +RUN apt-get update -q \ + && apt-get install -yq \ + unzip \ + autoconf \ + build-essential \ + libtool \ + libpcre3 \ + libpcre3-dev \ + libssl-dev \ + libgd-dev \ + zlib1g-dev \ + gcc \ + make \ + git \ + wget \ + curl \ + checkinstall + +# Download sources +RUN mkdir ip2location \ + && curl -sS -L https://github.com/chrislim2888/IP2Location-C-Library/archive/refs/tags/${IP2LOCATION_C_VERSION}.tar.gz \ + | tar -C ip2location -xzvf- --strip=1 + +RUN mkdir ip2proxy \ + && curl -sS -L https://github.com/ip2location/ip2proxy-c/archive/refs/tags/${IP2PROXY_C_VERSION}.tar.gz \ + | tar -C ip2proxy -xzvf- --strip=1 + +RUN mkdir ip2mod-location \ + && curl -sS -L https://github.com/ip2location/ip2location-nginx/archive/refs/tags/${IP2LOCATION_NGINX_VERSION}.tar.gz \ + | tar -C ip2mod-location -xzvf- --strip=1 + +RUN mkdir ip2mod-proxy \ + && curl -sS -L https://github.com/ip2location/ip2proxy-nginx/archive/refs/tags/${IP2PROXY_NGINX_VERSION}.tar.gz \ + | tar -C ip2mod-proxy -xzvf- --strip=1 + +RUN mkdir cache-purge-module \ + && curl -sS -L https://github.com/nginx-modules/ngx_cache_purge/archive/refs/tags/${NGINX_CACHE_PURGE_VERSION}.tar.gz \ + | tar -C cache-purge-module -xzvf- --strip=1 + +RUN mkdir nginx-module-vts \ + && curl -sS -L https://github.com/vozlt/nginx-module-vts/archive/refs/tags/v${NGINX_VTS_VERSION}.tar.gz \ + | tar -C nginx-module-vts -xzvf- --strip=1 + +RUN mkdir nginx \ + && curl -sS -L https://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz \ + | tar -C nginx -xzvf- --strip=1 + +# Compile C Library for IP2Location module +WORKDIR /ip2location +RUN autoreconf -i -v --force +RUN ./configure +RUN make +RUN checkinstall \ + -D \ + --install=no \ + --default \ + --pkgname=ip2location-c \ + --pkgversion=${IP2LOCATION_C_VERSION} \ + --pkgarch=amd64 \ + --pkggroup=lib \ + --pkgsource="https://github.com/chrislim2888/IP2Location-C-Library" \ + --maintainer="Eduard Generalov " \ + --requires=librtmp1 \ + --autodoinst=no \ + --deldoc=yes \ + --deldesc=yes \ + --delspec=yes \ + --backup=no \ + make install + +WORKDIR /ip2location/data +RUN perl ip-country.pl + +WORKDIR /ip2location/test +RUN ./test-IP2Location + +# Compile C Library for IP2Proxy module +WORKDIR /ip2proxy +RUN autoreconf -i -v --force +RUN ./configure +RUN make +RUN checkinstall \ + -D \ + --install=no \ + --default \ + --pkgname=ip2proxy-c \ + --pkgversion=${IP2PROXY_C_VERSION} \ + --pkgarch=amd64 \ + --pkggroup=lib \ + --pkgsource="https://github.com/ip2location/ip2proxy-c" \ + --maintainer="Eduard Generalov " \ + --requires=librtmp1 \ + --autodoinst=no \ + --deldoc=yes \ + --deldesc=yes \ + --delspec=yes \ + --backup=no \ + make install + +# Compile Nginx +WORKDIR /nginx +RUN ./configure \ + --with-compat \ + --prefix=/usr/share/nginx \ + --sbin-path=/usr/bin/nginx \ + --with-http_ssl_module \ + --conf-path=/etc/nginx/nginx.conf \ + --http-log-path=/var/log/nginx/access.log \ + --error-log-path=/var/log/nginx/error.log \ + --lock-path=/var/lock/nginx.lock \ + --pid-path=/run/nginx.pid \ + --modules-path=/usr/lib/nginx/modules \ + --http-client-body-temp-path=/var/lib/nginx/body \ + --http-fastcgi-temp-path=/var/lib/nginx/fastcgi \ + --http-proxy-temp-path=/var/lib/nginx/proxy \ + --http-scgi-temp-path=/var/lib/nginx/scgi \ + --http-uwsgi-temp-path=/var/lib/nginx/uwsgi \ + --with-http_realip_module \ + --with-http_stub_status_module \ + --with-stream \ + --add-module=../nginx-module-vts \ + --add-module=../cache-purge-module \ + --add-dynamic-module=../ip2mod-proxy \ + --add-dynamic-module=../ip2mod-location \ + --with-compat + +RUN make modules +RUN make -j 8 +RUN checkinstall \ + -D \ + --install=no \ + --default \ + --pkgname=nginx \ + --pkgversion=$VERS \ + --pkgarch=amd64 \ + --pkggroup=web \ + --provides=nginx \ + --requires=ip2location-c,ip2proxy-c,libssl3,libc-bin,libc6,libzstd1,libpcre++0v5,libpcre16-3,libpcre2-8-0,libpcre3,libpcre32-3,libpcrecpp0v5,libmaxminddb0 \ + --autodoinst=no \ + --deldoc=yes \ + --deldesc=yes \ + --delspec=yes \ + --backup=no \ + make install + +RUN mkdir /packages \ + && mv /*/*.deb /packages/ + +FROM ubuntu:22.04 +COPY --from=stage /packages /packages +COPY nginx-reloader.sh /usr/bin/nginx-reloader.sh + +RUN set -x \ + && groupadd --system --gid 101 nginx \ + && useradd --system --gid nginx --no-create-home --home /nonexistent --comment "nginx user" --shell /bin/false --uid 101 nginx \ + && apt update \ + && apt-get install --no-install-recommends --no-install-suggests -y gnupg1 ca-certificates inotify-tools \ + && apt -y install /packages/*.deb \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* \ + && mkdir -p /var/lib/nginx /var/log/nginx \ + && ln -sf /dev/stdout /var/log/nginx/access.log \ + && ln -sf /dev/stderr /var/log/nginx/error.log \ + && chown -R nginx: /var/lib/nginx /var/log/nginx + +ENTRYPOINT ["/usr/bin/nginx", "-g", "daemon off;"] diff --git a/packages/apps/http-cache/images/nginx-cache/nginx-reloader.sh b/packages/apps/http-cache/images/nginx-cache/nginx-reloader.sh new file mode 100755 index 00000000..2f0f87b6 --- /dev/null +++ b/packages/apps/http-cache/images/nginx-cache/nginx-reloader.sh @@ -0,0 +1,13 @@ +#!/bin/sh +set -e + +cleanup() { + echo "Received termination signal. Exiting..." + exit 0 +} + +trap cleanup INT +while true; do + inotifywait -s -e close_write,attrib --include 'reload' /data >/dev/null + nginx -s reload +done diff --git a/packages/apps/http-cache/templates/haproxy/configmap.yaml b/packages/apps/http-cache/templates/haproxy/configmap.yaml new file mode 100644 index 00000000..a6b5adf8 --- /dev/null +++ b/packages/apps/http-cache/templates/haproxy/configmap.yaml @@ -0,0 +1,106 @@ +{{- define "backendoptions" }} +{{- if eq . "http" }} +mode http +option forwardfor +balance uri whole +hash-type consistent +retry-on conn-failure 503 +retries 2 +option redispatch 1 +default-server observe layer7 error-limit 10 on-error mark-down check +{{- else if eq . "tcp" }} +mode tcp +balance roundrobin +default-server observe layer4 error-limit 10 on-error mark-down check +{{- else if eq . "tcp-with-proxy" }} +mode tcp +balance roundrobin +default-server observe layer4 error-limit 10 on-error mark-down check send-proxy-v2 +{{- else }} +{{- fail (printf "mode %s is not supported" .) }} +{{- end }} +{{- end }} + +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ .Release.Name }}-haproxy + labels: + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} +data: + haproxy.cfg: | + defaults + mode tcp + option dontlognull + timeout http-request 10s + timeout queue 20s + timeout connect 5s + timeout client 5m + timeout server 5m + timeout tunnel 5m + timeout http-keep-alive 10s + timeout check 10s + + frontend http + bind :::8080 v4v6 + mode http + {{- if $.Values.whitelistHTTP }} + {{- with $.Values.whitelist }} + acl whitelist src{{ range . }} {{ . }}{{ end }} + {{- end }} + acl all src 0.0.0.0 + tcp-request content accept if whitelist + tcp-request content reject + {{- end }} + tcp-request content set-dst-port int(80) + + # match real IP from cloudflare + acl from_cf src -f /usr/local/etc/haproxy/CF_ips.lst + acl cf_ip_hdr req.hdr(CF-Connecting-IP) -m found + http-request set-header X-Forwarded-For %[req.hdr(CF-Connecting-IP)] if from_cf cf_ip_hdr + + # overwrite real IP header from anywhere else + http-request set-header X-Forwarded-For %[src] if !from_cf + + default_backend http + + backend http + mode http + balance uri whole + hash-type consistent + retry-on conn-failure 503 + retries 2 + option redispatch 1 + default-server observe layer7 error-limit 10 on-error mark-down + + {{- range $i, $e := until (int $.Values.replicas) }} + server cache{{ $i }} {{ $.Release.Name }}-nginx-cache-{{ $i }}:80 check + {{- end }} + {{- range $i, $e := $.Values.endpoints }} + server origin{{ $i }} {{ $e }} backup + {{- end }} + # https://developers.cloudflare.com/support/troubleshooting/restoring-visitor-ips/restoring-original-visitor-ips/ + CF_ips.lst: | + 173.245.48.0/20 + 103.21.244.0/22 + 103.22.200.0/22 + 103.31.4.0/22 + 141.101.64.0/18 + 108.162.192.0/18 + 190.93.240.0/20 + 188.114.96.0/20 + 197.234.240.0/22 + 198.41.128.0/17 + 162.158.0.0/15 + 104.16.0.0/13 + 104.24.0.0/14 + 172.64.0.0/13 + 131.0.72.0/22 + 2400:cb00::/32 + 2606:4700::/32 + 2803:f800::/32 + 2405:b500::/32 + 2405:8100::/32 + 2a06:98c0::/29 + 2c0f:f248::/32 diff --git a/packages/apps/http-cache/templates/haproxy/deployment.yaml b/packages/apps/http-cache/templates/haproxy/deployment.yaml new file mode 100644 index 00000000..d0b0246e --- /dev/null +++ b/packages/apps/http-cache/templates/haproxy/deployment.yaml @@ -0,0 +1,45 @@ +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ .Release.Name }}-haproxy + labels: + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} +spec: + replicas: 2 + selector: + matchLabels: + app: {{ .Release.Name }}-haproxy + template: + metadata: + labels: + app: {{ .Release.Name }}-haproxy + annotations: + checksum/config: {{ include (print $.Template.BasePath "/haproxy/configmap.yaml") . | sha256sum }} + spec: + affinity: + podAntiAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 1 + podAffinityTerm: + labelSelector: + matchExpressions: + - key: app + operator: In + values: + - {{ .Release.Name }}-haproxy + topologyKey: kubernetes.io/hostname + containers: + - image: haproxy:latest + name: haproxy + ports: + - containerPort: 8080 + name: http + volumeMounts: + - mountPath: /usr/local/etc/haproxy + name: config + volumes: + - configMap: + name: {{ .Release.Name }}-haproxy + name: config diff --git a/packages/apps/http-cache/templates/haproxy/service.yaml b/packages/apps/http-cache/templates/haproxy/service.yaml new file mode 100644 index 00000000..39659212 --- /dev/null +++ b/packages/apps/http-cache/templates/haproxy/service.yaml @@ -0,0 +1,21 @@ +--- +apiVersion: v1 +kind: Service +metadata: + name: {{ .Release.Name }}-haproxy + labels: + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} +spec: + type: {{ ternary "LoadBalancer" "ClusterIP" .Values.external }} + {{- if .Values.external }} + externalTrafficPolicy: Local + allocateLoadBalancerNodePorts: false + {{- end }} + selector: + app: {{ .Release.Name }}-haproxy + ports: + - name: http + protocol: TCP + port: 80 + targetPort: http diff --git a/packages/apps/http-cache/templates/nginx/configmap.yaml b/packages/apps/http-cache/templates/nginx/configmap.yaml new file mode 100644 index 00000000..fdce5371 --- /dev/null +++ b/packages/apps/http-cache/templates/nginx/configmap.yaml @@ -0,0 +1,162 @@ +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ $.Release.Name }}-nginx-cache + labels: + app.kubernetes.io/instance: {{ $.Release.Name }} + app.kubernetes.io/managed-by: {{ $.Release.Service }} +data: + nginx.conf: | + user nginx; + worker_processes 2; + + error_log /var/log/nginx/error.log notice; + pid /var/run/nginx.pid; + + #load_module /usr/lib/nginx/modules/ngx_http_ip2location_module.so; + #load_module /usr/lib/nginx/modules/ngx_http_ip2proxy_module.so; + + events { + use epoll; + multi_accept on; + worker_connections 10240; + } + + http { + include /etc/nginx/mime.types; + default_type application/octet-stream; + + vhost_traffic_status_zone; + + log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for"'; + + access_log /var/log/nginx/access.log main; + + sendfile on; + tcp_nopush on; + + keepalive_timeout 65; + + gzip on; + + proxy_cache_path /data/cache levels=1:2 keys_zone=mycache:400m max_size=100g + inactive=30d use_temp_path=off; + + #ip2location_database /data/dbs/ip2location.bin; + #ip2location_proxy_recursive on; + #ip2location_proxy 10.0.0.0/8; + + #ip2proxy_database /data/dbs/ip2proxy.bin; + #ip2proxy_proxy_recursive on; + #ip2proxy_proxy 10.0.0.0/8; + + server { + listen *:10253; + server_name _; + + vhost_traffic_status_bypass_limit on; + vhost_traffic_status_bypass_stats on; + + location /health { + access_log off; + add_header 'Content-Type' 'text/plain'; + return 200 "healthy\n"; + } + + location /metrics { + vhost_traffic_status_display; + vhost_traffic_status_display_format prometheus; + } + } + + upstream origin_servers { + {{- range $num, $ep := $.Values.endpoints }} + server {{ $ep }}; + {{- end }} + } + + # URL shorter: + # / --> / + # /a --> /a + # /a/b --> /a/* + map $uri $shorten_url { + ~^/$ /; + ~^/([^/]+)$ /$1; + ~^/([^/]+)/.*$ /$1/*; + } + + # URL shortener: + # Example: / --> / + # Example: /a --> /a + # Example: /a/ --> /a + # Example: /a/b --> /a/* + map $uri $shorten_url { + ~^/$ /; + ~^/([^/]+)$ /$1; + ~^/([^/]+)/$ /$1; + ~^/([^/]+)/.*$ /$1/*; + } + + server { + listen *:80; + server_name _; + vhost_traffic_status_filter_by_host on; + + #vhost_traffic_status_filter_by_set_key $host country::$ip2location_country_short; + vhost_traffic_status_filter_by_set_key $shorten_url url::$host; + + proxy_cache mycache; + proxy_cache_revalidate on; + proxy_cache_lock on; + proxy_cache_key $scheme$http_host$request_uri; + proxy_cache_purge PURGE from all; + cache_purge_response_type json; + + proxy_cache_valid 200 1h; + proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504; + + proxy_cache_background_update on; + + proxy_connect_timeout 400ms; + proxy_next_upstream error timeout http_500 http_502 http_503 http_504; + + location / { + proxy_set_header Host $http_host; + + ## debug + add_header X-Cache-Status $upstream_cache_status; + #add_header X-Cache-Node $hostname; + #add_header X-Cache-Key $scheme$http_host$request_uri; + + proxy_set_header X-Real-IP $remote_addr; + real_ip_header $real_ip_header; + real_ip_recursive on; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + + #proxy_set_header X-Anonymous-Type $ip2proxy_proxy_type; + #proxy_set_header X-Country $ip2location_country_short; + + #proxy_set_header X-Country-Code $ip2location_country_short; + #proxy_set_header X-Country-Name $ip2location_country_long; + #proxy_set_header X-GeoIP-Region $ip2location_region; + #proxy_set_header X-GeoIP-City $ip2location_city; + #proxy_set_header X-Geoip-Country $ip2location_country_short; + #proxy_set_header X-Geoip-Latitude $ip2location_latitude; + #proxy_set_header X-Geoip-Longitude $ip2location_longitude; + #proxy_set_header X-GeoIP-ISP $ip2location_isp; + ##proxy_set_header X-GeoIP-Postal-Code $ip2location_zipcode; + ##proxy_set_header X-Geoip-Timezone $ip2location_timezone; + ##proxy_set_header X-Geoip-Asn $ip2location_asn; + + proxy_hide_header Pragma; + proxy_hide_header Expires; + + # to backends + proxy_pass http://origin_servers; + proxy_buffering on; + } + } + } diff --git a/packages/apps/http-cache/templates/nginx/deployment.yaml b/packages/apps/http-cache/templates/nginx/deployment.yaml new file mode 100644 index 00000000..175b393a --- /dev/null +++ b/packages/apps/http-cache/templates/nginx/deployment.yaml @@ -0,0 +1,140 @@ +--- +apiVersion: policy/v1 +kind: PodDisruptionBudget +metadata: + name: {{ $.Release.Name }}-nginx-cache + labels: + app.kubernetes.io/instance: {{ $.Release.Name }} + app.kubernetes.io/managed-by: {{ $.Release.Service }} +spec: + maxUnavailable: 1 + selector: + matchLabels: + app: {{ $.Release.Name }}-nginx-cache +{{- range $i := until 3 }} +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ $.Release.Name }}-nginx-cache-{{ $i }} + labels: + app.kubernetes.io/instance: {{ $.Release.Name }} + app.kubernetes.io/managed-by: {{ $.Release.Service }} +spec: + selector: + matchLabels: + app: {{ $.Release.Name }}-nginx-cache + instance: "{{ $i }}" + template: + metadata: + labels: + app: {{ $.Release.Name }}-nginx-cache + instance: "{{ $i }}" + annotations: + checksum/config: {{ include (print $.Template.BasePath "/nginx/configmap.yaml") $ | sha256sum }} + spec: + imagePullSecrets: + - name: {{ $.Release.Name }}-regsecret + affinity: + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchExpressions: + - key: app + operator: In + values: + - {{ $.Release.Name }}-nginx-cache + - key: instance + operator: NotIn + values: + - "{{ $i }}" + topologyKey: kubernetes.io/hostname + shareProcessNamespace: true + containers: + - name: nginx + image: "{{ $.Files.Get "images/nginx-cache.tag" | trim }}@{{ index ($.Files.Get "images/nginx-cache.json" | fromJson) "containerimage.digest" }}" + readinessProbe: + httpGet: + path: /healthz + port: metrics + initialDelaySeconds: 5 + periodSeconds: 5 + livenessProbe: + httpGet: + path: /healthz + port: metrics + failureThreshold: 1 + periodSeconds: 10 + ports: + - containerPort: 80 + name: http + - containerPort: 8087 + name: cache + - containerPort: 10253 + name: metrics + volumeMounts: + - mountPath: /etc/nginx/nginx.conf + name: config + subPath: nginx.conf + - mountPath: /data + name: data + - mountPath: /run + name: run + - name: reloader + image: "{{ $.Files.Get "images/nginx-cache.tag" | trim }}@{{ index ($.Files.Get "images/nginx-cache.json" | fromJson) "containerimage.digest" }}" + command: ["/usr/bin/nginx-reloader.sh"] + #command: ["sleep", "infinity"] + volumeMounts: + - mountPath: /etc/nginx/nginx.conf + name: config + subPath: nginx.conf + - mountPath: /data + name: data + - mountPath: /run + name: run + volumes: + - name: config + configMap: + name: {{ $.Release.Name }}-nginx-cache + - name: data + persistentVolumeClaim: + claimName: {{ $.Release.Name }}-nginx-cache-{{ $i }} + - name: run + emptyDir: {} +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: {{ $.Release.Name }}-nginx-cache-{{ $i }} + labels: + app.kubernetes.io/instance: {{ $.Release.Name }} + app.kubernetes.io/managed-by: {{ $.Release.Service }} +spec: + accessModes: [ "ReadWriteOnce" ] + resources: + requests: + storage: "{{ $.Values.size }}" +--- +apiVersion: v1 +kind: Service +metadata: + name: {{ $.Release.Name }}-nginx-cache-{{ $i }} + labels: + app: {{ $.Release.Name }}-nginx-cache + app.kubernetes.io/instance: {{ $.Release.Name }} + app.kubernetes.io/managed-by: {{ $.Release.Service }} +spec: + type: ClusterIP + selector: + app: {{ $.Release.Name }}-nginx-cache + instance: "{{ $i }}" + ports: + - name: http + protocol: TCP + port: 80 + targetPort: http + - name: metrics + protocol: TCP + port: 10253 + targetPort: metrics +{{- end }} diff --git a/packages/apps/http-cache/templates/nginx/nginx-scrape.yaml b/packages/apps/http-cache/templates/nginx/nginx-scrape.yaml new file mode 100644 index 00000000..8e5f2331 --- /dev/null +++ b/packages/apps/http-cache/templates/nginx/nginx-scrape.yaml @@ -0,0 +1,26 @@ +--- +apiVersion: operator.victoriametrics.com/v1beta1 +kind: VMServiceScrape +metadata: + name: nginx-cache +spec: + jobLabel: jobLabel + namespaceSelector: + matchNames: + - infra-nginx-cache + endpoints: + - path: /metrics + port: metrics + honorLabels: true + relabelConfigs: + - replacement: nginx-cache + targetLabel: job + - source_labels: [__meta_kubernetes_service_name] + target_label: instance + - sourceLabels: [__meta_kubernetes_pod_node_name] + targetLabel: node + - targetLabel: tier + replacement: cluster + selector: + matchLabels: + app: {{ $.Release.Name }}-nginx-cache diff --git a/packages/apps/http-cache/values.yaml b/packages/apps/http-cache/values.yaml new file mode 100644 index 00000000..68df71fc --- /dev/null +++ b/packages/apps/http-cache/values.yaml @@ -0,0 +1,9 @@ +external: false +size: 10Gi +endpoints: + - 10.100.3.1:80 + - 10.100.3.11:80 + - 10.100.3.2:80 + - 10.100.3.12:80 + - 10.100.3.3:80 + - 10.100.3.13:80 diff --git a/packages/apps/kubernetes/.helmignore b/packages/apps/kubernetes/.helmignore new file mode 100644 index 00000000..0e8a0eb3 --- /dev/null +++ b/packages/apps/kubernetes/.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/packages/apps/kubernetes/Chart.yaml b/packages/apps/kubernetes/Chart.yaml new file mode 100644 index 00000000..5e269c04 --- /dev/null +++ b/packages/apps/kubernetes/Chart.yaml @@ -0,0 +1,25 @@ +apiVersion: v2 +name: kubernetes +description: Managed Kubernetes service +icon: https://upload.wikimedia.org/wikipedia/commons/thumb/3/39/Kubernetes_logo_without_workmark.svg/723px-Kubernetes_logo_without_workmark.svg.png + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +# Versions are expected to follow Semantic Versioning (https://semver.org/) +version: 0.1.0 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. Versions are not expected to +# follow Semantic Versioning. They should reflect the version the application is using. +# It is recommended to use it with quotes. +appVersion: "1.16.0" diff --git a/packages/apps/kubernetes/Makefile b/packages/apps/kubernetes/Makefile new file mode 100644 index 00000000..d48cb999 --- /dev/null +++ b/packages/apps/kubernetes/Makefile @@ -0,0 +1,18 @@ +PUSH := 1 +LOAD := 0 +REGISTRY := ghcr.io/aenix-io/cozystack +TAG := v0.0.1 +UBUNTU_CONTAINER_DISK_TAG = v1.29.1 + +image: image-ubuntu-container-disk + +image-ubuntu-container-disk: + docker buildx build --platform linux/amd64 --build-arg ARCH=amd64 images/ubuntu-container-disk \ + --provenance false \ + --tag $(REGISTRY)/ubuntu-container-disk:$(TAG)-$(UBUNTU_CONTAINER_DISK_TAG) \ + --cache-from type=registry,ref=$(REGISTRY)/ubuntu-container-disk:$(UBUNTU_CONTAINER_DISK_TAG) \ + --cache-to type=inline \ + --metadata-file images/ubuntu-container-disk.json \ + --push=$(PUSH) \ + --load=$(LOAD) + echo "$(REGISTRY)/ubuntu-container-disk:$(UBUNTU_CONTAINER_DISK_TAG)" > images/ubuntu-container-disk.tag diff --git a/packages/apps/kubernetes/README.md b/packages/apps/kubernetes/README.md new file mode 100644 index 00000000..aaa8d398 --- /dev/null +++ b/packages/apps/kubernetes/README.md @@ -0,0 +1,28 @@ +# Managed Kubernetes Service + +## Overview + +The Managed Kubernetes Service offers a streamlined solution for efficiently managing server workloads. Kubernetes has emerged as the industry standard, providing a unified and accessible API, primarily utilizing YAML for configuration. This means that teams can easily understand and work with Kubernetes, streamlining infrastructure management. + +The Kubernetes leverages robust software design patterns, enabling continuous recovery in any scenario through the reconciliation method. Additionally, it ensures seamless scaling across a multitude of servers, addressing the challenges posed by complex and outdated APIs found in traditional virtualization platforms. This managed service eliminates the need for developing custom solutions or modifying source code, saving valuable time and effort. + +## Deployment Details + +The managed Kubernetes service deploys a standard Kubernetes cluster utilizing the Cluster API, Kamaji as control-plane provicer and the KubeVirt infrastructure provider. This ensures a consistent and reliable setup for workloads. + +Within this cluster, users can take advantage of LoadBalancer services and easily provision physical volumes as needed. The control-plane operates within containers, while the worker nodes are deployed as virtual machines, all seamlessly managed by the application. + +- Docs: https://github.com/clastix/kamaji +- Docs: https://cluster-api.sigs.k8s.io/ +- GitHub: https://github.com/clastix/kamaji +- GitHub: https://github.com/kubernetes-sigs/cluster-api-provider-kubevirt +- GitHub: https://github.com/kubevirt/csi-driver + + +## How-Tos + +How to access to deployed cluster: + +``` +kubectl get secret -n kubernetes--admin-kubeconfig -o go-template='{{ printf "%s\n" (index .data "super-admin.conf" | base64decode) }}' > test +``` diff --git a/packages/apps/kubernetes/images/ubuntu-container-disk.json b/packages/apps/kubernetes/images/ubuntu-container-disk.json new file mode 100644 index 00000000..f0953889 --- /dev/null +++ b/packages/apps/kubernetes/images/ubuntu-container-disk.json @@ -0,0 +1,4 @@ +{ + "containerimage.config.digest": "sha256:e982cfa2320d3139ed311ae44bcc5ea18db7e4e76d2746e0af04c516288ff0f1", + "containerimage.digest": "sha256:34f6aba5b5a2afbb46bbb891ef4ddc0855c2ffe4f9e5a99e8e553286ddd2c070" +} \ No newline at end of file diff --git a/packages/apps/kubernetes/images/ubuntu-container-disk.tag b/packages/apps/kubernetes/images/ubuntu-container-disk.tag new file mode 100644 index 00000000..c2389748 --- /dev/null +++ b/packages/apps/kubernetes/images/ubuntu-container-disk.tag @@ -0,0 +1 @@ +ghcr.io/aenix-io/cozystack/ubuntu-container-disk:v1.29.1 diff --git a/packages/apps/kubernetes/images/ubuntu-container-disk/Dockerfile b/packages/apps/kubernetes/images/ubuntu-container-disk/Dockerfile new file mode 100644 index 00000000..a30d70f7 --- /dev/null +++ b/packages/apps/kubernetes/images/ubuntu-container-disk/Dockerfile @@ -0,0 +1,51 @@ +FROM ubuntu:22.04 as guestfish + +ARG DEBIAN_FRONTEND=noninteractive +RUN apt-get update \ + && apt-get -y install \ + libguestfs-tools \ + linux-image-generic \ + make \ + bash-completion \ + && apt-get clean + +WORKDIR /build + +FROM guestfish as builder + +RUN wget -O image.img https://cloud-images.ubuntu.com/jammy/current/jammy-server-cloudimg-amd64.img + +RUN qemu-img resize image.img 5G \ + && eval "$(guestfish --listen --network)" \ + && guestfish --remote add-drive image.img \ + && guestfish --remote run \ + && guestfish --remote mount /dev/sda1 / \ + && guestfish --remote command "growpart /dev/sda 1 --verbose" \ + && guestfish --remote command "resize2fs /dev/sda1" \ +# docker repo + && guestfish --remote sh "curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg" \ + && guestfish --remote sh 'echo "deb [arch=amd64 signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list' \ +# kubernetes repo + && guestfish --remote sh "curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.29/deb/Release.key | gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg" \ + && guestfish --remote sh "echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.29/deb/ /' | tee /etc/apt/sources.list.d/kubernetes.list" \ +# install containerd + && guestfish --remote command "apt-get update -y" \ + && guestfish --remote command "apt-get install -y containerd.io" \ +# configure containerd + && guestfish --remote command "mkdir -p /etc/containerd" \ + && guestfish --remote sh "containerd config default | tee /etc/containerd/config.toml" \ + && guestfish --remote command "sed -i '/SystemdCgroup/ s/=.*/= true/' /etc/containerd/config.toml" \ +# install kubernetes + && guestfish --remote command "apt-get install -y kubelet kubeadm" \ +# clean apt cache + && guestfish --remote sh 'apt-get clean && rm -rf /var/lib/apt/lists/*' \ +# write system configuration + && guestfish --remote sh 'printf "%s\n" net.bridge.bridge-nf-call-iptables=1 net.bridge.bridge-nf-call-ip6tables=1 net.ipv4.ip_forward=1 net.ipv6.conf.all.forwarding=1 net.ipv6.conf.all.disable_ipv6=0 net.ipv4.tcp_congestion_control=bbr vm.overcommit_memory=1 kernel.panic=10 kernel.panic_on_oops=1 fs.inotify.max_user_instances=8192 fs.inotify.max_user_watches=524288 | tee > /etc/sysctl.d/kubernetes.conf' \ + && guestfish --remote sh 'printf "%s\n" overlay br_netfilter | tee /etc/modules-load.d/kubernetes.conf' \ + && guestfish --remote sh "rm -f /etc/resolv.conf && ln -s ../run/systemd/resolve/stub-resolv.conf /etc/resolv.conf" \ +# umount all and exit + && guestfish --remote umount-all \ + && guestfish --remote exit + +FROM scratch +COPY --from=builder /build/image.img /disk/image.qcow2 diff --git a/packages/apps/kubernetes/templates/NOTES.txt b/packages/apps/kubernetes/templates/NOTES.txt new file mode 100644 index 00000000..23e07dab --- /dev/null +++ b/packages/apps/kubernetes/templates/NOTES.txt @@ -0,0 +1,3 @@ +To get kubeconfig for this cluster run: + +kubectl get secret -n {{ .Release.Namespace }} {{ .Release.Name }}-admin-kubeconfig -o go-template='{{`{{ printf "%s\n" (index .data "super-admin.conf" | base64decode) }}`}}' diff --git a/packages/apps/kubernetes/templates/_helpers.tpl b/packages/apps/kubernetes/templates/_helpers.tpl new file mode 100644 index 00000000..36c06b64 --- /dev/null +++ b/packages/apps/kubernetes/templates/_helpers.tpl @@ -0,0 +1,51 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "kubernetes.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | 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 "kubernetes.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "kubernetes.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "kubernetes.labels" -}} +helm.sh/chart: {{ include "kubernetes.chart" . }} +{{ include "kubernetes.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "kubernetes.selectorLabels" -}} +app.kubernetes.io/name: {{ include "kubernetes.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} diff --git a/packages/apps/kubernetes/templates/cloud-config.yaml b/packages/apps/kubernetes/templates/cloud-config.yaml new file mode 100644 index 00000000..9f16548a --- /dev/null +++ b/packages/apps/kubernetes/templates/cloud-config.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ .Release.Name }}-cloud-config +data: + cloud-config: | + loadBalancer: + creationPollInterval: 5 + creationPollTimeout: 60 + namespace: {{ .Release.Namespace }} diff --git a/packages/apps/kubernetes/templates/cluster-autoscaler/deployment.yaml b/packages/apps/kubernetes/templates/cluster-autoscaler/deployment.yaml new file mode 100644 index 00000000..c6a6a19c --- /dev/null +++ b/packages/apps/kubernetes/templates/cluster-autoscaler/deployment.yaml @@ -0,0 +1,86 @@ +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ .Release.Name }}-cluster-autoscaler + labels: + app: {{ .Release.Name }}-cluster-autoscaler +spec: + selector: + matchLabels: + app: {{ .Release.Name }}-cluster-autoscaler + replicas: 1 + template: + metadata: + labels: + app: {{ .Release.Name }}-cluster-autoscaler + spec: + containers: + - image: ghcr.io/kvaps/test:cluster-autoscaller + name: cluster-autoscaler + command: + - /cluster-autoscaler + args: + - --cloud-provider=clusterapi + - --kubeconfig=/etc/kubernetes/kubeconfig/super-admin.svc + - --clusterapi-cloud-config-authoritative + - --node-group-auto-discovery=clusterapi:namespace={{ .Release.Namespace }},clusterName={{ .Release.Name }} + volumeMounts: + - mountPath: /etc/kubernetes/kubeconfig + name: kubeconfig + readOnly: true + volumes: + - configMap: + name: {{ .Release.Name }}-cloud-config + name: cloud-config + - secret: + secretName: {{ .Release.Name }}-admin-kubeconfig + name: kubeconfig + serviceAccountName: {{ .Release.Name }}-cluster-autoscaler + terminationGracePeriodSeconds: 10 +--- +kind: RoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ .Release.Name }}-cluster-autoscaler +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ .Release.Name }}-cluster-autoscaler +subjects: +- kind: ServiceAccount + name: {{ .Release.Name }}-cluster-autoscaler + namespace: {{ .Release.Namespace }} +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ .Release.Name }}-cluster-autoscaler +--- +kind: Role +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ .Release.Name }}-cluster-autoscaler +rules: + - apiGroups: + - cluster.x-k8s.io + resources: + - machinedeployments + - machinedeployments/scale + - machines + - machinesets + - machinepools + verbs: + - get + - list + - update + - watch + - apiGroups: + - infrastructure.cluster.x-k8s.io + resources: + - kubevirtmachinetemplates + verbs: + - get + - list + - update + - watch diff --git a/packages/apps/kubernetes/templates/cluster.yaml b/packages/apps/kubernetes/templates/cluster.yaml new file mode 100644 index 00000000..ee45816d --- /dev/null +++ b/packages/apps/kubernetes/templates/cluster.yaml @@ -0,0 +1,150 @@ +{{- $myNS := lookup "v1" "Namespace" "" .Release.Namespace }} +{{- $etcd := index $myNS.metadata.annotations "namespace.cozystack.io/etcd" }} +{{- $ingress := index $myNS.metadata.annotations "namespace.cozystack.io/ingress" }} +{{- $host := index $myNS.metadata.annotations "namespace.cozystack.io/host" }} +--- +apiVersion: cluster.x-k8s.io/v1beta1 +kind: Cluster +metadata: + name: {{ .Release.Name }} + namespace: {{ .Release.Namespace }} +spec: + clusterNetwork: + pods: + cidrBlocks: + - 10.243.0.0/16 + services: + cidrBlocks: + - 10.95.0.0/16 + controlPlaneRef: + namespace: {{ .Release.Namespace }} + apiVersion: controlplane.cluster.x-k8s.io/v1alpha1 + kind: KamajiControlPlane + name: {{ .Release.Name }} + infrastructureRef: + apiVersion: infrastructure.cluster.x-k8s.io/v1alpha1 + kind: KubevirtCluster + name: {{ .Release.Name }} + namespace: {{ .Release.Namespace }} +--- +apiVersion: controlplane.cluster.x-k8s.io/v1alpha1 +kind: KamajiControlPlane +metadata: + name: {{ .Release.Name }} + namespace: {{ .Release.Namespace }} + labels: + cluster.x-k8s.io/role: control-plane + annotations: + kamaji.clastix.io/kubeconfig-secret-key: "super-admin.svc" +spec: + dataStoreName: "{{ $etcd }}" + addons: + coreDNS: {} + konnectivity: {} + kubelet: + cgroupfs: systemd + preferredAddressTypes: + - InternalIP + - ExternalIP + network: + serviceType: ClusterIP + ingress: + extraAnnotations: + nginx.ingress.kubernetes.io/ssl-passthrough: "true" + hostname: {{ .Values.host | default (printf "%s.%s" .Release.Name $host) }}:443 + className: "{{ $ingress }}" + deployment: + replicas: 2 + version: 1.29.0 +--- +apiVersion: infrastructure.cluster.x-k8s.io/v1alpha1 +kind: KubevirtCluster +metadata: + annotations: + cluster.x-k8s.io/managed-by: kamaji + name: {{ .Release.Name }} + namespace: {{ .Release.Namespace }} +--- +apiVersion: bootstrap.cluster.x-k8s.io/v1beta1 +kind: KubeadmConfigTemplate +metadata: + name: {{ .Release.Name }}-md-0 + namespace: {{ .Release.Namespace }} +spec: + template: + spec: + joinConfiguration: + nodeRegistration: + kubeletExtraArgs: {} + discovery: + bootstrapToken: + apiServerEndpoint: {{ .Release.Name }}.{{ .Release.Namespace }}.svc:6443 + initConfiguration: + skipPhases: + - addon/kube-proxy +--- +apiVersion: infrastructure.cluster.x-k8s.io/v1alpha1 +kind: KubevirtMachineTemplate +metadata: + name: {{ .Release.Name }}-md-0 + namespace: {{ .Release.Namespace }} +spec: + template: + spec: + virtualMachineBootstrapCheck: + checkStrategy: ssh + virtualMachineTemplate: + metadata: + namespace: {{ .Release.Namespace }} + spec: + runStrategy: Always + template: + spec: + domain: + cpu: + threads: 1 + cores: 2 + sockets: 1 + devices: + disks: + - disk: + bus: virtio + name: containervolume + networkInterfaceMultiqueue: true + memory: + guest: 1024Mi + evictionStrategy: External + volumes: + - containerDisk: + image: "{{ $.Files.Get "images/ubuntu-container-disk.tag" | trim }}@{{ index ($.Files.Get "images/ubuntu-container-disk.json" | fromJson) "containerimage.digest" }}" + name: containervolume +--- +apiVersion: cluster.x-k8s.io/v1beta1 +kind: MachineDeployment +metadata: + name: {{ .Release.Name }}-md-0 + namespace: {{ .Release.Namespace }} + annotations: + cluster.x-k8s.io/cluster-api-autoscaler-node-group-max-size: "2" + cluster.x-k8s.io/cluster-api-autoscaler-node-group-min-size: "0" + capacity.cluster-autoscaler.kubernetes.io/memory: "1024Mi" + capacity.cluster-autoscaler.kubernetes.io/cpu: "2" +spec: + clusterName: {{ .Release.Name }} + selector: + matchLabels: null + template: + spec: + bootstrap: + configRef: + apiVersion: bootstrap.cluster.x-k8s.io/v1beta1 + kind: KubeadmConfigTemplate + name: {{ .Release.Name }}-md-0 + namespace: default + clusterName: {{ .Release.Name }} + infrastructureRef: + apiVersion: infrastructure.cluster.x-k8s.io/v1alpha1 + kind: KubevirtMachineTemplate + name: {{ .Release.Name }}-md-0 + namespace: default + version: v1.23.10 diff --git a/packages/apps/kubernetes/templates/csi/deploy.yaml b/packages/apps/kubernetes/templates/csi/deploy.yaml new file mode 100644 index 00000000..6d8783cf --- /dev/null +++ b/packages/apps/kubernetes/templates/csi/deploy.yaml @@ -0,0 +1,126 @@ +kind: Deployment +apiVersion: apps/v1 +metadata: + name: {{ .Release.Name }}-kcsi-controller + labels: + app: {{ .Release.Name }}-kcsi-driver +spec: + replicas: 1 + selector: + matchLabels: + app: {{ .Release.Name }}-kcsi-driver + template: + metadata: + labels: + app: {{ .Release.Name }}-kcsi-driver + spec: + serviceAccountName: {{ .Release.Name }}-kcsi + priorityClassName: system-cluster-critical + nodeSelector: + node-role.kubernetes.io/control-plane: "" + tolerations: + - key: CriticalAddonsOnly + operator: Exists + - key: node-role.kubernetes.io/master + operator: Exists + effect: "NoSchedule" + containers: + - name: csi-driver + imagePullPolicy: Always + image: ghcr.io/kvaps/test:kubevirt-csi-driver + args: + - "--endpoint=$(CSI_ENDPOINT)" + - "--infra-cluster-namespace=$(INFRACLUSTER_NAMESPACE)" + - "--infra-cluster-labels=$(INFRACLUSTER_LABELS)" + - "--v=5" + ports: + - name: healthz + containerPort: 10301 + protocol: TCP + env: + - name: CSI_ENDPOINT + value: unix:///var/lib/csi/sockets/pluginproxy/csi.sock + - name: KUBE_NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + - name: INFRACLUSTER_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: INFRACLUSTER_LABELS + value: "csi-driver/cluster=test" + - name: INFRA_STORAGE_CLASS_ENFORCEMENT + valueFrom: + configMapKeyRef: + name: driver-config + key: infraStorageClassEnforcement + optional: true + volumeMounts: + - name: socket-dir + mountPath: /var/lib/csi/sockets/pluginproxy/ + - name: kubeconfig + mountPath: /etc/kubernetes/kubeconfig + readOnly: true + resources: + requests: + memory: 50Mi + cpu: 10m + - name: csi-provisioner + image: quay.io/openshift/origin-csi-external-provisioner:latest + args: + - "--csi-address=$(ADDRESS)" + - "--default-fstype=ext4" + - "--kubeconfig=/etc/kubernetes/kubeconfig/super-admin.svc" + - "--v=5" + - "--timeout=3m" + - "--retry-interval-max=1m" + env: + - name: ADDRESS + value: /var/lib/csi/sockets/pluginproxy/csi.sock + volumeMounts: + - name: socket-dir + mountPath: /var/lib/csi/sockets/pluginproxy/ + - name: kubeconfig + mountPath: /etc/kubernetes/kubeconfig + readOnly: true + - name: csi-attacher + image: quay.io/openshift/origin-csi-external-attacher:latest + args: + - "--csi-address=$(ADDRESS)" + - "--kubeconfig=/etc/kubernetes/kubeconfig/super-admin.svc" + - "--v=5" + - "--timeout=3m" + - "--retry-interval-max=1m" + env: + - name: ADDRESS + value: /var/lib/csi/sockets/pluginproxy/csi.sock + volumeMounts: + - name: socket-dir + mountPath: /var/lib/csi/sockets/pluginproxy/ + - name: kubeconfig + mountPath: /etc/kubernetes/kubeconfig + readOnly: true + resources: + requests: + memory: 50Mi + cpu: 10m + - name: csi-liveness-probe + image: quay.io/openshift/origin-csi-livenessprobe:latest + args: + - "--csi-address=/csi/csi.sock" + - "--probe-timeout=3s" + - "--health-port=10301" + volumeMounts: + - name: socket-dir + mountPath: /csi + resources: + requests: + memory: 50Mi + cpu: 10m + volumes: + - name: socket-dir + emptyDir: {} + - secret: + secretName: {{ .Release.Name }}-admin-kubeconfig + name: kubeconfig diff --git a/packages/apps/kubernetes/templates/csi/infra-cluster-service-account.yaml b/packages/apps/kubernetes/templates/csi/infra-cluster-service-account.yaml new file mode 100644 index 00000000..d70ea04a --- /dev/null +++ b/packages/apps/kubernetes/templates/csi/infra-cluster-service-account.yaml @@ -0,0 +1,32 @@ +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ .Release.Name }}-kcsi +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ .Release.Name }}-kcsi +rules: +- apiGroups: ["cdi.kubevirt.io"] + resources: ["datavolumes"] + verbs: ["get", "create", "delete"] +- apiGroups: ["kubevirt.io"] + resources: ["virtualmachineinstances"] + verbs: ["list", "get"] +- apiGroups: ["subresources.kubevirt.io"] + resources: ["virtualmachineinstances/addvolume", "virtualmachineinstances/removevolume"] + verbs: ["update"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ .Release.Name }}-kcsi +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ .Release.Name }}-kcsi +subjects: +- kind: ServiceAccount + name: {{ .Release.Name }}-kcsi diff --git a/packages/apps/kubernetes/templates/helmreleases/cilium.yaml b/packages/apps/kubernetes/templates/helmreleases/cilium.yaml new file mode 100644 index 00000000..96c759fd --- /dev/null +++ b/packages/apps/kubernetes/templates/helmreleases/cilium.yaml @@ -0,0 +1,46 @@ +apiVersion: helm.toolkit.fluxcd.io/v2beta1 +kind: HelmRelease +metadata: + name: {{ .Release.Name }}-cilium + labels: + cozystack.io/repository: system + coztstack.io/target-cluster-name: {{ .Release.Name }} +spec: + interval: 1m + releaseName: cilium + chart: + spec: + chart: cozy-cilium + reconcileStrategy: Revision + sourceRef: + kind: HelmRepository + name: cozystack-system + namespace: cozy-system + kubeConfig: + secretRef: + name: {{ .Release.Name }}-kubeconfig + targetNamespace: cozy-cilium + storageNamespace: cozy-cilium + install: + createNamespace: true + values: + cilium: + tunnel: disabled + autoDirectNodeRoutes: true + cgroup: + autoMount: + enabled: true + hostRoot: /run/cilium/cgroupv2 + k8sServiceHost: {{ .Release.Name }}.{{ .Release.Namespace }}.svc + k8sServicePort: 6443 + + cni: + chainingMode: ~ + customConf: false + configMap: "" + routingMode: native + enableIPv4Masquerade: true + ipv4NativeRoutingCIDR: "10.244.0.0/16" + dependsOn: + - name: {{ .Release.Name }} + namespace: {{ .Release.Namespace }} diff --git a/packages/apps/kubernetes/templates/helmreleases/csi.yaml b/packages/apps/kubernetes/templates/helmreleases/csi.yaml new file mode 100644 index 00000000..55169278 --- /dev/null +++ b/packages/apps/kubernetes/templates/helmreleases/csi.yaml @@ -0,0 +1,28 @@ +apiVersion: helm.toolkit.fluxcd.io/v2beta1 +kind: HelmRelease +metadata: + name: {{ .Release.Name }}-csi + labels: + cozystack.io/repository: system + coztstack.io/target-cluster-name: {{ .Release.Name }} +spec: + interval: 1m + releaseName: csi + chart: + spec: + chart: cozy-kubevirt-csi-node + reconcileStrategy: Revision + sourceRef: + kind: HelmRepository + name: cozystack-system + namespace: cozy-system + kubeConfig: + secretRef: + name: {{ .Release.Name }}-kubeconfig + targetNamespace: cozy-csi + storageNamespace: cozy-csi + install: + createNamespace: true + dependsOn: + - name: {{ .Release.Name }} + namespace: {{ .Release.Namespace }} diff --git a/packages/apps/kubernetes/templates/helmreleases/delete.yaml b/packages/apps/kubernetes/templates/helmreleases/delete.yaml new file mode 100644 index 00000000..e143653a --- /dev/null +++ b/packages/apps/kubernetes/templates/helmreleases/delete.yaml @@ -0,0 +1,73 @@ +--- +apiVersion: batch/v1 +kind: Job +metadata: + annotations: + "helm.sh/hook": pre-delete + "helm.sh/hook-weight": "10" + "helm.sh/hook-delete-policy": hook-succeeded,before-hook-creation,hook-failed + name: {{ .Release.Name }}-flux-teardown +spec: + template: + spec: + serviceAccountName: {{ .Release.Name }}-flux-teardown + restartPolicy: Never + containers: + - name: kubectl + image: docker.io/clastix/kubectl:v1.29.1 + command: + - kubectl + - --namespace={{ .Release.Namespace }} + - patch + - helmrelease + - {{ .Release.Name }}-cilium + - {{ .Release.Name }}-csi + - -p + - '{"spec": {"suspend": true}}' + - --type=merge +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ .Release.Name }}-flux-teardown + annotations: + helm.sh/hook: pre-delete + helm.sh/hook-delete-policy: before-hook-creation,hook-failed + helm.sh/hook-weight: "0" +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + annotations: + "helm.sh/hook": pre-install,post-install,pre-delete + "helm.sh/hook-delete-policy": hook-succeeded,before-hook-creation,hook-failed + "helm.sh/hook-weight": "5" + name: {{ .Release.Name }}-flux-teardown +rules: + - apiGroups: + - "helm.toolkit.fluxcd.io" + resources: + - helmreleases + verbs: + - get + - patch + resourceNames: + - {{ .Release.Name }}-cilium + - {{ .Release.Name }}-csi +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + annotations: + helm.sh/hook: pre-delete + helm.sh/hook-delete-policy: hook-succeeded,before-hook-creation,hook-failed + helm.sh/hook-weight: "5" + name: {{ .Release.Name }}-flux-teardown +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ .Release.Name }}-flux-teardown +subjects: + - kind: ServiceAccount + name: {{ .Release.Name }}-flux-teardown + namespace: {{ .Release.Namespace }} diff --git a/packages/apps/kubernetes/templates/kccm/kccm_cluster_role.yaml b/packages/apps/kubernetes/templates/kccm/kccm_cluster_role.yaml new file mode 100644 index 00000000..cd27da11 --- /dev/null +++ b/packages/apps/kubernetes/templates/kccm/kccm_cluster_role.yaml @@ -0,0 +1,11 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ .Release.Namespace }}-{{ .Release.Name }}-kccm +rules: +- apiGroups: + - "" + resources: + - nodes + verbs: + - get diff --git a/packages/apps/kubernetes/templates/kccm/kccm_cluster_role_binding.yaml b/packages/apps/kubernetes/templates/kccm/kccm_cluster_role_binding.yaml new file mode 100644 index 00000000..3a8a45b7 --- /dev/null +++ b/packages/apps/kubernetes/templates/kccm/kccm_cluster_role_binding.yaml @@ -0,0 +1,12 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ .Release.Namespace }}-{{ .Release.Name }}-kccm +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ .Release.Namespace }}-{{ .Release.Name }}-kccm +subjects: +- kind: ServiceAccount + name: {{ .Release.Name }}-kccm + namespace: {{ .Release.Namespace }} diff --git a/packages/apps/kubernetes/templates/kccm/kccm_role.yaml b/packages/apps/kubernetes/templates/kccm/kccm_role.yaml new file mode 100644 index 00000000..fee06003 --- /dev/null +++ b/packages/apps/kubernetes/templates/kccm/kccm_role.yaml @@ -0,0 +1,42 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ .Release.Name }}-kccm +rules: +- apiGroups: + - kubevirt.io + resources: + - virtualmachines + verbs: + - get + - watch + - list +- apiGroups: + - kubevirt.io + resources: + - virtualmachineinstances + verbs: + - get + - watch + - list + - update +- apiGroups: + - "" + resources: + - pods + verbs: + - get + - list + - watch +- apiGroups: + - "" + resources: + - services + verbs: + - "*" +- apiGroups: + - "" + resources: + - nodes + verbs: + - get diff --git a/packages/apps/kubernetes/templates/kccm/kccm_role_binding.yaml b/packages/apps/kubernetes/templates/kccm/kccm_role_binding.yaml new file mode 100644 index 00000000..cb51808f --- /dev/null +++ b/packages/apps/kubernetes/templates/kccm/kccm_role_binding.yaml @@ -0,0 +1,27 @@ +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ .Release.Namespace }}-{{ .Release.Name }}-kccm + namespace: kube-system +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: extension-apiserver-authentication-reader +subjects: +- kind: ServiceAccount + name: {{ .Release.Name }}-kccm + namespace: {{ .Release.Namespace }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ .Release.Name }}-kccm +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ .Release.Name }}-kccm +subjects: +- kind: ServiceAccount + name: {{ .Release.Name }}-kccm + namespace: {{ .Release.Namespace }} diff --git a/packages/apps/kubernetes/templates/kccm/manager.yaml b/packages/apps/kubernetes/templates/kccm/manager.yaml new file mode 100644 index 00000000..81a02e97 --- /dev/null +++ b/packages/apps/kubernetes/templates/kccm/manager.yaml @@ -0,0 +1,49 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ .Release.Name }}-kccm + labels: + k8s-app: {{ .Release.Name }}-kccm +spec: + replicas: 1 + selector: + matchLabels: + k8s-app: {{ .Release.Name }}-kccm + template: + metadata: + labels: + k8s-app: {{ .Release.Name }}-kccm + spec: + containers: + - name: kubevirt-cloud-controller-manager + args: + - --cloud-provider=kubevirt + - --cloud-config=/etc/cloud/cloud-config + - --kubeconfig=/etc/kubernetes/kubeconfig/super-admin.svc + - --cluster-name={{ .Release.Name }} + command: + - /bin/kubevirt-cloud-controller-manager + image: ghcr.io/kvaps/test:kubevirt-cloud-provider + imagePullPolicy: Always + #securityContext: + # privileged: true + resources: + requests: + cpu: 100m + volumeMounts: + - mountPath: /etc/kubernetes/kubeconfig + name: kubeconfig + readOnly: true + - mountPath: /etc/cloud + name: cloud-config + readOnly: true + volumes: + - configMap: + name: {{ .Release.Name }}-cloud-config + name: cloud-config + - secret: + secretName: {{ .Release.Name }}-admin-kubeconfig + name: kubeconfig + tolerations: + - operator: Exists + serviceAccountName: {{ .Release.Name }}-kccm diff --git a/packages/apps/kubernetes/templates/kccm/service_account.yaml b/packages/apps/kubernetes/templates/kccm/service_account.yaml new file mode 100644 index 00000000..10a690b2 --- /dev/null +++ b/packages/apps/kubernetes/templates/kccm/service_account.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ .Release.Name }}-kccm diff --git a/packages/apps/kubernetes/values.schema.json b/packages/apps/kubernetes/values.schema.json new file mode 100644 index 00000000..a0202ab5 --- /dev/null +++ b/packages/apps/kubernetes/values.schema.json @@ -0,0 +1,11 @@ +{ + "$schema": "http://json-schema.org/schema#", + "type": "object", + "properties": { + "host": { + "type": "string", + "title": "Domain name for this kubernetes cluster", + "description": "This host will be used for all apps deployed in this tenant" + } + } +} diff --git a/packages/apps/kubernetes/values.yaml b/packages/apps/kubernetes/values.yaml new file mode 100644 index 00000000..aa0b60b1 --- /dev/null +++ b/packages/apps/kubernetes/values.yaml @@ -0,0 +1 @@ +host: "" diff --git a/packages/apps/mysql/.helmignore b/packages/apps/mysql/.helmignore new file mode 100644 index 00000000..0e8a0eb3 --- /dev/null +++ b/packages/apps/mysql/.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/packages/apps/mysql/Chart.yaml b/packages/apps/mysql/Chart.yaml new file mode 100644 index 00000000..67bbacc7 --- /dev/null +++ b/packages/apps/mysql/Chart.yaml @@ -0,0 +1,25 @@ +apiVersion: v2 +name: mysql +description: Managed MariaDB service +icon: https://static-00.iconduck.com/assets.00/mariadb-icon-512x340-txozryr2.png + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +# Versions are expected to follow Semantic Versioning (https://semver.org/) +version: 0.1.0 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. Versions are not expected to +# follow Semantic Versioning. They should reflect the version the application is using. +# It is recommended to use it with quotes. +appVersion: "1.16.0" diff --git a/packages/apps/mysql/README.md b/packages/apps/mysql/README.md new file mode 100644 index 00000000..f8ff37dc --- /dev/null +++ b/packages/apps/mysql/README.md @@ -0,0 +1,64 @@ +## Managed MariaDB Service + +The Managed MariaDB Service offers a powerful and widely used relational database solution. This service allows you to create and manage a replicated MariaDB cluster seamlessly. + +## Deployment Details + +This managed service is controlled by mariadb-operator, ensuring efficient management and seamless operation. + +- Docs: https://mariadb.com/kb/en/documentation/ +- GitHub: https://github.com/mariadb-operator/mariadb-operator + +## HowTos + +### How to switch master/slave replica + +``` +kubectl edit mariadb +``` +update: + +``` +spec: + replication: + primary: + podIndex: 1 +``` + +check status: + +``` +NAME READY STATUS PRIMARY POD AGE + True Running app-db1-1 41d +``` + +### How to restore backup: + +find snapshot: +``` +restic -r s3:s3.example.org/mariadb-backups/database_name snapshots +``` + + +restore: +``` +restic -r s3:s3.example.org/mariadb-backups/database_name restore latest --target /tmp/ +``` + +more details: +- https://itnext.io/restic-effective-backup-from-stdin-4bc1e8f083c1 + +### Known issues + +- **Replication can't not be finished with various errors** +- **Replication can't be finised in case if binlog purged** + Until mariadbbackup is not used to bootstrap a node by mariadb-operator (this feature is not inmplemented yet), follow these manual steps to fix it: + https://github.com/mariadb-operator/mariadb-operator/issues/141#issuecomment-1804760231 + +- **Corrupted indicies** + Sometimes some indecies can be corrupted on master replica, you can recover them from slave: + + ``` + mysqldump -h -P 3306 -u -p --column-statistics=0 ~/tmp/fix-table.sql + mysql -h -P 3306 -u -p < ~/tmp/fix-table.sql + ``` diff --git a/packages/apps/mysql/templates/.gitkeep b/packages/apps/mysql/templates/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/packages/apps/mysql/templates/backup-cronjob.yaml b/packages/apps/mysql/templates/backup-cronjob.yaml new file mode 100644 index 00000000..26810f74 --- /dev/null +++ b/packages/apps/mysql/templates/backup-cronjob.yaml @@ -0,0 +1,94 @@ +{{- if .Values.backup.enabled }} +{{ $image := .Files.Get "images/backup.json" | fromJson }} + +apiVersion: batch/v1 +kind: CronJob +metadata: + name: {{ .Release.Name }}-backup +spec: + schedule: "{{ .Values.backup.schedule }}" + concurrencyPolicy: Forbid + successfulJobsHistoryLimit: 3 + failedJobsHistoryLimit: 3 + jobTemplate: + spec: + backoffLimit: 2 + template: + spec: + restartPolicy: OnFailure + template: + metadata: + annotations: + checksum/config: {{ include (print $.Template.BasePath "/backup-script.yaml") . | sha256sum }} + checksum/secret: {{ include (print $.Template.BasePath "/backup-secret.yaml") . | sha256sum }} + spec: + imagePullSecrets: + - name: {{ .Release.Name }}-regsecret + restartPolicy: Never + containers: + - name: mysqldump + image: "{{ index $image "image.name" }}@{{ index $image "containerimage.digest" }}" + command: + - /bin/sh + - /scripts/backup.sh + env: + - name: REPO_PREFIX + value: {{ required "s3Bucket is not specified!" .Values.backup.s3Bucket | quote }} + - name: CLEANUP_STRATEGY + value: {{ required "cleanupPolicy is not specified!" .Values.backup.cleanupStrategy | quote }} + - name: MYSQL_USER + value: root + - name: MYSQL_PWD + valueFrom: + secretKeyRef: + name: {{ .Release.Name }} + key: root-password + - name: MYSQL_HOST + value: {{ .Release.Name }}-secondary + - name: AWS_ACCESS_KEY_ID + valueFrom: + secretKeyRef: + name: {{ .Release.Name }}-backup + key: s3AccessKey + - name: AWS_SECRET_ACCESS_KEY + valueFrom: + secretKeyRef: + name: {{ .Release.Name }}-backup + key: s3SecretKey + - name: AWS_DEFAULT_REGION + value: {{ .Values.backup.s3Region }} + - name: RESTIC_PASSWORD + valueFrom: + secretKeyRef: + name: {{ .Release.Name }}-backup + key: resticPassword + volumeMounts: + - mountPath: /scripts + name: scripts + - mountPath: /tmp + name: tmp + - mountPath: /.cache + name: cache + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + privileged: false + readOnlyRootFilesystem: true + runAsNonRoot: true + volumes: + - name: scripts + secret: + secretName: {{ .Release.Name }}-backup-script + - name: tmp + emptyDir: {} + - name: cache + emptyDir: {} + securityContext: + runAsNonRoot: true + runAsUser: 9000 + runAsGroup: 9000 + seccompProfile: + type: RuntimeDefault +{{- end }} diff --git a/packages/apps/mysql/templates/backup-script.yaml b/packages/apps/mysql/templates/backup-script.yaml new file mode 100644 index 00000000..b261cdea --- /dev/null +++ b/packages/apps/mysql/templates/backup-script.yaml @@ -0,0 +1,50 @@ +{{- if .Values.backup.enabled }} +--- +apiVersion: v1 +kind: Secret +metadata: + name: {{ .Release.Name }}-backup-script +stringData: + backup.sh: | + #!/bin/sh + set -e + set -o pipefail + + JOB_ID="job-$(uuidgen|cut -f1 -d-)" + DB_LIST=$(mysql -u "$MYSQL_USER" -h "$MYSQL_HOST" -sNe 'SHOW DATABASES;' | grep -v '^\(#.*\|mysql\|sys\|information_schema\|performance_schema\)$') + echo DB_LIST=$(echo "$DB_LIST" | shuf) # shuffle list + echo "Job ID: $JOB_ID" + echo "Target repo: $REPO_PREFIX" + echo "Cleanup strategy: $CLEANUP_STRATEGY" + echo "Start backup for:" + echo "$DB_LIST" + echo + echo "Backup started at `date +%Y-%m-%d\ %H:%M:%S`" + for db in $DB_LIST; do + ( + set -x + restic -r "s3:${REPO_PREFIX}/$db" cat config >/dev/null 2>&1 || \ + restic -r "s3:${REPO_PREFIX}/$db" init --repository-version 2 + restic -r "s3:${REPO_PREFIX}/$db" unlock --remove-all >/dev/null 2>&1 || true # no locks, k8s takes care of it + mysqldump -u "$MYSQL_USER" -h "$MYSQL_HOST" --single-transaction --databases $db | \ + restic -r "s3:${REPO_PREFIX}/$db" backup --tag "$JOB_ID" --stdin --stdin-filename dump.sql + restic -r "s3:${REPO_PREFIX}/$db" tag --tag "$JOB_ID" --set "completed" + ) + done + echo "Backup finished at `date +%Y-%m-%d\ %H:%M:%S`" + + echo + echo "Run cleanup:" + echo + + echo "Cleanup started at `date +%Y-%m-%d\ %H:%M:%S`" + for db in $DB_LIST; do + ( + set -x + restic forget -r "s3:${REPO_PREFIX}/$db" --group-by=tags --keep-tag "completed" # keep completed snapshots only + restic forget -r "s3:${REPO_PREFIX}/$db" --group-by=tags $CLEANUP_STRATEGY + restic prune -r "s3:${REPO_PREFIX}/$db" + ) + done + echo "Cleanup finished at `date +%Y-%m-%d\ %H:%M:%S`" +{{- end }} diff --git a/packages/apps/mysql/templates/backup-secret.yaml b/packages/apps/mysql/templates/backup-secret.yaml new file mode 100644 index 00000000..be221e2f --- /dev/null +++ b/packages/apps/mysql/templates/backup-secret.yaml @@ -0,0 +1,11 @@ +{{- if .Values.backup.enabled }} +--- +apiVersion: v1 +kind: Secret +metadata: + name: {{ .Release.Name }}-backup +stringData: + s3AccessKey: {{ required "s3AccessKey is not specified!" .Values.backup.s3AccessKey }} + s3SecretKey: {{ required "s3SecretKey is not specified!" .Values.backup.s3SecretKey }} + resticPassword: {{ required "resticPassword is not specified!" .Values.backup.resticPassword }} +{{- end }} diff --git a/packages/apps/mysql/templates/config.yaml b/packages/apps/mysql/templates/config.yaml new file mode 100644 index 00000000..cc60dd2c --- /dev/null +++ b/packages/apps/mysql/templates/config.yaml @@ -0,0 +1,35 @@ +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ .Release.Name }}-my-cnf +data: + config: | + [mysqld] + sql-mode=NO_ENGINE_SUBSTITUTION + max_connections=4096 + default_authentication_plugin=mysql_native_password + #innodb_buffer_pool_dump_at_shutdown=1 + innodb_buffer_pool_instances=48 + innodb_buffer_pool_size=60G + innodb_fast_shutdown=0 + innodb_flush_method=O_DIRECT_NO_FSYNC + innodb_flush_log_at_trx_commit=2 + innodb_io_capacity=10000 + innodb_io_capacity_max=50000 + #innodb_log_buffer_size=128M + innodb_log_file_size=4096M + #innodb_log_files_in_group=6 + innodb_thread_concurrency=24 + join_buffer_size=2M + key_buffer_size=1024M + read_rnd_buffer_size=16M + #sync_binlog=0 + table_open_cache=40714 + table_definition_cache=4000 + thread_pool_size=24 + tmp_table_size=512M + master_info_repository=TABLE + relay_log_info_repository=TABLE + innodb_read_io_threads=12 + innodb_write_io_threads=12 diff --git a/packages/apps/mysql/templates/db.yaml b/packages/apps/mysql/templates/db.yaml new file mode 100644 index 00000000..ed6483c7 --- /dev/null +++ b/packages/apps/mysql/templates/db.yaml @@ -0,0 +1,14 @@ +{{- range $name := .Values.databases }} +{{ $dnsName := replace "_" "-" $name }} +--- +apiVersion: mariadb.mmontes.io/v1alpha1 +kind: Database +metadata: + name: {{ $.Release.Name }}-{{ $dnsName }} +spec: + name: {{ $name }} + mariaDbRef: + name: {{ $.Release.Name }} + characterSet: utf8 + collate: utf8_general_ci +{{- end }} diff --git a/packages/apps/mysql/templates/mariadb.yaml b/packages/apps/mysql/templates/mariadb.yaml new file mode 100644 index 00000000..56d90ea5 --- /dev/null +++ b/packages/apps/mysql/templates/mariadb.yaml @@ -0,0 +1,71 @@ +--- +apiVersion: mariadb.mmontes.io/v1alpha1 +kind: MariaDB +metadata: + name: {{ .Release.Name }} +spec: + rootPasswordSecretKeyRef: + name: {{ .Release.Name }} + key: root-password + + image: "mariadb:11.0.2" + + port: 3306 + + replicas: 2 + affinity: + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchExpressions: + - key: app.kubernetes.io/name + operator: In + values: + - mariadb + - key: app.kubernetes.io/instance + operator: In + values: + - {{ .Release.Name }} + topologyKey: "kubernetes.io/hostname" + + replication: + enabled: true + #primary: + # podIndex: 0 + # automaticFailover: true + + metrics: + exporter: + image: prom/mysqld-exporter:v0.14.0 + resources: + requests: + cpu: 50m + memory: 64Mi + limits: + cpu: 300m + memory: 512Mi + port: 9104 + serviceMonitor: + interval: 10s + scrapeTimeout: 10s + + myCnfConfigMapKeyRef: + name: {{ .Release.Name }}-my-cnf + key: config + + volumeClaimTemplate: + resources: + requests: + storage: {{ .Values.size }} + accessModes: + - ReadWriteOnce + + + + {{- if .Values.external }} + primaryService: + type: LoadBalancer + {{- end }} + + #secondaryService: + # type: LoadBalancer diff --git a/packages/apps/mysql/templates/regsecret.yaml b/packages/apps/mysql/templates/regsecret.yaml new file mode 100644 index 00000000..a76dd946 --- /dev/null +++ b/packages/apps/mysql/templates/regsecret.yaml @@ -0,0 +1,10 @@ +{{- if .Values.registrySecret }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ .Release.Name }}-regsecret +type: kubernetes.io/dockerconfigjson +stringData: + .dockerconfigjson: | + {{- toJson .Values.registrySecret | nindent 4 }} +{{- end }} diff --git a/packages/apps/mysql/templates/secret.yaml b/packages/apps/mysql/templates/secret.yaml new file mode 100644 index 00000000..821b3a00 --- /dev/null +++ b/packages/apps/mysql/templates/secret.yaml @@ -0,0 +1,9 @@ +--- +apiVersion: v1 +kind: Secret +metadata: + name: {{ .Release.Name }} +stringData: + {{- range $name, $u := .Values.users }} + {{ $name }}-password: {{ $u.password }} + {{- end }} diff --git a/packages/apps/mysql/templates/user.yaml b/packages/apps/mysql/templates/user.yaml new file mode 100644 index 00000000..9074f1cd --- /dev/null +++ b/packages/apps/mysql/templates/user.yaml @@ -0,0 +1,31 @@ +{{- range $name, $u := .Values.users }} +{{ if not (eq $name "root") }} +{{ $dnsName := replace "_" "-" $name }} +--- +apiVersion: mariadb.mmontes.io/v1alpha1 +kind: User +metadata: + name: {{ $.Release.Name }}-{{ $dnsName }} +spec: + name: {{ $name }} + mariaDbRef: + name: {{ $.Release.Name }} + passwordSecretKeyRef: + name: {{ $.Release.Name }} + key: {{ $name }}-password + maxUserConnections: {{ $u.maxUserConnections }} +--- +apiVersion: mariadb.mmontes.io/v1alpha1 +kind: Grant +metadata: + name: {{ $.Release.Name }}-{{ $dnsName }} +spec: + mariaDbRef: + name: {{ $.Release.Name }} + privileges: {{ $u.privileges | toJson }} + database: "*" + table: "*" + username: {{ $name }} + grantOption: true +{{- end }} +{{- end }} diff --git a/packages/apps/mysql/values.yaml b/packages/apps/mysql/values.yaml new file mode 100644 index 00000000..7c15f60f --- /dev/null +++ b/packages/apps/mysql/values.yaml @@ -0,0 +1,30 @@ +external: false +size: 10Gi + +users: + root: + password: strongpassword + user1: + privileges: ['ALL'] + maxUserConnections: 1000 + password: hackme + user2: + privileges: ['SELECT'] + maxUserConnections: 1000 + password: hackme + +databases: +- wordpress1 +- wordpress2 +- wordpress3 +- wordpress4 + +backup: + enabled: false + s3Region: us-east-1 + s3Bucket: s3.example.org/postgres-backups + schedule: "0 2 * * *" + cleanupStrategy: "--keep-last=3 --keep-daily=3 --keep-within-weekly=1m" + s3AccessKey: oobaiRus9pah8PhohL1ThaeTa4UVa7gu + s3SecretKey: ju3eum4dekeich9ahM1te8waeGai0oog + resticPassword: ChaXoveekoh6eigh4siesheeda2quai0 diff --git a/packages/apps/postgres/.helmignore b/packages/apps/postgres/.helmignore new file mode 100644 index 00000000..0e8a0eb3 --- /dev/null +++ b/packages/apps/postgres/.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/packages/apps/postgres/Chart.yaml b/packages/apps/postgres/Chart.yaml new file mode 100644 index 00000000..fabef869 --- /dev/null +++ b/packages/apps/postgres/Chart.yaml @@ -0,0 +1,25 @@ +apiVersion: v2 +name: postgres +description: Managed PostgreSQL service +icon: https://cdn-icons-png.flaticon.com/512/5968/5968342.png + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +# Versions are expected to follow Semantic Versioning (https://semver.org/) +version: 0.1.0 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. Versions are not expected to +# follow Semantic Versioning. They should reflect the version the application is using. +# It is recommended to use it with quotes. +appVersion: "1.16.0" diff --git a/packages/apps/postgres/README.md b/packages/apps/postgres/README.md new file mode 100644 index 00000000..6ca0c381 --- /dev/null +++ b/packages/apps/postgres/README.md @@ -0,0 +1,32 @@ +# Managed PostgreSQL Service + +PostgreSQL is currently the leading choice among relational databases, known for its robust features and performance. Our Managed PostgreSQL Service takes advantage of platform-side implementation to provide a self-healing replicated cluster. This cluster is efficiently managed using the highly acclaimed CloudNativePG operator, which has gained popularity within the community. + +## Deployment Details + +This managed service is controlled by the CloudNativePG operator, ensuring efficient management and seamless operation. + +- Docs: https://cloudnative-pg.io/documentation/ +- Github: https://github.com/cloudnative-pg/cloudnative-pg + +## HowTos + +### How to switch master/slave replica + +See: +- https://cloudnative-pg.io/documentation/1.15/rolling_update/#manual-updates-supervised + +### How to restore backup: + +find snapshot: +``` +restic -r s3:s3.example.org/postgres-backups/database_name snapshots +``` + +restore: +``` +restic -r s3:s3.example.org/postgres-backups/database_name restore latest --target /tmp/ +``` + +more details: +- https://itnext.io/restic-effective-backup-from-stdin-4bc1e8f083c1 diff --git a/packages/apps/postgres/templates/.gitkeep b/packages/apps/postgres/templates/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/packages/apps/postgres/templates/backup-cronjob.yaml b/packages/apps/postgres/templates/backup-cronjob.yaml new file mode 100644 index 00000000..45afb152 --- /dev/null +++ b/packages/apps/postgres/templates/backup-cronjob.yaml @@ -0,0 +1,101 @@ +{{- if .Values.backup.enabled }} +{{ $image := .Files.Get "images/backup.json" | fromJson }} + +apiVersion: batch/v1 +kind: CronJob +metadata: + name: {{ .Release.Name }}-backup +spec: + schedule: "{{ .Values.backup.schedule }}" + concurrencyPolicy: Forbid + successfulJobsHistoryLimit: 3 + failedJobsHistoryLimit: 3 + jobTemplate: + spec: + backoffLimit: 2 + template: + spec: + restartPolicy: OnFailure + template: + metadata: + annotations: + checksum/config: {{ include (print $.Template.BasePath "/backup-script.yaml") . | sha256sum }} + checksum/secret: {{ include (print $.Template.BasePath "/backup-secret.yaml") . | sha256sum }} + spec: + imagePullSecrets: + - name: {{ .Release.Name }}-regsecret + restartPolicy: Never + containers: + - name: mysqldump + image: "{{ index $image "image.name" }}@{{ index $image "containerimage.digest" }}" + command: + - /bin/sh + - /scripts/backup.sh + env: + - name: REPO_PREFIX + value: {{ required "s3Bucket is not specified!" .Values.backup.s3Bucket | quote }} + - name: CLEANUP_STRATEGY + value: {{ required "cleanupStrategy is not specified!" .Values.backup.cleanupStrategy | quote }} + - name: PGUSER + valueFrom: + secretKeyRef: + name: {{ .Release.Name }}-superuser + key: username + - name: PGPASSWORD + valueFrom: + secretKeyRef: + name: {{ .Release.Name }}-superuser + key: password + - name: PGHOST + value: {{ .Release.Name }}-rw + - name: PGPORT + value: "5432" + - name: PGDATABASE + value: postgres + - name: AWS_ACCESS_KEY_ID + valueFrom: + secretKeyRef: + name: {{ .Release.Name }}-backup + key: s3AccessKey + - name: AWS_SECRET_ACCESS_KEY + valueFrom: + secretKeyRef: + name: {{ .Release.Name }}-backup + key: s3SecretKey + - name: AWS_DEFAULT_REGION + value: {{ .Values.backup.s3Region }} + - name: RESTIC_PASSWORD + valueFrom: + secretKeyRef: + name: {{ .Release.Name }}-backup + key: resticPassword + volumeMounts: + - mountPath: /scripts + name: scripts + - mountPath: /tmp + name: tmp + - mountPath: /.cache + name: cache + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + privileged: false + readOnlyRootFilesystem: true + runAsNonRoot: true + volumes: + - name: scripts + secret: + secretName: {{ .Release.Name }}-backup-script + - name: tmp + emptyDir: {} + - name: cache + emptyDir: {} + securityContext: + runAsNonRoot: true + runAsUser: 9000 + runAsGroup: 9000 + seccompProfile: + type: RuntimeDefault +{{- end }} diff --git a/packages/apps/postgres/templates/backup-script.yaml b/packages/apps/postgres/templates/backup-script.yaml new file mode 100644 index 00000000..362bdc01 --- /dev/null +++ b/packages/apps/postgres/templates/backup-script.yaml @@ -0,0 +1,50 @@ +{{- if .Values.backup.enabled }} +--- +apiVersion: v1 +kind: Secret +metadata: + name: {{ .Release.Name }}-backup-script +stringData: + backup.sh: | + #!/bin/sh + set -e + set -o pipefail + + JOB_ID="job-$(uuidgen|cut -f1 -d-)" + DB_LIST=$(psql -Atq -c 'SELECT datname FROM pg_catalog.pg_database;' | grep -v '^\(postgres\|app\|template.*\)$') + echo DB_LIST=$(echo "$DB_LIST" | shuf) # shuffle list + echo "Job ID: $JOB_ID" + echo "Target repo: $REPO_PREFIX" + echo "Cleanup strategy: $CLEANUP_STRATEGY" + echo "Start backup for:" + echo "$DB_LIST" + echo + echo "Backup started at `date +%Y-%m-%d\ %H:%M:%S`" + for db in $DB_LIST; do + ( + set -x + restic -r "s3:${REPO_PREFIX}/$db" cat config >/dev/null 2>&1 || \ + restic -r "s3:${REPO_PREFIX}/$db" init --repository-version 2 + restic -r "s3:${REPO_PREFIX}/$db" unlock --remove-all >/dev/null 2>&1 || true # no locks, k8s takes care of it + pg_dump -Z0 -Ft -d "$db" | \ + restic -r "s3:${REPO_PREFIX}/$db" backup --tag "$JOB_ID" --stdin --stdin-filename dump.tar + restic -r "s3:${REPO_PREFIX}/$db" tag --tag "$JOB_ID" --set "completed" + ) + done + echo "Backup finished at `date +%Y-%m-%d\ %H:%M:%S`" + + echo + echo "Run cleanup:" + echo + + echo "Cleanup started at `date +%Y-%m-%d\ %H:%M:%S`" + for db in $DB_LIST; do + ( + set -x + restic forget -r "s3:${REPO_PREFIX}/$db" --group-by=tags --keep-tag "completed" # keep completed snapshots only + restic forget -r "s3:${REPO_PREFIX}/$db" --group-by=tags $CLEANUP_STRATEGY + restic prune -r "s3:${REPO_PREFIX}/$db" + ) + done + echo "Cleanup finished at `date +%Y-%m-%d\ %H:%M:%S`" +{{- end }} diff --git a/packages/apps/postgres/templates/backup-secret.yaml b/packages/apps/postgres/templates/backup-secret.yaml new file mode 100644 index 00000000..be221e2f --- /dev/null +++ b/packages/apps/postgres/templates/backup-secret.yaml @@ -0,0 +1,11 @@ +{{- if .Values.backup.enabled }} +--- +apiVersion: v1 +kind: Secret +metadata: + name: {{ .Release.Name }}-backup +stringData: + s3AccessKey: {{ required "s3AccessKey is not specified!" .Values.backup.s3AccessKey }} + s3SecretKey: {{ required "s3SecretKey is not specified!" .Values.backup.s3SecretKey }} + resticPassword: {{ required "resticPassword is not specified!" .Values.backup.resticPassword }} +{{- end }} diff --git a/packages/apps/postgres/templates/db.yaml b/packages/apps/postgres/templates/db.yaml new file mode 100644 index 00000000..b1821201 --- /dev/null +++ b/packages/apps/postgres/templates/db.yaml @@ -0,0 +1,18 @@ +--- +apiVersion: postgresql.cnpg.io/v1 +kind: Cluster +metadata: + name: {{ .Release.Name }} +spec: + instances: 2 + enableSuperuserAccess: true + + postgresql: + parameters: + max_wal_senders: "30" + + monitoring: + enablePodMonitor: true + + storage: + size: {{ required ".Values.size is required" .Values.size }} diff --git a/packages/apps/postgres/templates/external-svc.yaml b/packages/apps/postgres/templates/external-svc.yaml new file mode 100644 index 00000000..2f4e8b91 --- /dev/null +++ b/packages/apps/postgres/templates/external-svc.yaml @@ -0,0 +1,18 @@ +{{- if .Values.external }} +apiVersion: v1 +kind: Service +metadata: + name: {{ .Release.Name }}-external-write +spec: + type: {{ ternary "LoadBalancer" "ClusterIP" .Values.external }} + {{- if .Values.external }} + externalTrafficPolicy: Local + allocateLoadBalancerNodePorts: false + {{- end }} + ports: + - name: postgres + port: 5432 + selector: + cnpg.io/cluster: {{ .Release.Name }} + role: primary +{{- end }} diff --git a/packages/apps/postgres/templates/init-job.yaml b/packages/apps/postgres/templates/init-job.yaml new file mode 100644 index 00000000..8b17a2c1 --- /dev/null +++ b/packages/apps/postgres/templates/init-job.yaml @@ -0,0 +1,66 @@ +apiVersion: batch/v1 +kind: Job +metadata: + name: {{ .Release.Name }}-init-job + annotations: + "helm.sh/hook": post-install,post-upgrade + "helm.sh/hook-weight": "-5" + "helm.sh/hook-delete-policy": before-hook-creation +spec: + template: + metadata: + name: {{ .Release.Name }}-init-job + annotations: + checksum/config: {{ include (print $.Template.BasePath "/init-script.yaml") . | sha256sum }} + spec: + restartPolicy: Never + containers: + - name: postgres + image: ghcr.io/cloudnative-pg/postgresql:15.3 + command: + - bash + - /scripts/init.sh + env: + - name: PGUSER + valueFrom: + secretKeyRef: + name: {{ .Release.Name }}-superuser + key: username + - name: PGPASSWORD + valueFrom: + secretKeyRef: + name: {{ .Release.Name }}-superuser + key: password + - name: PGHOST + value: {{ .Release.Name }}-rw + - name: PGPORT + value: "5432" + - name: PGDATABASE + value: postgres + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + privileged: false + readOnlyRootFilesystem: true + runAsNonRoot: true + volumeMounts: + - mountPath: /etc/secret + name: secret + - mountPath: /scripts + name: scripts + securityContext: + fsGroup: 26 + runAsGroup: 26 + runAsNonRoot: true + runAsUser: 26 + seccompProfile: + type: RuntimeDefault + volumes: + - name: secret + secret: + secretName: {{ .Release.Name }}-superuser + - name: scripts + secret: + secretName: {{ .Release.Name }}-init-script diff --git a/packages/apps/postgres/templates/init-script.yaml b/packages/apps/postgres/templates/init-script.yaml new file mode 100644 index 00000000..e402fce3 --- /dev/null +++ b/packages/apps/postgres/templates/init-script.yaml @@ -0,0 +1,127 @@ +--- +apiVersion: v1 +kind: Secret +metadata: + name: {{ .Release.Name }}-init-script +stringData: + init.sh: | + #!/bin/bash + set -e + echo "== create users" + {{- if .Values.users }} + psql -v ON_ERROR_STOP=1 <<\EOT + {{- range $user, $u := .Values.users }} + SELECT 'CREATE ROLE {{ $user }} LOGIN INHERIT;' + WHERE NOT EXISTS (SELECT FROM pg_catalog.pg_roles WHERE rolname = '{{ $user }}')\gexec + ALTER ROLE {{ $user }} WITH PASSWORD '{{ $u.password }}' LOGIN INHERIT {{ ternary "REPLICATION" "NOREPLICATION" (default false $u.replication) }}; + COMMENT ON ROLE {{ $user }} IS 'user managed by helm'; + {{- end }} + EOT + {{- end }} + + echo "== delete users" + MANAGED_USERS=$(echo '\du+' | psql | awk -F'|' '$4 == " user managed by helm" {print $1}' | awk NF=NF RS= OFS=' ') + DEFINED_USERS="{{ join " " (keys .Values.users) }}" + DELETE_USERS=$(for user in $MANAGED_USERS; do case " $DEFINED_USERS " in *" $user "*) :;; *) echo $user;; esac; done) + + echo "users to delete: $DELETE_USERS" + for user in $DELETE_USERS; do + # https://stackoverflow.com/a/51257346/2931267 + psql -v ON_ERROR_STOP=1 --echo-all < "$$i/Chart.yaml"; done diff --git a/packages/core/installer/Chart.yaml b/packages/core/installer/Chart.yaml new file mode 100644 index 00000000..750dd5a6 --- /dev/null +++ b/packages/core/installer/Chart.yaml @@ -0,0 +1,2 @@ +name: cozy-installer +version: 1.0.0 diff --git a/packages/core/installer/Makefile b/packages/core/installer/Makefile new file mode 100644 index 00000000..14e5f317 --- /dev/null +++ b/packages/core/installer/Makefile @@ -0,0 +1,56 @@ +NAMESPACE=cozy-installer +NAME=installer +PUSH := 1 +LOAD := 0 +REGISTRY := ghcr.io/aenix-io/cozystack +TAG := v0.0.1 +TALOS_VERSION=$(shell awk '/^version:/ {print $$2}' images/talos/profiles/installer.yaml) + +show: + helm template -n $(NAMESPACE) $(NAME) . + +apply: + helm template -n $(NAMESPACE) $(NAME) . | kubectl apply -f - + +diff: + helm template -n $(NAMESPACE) $(NAME) . | kubectl diff -f - + +update: + hack/gen-profiles.sh + +image: image-installer image-talos image-matchbox + +image-installer: + docker buildx build -f images/installer/Dockerfile ../../.. \ + --provenance false \ + --tag $(REGISTRY)/installer:$(TAG) \ + --cache-from type=registry,ref=$(REGISTRY)/installer:$(TAG) \ + --cache-to type=inline \ + --metadata-file images/installer.json \ + --push=$(PUSH) \ + --load=$(LOAD) + echo "$(REGISTRY)/installer:$(TAG)" > images/installer.tag + +image-talos: + test -f ../../../_out/assets/installer-amd64.tar || make talos-installer + docker load -i ../../../_out/assets/installer-amd64.tar + docker tag ghcr.io/siderolabs/installer:$(TALOS_VERSION) ghcr.io/aenix-io/cozystack/talos:$(TALOS_VERSION) + docker push ghcr.io/aenix-io/cozystack/talos:$(TALOS_VERSION) + +image-matchbox: + test -f ../../../_out/assets/kernel-amd64 || make talos-kernel + test -f ../../../_out/assets/initramfs-metal-amd64.xz || make talos-initramfs + docker buildx build -f images/matchbox/Dockerfile ../../.. \ + --provenance false \ + --tag $(REGISTRY)/matchbox:$(TAG) \ + --cache-from type=registry,ref=$(REGISTRY)/matchbox:$(TAG) \ + --cache-to type=inline \ + --metadata-file images/matchbox.json \ + --push=$(PUSH) \ + --load=$(LOAD) + echo "$(REGISTRY)/matchbox:$(TAG)" > images/matchbox.tag + +assets: talos-iso + +talos-initramfs talos-kernel talos-installer talos-iso: + cat images/talos/profiles/$(subst talos-,,$@).yaml | docker run --rm -i -v $${PWD}/../../../_out/assets:/out -v /dev:/dev --privileged "ghcr.io/siderolabs/imager:$(TALOS_VERSION)" - diff --git a/packages/core/installer/hack/gen-profiles.sh b/packages/core/installer/hack/gen-profiles.sh new file mode 100755 index 00000000..409e0f28 --- /dev/null +++ b/packages/core/installer/hack/gen-profiles.sh @@ -0,0 +1,63 @@ +#!/bin/sh +set -e +set -u + +PROFILES="initramfs kernel iso installer" +FIRMWARES="amd-ucode amdgpu-firmware bnx2-bnx2x i915-ucode intel-ice-firmware intel-ucode qlogic-firmware" +EXTENSIONS="drbd zfs" + +mkdir -p images/talos/profiles + +printf "fetching talos version: " +talos_version=${1:-$(skopeo --override-os linux --override-arch amd64 list-tags docker://ghcr.io/siderolabs/imager | jq -r '.Tags[]' | grep '^v[0-9]\+.[0-9]\+.[0-9]\+$' | sort -V | tail -n 1)} +echo "$talos_version" + +export "TALOS_VERSION=$talos_version" + +for firmware in $FIRMWARES; do + printf "fetching %s version: " "$firmware" + firmware_var=$(echo "$firmware" | tr '[:lower:]' '[:upper:]' | tr - _)_VERSION + version=$(skopeo list-tags docker://ghcr.io/siderolabs/$firmware | jq -r '.Tags[]|select(length == 8)|select(startswith("20"))' | sort -V | tail -n 1) + echo "$version" + export "$firmware_var=$version" +done + +for extension in $EXTENSIONS; do + printf "fetching %s version: " "$extension" + extension_var=$(echo "$extension" | tr '[:lower:]' '[:upper:]' | tr - _)_VERSION + version=$(skopeo --override-os linux --override-arch amd64 list-tags docker://ghcr.io/siderolabs/$extension | jq -r '.Tags[]' | grep "\-${talos_version}$" | sort -V | tail -n1) + echo "$version" + export "$extension_var=$version" +done + +for profile in $PROFILES; do + echo "writing profile images/talos/profiles/$profile.yaml" + cat > images/talos/profiles/$profile.yaml < "$$i/Chart.yaml"; done diff --git a/packages/system/capi-operator/.helmignore b/packages/system/capi-operator/.helmignore new file mode 100644 index 00000000..d5c178e8 --- /dev/null +++ b/packages/system/capi-operator/.helmignore @@ -0,0 +1,3 @@ +images +hack +.gitkeep diff --git a/packages/system/capi-operator/Chart.yaml b/packages/system/capi-operator/Chart.yaml new file mode 100644 index 00000000..421eb3e6 --- /dev/null +++ b/packages/system/capi-operator/Chart.yaml @@ -0,0 +1,2 @@ +name: cozy-capi-operator +version: 1.0.0 diff --git a/packages/system/capi-operator/Makefile b/packages/system/capi-operator/Makefile new file mode 100644 index 00000000..e93380c6 --- /dev/null +++ b/packages/system/capi-operator/Makefile @@ -0,0 +1,18 @@ +NAME=capi-operator +NAMESPACE=cozy-cluster-api + +show: + helm template --dry-run=server -n $(NAMESPACE) $(NAME) . + +apply: + helm upgrade -i -n $(NAMESPACE) $(NAME) . + +diff: + helm diff upgrade --allow-unreleased --normalize-manifests -n $(NAMESPACE) $(NAME) . + +update: + rm -rf charts + helm repo add capi-operator https://kubernetes-sigs.github.io/cluster-api-operator + helm repo update capi-operator + helm pull capi-operator/cluster-api-operator --untar --untardir charts + rm -rf charts/cluster-api-operator/charts diff --git a/packages/system/capi-operator/charts/cluster-api-operator/.helmignore b/packages/system/capi-operator/charts/cluster-api-operator/.helmignore new file mode 100644 index 00000000..0e8a0eb3 --- /dev/null +++ b/packages/system/capi-operator/charts/cluster-api-operator/.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/packages/system/capi-operator/charts/cluster-api-operator/Chart.lock b/packages/system/capi-operator/charts/cluster-api-operator/Chart.lock new file mode 100644 index 00000000..5d3381ff --- /dev/null +++ b/packages/system/capi-operator/charts/cluster-api-operator/Chart.lock @@ -0,0 +1,6 @@ +dependencies: +- name: cert-manager + repository: https://charts.jetstack.io + version: v1.13.2 +digest: sha256:b92a86c20cdd8a5e44995e71addefd379fdf302410a7dde388623f0e06187406 +generated: "2024-01-16T12:59:42.630842426Z" diff --git a/packages/system/capi-operator/charts/cluster-api-operator/Chart.yaml b/packages/system/capi-operator/charts/cluster-api-operator/Chart.yaml new file mode 100644 index 00000000..d505a05d --- /dev/null +++ b/packages/system/capi-operator/charts/cluster-api-operator/Chart.yaml @@ -0,0 +1,11 @@ +apiVersion: v2 +appVersion: 0.8.1 +dependencies: +- condition: cert-manager.enabled + name: cert-manager + repository: https://charts.jetstack.io + version: v1.13.2 +description: Cluster API Operator +name: cluster-api-operator +type: application +version: 0.8.1 diff --git a/packages/system/capi-operator/charts/cluster-api-operator/crds/cert-manager.crds.yaml b/packages/system/capi-operator/charts/cluster-api-operator/crds/cert-manager.crds.yaml new file mode 100644 index 00000000..14c0726c --- /dev/null +++ b/packages/system/capi-operator/charts/cluster-api-operator/crds/cert-manager.crds.yaml @@ -0,0 +1,4482 @@ +# Copyright 2022 The cert-manager Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Source: cert-manager/templates/crds.yaml +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: certificaterequests.cert-manager.io + labels: + app: 'cert-manager' + app.kubernetes.io/name: 'cert-manager' + app.kubernetes.io/instance: 'cert-manager' + # Generated labels + app.kubernetes.io/version: "v1.13.2" +spec: + group: cert-manager.io + names: + kind: CertificateRequest + listKind: CertificateRequestList + plural: certificaterequests + shortNames: + - cr + - crs + singular: certificaterequest + categories: + - cert-manager + scope: Namespaced + versions: + - name: v1 + subresources: + status: {} + additionalPrinterColumns: + - jsonPath: .status.conditions[?(@.type=="Approved")].status + name: Approved + type: string + - jsonPath: .status.conditions[?(@.type=="Denied")].status + name: Denied + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].status + name: Ready + type: string + - jsonPath: .spec.issuerRef.name + name: Issuer + type: string + - jsonPath: .spec.username + name: Requestor + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].message + name: Status + priority: 1 + type: string + - jsonPath: .metadata.creationTimestamp + description: CreationTimestamp is a timestamp representing the server time when this object was created. It is not guaranteed to be set in happens-before order across separate operations. Clients may not set this value. It is represented in RFC3339 form and is in UTC. + name: Age + type: date + schema: + openAPIV3Schema: + description: "A CertificateRequest is used to request a signed certificate from one of the configured issuers. \n All fields within the CertificateRequest's `spec` are immutable after creation. A CertificateRequest will either succeed or fail, as denoted by its `Ready` status condition and its `status.failureTime` field. \n A CertificateRequest is a one-shot resource, meaning it represents a single point in time request for a certificate and cannot be re-used." + type: object + 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: Specification of the desired state of the CertificateRequest resource. https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status + type: object + required: + - issuerRef + - request + properties: + duration: + description: Requested 'duration' (i.e. lifetime) of the Certificate. Note that the issuer may choose to ignore the requested duration, just like any other requested attribute. + type: string + extra: + description: Extra contains extra attributes of the user that created the CertificateRequest. Populated by the cert-manager webhook on creation and immutable. + type: object + additionalProperties: + type: array + items: + type: string + groups: + description: Groups contains group membership of the user that created the CertificateRequest. Populated by the cert-manager webhook on creation and immutable. + type: array + items: + type: string + x-kubernetes-list-type: atomic + isCA: + description: "Requested basic constraints isCA value. Note that the issuer may choose to ignore the requested isCA value, just like any other requested attribute. \n NOTE: If the CSR in the `Request` field has a BasicConstraints extension, it must have the same isCA value as specified here. \n If true, this will automatically add the `cert sign` usage to the list of requested `usages`." + type: boolean + issuerRef: + description: "Reference to the issuer responsible for issuing the certificate. If the issuer is namespace-scoped, it must be in the same namespace as the Certificate. If the issuer is cluster-scoped, it can be used from any namespace. \n The `name` field of the reference must always be specified." + type: object + required: + - name + properties: + group: + description: Group of the resource being referred to. + type: string + kind: + description: Kind of the resource being referred to. + type: string + name: + description: Name of the resource being referred to. + type: string + request: + description: "The PEM-encoded X.509 certificate signing request to be submitted to the issuer for signing. \n If the CSR has a BasicConstraints extension, its isCA attribute must match the `isCA` value of this CertificateRequest. If the CSR has a KeyUsage extension, its key usages must match the key usages in the `usages` field of this CertificateRequest. If the CSR has a ExtKeyUsage extension, its extended key usages must match the extended key usages in the `usages` field of this CertificateRequest." + type: string + format: byte + uid: + description: UID contains the uid of the user that created the CertificateRequest. Populated by the cert-manager webhook on creation and immutable. + type: string + usages: + description: "Requested key usages and extended key usages. \n NOTE: If the CSR in the `Request` field has uses the KeyUsage or ExtKeyUsage extension, these extensions must have the same values as specified here without any additional values. \n If unset, defaults to `digital signature` and `key encipherment`." + type: array + items: + description: "KeyUsage specifies valid usage contexts for keys. See: https://tools.ietf.org/html/rfc5280#section-4.2.1.3 https://tools.ietf.org/html/rfc5280#section-4.2.1.12 \n Valid KeyUsage values are as follows: \"signing\", \"digital signature\", \"content commitment\", \"key encipherment\", \"key agreement\", \"data encipherment\", \"cert sign\", \"crl sign\", \"encipher only\", \"decipher only\", \"any\", \"server auth\", \"client auth\", \"code signing\", \"email protection\", \"s/mime\", \"ipsec end system\", \"ipsec tunnel\", \"ipsec user\", \"timestamping\", \"ocsp signing\", \"microsoft sgc\", \"netscape sgc\"" + type: string + enum: + - signing + - digital signature + - content commitment + - key encipherment + - key agreement + - data encipherment + - cert sign + - crl sign + - encipher only + - decipher only + - any + - server auth + - client auth + - code signing + - email protection + - s/mime + - ipsec end system + - ipsec tunnel + - ipsec user + - timestamping + - ocsp signing + - microsoft sgc + - netscape sgc + username: + description: Username contains the name of the user that created the CertificateRequest. Populated by the cert-manager webhook on creation and immutable. + type: string + status: + description: 'Status of the CertificateRequest. This is set and managed automatically. Read-only. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status' + type: object + properties: + ca: + description: The PEM encoded X.509 certificate of the signer, also known as the CA (Certificate Authority). This is set on a best-effort basis by different issuers. If not set, the CA is assumed to be unknown/not available. + type: string + format: byte + certificate: + description: The PEM encoded X.509 certificate resulting from the certificate signing request. If not set, the CertificateRequest has either not been completed or has failed. More information on failure can be found by checking the `conditions` field. + type: string + format: byte + conditions: + description: List of status conditions to indicate the status of a CertificateRequest. Known condition types are `Ready`, `InvalidRequest`, `Approved` and `Denied`. + type: array + items: + description: CertificateRequestCondition contains condition information for a CertificateRequest. + type: object + required: + - status + - type + properties: + lastTransitionTime: + description: LastTransitionTime is the timestamp corresponding to the last status change of this condition. + type: string + format: date-time + message: + description: Message is a human readable description of the details of the last transition, complementing reason. + type: string + reason: + description: Reason is a brief machine readable explanation for the condition's last transition. + type: string + status: + description: Status of the condition, one of (`True`, `False`, `Unknown`). + type: string + enum: + - "True" + - "False" + - Unknown + type: + description: Type of the condition, known values are (`Ready`, `InvalidRequest`, `Approved`, `Denied`). + type: string + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + failureTime: + description: FailureTime stores the time that this CertificateRequest failed. This is used to influence garbage collection and back-off. + type: string + format: date-time + served: true + storage: true +--- +# Source: cert-manager/templates/crds.yaml +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: certificates.cert-manager.io + labels: + app: 'cert-manager' + app.kubernetes.io/name: 'cert-manager' + app.kubernetes.io/instance: 'cert-manager' + # Generated labels + app.kubernetes.io/version: "v1.13.2" +spec: + group: cert-manager.io + names: + kind: Certificate + listKind: CertificateList + plural: certificates + shortNames: + - cert + - certs + singular: certificate + categories: + - cert-manager + scope: Namespaced + versions: + - name: v1 + subresources: + status: {} + additionalPrinterColumns: + - jsonPath: .status.conditions[?(@.type=="Ready")].status + name: Ready + type: string + - jsonPath: .spec.secretName + name: Secret + type: string + - jsonPath: .spec.issuerRef.name + name: Issuer + priority: 1 + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].message + name: Status + priority: 1 + type: string + - jsonPath: .metadata.creationTimestamp + description: CreationTimestamp is a timestamp representing the server time when this object was created. It is not guaranteed to be set in happens-before order across separate operations. Clients may not set this value. It is represented in RFC3339 form and is in UTC. + name: Age + type: date + schema: + openAPIV3Schema: + description: "A Certificate resource should be created to ensure an up to date and signed X.509 certificate is stored in the Kubernetes Secret resource named in `spec.secretName`. \n The stored certificate will be renewed before it expires (as configured by `spec.renewBefore`)." + type: object + 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: Specification of the desired state of the Certificate resource. https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status + type: object + required: + - issuerRef + - secretName + properties: + additionalOutputFormats: + description: "Defines extra output formats of the private key and signed certificate chain to be written to this Certificate's target Secret. \n This is an Alpha Feature and is only enabled with the `--feature-gates=AdditionalCertificateOutputFormats=true` option set on both the controller and webhook components." + type: array + items: + description: CertificateAdditionalOutputFormat defines an additional output format of a Certificate resource. These contain supplementary data formats of the signed certificate chain and paired private key. + type: object + required: + - type + properties: + type: + description: Type is the name of the format type that should be written to the Certificate's target Secret. + type: string + enum: + - DER + - CombinedPEM + commonName: + description: "Requested common name X509 certificate subject attribute. More info: https://datatracker.ietf.org/doc/html/rfc5280#section-4.1.2.6 NOTE: TLS clients will ignore this value when any subject alternative name is set (see https://tools.ietf.org/html/rfc6125#section-6.4.4). \n Should have a length of 64 characters or fewer to avoid generating invalid CSRs. Cannot be set if the `literalSubject` field is set." + type: string + dnsNames: + description: Requested DNS subject alternative names. + type: array + items: + type: string + duration: + description: "Requested 'duration' (i.e. lifetime) of the Certificate. Note that the issuer may choose to ignore the requested duration, just like any other requested attribute. \n If unset, this defaults to 90 days. Minimum accepted duration is 1 hour. Value must be in units accepted by Go time.ParseDuration https://golang.org/pkg/time/#ParseDuration." + type: string + emailAddresses: + description: Requested email subject alternative names. + type: array + items: + type: string + encodeUsagesInRequest: + description: "Whether the KeyUsage and ExtKeyUsage extensions should be set in the encoded CSR. \n This option defaults to true, and should only be disabled if the target issuer does not support CSRs with these X509 KeyUsage/ ExtKeyUsage extensions." + type: boolean + ipAddresses: + description: Requested IP address subject alternative names. + type: array + items: + type: string + isCA: + description: "Requested basic constraints isCA value. The isCA value is used to set the `isCA` field on the created CertificateRequest resources. Note that the issuer may choose to ignore the requested isCA value, just like any other requested attribute. \n If true, this will automatically add the `cert sign` usage to the list of requested `usages`." + type: boolean + issuerRef: + description: "Reference to the issuer responsible for issuing the certificate. If the issuer is namespace-scoped, it must be in the same namespace as the Certificate. If the issuer is cluster-scoped, it can be used from any namespace. \n The `name` field of the reference must always be specified." + type: object + required: + - name + properties: + group: + description: Group of the resource being referred to. + type: string + kind: + description: Kind of the resource being referred to. + type: string + name: + description: Name of the resource being referred to. + type: string + keystores: + description: Additional keystore output formats to be stored in the Certificate's Secret. + type: object + properties: + jks: + description: JKS configures options for storing a JKS keystore in the `spec.secretName` Secret resource. + type: object + required: + - create + - passwordSecretRef + properties: + create: + description: Create enables JKS keystore creation for the Certificate. If true, a file named `keystore.jks` will be created in the target Secret resource, encrypted using the password stored in `passwordSecretRef`. The keystore file will be updated immediately. If the issuer provided a CA certificate, a file named `truststore.jks` will also be created in the target Secret resource, encrypted using the password stored in `passwordSecretRef` containing the issuing Certificate Authority + type: boolean + passwordSecretRef: + description: PasswordSecretRef is a reference to a key in a Secret resource containing the password used to encrypt the JKS keystore. + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + pkcs12: + description: PKCS12 configures options for storing a PKCS12 keystore in the `spec.secretName` Secret resource. + type: object + required: + - create + - passwordSecretRef + properties: + create: + description: Create enables PKCS12 keystore creation for the Certificate. If true, a file named `keystore.p12` will be created in the target Secret resource, encrypted using the password stored in `passwordSecretRef`. The keystore file will be updated immediately. If the issuer provided a CA certificate, a file named `truststore.p12` will also be created in the target Secret resource, encrypted using the password stored in `passwordSecretRef` containing the issuing Certificate Authority + type: boolean + passwordSecretRef: + description: PasswordSecretRef is a reference to a key in a Secret resource containing the password used to encrypt the PKCS12 keystore. + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + literalSubject: + description: "Requested X.509 certificate subject, represented using the LDAP \"String Representation of a Distinguished Name\" [1]. Important: the LDAP string format also specifies the order of the attributes in the subject, this is important when issuing certs for LDAP authentication. Example: `CN=foo,DC=corp,DC=example,DC=com` More info [1]: https://datatracker.ietf.org/doc/html/rfc4514 More info: https://github.com/cert-manager/cert-manager/issues/3203 More info: https://github.com/cert-manager/cert-manager/issues/4424 \n Cannot be set if the `subject` or `commonName` field is set. This is an Alpha Feature and is only enabled with the `--feature-gates=LiteralCertificateSubject=true` option set on both the controller and webhook components." + type: string + privateKey: + description: Private key options. These include the key algorithm and size, the used encoding and the rotation policy. + type: object + properties: + algorithm: + description: "Algorithm is the private key algorithm of the corresponding private key for this certificate. \n If provided, allowed values are either `RSA`, `ECDSA` or `Ed25519`. If `algorithm` is specified and `size` is not provided, key size of 2048 will be used for `RSA` key algorithm and key size of 256 will be used for `ECDSA` key algorithm. key size is ignored when using the `Ed25519` key algorithm." + type: string + enum: + - RSA + - ECDSA + - Ed25519 + encoding: + description: "The private key cryptography standards (PKCS) encoding for this certificate's private key to be encoded in. \n If provided, allowed values are `PKCS1` and `PKCS8` standing for PKCS#1 and PKCS#8, respectively. Defaults to `PKCS1` if not specified." + type: string + enum: + - PKCS1 + - PKCS8 + rotationPolicy: + description: "RotationPolicy controls how private keys should be regenerated when a re-issuance is being processed. \n If set to `Never`, a private key will only be generated if one does not already exist in the target `spec.secretName`. If one does exists but it does not have the correct algorithm or size, a warning will be raised to await user intervention. If set to `Always`, a private key matching the specified requirements will be generated whenever a re-issuance occurs. Default is `Never` for backward compatibility." + type: string + enum: + - Never + - Always + size: + description: "Size is the key bit size of the corresponding private key for this certificate. \n If `algorithm` is set to `RSA`, valid values are `2048`, `4096` or `8192`, and will default to `2048` if not specified. If `algorithm` is set to `ECDSA`, valid values are `256`, `384` or `521`, and will default to `256` if not specified. If `algorithm` is set to `Ed25519`, Size is ignored. No other values are allowed." + type: integer + renewBefore: + description: "How long before the currently issued certificate's expiry cert-manager should renew the certificate. For example, if a certificate is valid for 60 minutes, and `renewBefore=10m`, cert-manager will begin to attempt to renew the certificate 50 minutes after it was issued (i.e. when there are 10 minutes remaining until the certificate is no longer valid). \n NOTE: The actual lifetime of the issued certificate is used to determine the renewal time. If an issuer returns a certificate with a different lifetime than the one requested, cert-manager will use the lifetime of the issued certificate. \n If unset, this defaults to 1/3 of the issued certificate's lifetime. Minimum accepted value is 5 minutes. Value must be in units accepted by Go time.ParseDuration https://golang.org/pkg/time/#ParseDuration." + type: string + revisionHistoryLimit: + description: "The maximum number of CertificateRequest revisions that are maintained in the Certificate's history. Each revision represents a single `CertificateRequest` created by this Certificate, either when it was created, renewed, or Spec was changed. Revisions will be removed by oldest first if the number of revisions exceeds this number. \n If set, revisionHistoryLimit must be a value of `1` or greater. If unset (`nil`), revisions will not be garbage collected. Default value is `nil`." + type: integer + format: int32 + secretName: + description: Name of the Secret resource that will be automatically created and managed by this Certificate resource. It will be populated with a private key and certificate, signed by the denoted issuer. The Secret resource lives in the same namespace as the Certificate resource. + type: string + secretTemplate: + description: Defines annotations and labels to be copied to the Certificate's Secret. Labels and annotations on the Secret will be changed as they appear on the SecretTemplate when added or removed. SecretTemplate annotations are added in conjunction with, and cannot overwrite, the base set of annotations cert-manager sets on the Certificate's Secret. + type: object + properties: + annotations: + description: Annotations is a key value map to be copied to the target Kubernetes Secret. + type: object + additionalProperties: + type: string + labels: + description: Labels is a key value map to be copied to the target Kubernetes Secret. + type: object + additionalProperties: + type: string + subject: + description: "Requested set of X509 certificate subject attributes. More info: https://datatracker.ietf.org/doc/html/rfc5280#section-4.1.2.6 \n The common name attribute is specified separately in the `commonName` field. Cannot be set if the `literalSubject` field is set." + type: object + properties: + countries: + description: Countries to be used on the Certificate. + type: array + items: + type: string + localities: + description: Cities to be used on the Certificate. + type: array + items: + type: string + organizationalUnits: + description: Organizational Units to be used on the Certificate. + type: array + items: + type: string + organizations: + description: Organizations to be used on the Certificate. + type: array + items: + type: string + postalCodes: + description: Postal codes to be used on the Certificate. + type: array + items: + type: string + provinces: + description: State/Provinces to be used on the Certificate. + type: array + items: + type: string + serialNumber: + description: Serial number to be used on the Certificate. + type: string + streetAddresses: + description: Street addresses to be used on the Certificate. + type: array + items: + type: string + uris: + description: Requested URI subject alternative names. + type: array + items: + type: string + usages: + description: "Requested key usages and extended key usages. These usages are used to set the `usages` field on the created CertificateRequest resources. If `encodeUsagesInRequest` is unset or set to `true`, the usages will additionally be encoded in the `request` field which contains the CSR blob. \n If unset, defaults to `digital signature` and `key encipherment`." + type: array + items: + description: "KeyUsage specifies valid usage contexts for keys. See: https://tools.ietf.org/html/rfc5280#section-4.2.1.3 https://tools.ietf.org/html/rfc5280#section-4.2.1.12 \n Valid KeyUsage values are as follows: \"signing\", \"digital signature\", \"content commitment\", \"key encipherment\", \"key agreement\", \"data encipherment\", \"cert sign\", \"crl sign\", \"encipher only\", \"decipher only\", \"any\", \"server auth\", \"client auth\", \"code signing\", \"email protection\", \"s/mime\", \"ipsec end system\", \"ipsec tunnel\", \"ipsec user\", \"timestamping\", \"ocsp signing\", \"microsoft sgc\", \"netscape sgc\"" + type: string + enum: + - signing + - digital signature + - content commitment + - key encipherment + - key agreement + - data encipherment + - cert sign + - crl sign + - encipher only + - decipher only + - any + - server auth + - client auth + - code signing + - email protection + - s/mime + - ipsec end system + - ipsec tunnel + - ipsec user + - timestamping + - ocsp signing + - microsoft sgc + - netscape sgc + status: + description: 'Status of the Certificate. This is set and managed automatically. Read-only. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status' + type: object + properties: + conditions: + description: List of status conditions to indicate the status of certificates. Known condition types are `Ready` and `Issuing`. + type: array + items: + description: CertificateCondition contains condition information for an Certificate. + type: object + required: + - status + - type + properties: + lastTransitionTime: + description: LastTransitionTime is the timestamp corresponding to the last status change of this condition. + type: string + format: date-time + message: + description: Message is a human readable description of the details of the last transition, complementing reason. + type: string + observedGeneration: + description: If set, this represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.condition[x].observedGeneration is 9, the condition is out of date with respect to the current state of the Certificate. + type: integer + format: int64 + reason: + description: Reason is a brief machine readable explanation for the condition's last transition. + type: string + status: + description: Status of the condition, one of (`True`, `False`, `Unknown`). + type: string + enum: + - "True" + - "False" + - Unknown + type: + description: Type of the condition, known values are (`Ready`, `Issuing`). + type: string + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + failedIssuanceAttempts: + description: The number of continuous failed issuance attempts up till now. This field gets removed (if set) on a successful issuance and gets set to 1 if unset and an issuance has failed. If an issuance has failed, the delay till the next issuance will be calculated using formula time.Hour * 2 ^ (failedIssuanceAttempts - 1). + type: integer + lastFailureTime: + description: LastFailureTime is set only if the lastest issuance for this Certificate failed and contains the time of the failure. If an issuance has failed, the delay till the next issuance will be calculated using formula time.Hour * 2 ^ (failedIssuanceAttempts - 1). If the latest issuance has succeeded this field will be unset. + type: string + format: date-time + nextPrivateKeySecretName: + description: The name of the Secret resource containing the private key to be used for the next certificate iteration. The keymanager controller will automatically set this field if the `Issuing` condition is set to `True`. It will automatically unset this field when the Issuing condition is not set or False. + type: string + notAfter: + description: The expiration time of the certificate stored in the secret named by this resource in `spec.secretName`. + type: string + format: date-time + notBefore: + description: The time after which the certificate stored in the secret named by this resource in `spec.secretName` is valid. + type: string + format: date-time + renewalTime: + description: RenewalTime is the time at which the certificate will be next renewed. If not set, no upcoming renewal is scheduled. + type: string + format: date-time + revision: + description: "The current 'revision' of the certificate as issued. \n When a CertificateRequest resource is created, it will have the `cert-manager.io/certificate-revision` set to one greater than the current value of this field. \n Upon issuance, this field will be set to the value of the annotation on the CertificateRequest resource used to issue the certificate. \n Persisting the value on the CertificateRequest resource allows the certificates controller to know whether a request is part of an old issuance or if it is part of the ongoing revision's issuance by checking if the revision value in the annotation is greater than this field." + type: integer + served: true + storage: true +--- +# Source: cert-manager/templates/crds.yaml +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: challenges.acme.cert-manager.io + labels: + app: 'cert-manager' + app.kubernetes.io/name: 'cert-manager' + app.kubernetes.io/instance: 'cert-manager' + # Generated labels + app.kubernetes.io/version: "v1.13.2" +spec: + group: acme.cert-manager.io + names: + kind: Challenge + listKind: ChallengeList + plural: challenges + singular: challenge + categories: + - cert-manager + - cert-manager-acme + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .status.state + name: State + type: string + - jsonPath: .spec.dnsName + name: Domain + type: string + - jsonPath: .status.reason + name: Reason + priority: 1 + type: string + - description: CreationTimestamp is a timestamp representing the server time when this object was created. It is not guaranteed to be set in happens-before order across separate operations. Clients may not set this value. It is represented in RFC3339 form and is in UTC. + jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1 + schema: + openAPIV3Schema: + description: Challenge is a type to represent a Challenge request with an ACME server + type: object + required: + - metadata + - spec + 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: + type: object + required: + - authorizationURL + - dnsName + - issuerRef + - key + - solver + - token + - type + - url + properties: + authorizationURL: + description: The URL to the ACME Authorization resource that this challenge is a part of. + type: string + dnsName: + description: dnsName is the identifier that this challenge is for, e.g. example.com. If the requested DNSName is a 'wildcard', this field MUST be set to the non-wildcard domain, e.g. for `*.example.com`, it must be `example.com`. + type: string + issuerRef: + description: References a properly configured ACME-type Issuer which should be used to create this Challenge. If the Issuer does not exist, processing will be retried. If the Issuer is not an 'ACME' Issuer, an error will be returned and the Challenge will be marked as failed. + type: object + required: + - name + properties: + group: + description: Group of the resource being referred to. + type: string + kind: + description: Kind of the resource being referred to. + type: string + name: + description: Name of the resource being referred to. + type: string + key: + description: 'The ACME challenge key for this challenge For HTTP01 challenges, this is the value that must be responded with to complete the HTTP01 challenge in the format: `.`. For DNS01 challenges, this is the base64 encoded SHA256 sum of the `.` text that must be set as the TXT record content.' + type: string + solver: + description: Contains the domain solving configuration that should be used to solve this challenge resource. + type: object + properties: + dns01: + description: Configures cert-manager to attempt to complete authorizations by performing the DNS01 challenge flow. + type: object + properties: + acmeDNS: + description: Use the 'ACME DNS' (https://github.com/joohoi/acme-dns) API to manage DNS01 challenge records. + type: object + required: + - accountSecretRef + - host + properties: + accountSecretRef: + description: A reference to a specific 'key' within a Secret resource. In some instances, `key` is a required field. + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + host: + type: string + akamai: + description: Use the Akamai DNS zone management API to manage DNS01 challenge records. + type: object + required: + - accessTokenSecretRef + - clientSecretSecretRef + - clientTokenSecretRef + - serviceConsumerDomain + properties: + accessTokenSecretRef: + description: A reference to a specific 'key' within a Secret resource. In some instances, `key` is a required field. + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + clientSecretSecretRef: + description: A reference to a specific 'key' within a Secret resource. In some instances, `key` is a required field. + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + clientTokenSecretRef: + description: A reference to a specific 'key' within a Secret resource. In some instances, `key` is a required field. + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + serviceConsumerDomain: + type: string + azureDNS: + description: Use the Microsoft Azure DNS API to manage DNS01 challenge records. + type: object + required: + - resourceGroupName + - subscriptionID + properties: + clientID: + description: if both this and ClientSecret are left unset MSI will be used + type: string + clientSecretSecretRef: + description: if both this and ClientID are left unset MSI will be used + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + environment: + description: name of the Azure environment (default AzurePublicCloud) + type: string + enum: + - AzurePublicCloud + - AzureChinaCloud + - AzureGermanCloud + - AzureUSGovernmentCloud + hostedZoneName: + description: name of the DNS zone that should be used + type: string + managedIdentity: + description: managed identity configuration, can not be used at the same time as clientID, clientSecretSecretRef or tenantID + type: object + properties: + clientID: + description: client ID of the managed identity, can not be used at the same time as resourceID + type: string + resourceID: + description: resource ID of the managed identity, can not be used at the same time as clientID + type: string + resourceGroupName: + description: resource group the DNS zone is located in + type: string + subscriptionID: + description: ID of the Azure subscription + type: string + tenantID: + description: when specifying ClientID and ClientSecret then this field is also needed + type: string + cloudDNS: + description: Use the Google Cloud DNS API to manage DNS01 challenge records. + type: object + required: + - project + properties: + hostedZoneName: + description: HostedZoneName is an optional field that tells cert-manager in which Cloud DNS zone the challenge record has to be created. If left empty cert-manager will automatically choose a zone. + type: string + project: + type: string + serviceAccountSecretRef: + description: A reference to a specific 'key' within a Secret resource. In some instances, `key` is a required field. + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + cloudflare: + description: Use the Cloudflare API to manage DNS01 challenge records. + type: object + properties: + apiKeySecretRef: + description: 'API key to use to authenticate with Cloudflare. Note: using an API token to authenticate is now the recommended method as it allows greater control of permissions.' + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + apiTokenSecretRef: + description: API token used to authenticate with Cloudflare. + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + email: + description: Email of the account, only required when using API key based authentication. + type: string + cnameStrategy: + description: CNAMEStrategy configures how the DNS01 provider should handle CNAME records when found in DNS zones. + type: string + enum: + - None + - Follow + digitalocean: + description: Use the DigitalOcean DNS API to manage DNS01 challenge records. + type: object + required: + - tokenSecretRef + properties: + tokenSecretRef: + description: A reference to a specific 'key' within a Secret resource. In some instances, `key` is a required field. + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + rfc2136: + description: Use RFC2136 ("Dynamic Updates in the Domain Name System") (https://datatracker.ietf.org/doc/rfc2136/) to manage DNS01 challenge records. + type: object + required: + - nameserver + properties: + nameserver: + description: The IP address or hostname of an authoritative DNS server supporting RFC2136 in the form host:port. If the host is an IPv6 address it must be enclosed in square brackets (e.g [2001:db8::1]) ; port is optional. This field is required. + type: string + tsigAlgorithm: + description: 'The TSIG Algorithm configured in the DNS supporting RFC2136. Used only when ``tsigSecretSecretRef`` and ``tsigKeyName`` are defined. Supported values are (case-insensitive): ``HMACMD5`` (default), ``HMACSHA1``, ``HMACSHA256`` or ``HMACSHA512``.' + type: string + tsigKeyName: + description: The TSIG Key name configured in the DNS. If ``tsigSecretSecretRef`` is defined, this field is required. + type: string + tsigSecretSecretRef: + description: The name of the secret containing the TSIG value. If ``tsigKeyName`` is defined, this field is required. + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + route53: + description: Use the AWS Route53 API to manage DNS01 challenge records. + type: object + required: + - region + properties: + accessKeyID: + description: 'The AccessKeyID is used for authentication. Cannot be set when SecretAccessKeyID is set. If neither the Access Key nor Key ID are set, we fall-back to using env vars, shared credentials file or AWS Instance metadata, see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials' + type: string + accessKeyIDSecretRef: + description: 'The SecretAccessKey is used for authentication. If set, pull the AWS access key ID from a key within a Kubernetes Secret. Cannot be set when AccessKeyID is set. If neither the Access Key nor Key ID are set, we fall-back to using env vars, shared credentials file or AWS Instance metadata, see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials' + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + hostedZoneID: + description: If set, the provider will manage only this zone in Route53 and will not do an lookup using the route53:ListHostedZonesByName api call. + type: string + region: + description: Always set the region when using AccessKeyID and SecretAccessKey + type: string + role: + description: Role is a Role ARN which the Route53 provider will assume using either the explicit credentials AccessKeyID/SecretAccessKey or the inferred credentials from environment variables, shared credentials file or AWS Instance metadata + type: string + secretAccessKeySecretRef: + description: 'The SecretAccessKey is used for authentication. If neither the Access Key nor Key ID are set, we fall-back to using env vars, shared credentials file or AWS Instance metadata, see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials' + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + webhook: + description: Configure an external webhook based DNS01 challenge solver to manage DNS01 challenge records. + type: object + required: + - groupName + - solverName + properties: + config: + description: Additional configuration that should be passed to the webhook apiserver when challenges are processed. This can contain arbitrary JSON data. Secret values should not be specified in this stanza. If secret values are needed (e.g. credentials for a DNS service), you should use a SecretKeySelector to reference a Secret resource. For details on the schema of this field, consult the webhook provider implementation's documentation. + x-kubernetes-preserve-unknown-fields: true + groupName: + description: The API group name that should be used when POSTing ChallengePayload resources to the webhook apiserver. This should be the same as the GroupName specified in the webhook provider implementation. + type: string + solverName: + description: The name of the solver to use, as defined in the webhook provider implementation. This will typically be the name of the provider, e.g. 'cloudflare'. + type: string + http01: + description: Configures cert-manager to attempt to complete authorizations by performing the HTTP01 challenge flow. It is not possible to obtain certificates for wildcard domain names (e.g. `*.example.com`) using the HTTP01 challenge mechanism. + type: object + properties: + gatewayHTTPRoute: + description: The Gateway API is a sig-network community API that models service networking in Kubernetes (https://gateway-api.sigs.k8s.io/). The Gateway solver will create HTTPRoutes with the specified labels in the same namespace as the challenge. This solver is experimental, and fields / behaviour may change in the future. + type: object + properties: + labels: + description: Custom labels that will be applied to HTTPRoutes created by cert-manager while solving HTTP-01 challenges. + type: object + additionalProperties: + type: string + parentRefs: + description: 'When solving an HTTP-01 challenge, cert-manager creates an HTTPRoute. cert-manager needs to know which parentRefs should be used when creating the HTTPRoute. Usually, the parentRef references a Gateway. See: https://gateway-api.sigs.k8s.io/api-types/httproute/#attaching-to-gateways' + type: array + items: + description: "ParentReference identifies an API object (usually a Gateway) that can be considered a parent of this resource (usually a route). There are two kinds of parent resources with \"Core\" support: \n * Gateway (Gateway conformance profile) * Service (Mesh conformance profile, experimental, ClusterIP Services only) \n This API may be extended in the future to support additional kinds of parent resources. \n The API object must be valid in the cluster; the Group and Kind must be registered in the cluster for this reference to be valid." + type: object + required: + - name + properties: + group: + description: "Group is the group of the referent. When unspecified, \"gateway.networking.k8s.io\" is inferred. To set the core API group (such as for a \"Service\" kind referent), Group must be explicitly set to \"\" (empty string). \n Support: Core" + type: string + default: gateway.networking.k8s.io + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + kind: + description: "Kind is kind of the referent. \n There are two kinds of parent resources with \"Core\" support: \n * Gateway (Gateway conformance profile) * Service (Mesh conformance profile, experimental, ClusterIP Services only) \n Support for other resources is Implementation-Specific." + type: string + default: Gateway + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + name: + description: "Name is the name of the referent. \n Support: Core" + type: string + maxLength: 253 + minLength: 1 + namespace: + description: "Namespace is the namespace of the referent. When unspecified, this refers to the local namespace of the Route. \n Note that there are specific rules for ParentRefs which cross namespace boundaries. Cross-namespace references are only valid if they are explicitly allowed by something in the namespace they are referring to. For example: Gateway has the AllowedRoutes field, and ReferenceGrant provides a generic way to enable any other kind of cross-namespace reference. \n ParentRefs from a Route to a Service in the same namespace are \"producer\" routes, which apply default routing rules to inbound connections from any namespace to the Service. \n ParentRefs from a Route to a Service in a different namespace are \"consumer\" routes, and these routing rules are only applied to outbound connections originating from the same namespace as the Route, for which the intended destination of the connections are a Service targeted as a ParentRef of the Route. \n Support: Core" + type: string + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + port: + description: "Port is the network port this Route targets. It can be interpreted differently based on the type of parent resource. \n When the parent resource is a Gateway, this targets all listeners listening on the specified port that also support this kind of Route(and select this Route). It's not recommended to set `Port` unless the networking behaviors specified in a Route must apply to a specific port as opposed to a listener(s) whose port(s) may be changed. When both Port and SectionName are specified, the name and port of the selected listener must match both specified values. \n When the parent resource is a Service, this targets a specific port in the Service spec. When both Port (experimental) and SectionName are specified, the name and port of the selected port must match both specified values. \n Implementations MAY choose to support other parent resources. Implementations supporting other types of parent resources MUST clearly document how/if Port is interpreted. \n For the purpose of status, an attachment is considered successful as long as the parent resource accepts it partially. For example, Gateway listeners can restrict which Routes can attach to them by Route kind, namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from the referencing Route, the Route MUST be considered successfully attached. If no Gateway listeners accept attachment from this Route, the Route MUST be considered detached from the Gateway. \n Support: Extended \n " + type: integer + format: int32 + maximum: 65535 + minimum: 1 + sectionName: + description: "SectionName is the name of a section within the target resource. In the following resources, SectionName is interpreted as the following: \n * Gateway: Listener Name. When both Port (experimental) and SectionName are specified, the name and port of the selected listener must match both specified values. * Service: Port Name. When both Port (experimental) and SectionName are specified, the name and port of the selected listener must match both specified values. Note that attaching Routes to Services as Parents is part of experimental Mesh support and is not supported for any other purpose. \n Implementations MAY choose to support attaching Routes to other resources. If that is the case, they MUST clearly document how SectionName is interpreted. \n When unspecified (empty string), this will reference the entire resource. For the purpose of status, an attachment is considered successful if at least one section in the parent resource accepts it. For example, Gateway listeners can restrict which Routes can attach to them by Route kind, namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from the referencing Route, the Route MUST be considered successfully attached. If no Gateway listeners accept attachment from this Route, the Route MUST be considered detached from the Gateway. \n Support: Core" + type: string + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + serviceType: + description: Optional service type for Kubernetes solver service. Supported values are NodePort or ClusterIP. If unset, defaults to NodePort. + type: string + ingress: + description: The ingress based HTTP01 challenge solver will solve challenges by creating or modifying Ingress resources in order to route requests for '/.well-known/acme-challenge/XYZ' to 'challenge solver' pods that are provisioned by cert-manager for each Challenge to be completed. + type: object + properties: + class: + description: This field configures the annotation `kubernetes.io/ingress.class` when creating Ingress resources to solve ACME challenges that use this challenge solver. Only one of `class`, `name` or `ingressClassName` may be specified. + type: string + ingressClassName: + description: This field configures the field `ingressClassName` on the created Ingress resources used to solve ACME challenges that use this challenge solver. This is the recommended way of configuring the ingress class. Only one of `class`, `name` or `ingressClassName` may be specified. + type: string + ingressTemplate: + description: Optional ingress template used to configure the ACME challenge solver ingress used for HTTP01 challenges. + type: object + properties: + metadata: + description: ObjectMeta overrides for the ingress used to solve HTTP01 challenges. Only the 'labels' and 'annotations' fields may be set. If labels or annotations overlap with in-built values, the values here will override the in-built values. + type: object + properties: + annotations: + description: Annotations that should be added to the created ACME HTTP01 solver ingress. + type: object + additionalProperties: + type: string + labels: + description: Labels that should be added to the created ACME HTTP01 solver ingress. + type: object + additionalProperties: + type: string + name: + description: The name of the ingress resource that should have ACME challenge solving routes inserted into it in order to solve HTTP01 challenges. This is typically used in conjunction with ingress controllers like ingress-gce, which maintains a 1:1 mapping between external IPs and ingress resources. Only one of `class`, `name` or `ingressClassName` may be specified. + type: string + podTemplate: + description: Optional pod template used to configure the ACME challenge solver pods used for HTTP01 challenges. + type: object + properties: + metadata: + description: ObjectMeta overrides for the pod used to solve HTTP01 challenges. Only the 'labels' and 'annotations' fields may be set. If labels or annotations overlap with in-built values, the values here will override the in-built values. + type: object + properties: + annotations: + description: Annotations that should be added to the create ACME HTTP01 solver pods. + type: object + additionalProperties: + type: string + labels: + description: Labels that should be added to the created ACME HTTP01 solver pods. + type: object + additionalProperties: + type: string + spec: + description: PodSpec defines overrides for the HTTP01 challenge solver pod. Check ACMEChallengeSolverHTTP01IngressPodSpec to find out currently supported fields. All other fields will be ignored. + type: object + properties: + affinity: + description: If specified, the pod's scheduling constraints + type: object + properties: + nodeAffinity: + description: Describes node affinity scheduling rules for the pod. + type: object + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods to nodes that satisfy the affinity expressions specified by this field, but it may choose a node that violates one or more of the expressions. The node that is most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling affinity expressions, etc.), compute a sum by iterating through the elements of this field and adding "weight" to the sum if the node matches the corresponding matchExpressions; the node(s) with the highest sum are the most preferred. + type: array + items: + description: An empty preferred scheduling term matches all objects with implicit weight 0 (i.e. it's a no-op). A null preferred scheduling term matches no objects (i.e. is also a no-op). + type: object + required: + - preference + - weight + properties: + preference: + description: A node selector term, associated with the corresponding weight. + type: object + properties: + matchExpressions: + description: A list of node selector requirements by node's labels. + type: array + items: + description: A node selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: The label key that the selector applies to. + type: string + operator: + description: Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: 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. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch. + type: array + items: + type: string + matchFields: + description: A list of node selector requirements by node's fields. + type: array + items: + description: A node selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: The label key that the selector applies to. + type: string + operator: + description: Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: 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. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch. + type: array + items: + type: string + x-kubernetes-map-type: atomic + weight: + description: Weight associated with matching the corresponding nodeSelectorTerm, in the range 1-100. + type: integer + format: int32 + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by this field are not met at scheduling time, the pod will not be scheduled onto the node. If the affinity requirements specified by this field cease to be met at some point during pod execution (e.g. due to an update), the system may or may not try to eventually evict the pod from its node. + type: object + required: + - nodeSelectorTerms + properties: + nodeSelectorTerms: + description: Required. A list of node selector terms. The terms are ORed. + type: array + items: + description: A null or empty node selector term matches no objects. The requirements of them are ANDed. The TopologySelectorTerm type implements a subset of the NodeSelectorTerm. + type: object + properties: + matchExpressions: + description: A list of node selector requirements by node's labels. + type: array + items: + description: A node selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: The label key that the selector applies to. + type: string + operator: + description: Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: 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. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch. + type: array + items: + type: string + matchFields: + description: A list of node selector requirements by node's fields. + type: array + items: + description: A node selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: The label key that the selector applies to. + type: string + operator: + description: Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: 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. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch. + type: array + items: + type: string + x-kubernetes-map-type: atomic + x-kubernetes-map-type: atomic + podAffinity: + description: Describes pod affinity scheduling rules (e.g. co-locate this pod in the same node, zone, etc. as some other pod(s)). + type: object + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods to nodes that satisfy the affinity expressions specified by this field, but it may choose a node that violates one or more of the expressions. The node that is most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling affinity expressions, etc.), compute a sum by iterating through the elements of this field and adding "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. + type: array + items: + description: The weights of all of the matched WeightedPodAffinityTerm fields are added per-node to find the most preferred node(s) + type: object + required: + - podAffinityTerm + - weight + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated with the corresponding weight. + type: object + required: + - topologyKey + properties: + labelSelector: + description: A label query over a set of resources, in this case pods. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + matchLabels: + 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 + additionalProperties: + type: string + x-kubernetes-map-type: atomic + namespaceSelector: + description: A label query over the set of namespaces that the term applies to. The term is applied to the union of the namespaces selected by this field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector ({}) matches all namespaces. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + matchLabels: + 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 + additionalProperties: + type: string + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static list of namespace names that the term applies to. The term is applied to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list and null namespaceSelector means "this pod's namespace". + type: array + items: + type: string + topologyKey: + description: This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. Empty topologyKey is not allowed. + type: string + weight: + description: weight associated with matching the corresponding podAffinityTerm, in the range 1-100. + type: integer + format: int32 + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by this field are not met at scheduling time, the pod will not be scheduled onto the node. If the affinity requirements specified by this field cease to be met at some point during pod execution (e.g. due to a pod label update), the system may or may not try to eventually evict the pod from its node. When there are multiple elements, the lists of nodes corresponding to each podAffinityTerm are intersected, i.e. all terms must be satisfied. + type: array + items: + description: Defines a set of pods (namely those matching the labelSelector relative to the given namespace(s)) that this pod should be co-located (affinity) or not co-located (anti-affinity) with, where co-located is defined as running on a node whose value of the label with key matches that of any node on which a pod of the set of pods is running + type: object + required: + - topologyKey + properties: + labelSelector: + description: A label query over a set of resources, in this case pods. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + matchLabels: + 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 + additionalProperties: + type: string + x-kubernetes-map-type: atomic + namespaceSelector: + description: A label query over the set of namespaces that the term applies to. The term is applied to the union of the namespaces selected by this field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector ({}) matches all namespaces. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + matchLabels: + 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 + additionalProperties: + type: string + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static list of namespace names that the term applies to. The term is applied to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list and null namespaceSelector means "this pod's namespace". + type: array + items: + type: string + topologyKey: + description: This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. Empty topologyKey is not allowed. + type: string + podAntiAffinity: + description: Describes pod anti-affinity scheduling rules (e.g. avoid putting this pod in the same node, zone, etc. as some other pod(s)). + type: object + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods to nodes that satisfy the anti-affinity expressions specified by this field, but it may choose a node that violates one or more of the expressions. The node that is most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), compute a sum by iterating through the elements of this field and adding "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. + type: array + items: + description: The weights of all of the matched WeightedPodAffinityTerm fields are added per-node to find the most preferred node(s) + type: object + required: + - podAffinityTerm + - weight + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated with the corresponding weight. + type: object + required: + - topologyKey + properties: + labelSelector: + description: A label query over a set of resources, in this case pods. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + matchLabels: + 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 + additionalProperties: + type: string + x-kubernetes-map-type: atomic + namespaceSelector: + description: A label query over the set of namespaces that the term applies to. The term is applied to the union of the namespaces selected by this field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector ({}) matches all namespaces. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + matchLabels: + 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 + additionalProperties: + type: string + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static list of namespace names that the term applies to. The term is applied to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list and null namespaceSelector means "this pod's namespace". + type: array + items: + type: string + topologyKey: + description: This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. Empty topologyKey is not allowed. + type: string + weight: + description: weight associated with matching the corresponding podAffinityTerm, in the range 1-100. + type: integer + format: int32 + requiredDuringSchedulingIgnoredDuringExecution: + description: If the anti-affinity requirements specified by this field are not met at scheduling time, the pod will not be scheduled onto the node. If the anti-affinity requirements specified by this field cease to be met at some point during pod execution (e.g. due to a pod label update), the system may or may not try to eventually evict the pod from its node. When there are multiple elements, the lists of nodes corresponding to each podAffinityTerm are intersected, i.e. all terms must be satisfied. + type: array + items: + description: Defines a set of pods (namely those matching the labelSelector relative to the given namespace(s)) that this pod should be co-located (affinity) or not co-located (anti-affinity) with, where co-located is defined as running on a node whose value of the label with key matches that of any node on which a pod of the set of pods is running + type: object + required: + - topologyKey + properties: + labelSelector: + description: A label query over a set of resources, in this case pods. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + matchLabels: + 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 + additionalProperties: + type: string + x-kubernetes-map-type: atomic + namespaceSelector: + description: A label query over the set of namespaces that the term applies to. The term is applied to the union of the namespaces selected by this field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector ({}) matches all namespaces. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + matchLabels: + 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 + additionalProperties: + type: string + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static list of namespace names that the term applies to. The term is applied to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list and null namespaceSelector means "this pod's namespace". + type: array + items: + type: string + topologyKey: + description: This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. Empty topologyKey is not allowed. + type: string + imagePullSecrets: + description: If specified, the pod's imagePullSecrets + type: array + items: + description: LocalObjectReference contains enough information to let you locate the referenced object inside the same namespace. + type: object + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + x-kubernetes-map-type: atomic + nodeSelector: + description: 'NodeSelector is a selector which must be true for the pod to fit on a node. Selector which must match a node''s labels for the pod to be scheduled on that node. More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/' + type: object + additionalProperties: + type: string + priorityClassName: + description: If specified, the pod's priorityClassName. + type: string + serviceAccountName: + description: If specified, the pod's service account + type: string + tolerations: + description: If specified, the pod's tolerations. + type: array + items: + description: The pod this Toleration is attached to tolerates any taint that matches the triple using the matching operator . + type: object + 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. + type: integer + format: int64 + 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 + serviceType: + description: Optional service type for Kubernetes solver service. Supported values are NodePort or ClusterIP. If unset, defaults to NodePort. + type: string + selector: + description: Selector selects a set of DNSNames on the Certificate resource that should be solved using this challenge solver. If not specified, the solver will be treated as the 'default' solver with the lowest priority, i.e. if any other solver has a more specific match, it will be used instead. + type: object + properties: + dnsNames: + description: List of DNSNames that this solver will be used to solve. If specified and a match is found, a dnsNames selector will take precedence over a dnsZones selector. If multiple solvers match with the same dnsNames value, the solver with the most matching labels in matchLabels will be selected. If neither has more matches, the solver defined earlier in the list will be selected. + type: array + items: + type: string + dnsZones: + description: List of DNSZones that this solver will be used to solve. The most specific DNS zone match specified here will take precedence over other DNS zone matches, so a solver specifying sys.example.com will be selected over one specifying example.com for the domain www.sys.example.com. If multiple solvers match with the same dnsZones value, the solver with the most matching labels in matchLabels will be selected. If neither has more matches, the solver defined earlier in the list will be selected. + type: array + items: + type: string + matchLabels: + description: A label selector that is used to refine the set of certificate's that this challenge solver will apply to. + type: object + additionalProperties: + type: string + token: + description: The ACME challenge token for this challenge. This is the raw value returned from the ACME server. + type: string + type: + description: The type of ACME challenge this resource represents. One of "HTTP-01" or "DNS-01". + type: string + enum: + - HTTP-01 + - DNS-01 + url: + description: The URL of the ACME Challenge resource for this challenge. This can be used to lookup details about the status of this challenge. + type: string + wildcard: + description: wildcard will be true if this challenge is for a wildcard identifier, for example '*.example.com'. + type: boolean + status: + type: object + properties: + presented: + description: presented will be set to true if the challenge values for this challenge are currently 'presented'. This *does not* imply the self check is passing. Only that the values have been 'submitted' for the appropriate challenge mechanism (i.e. the DNS01 TXT record has been presented, or the HTTP01 configuration has been configured). + type: boolean + processing: + description: Used to denote whether this challenge should be processed or not. This field will only be set to true by the 'scheduling' component. It will only be set to false by the 'challenges' controller, after the challenge has reached a final state or timed out. If this field is set to false, the challenge controller will not take any more action. + type: boolean + reason: + description: Contains human readable information on why the Challenge is in the current state. + type: string + state: + description: Contains the current 'state' of the challenge. If not set, the state of the challenge is unknown. + type: string + enum: + - valid + - ready + - pending + - processing + - invalid + - expired + - errored + served: true + storage: true + subresources: + status: {} +--- +# Source: cert-manager/templates/crds.yaml +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: clusterissuers.cert-manager.io + labels: + app: 'cert-manager' + app.kubernetes.io/name: 'cert-manager' + app.kubernetes.io/instance: "cert-manager" + # Generated labels + app.kubernetes.io/version: "v1.13.2" +spec: + group: cert-manager.io + names: + kind: ClusterIssuer + listKind: ClusterIssuerList + plural: clusterissuers + singular: clusterissuer + categories: + - cert-manager + scope: Cluster + versions: + - name: v1 + subresources: + status: {} + additionalPrinterColumns: + - jsonPath: .status.conditions[?(@.type=="Ready")].status + name: Ready + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].message + name: Status + priority: 1 + type: string + - jsonPath: .metadata.creationTimestamp + description: CreationTimestamp is a timestamp representing the server time when this object was created. It is not guaranteed to be set in happens-before order across separate operations. Clients may not set this value. It is represented in RFC3339 form and is in UTC. + name: Age + type: date + schema: + openAPIV3Schema: + description: A ClusterIssuer represents a certificate issuing authority which can be referenced as part of `issuerRef` fields. It is similar to an Issuer, however it is cluster-scoped and therefore can be referenced by resources that exist in *any* namespace, not just the same namespace as the referent. + type: object + required: + - spec + 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: Desired state of the ClusterIssuer resource. + type: object + properties: + acme: + description: ACME configures this issuer to communicate with a RFC8555 (ACME) server to obtain signed x509 certificates. + type: object + required: + - privateKeySecretRef + - server + properties: + caBundle: + description: Base64-encoded bundle of PEM CAs which can be used to validate the certificate chain presented by the ACME server. Mutually exclusive with SkipTLSVerify; prefer using CABundle to prevent various kinds of security vulnerabilities. If CABundle and SkipTLSVerify are unset, the system certificate bundle inside the container is used to validate the TLS connection. + type: string + format: byte + disableAccountKeyGeneration: + description: Enables or disables generating a new ACME account key. If true, the Issuer resource will *not* request a new account but will expect the account key to be supplied via an existing secret. If false, the cert-manager system will generate a new ACME account key for the Issuer. Defaults to false. + type: boolean + email: + description: Email is the email address to be associated with the ACME account. This field is optional, but it is strongly recommended to be set. It will be used to contact you in case of issues with your account or certificates, including expiry notification emails. This field may be updated after the account is initially registered. + type: string + enableDurationFeature: + description: Enables requesting a Not After date on certificates that matches the duration of the certificate. This is not supported by all ACME servers like Let's Encrypt. If set to true when the ACME server does not support it it will create an error on the Order. Defaults to false. + type: boolean + externalAccountBinding: + description: ExternalAccountBinding is a reference to a CA external account of the ACME server. If set, upon registration cert-manager will attempt to associate the given external account credentials with the registered ACME account. + type: object + required: + - keyID + - keySecretRef + properties: + keyAlgorithm: + description: 'Deprecated: keyAlgorithm field exists for historical compatibility reasons and should not be used. The algorithm is now hardcoded to HS256 in golang/x/crypto/acme.' + type: string + enum: + - HS256 + - HS384 + - HS512 + keyID: + description: keyID is the ID of the CA key that the External Account is bound to. + type: string + keySecretRef: + description: keySecretRef is a Secret Key Selector referencing a data item in a Kubernetes Secret which holds the symmetric MAC key of the External Account Binding. The `key` is the index string that is paired with the key data in the Secret and should not be confused with the key data itself, or indeed with the External Account Binding keyID above. The secret key stored in the Secret **must** be un-padded, base64 URL encoded data. + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + preferredChain: + description: 'PreferredChain is the chain to use if the ACME server outputs multiple. PreferredChain is no guarantee that this one gets delivered by the ACME endpoint. For example, for Let''s Encrypt''s DST crosssign you would use: "DST Root CA X3" or "ISRG Root X1" for the newer Let''s Encrypt root CA. This value picks the first certificate bundle in the ACME alternative chains that has a certificate with this value as its issuer''s CN' + type: string + maxLength: 64 + privateKeySecretRef: + description: PrivateKey is the name of a Kubernetes Secret resource that will be used to store the automatically generated ACME account private key. Optionally, a `key` may be specified to select a specific entry within the named Secret resource. If `key` is not specified, a default of `tls.key` will be used. + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + server: + description: 'Server is the URL used to access the ACME server''s ''directory'' endpoint. For example, for Let''s Encrypt''s staging endpoint, you would use: "https://acme-staging-v02.api.letsencrypt.org/directory". Only ACME v2 endpoints (i.e. RFC 8555) are supported.' + type: string + skipTLSVerify: + description: 'INSECURE: Enables or disables validation of the ACME server TLS certificate. If true, requests to the ACME server will not have the TLS certificate chain validated. Mutually exclusive with CABundle; prefer using CABundle to prevent various kinds of security vulnerabilities. Only enable this option in development environments. If CABundle and SkipTLSVerify are unset, the system certificate bundle inside the container is used to validate the TLS connection. Defaults to false.' + type: boolean + solvers: + description: 'Solvers is a list of challenge solvers that will be used to solve ACME challenges for the matching domains. Solver configurations must be provided in order to obtain certificates from an ACME server. For more information, see: https://cert-manager.io/docs/configuration/acme/' + type: array + items: + description: An ACMEChallengeSolver describes how to solve ACME challenges for the issuer it is part of. A selector may be provided to use different solving strategies for different DNS names. Only one of HTTP01 or DNS01 must be provided. + type: object + properties: + dns01: + description: Configures cert-manager to attempt to complete authorizations by performing the DNS01 challenge flow. + type: object + properties: + acmeDNS: + description: Use the 'ACME DNS' (https://github.com/joohoi/acme-dns) API to manage DNS01 challenge records. + type: object + required: + - accountSecretRef + - host + properties: + accountSecretRef: + description: A reference to a specific 'key' within a Secret resource. In some instances, `key` is a required field. + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + host: + type: string + akamai: + description: Use the Akamai DNS zone management API to manage DNS01 challenge records. + type: object + required: + - accessTokenSecretRef + - clientSecretSecretRef + - clientTokenSecretRef + - serviceConsumerDomain + properties: + accessTokenSecretRef: + description: A reference to a specific 'key' within a Secret resource. In some instances, `key` is a required field. + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + clientSecretSecretRef: + description: A reference to a specific 'key' within a Secret resource. In some instances, `key` is a required field. + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + clientTokenSecretRef: + description: A reference to a specific 'key' within a Secret resource. In some instances, `key` is a required field. + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + serviceConsumerDomain: + type: string + azureDNS: + description: Use the Microsoft Azure DNS API to manage DNS01 challenge records. + type: object + required: + - resourceGroupName + - subscriptionID + properties: + clientID: + description: if both this and ClientSecret are left unset MSI will be used + type: string + clientSecretSecretRef: + description: if both this and ClientID are left unset MSI will be used + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + environment: + description: name of the Azure environment (default AzurePublicCloud) + type: string + enum: + - AzurePublicCloud + - AzureChinaCloud + - AzureGermanCloud + - AzureUSGovernmentCloud + hostedZoneName: + description: name of the DNS zone that should be used + type: string + managedIdentity: + description: managed identity configuration, can not be used at the same time as clientID, clientSecretSecretRef or tenantID + type: object + properties: + clientID: + description: client ID of the managed identity, can not be used at the same time as resourceID + type: string + resourceID: + description: resource ID of the managed identity, can not be used at the same time as clientID + type: string + resourceGroupName: + description: resource group the DNS zone is located in + type: string + subscriptionID: + description: ID of the Azure subscription + type: string + tenantID: + description: when specifying ClientID and ClientSecret then this field is also needed + type: string + cloudDNS: + description: Use the Google Cloud DNS API to manage DNS01 challenge records. + type: object + required: + - project + properties: + hostedZoneName: + description: HostedZoneName is an optional field that tells cert-manager in which Cloud DNS zone the challenge record has to be created. If left empty cert-manager will automatically choose a zone. + type: string + project: + type: string + serviceAccountSecretRef: + description: A reference to a specific 'key' within a Secret resource. In some instances, `key` is a required field. + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + cloudflare: + description: Use the Cloudflare API to manage DNS01 challenge records. + type: object + properties: + apiKeySecretRef: + description: 'API key to use to authenticate with Cloudflare. Note: using an API token to authenticate is now the recommended method as it allows greater control of permissions.' + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + apiTokenSecretRef: + description: API token used to authenticate with Cloudflare. + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + email: + description: Email of the account, only required when using API key based authentication. + type: string + cnameStrategy: + description: CNAMEStrategy configures how the DNS01 provider should handle CNAME records when found in DNS zones. + type: string + enum: + - None + - Follow + digitalocean: + description: Use the DigitalOcean DNS API to manage DNS01 challenge records. + type: object + required: + - tokenSecretRef + properties: + tokenSecretRef: + description: A reference to a specific 'key' within a Secret resource. In some instances, `key` is a required field. + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + rfc2136: + description: Use RFC2136 ("Dynamic Updates in the Domain Name System") (https://datatracker.ietf.org/doc/rfc2136/) to manage DNS01 challenge records. + type: object + required: + - nameserver + properties: + nameserver: + description: The IP address or hostname of an authoritative DNS server supporting RFC2136 in the form host:port. If the host is an IPv6 address it must be enclosed in square brackets (e.g [2001:db8::1]) ; port is optional. This field is required. + type: string + tsigAlgorithm: + description: 'The TSIG Algorithm configured in the DNS supporting RFC2136. Used only when ``tsigSecretSecretRef`` and ``tsigKeyName`` are defined. Supported values are (case-insensitive): ``HMACMD5`` (default), ``HMACSHA1``, ``HMACSHA256`` or ``HMACSHA512``.' + type: string + tsigKeyName: + description: The TSIG Key name configured in the DNS. If ``tsigSecretSecretRef`` is defined, this field is required. + type: string + tsigSecretSecretRef: + description: The name of the secret containing the TSIG value. If ``tsigKeyName`` is defined, this field is required. + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + route53: + description: Use the AWS Route53 API to manage DNS01 challenge records. + type: object + required: + - region + properties: + accessKeyID: + description: 'The AccessKeyID is used for authentication. Cannot be set when SecretAccessKeyID is set. If neither the Access Key nor Key ID are set, we fall-back to using env vars, shared credentials file or AWS Instance metadata, see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials' + type: string + accessKeyIDSecretRef: + description: 'The SecretAccessKey is used for authentication. If set, pull the AWS access key ID from a key within a Kubernetes Secret. Cannot be set when AccessKeyID is set. If neither the Access Key nor Key ID are set, we fall-back to using env vars, shared credentials file or AWS Instance metadata, see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials' + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + hostedZoneID: + description: If set, the provider will manage only this zone in Route53 and will not do an lookup using the route53:ListHostedZonesByName api call. + type: string + region: + description: Always set the region when using AccessKeyID and SecretAccessKey + type: string + role: + description: Role is a Role ARN which the Route53 provider will assume using either the explicit credentials AccessKeyID/SecretAccessKey or the inferred credentials from environment variables, shared credentials file or AWS Instance metadata + type: string + secretAccessKeySecretRef: + description: 'The SecretAccessKey is used for authentication. If neither the Access Key nor Key ID are set, we fall-back to using env vars, shared credentials file or AWS Instance metadata, see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials' + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + webhook: + description: Configure an external webhook based DNS01 challenge solver to manage DNS01 challenge records. + type: object + required: + - groupName + - solverName + properties: + config: + description: Additional configuration that should be passed to the webhook apiserver when challenges are processed. This can contain arbitrary JSON data. Secret values should not be specified in this stanza. If secret values are needed (e.g. credentials for a DNS service), you should use a SecretKeySelector to reference a Secret resource. For details on the schema of this field, consult the webhook provider implementation's documentation. + x-kubernetes-preserve-unknown-fields: true + groupName: + description: The API group name that should be used when POSTing ChallengePayload resources to the webhook apiserver. This should be the same as the GroupName specified in the webhook provider implementation. + type: string + solverName: + description: The name of the solver to use, as defined in the webhook provider implementation. This will typically be the name of the provider, e.g. 'cloudflare'. + type: string + http01: + description: Configures cert-manager to attempt to complete authorizations by performing the HTTP01 challenge flow. It is not possible to obtain certificates for wildcard domain names (e.g. `*.example.com`) using the HTTP01 challenge mechanism. + type: object + properties: + gatewayHTTPRoute: + description: The Gateway API is a sig-network community API that models service networking in Kubernetes (https://gateway-api.sigs.k8s.io/). The Gateway solver will create HTTPRoutes with the specified labels in the same namespace as the challenge. This solver is experimental, and fields / behaviour may change in the future. + type: object + properties: + labels: + description: Custom labels that will be applied to HTTPRoutes created by cert-manager while solving HTTP-01 challenges. + type: object + additionalProperties: + type: string + parentRefs: + description: 'When solving an HTTP-01 challenge, cert-manager creates an HTTPRoute. cert-manager needs to know which parentRefs should be used when creating the HTTPRoute. Usually, the parentRef references a Gateway. See: https://gateway-api.sigs.k8s.io/api-types/httproute/#attaching-to-gateways' + type: array + items: + description: "ParentReference identifies an API object (usually a Gateway) that can be considered a parent of this resource (usually a route). There are two kinds of parent resources with \"Core\" support: \n * Gateway (Gateway conformance profile) * Service (Mesh conformance profile, experimental, ClusterIP Services only) \n This API may be extended in the future to support additional kinds of parent resources. \n The API object must be valid in the cluster; the Group and Kind must be registered in the cluster for this reference to be valid." + type: object + required: + - name + properties: + group: + description: "Group is the group of the referent. When unspecified, \"gateway.networking.k8s.io\" is inferred. To set the core API group (such as for a \"Service\" kind referent), Group must be explicitly set to \"\" (empty string). \n Support: Core" + type: string + default: gateway.networking.k8s.io + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + kind: + description: "Kind is kind of the referent. \n There are two kinds of parent resources with \"Core\" support: \n * Gateway (Gateway conformance profile) * Service (Mesh conformance profile, experimental, ClusterIP Services only) \n Support for other resources is Implementation-Specific." + type: string + default: Gateway + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + name: + description: "Name is the name of the referent. \n Support: Core" + type: string + maxLength: 253 + minLength: 1 + namespace: + description: "Namespace is the namespace of the referent. When unspecified, this refers to the local namespace of the Route. \n Note that there are specific rules for ParentRefs which cross namespace boundaries. Cross-namespace references are only valid if they are explicitly allowed by something in the namespace they are referring to. For example: Gateway has the AllowedRoutes field, and ReferenceGrant provides a generic way to enable any other kind of cross-namespace reference. \n ParentRefs from a Route to a Service in the same namespace are \"producer\" routes, which apply default routing rules to inbound connections from any namespace to the Service. \n ParentRefs from a Route to a Service in a different namespace are \"consumer\" routes, and these routing rules are only applied to outbound connections originating from the same namespace as the Route, for which the intended destination of the connections are a Service targeted as a ParentRef of the Route. \n Support: Core" + type: string + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + port: + description: "Port is the network port this Route targets. It can be interpreted differently based on the type of parent resource. \n When the parent resource is a Gateway, this targets all listeners listening on the specified port that also support this kind of Route(and select this Route). It's not recommended to set `Port` unless the networking behaviors specified in a Route must apply to a specific port as opposed to a listener(s) whose port(s) may be changed. When both Port and SectionName are specified, the name and port of the selected listener must match both specified values. \n When the parent resource is a Service, this targets a specific port in the Service spec. When both Port (experimental) and SectionName are specified, the name and port of the selected port must match both specified values. \n Implementations MAY choose to support other parent resources. Implementations supporting other types of parent resources MUST clearly document how/if Port is interpreted. \n For the purpose of status, an attachment is considered successful as long as the parent resource accepts it partially. For example, Gateway listeners can restrict which Routes can attach to them by Route kind, namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from the referencing Route, the Route MUST be considered successfully attached. If no Gateway listeners accept attachment from this Route, the Route MUST be considered detached from the Gateway. \n Support: Extended \n " + type: integer + format: int32 + maximum: 65535 + minimum: 1 + sectionName: + description: "SectionName is the name of a section within the target resource. In the following resources, SectionName is interpreted as the following: \n * Gateway: Listener Name. When both Port (experimental) and SectionName are specified, the name and port of the selected listener must match both specified values. * Service: Port Name. When both Port (experimental) and SectionName are specified, the name and port of the selected listener must match both specified values. Note that attaching Routes to Services as Parents is part of experimental Mesh support and is not supported for any other purpose. \n Implementations MAY choose to support attaching Routes to other resources. If that is the case, they MUST clearly document how SectionName is interpreted. \n When unspecified (empty string), this will reference the entire resource. For the purpose of status, an attachment is considered successful if at least one section in the parent resource accepts it. For example, Gateway listeners can restrict which Routes can attach to them by Route kind, namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from the referencing Route, the Route MUST be considered successfully attached. If no Gateway listeners accept attachment from this Route, the Route MUST be considered detached from the Gateway. \n Support: Core" + type: string + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + serviceType: + description: Optional service type for Kubernetes solver service. Supported values are NodePort or ClusterIP. If unset, defaults to NodePort. + type: string + ingress: + description: The ingress based HTTP01 challenge solver will solve challenges by creating or modifying Ingress resources in order to route requests for '/.well-known/acme-challenge/XYZ' to 'challenge solver' pods that are provisioned by cert-manager for each Challenge to be completed. + type: object + properties: + class: + description: This field configures the annotation `kubernetes.io/ingress.class` when creating Ingress resources to solve ACME challenges that use this challenge solver. Only one of `class`, `name` or `ingressClassName` may be specified. + type: string + ingressClassName: + description: This field configures the field `ingressClassName` on the created Ingress resources used to solve ACME challenges that use this challenge solver. This is the recommended way of configuring the ingress class. Only one of `class`, `name` or `ingressClassName` may be specified. + type: string + ingressTemplate: + description: Optional ingress template used to configure the ACME challenge solver ingress used for HTTP01 challenges. + type: object + properties: + metadata: + description: ObjectMeta overrides for the ingress used to solve HTTP01 challenges. Only the 'labels' and 'annotations' fields may be set. If labels or annotations overlap with in-built values, the values here will override the in-built values. + type: object + properties: + annotations: + description: Annotations that should be added to the created ACME HTTP01 solver ingress. + type: object + additionalProperties: + type: string + labels: + description: Labels that should be added to the created ACME HTTP01 solver ingress. + type: object + additionalProperties: + type: string + name: + description: The name of the ingress resource that should have ACME challenge solving routes inserted into it in order to solve HTTP01 challenges. This is typically used in conjunction with ingress controllers like ingress-gce, which maintains a 1:1 mapping between external IPs and ingress resources. Only one of `class`, `name` or `ingressClassName` may be specified. + type: string + podTemplate: + description: Optional pod template used to configure the ACME challenge solver pods used for HTTP01 challenges. + type: object + properties: + metadata: + description: ObjectMeta overrides for the pod used to solve HTTP01 challenges. Only the 'labels' and 'annotations' fields may be set. If labels or annotations overlap with in-built values, the values here will override the in-built values. + type: object + properties: + annotations: + description: Annotations that should be added to the create ACME HTTP01 solver pods. + type: object + additionalProperties: + type: string + labels: + description: Labels that should be added to the created ACME HTTP01 solver pods. + type: object + additionalProperties: + type: string + spec: + description: PodSpec defines overrides for the HTTP01 challenge solver pod. Check ACMEChallengeSolverHTTP01IngressPodSpec to find out currently supported fields. All other fields will be ignored. + type: object + properties: + affinity: + description: If specified, the pod's scheduling constraints + type: object + properties: + nodeAffinity: + description: Describes node affinity scheduling rules for the pod. + type: object + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods to nodes that satisfy the affinity expressions specified by this field, but it may choose a node that violates one or more of the expressions. The node that is most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling affinity expressions, etc.), compute a sum by iterating through the elements of this field and adding "weight" to the sum if the node matches the corresponding matchExpressions; the node(s) with the highest sum are the most preferred. + type: array + items: + description: An empty preferred scheduling term matches all objects with implicit weight 0 (i.e. it's a no-op). A null preferred scheduling term matches no objects (i.e. is also a no-op). + type: object + required: + - preference + - weight + properties: + preference: + description: A node selector term, associated with the corresponding weight. + type: object + properties: + matchExpressions: + description: A list of node selector requirements by node's labels. + type: array + items: + description: A node selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: The label key that the selector applies to. + type: string + operator: + description: Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: 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. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch. + type: array + items: + type: string + matchFields: + description: A list of node selector requirements by node's fields. + type: array + items: + description: A node selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: The label key that the selector applies to. + type: string + operator: + description: Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: 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. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch. + type: array + items: + type: string + x-kubernetes-map-type: atomic + weight: + description: Weight associated with matching the corresponding nodeSelectorTerm, in the range 1-100. + type: integer + format: int32 + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by this field are not met at scheduling time, the pod will not be scheduled onto the node. If the affinity requirements specified by this field cease to be met at some point during pod execution (e.g. due to an update), the system may or may not try to eventually evict the pod from its node. + type: object + required: + - nodeSelectorTerms + properties: + nodeSelectorTerms: + description: Required. A list of node selector terms. The terms are ORed. + type: array + items: + description: A null or empty node selector term matches no objects. The requirements of them are ANDed. The TopologySelectorTerm type implements a subset of the NodeSelectorTerm. + type: object + properties: + matchExpressions: + description: A list of node selector requirements by node's labels. + type: array + items: + description: A node selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: The label key that the selector applies to. + type: string + operator: + description: Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: 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. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch. + type: array + items: + type: string + matchFields: + description: A list of node selector requirements by node's fields. + type: array + items: + description: A node selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: The label key that the selector applies to. + type: string + operator: + description: Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: 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. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch. + type: array + items: + type: string + x-kubernetes-map-type: atomic + x-kubernetes-map-type: atomic + podAffinity: + description: Describes pod affinity scheduling rules (e.g. co-locate this pod in the same node, zone, etc. as some other pod(s)). + type: object + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods to nodes that satisfy the affinity expressions specified by this field, but it may choose a node that violates one or more of the expressions. The node that is most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling affinity expressions, etc.), compute a sum by iterating through the elements of this field and adding "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. + type: array + items: + description: The weights of all of the matched WeightedPodAffinityTerm fields are added per-node to find the most preferred node(s) + type: object + required: + - podAffinityTerm + - weight + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated with the corresponding weight. + type: object + required: + - topologyKey + properties: + labelSelector: + description: A label query over a set of resources, in this case pods. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + matchLabels: + 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 + additionalProperties: + type: string + x-kubernetes-map-type: atomic + namespaceSelector: + description: A label query over the set of namespaces that the term applies to. The term is applied to the union of the namespaces selected by this field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector ({}) matches all namespaces. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + matchLabels: + 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 + additionalProperties: + type: string + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static list of namespace names that the term applies to. The term is applied to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list and null namespaceSelector means "this pod's namespace". + type: array + items: + type: string + topologyKey: + description: This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. Empty topologyKey is not allowed. + type: string + weight: + description: weight associated with matching the corresponding podAffinityTerm, in the range 1-100. + type: integer + format: int32 + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by this field are not met at scheduling time, the pod will not be scheduled onto the node. If the affinity requirements specified by this field cease to be met at some point during pod execution (e.g. due to a pod label update), the system may or may not try to eventually evict the pod from its node. When there are multiple elements, the lists of nodes corresponding to each podAffinityTerm are intersected, i.e. all terms must be satisfied. + type: array + items: + description: Defines a set of pods (namely those matching the labelSelector relative to the given namespace(s)) that this pod should be co-located (affinity) or not co-located (anti-affinity) with, where co-located is defined as running on a node whose value of the label with key matches that of any node on which a pod of the set of pods is running + type: object + required: + - topologyKey + properties: + labelSelector: + description: A label query over a set of resources, in this case pods. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + matchLabels: + 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 + additionalProperties: + type: string + x-kubernetes-map-type: atomic + namespaceSelector: + description: A label query over the set of namespaces that the term applies to. The term is applied to the union of the namespaces selected by this field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector ({}) matches all namespaces. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + matchLabels: + 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 + additionalProperties: + type: string + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static list of namespace names that the term applies to. The term is applied to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list and null namespaceSelector means "this pod's namespace". + type: array + items: + type: string + topologyKey: + description: This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. Empty topologyKey is not allowed. + type: string + podAntiAffinity: + description: Describes pod anti-affinity scheduling rules (e.g. avoid putting this pod in the same node, zone, etc. as some other pod(s)). + type: object + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods to nodes that satisfy the anti-affinity expressions specified by this field, but it may choose a node that violates one or more of the expressions. The node that is most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), compute a sum by iterating through the elements of this field and adding "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. + type: array + items: + description: The weights of all of the matched WeightedPodAffinityTerm fields are added per-node to find the most preferred node(s) + type: object + required: + - podAffinityTerm + - weight + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated with the corresponding weight. + type: object + required: + - topologyKey + properties: + labelSelector: + description: A label query over a set of resources, in this case pods. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + matchLabels: + 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 + additionalProperties: + type: string + x-kubernetes-map-type: atomic + namespaceSelector: + description: A label query over the set of namespaces that the term applies to. The term is applied to the union of the namespaces selected by this field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector ({}) matches all namespaces. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + matchLabels: + 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 + additionalProperties: + type: string + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static list of namespace names that the term applies to. The term is applied to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list and null namespaceSelector means "this pod's namespace". + type: array + items: + type: string + topologyKey: + description: This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. Empty topologyKey is not allowed. + type: string + weight: + description: weight associated with matching the corresponding podAffinityTerm, in the range 1-100. + type: integer + format: int32 + requiredDuringSchedulingIgnoredDuringExecution: + description: If the anti-affinity requirements specified by this field are not met at scheduling time, the pod will not be scheduled onto the node. If the anti-affinity requirements specified by this field cease to be met at some point during pod execution (e.g. due to a pod label update), the system may or may not try to eventually evict the pod from its node. When there are multiple elements, the lists of nodes corresponding to each podAffinityTerm are intersected, i.e. all terms must be satisfied. + type: array + items: + description: Defines a set of pods (namely those matching the labelSelector relative to the given namespace(s)) that this pod should be co-located (affinity) or not co-located (anti-affinity) with, where co-located is defined as running on a node whose value of the label with key matches that of any node on which a pod of the set of pods is running + type: object + required: + - topologyKey + properties: + labelSelector: + description: A label query over a set of resources, in this case pods. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + matchLabels: + 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 + additionalProperties: + type: string + x-kubernetes-map-type: atomic + namespaceSelector: + description: A label query over the set of namespaces that the term applies to. The term is applied to the union of the namespaces selected by this field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector ({}) matches all namespaces. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + matchLabels: + 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 + additionalProperties: + type: string + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static list of namespace names that the term applies to. The term is applied to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list and null namespaceSelector means "this pod's namespace". + type: array + items: + type: string + topologyKey: + description: This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. Empty topologyKey is not allowed. + type: string + imagePullSecrets: + description: If specified, the pod's imagePullSecrets + type: array + items: + description: LocalObjectReference contains enough information to let you locate the referenced object inside the same namespace. + type: object + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + x-kubernetes-map-type: atomic + nodeSelector: + description: 'NodeSelector is a selector which must be true for the pod to fit on a node. Selector which must match a node''s labels for the pod to be scheduled on that node. More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/' + type: object + additionalProperties: + type: string + priorityClassName: + description: If specified, the pod's priorityClassName. + type: string + serviceAccountName: + description: If specified, the pod's service account + type: string + tolerations: + description: If specified, the pod's tolerations. + type: array + items: + description: The pod this Toleration is attached to tolerates any taint that matches the triple using the matching operator . + type: object + 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. + type: integer + format: int64 + 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 + serviceType: + description: Optional service type for Kubernetes solver service. Supported values are NodePort or ClusterIP. If unset, defaults to NodePort. + type: string + selector: + description: Selector selects a set of DNSNames on the Certificate resource that should be solved using this challenge solver. If not specified, the solver will be treated as the 'default' solver with the lowest priority, i.e. if any other solver has a more specific match, it will be used instead. + type: object + properties: + dnsNames: + description: List of DNSNames that this solver will be used to solve. If specified and a match is found, a dnsNames selector will take precedence over a dnsZones selector. If multiple solvers match with the same dnsNames value, the solver with the most matching labels in matchLabels will be selected. If neither has more matches, the solver defined earlier in the list will be selected. + type: array + items: + type: string + dnsZones: + description: List of DNSZones that this solver will be used to solve. The most specific DNS zone match specified here will take precedence over other DNS zone matches, so a solver specifying sys.example.com will be selected over one specifying example.com for the domain www.sys.example.com. If multiple solvers match with the same dnsZones value, the solver with the most matching labels in matchLabels will be selected. If neither has more matches, the solver defined earlier in the list will be selected. + type: array + items: + type: string + matchLabels: + description: A label selector that is used to refine the set of certificate's that this challenge solver will apply to. + type: object + additionalProperties: + type: string + ca: + description: CA configures this issuer to sign certificates using a signing CA keypair stored in a Secret resource. This is used to build internal PKIs that are managed by cert-manager. + type: object + required: + - secretName + properties: + crlDistributionPoints: + description: The CRL distribution points is an X.509 v3 certificate extension which identifies the location of the CRL from which the revocation of this certificate can be checked. If not set, certificates will be issued without distribution points set. + type: array + items: + type: string + ocspServers: + description: The OCSP server list is an X.509 v3 extension that defines a list of URLs of OCSP responders. The OCSP responders can be queried for the revocation status of an issued certificate. If not set, the certificate will be issued with no OCSP servers set. For example, an OCSP server URL could be "http://ocsp.int-x3.letsencrypt.org". + type: array + items: + type: string + secretName: + description: SecretName is the name of the secret used to sign Certificates issued by this Issuer. + type: string + selfSigned: + description: SelfSigned configures this issuer to 'self sign' certificates using the private key used to create the CertificateRequest object. + type: object + properties: + crlDistributionPoints: + description: The CRL distribution points is an X.509 v3 certificate extension which identifies the location of the CRL from which the revocation of this certificate can be checked. If not set certificate will be issued without CDP. Values are strings. + type: array + items: + type: string + vault: + description: Vault configures this issuer to sign certificates using a HashiCorp Vault PKI backend. + type: object + required: + - auth + - path + - server + properties: + auth: + description: Auth configures how cert-manager authenticates with the Vault server. + type: object + properties: + appRole: + description: AppRole authenticates with Vault using the App Role auth mechanism, with the role and secret stored in a Kubernetes Secret resource. + type: object + required: + - path + - roleId + - secretRef + properties: + path: + description: 'Path where the App Role authentication backend is mounted in Vault, e.g: "approle"' + type: string + roleId: + description: RoleID configured in the App Role authentication backend when setting up the authentication backend in Vault. + type: string + secretRef: + description: Reference to a key in a Secret that contains the App Role secret used to authenticate with Vault. The `key` field must be specified and denotes which entry within the Secret resource is used as the app role secret. + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + kubernetes: + description: Kubernetes authenticates with Vault by passing the ServiceAccount token stored in the named Secret resource to the Vault server. + type: object + required: + - role + properties: + mountPath: + description: The Vault mountPath here is the mount path to use when authenticating with Vault. For example, setting a value to `/v1/auth/foo`, will use the path `/v1/auth/foo/login` to authenticate with Vault. If unspecified, the default value "/v1/auth/kubernetes" will be used. + type: string + role: + description: A required field containing the Vault Role to assume. A Role binds a Kubernetes ServiceAccount with a set of Vault policies. + type: string + secretRef: + description: The required Secret field containing a Kubernetes ServiceAccount JWT used for authenticating with Vault. Use of 'ambient credentials' is not supported. + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + serviceAccountRef: + description: A reference to a service account that will be used to request a bound token (also known as "projected token"). Compared to using "secretRef", using this field means that you don't rely on statically bound tokens. To use this field, you must configure an RBAC rule to let cert-manager request a token. + type: object + required: + - name + properties: + name: + description: Name of the ServiceAccount used to request a token. + type: string + tokenSecretRef: + description: TokenSecretRef authenticates with Vault by presenting a token. + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + caBundle: + description: Base64-encoded bundle of PEM CAs which will be used to validate the certificate chain presented by Vault. Only used if using HTTPS to connect to Vault and ignored for HTTP connections. Mutually exclusive with CABundleSecretRef. If neither CABundle nor CABundleSecretRef are defined, the certificate bundle in the cert-manager controller container is used to validate the TLS connection. + type: string + format: byte + caBundleSecretRef: + description: Reference to a Secret containing a bundle of PEM-encoded CAs to use when verifying the certificate chain presented by Vault when using HTTPS. Mutually exclusive with CABundle. If neither CABundle nor CABundleSecretRef are defined, the certificate bundle in the cert-manager controller container is used to validate the TLS connection. If no key for the Secret is specified, cert-manager will default to 'ca.crt'. + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + namespace: + description: 'Name of the vault namespace. Namespaces is a set of features within Vault Enterprise that allows Vault environments to support Secure Multi-tenancy. e.g: "ns1" More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces' + type: string + path: + description: 'Path is the mount path of the Vault PKI backend''s `sign` endpoint, e.g: "my_pki_mount/sign/my-role-name".' + type: string + server: + description: 'Server is the connection address for the Vault server, e.g: "https://vault.example.com:8200".' + type: string + venafi: + description: Venafi configures this issuer to sign certificates using a Venafi TPP or Venafi Cloud policy zone. + type: object + required: + - zone + properties: + cloud: + description: Cloud specifies the Venafi cloud configuration settings. Only one of TPP or Cloud may be specified. + type: object + required: + - apiTokenSecretRef + properties: + apiTokenSecretRef: + description: APITokenSecretRef is a secret key selector for the Venafi Cloud API token. + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + url: + description: URL is the base URL for Venafi Cloud. Defaults to "https://api.venafi.cloud/v1". + type: string + tpp: + description: TPP specifies Trust Protection Platform configuration settings. Only one of TPP or Cloud may be specified. + type: object + required: + - credentialsRef + - url + properties: + caBundle: + description: Base64-encoded bundle of PEM CAs which will be used to validate the certificate chain presented by the TPP server. Only used if using HTTPS; ignored for HTTP. If undefined, the certificate bundle in the cert-manager controller container is used to validate the chain. + type: string + format: byte + credentialsRef: + description: CredentialsRef is a reference to a Secret containing the username and password for the TPP server. The secret must contain two keys, 'username' and 'password'. + type: object + required: + - name + properties: + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + url: + description: 'URL is the base URL for the vedsdk endpoint of the Venafi TPP instance, for example: "https://tpp.example.com/vedsdk".' + type: string + zone: + description: Zone is the Venafi Policy Zone to use for this issuer. All requests made to the Venafi platform will be restricted by the named zone policy. This field is required. + type: string + status: + description: Status of the ClusterIssuer. This is set and managed automatically. + type: object + properties: + acme: + description: ACME specific status options. This field should only be set if the Issuer is configured to use an ACME server to issue certificates. + type: object + properties: + lastPrivateKeyHash: + description: LastPrivateKeyHash is a hash of the private key associated with the latest registered ACME account, in order to track changes made to registered account associated with the Issuer + type: string + lastRegisteredEmail: + description: LastRegisteredEmail is the email associated with the latest registered ACME account, in order to track changes made to registered account associated with the Issuer + type: string + uri: + description: URI is the unique account identifier, which can also be used to retrieve account details from the CA + type: string + conditions: + description: List of status conditions to indicate the status of a CertificateRequest. Known condition types are `Ready`. + type: array + items: + description: IssuerCondition contains condition information for an Issuer. + type: object + required: + - status + - type + properties: + lastTransitionTime: + description: LastTransitionTime is the timestamp corresponding to the last status change of this condition. + type: string + format: date-time + message: + description: Message is a human readable description of the details of the last transition, complementing reason. + type: string + observedGeneration: + description: If set, this represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.condition[x].observedGeneration is 9, the condition is out of date with respect to the current state of the Issuer. + type: integer + format: int64 + reason: + description: Reason is a brief machine readable explanation for the condition's last transition. + type: string + status: + description: Status of the condition, one of (`True`, `False`, `Unknown`). + type: string + enum: + - "True" + - "False" + - Unknown + type: + description: Type of the condition, known values are (`Ready`). + type: string + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + served: true + storage: true +--- +# Source: cert-manager/templates/crds.yaml +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: issuers.cert-manager.io + labels: + app: 'cert-manager' + app.kubernetes.io/name: 'cert-manager' + app.kubernetes.io/instance: "cert-manager" + # Generated labels + app.kubernetes.io/version: "v1.13.2" +spec: + group: cert-manager.io + names: + kind: Issuer + listKind: IssuerList + plural: issuers + singular: issuer + categories: + - cert-manager + scope: Namespaced + versions: + - name: v1 + subresources: + status: {} + additionalPrinterColumns: + - jsonPath: .status.conditions[?(@.type=="Ready")].status + name: Ready + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].message + name: Status + priority: 1 + type: string + - jsonPath: .metadata.creationTimestamp + description: CreationTimestamp is a timestamp representing the server time when this object was created. It is not guaranteed to be set in happens-before order across separate operations. Clients may not set this value. It is represented in RFC3339 form and is in UTC. + name: Age + type: date + schema: + openAPIV3Schema: + description: An Issuer represents a certificate issuing authority which can be referenced as part of `issuerRef` fields. It is scoped to a single namespace and can therefore only be referenced by resources within the same namespace. + type: object + required: + - spec + 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: Desired state of the Issuer resource. + type: object + properties: + acme: + description: ACME configures this issuer to communicate with a RFC8555 (ACME) server to obtain signed x509 certificates. + type: object + required: + - privateKeySecretRef + - server + properties: + caBundle: + description: Base64-encoded bundle of PEM CAs which can be used to validate the certificate chain presented by the ACME server. Mutually exclusive with SkipTLSVerify; prefer using CABundle to prevent various kinds of security vulnerabilities. If CABundle and SkipTLSVerify are unset, the system certificate bundle inside the container is used to validate the TLS connection. + type: string + format: byte + disableAccountKeyGeneration: + description: Enables or disables generating a new ACME account key. If true, the Issuer resource will *not* request a new account but will expect the account key to be supplied via an existing secret. If false, the cert-manager system will generate a new ACME account key for the Issuer. Defaults to false. + type: boolean + email: + description: Email is the email address to be associated with the ACME account. This field is optional, but it is strongly recommended to be set. It will be used to contact you in case of issues with your account or certificates, including expiry notification emails. This field may be updated after the account is initially registered. + type: string + enableDurationFeature: + description: Enables requesting a Not After date on certificates that matches the duration of the certificate. This is not supported by all ACME servers like Let's Encrypt. If set to true when the ACME server does not support it it will create an error on the Order. Defaults to false. + type: boolean + externalAccountBinding: + description: ExternalAccountBinding is a reference to a CA external account of the ACME server. If set, upon registration cert-manager will attempt to associate the given external account credentials with the registered ACME account. + type: object + required: + - keyID + - keySecretRef + properties: + keyAlgorithm: + description: 'Deprecated: keyAlgorithm field exists for historical compatibility reasons and should not be used. The algorithm is now hardcoded to HS256 in golang/x/crypto/acme.' + type: string + enum: + - HS256 + - HS384 + - HS512 + keyID: + description: keyID is the ID of the CA key that the External Account is bound to. + type: string + keySecretRef: + description: keySecretRef is a Secret Key Selector referencing a data item in a Kubernetes Secret which holds the symmetric MAC key of the External Account Binding. The `key` is the index string that is paired with the key data in the Secret and should not be confused with the key data itself, or indeed with the External Account Binding keyID above. The secret key stored in the Secret **must** be un-padded, base64 URL encoded data. + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + preferredChain: + description: 'PreferredChain is the chain to use if the ACME server outputs multiple. PreferredChain is no guarantee that this one gets delivered by the ACME endpoint. For example, for Let''s Encrypt''s DST crosssign you would use: "DST Root CA X3" or "ISRG Root X1" for the newer Let''s Encrypt root CA. This value picks the first certificate bundle in the ACME alternative chains that has a certificate with this value as its issuer''s CN' + type: string + maxLength: 64 + privateKeySecretRef: + description: PrivateKey is the name of a Kubernetes Secret resource that will be used to store the automatically generated ACME account private key. Optionally, a `key` may be specified to select a specific entry within the named Secret resource. If `key` is not specified, a default of `tls.key` will be used. + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + server: + description: 'Server is the URL used to access the ACME server''s ''directory'' endpoint. For example, for Let''s Encrypt''s staging endpoint, you would use: "https://acme-staging-v02.api.letsencrypt.org/directory". Only ACME v2 endpoints (i.e. RFC 8555) are supported.' + type: string + skipTLSVerify: + description: 'INSECURE: Enables or disables validation of the ACME server TLS certificate. If true, requests to the ACME server will not have the TLS certificate chain validated. Mutually exclusive with CABundle; prefer using CABundle to prevent various kinds of security vulnerabilities. Only enable this option in development environments. If CABundle and SkipTLSVerify are unset, the system certificate bundle inside the container is used to validate the TLS connection. Defaults to false.' + type: boolean + solvers: + description: 'Solvers is a list of challenge solvers that will be used to solve ACME challenges for the matching domains. Solver configurations must be provided in order to obtain certificates from an ACME server. For more information, see: https://cert-manager.io/docs/configuration/acme/' + type: array + items: + description: An ACMEChallengeSolver describes how to solve ACME challenges for the issuer it is part of. A selector may be provided to use different solving strategies for different DNS names. Only one of HTTP01 or DNS01 must be provided. + type: object + properties: + dns01: + description: Configures cert-manager to attempt to complete authorizations by performing the DNS01 challenge flow. + type: object + properties: + acmeDNS: + description: Use the 'ACME DNS' (https://github.com/joohoi/acme-dns) API to manage DNS01 challenge records. + type: object + required: + - accountSecretRef + - host + properties: + accountSecretRef: + description: A reference to a specific 'key' within a Secret resource. In some instances, `key` is a required field. + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + host: + type: string + akamai: + description: Use the Akamai DNS zone management API to manage DNS01 challenge records. + type: object + required: + - accessTokenSecretRef + - clientSecretSecretRef + - clientTokenSecretRef + - serviceConsumerDomain + properties: + accessTokenSecretRef: + description: A reference to a specific 'key' within a Secret resource. In some instances, `key` is a required field. + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + clientSecretSecretRef: + description: A reference to a specific 'key' within a Secret resource. In some instances, `key` is a required field. + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + clientTokenSecretRef: + description: A reference to a specific 'key' within a Secret resource. In some instances, `key` is a required field. + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + serviceConsumerDomain: + type: string + azureDNS: + description: Use the Microsoft Azure DNS API to manage DNS01 challenge records. + type: object + required: + - resourceGroupName + - subscriptionID + properties: + clientID: + description: if both this and ClientSecret are left unset MSI will be used + type: string + clientSecretSecretRef: + description: if both this and ClientID are left unset MSI will be used + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + environment: + description: name of the Azure environment (default AzurePublicCloud) + type: string + enum: + - AzurePublicCloud + - AzureChinaCloud + - AzureGermanCloud + - AzureUSGovernmentCloud + hostedZoneName: + description: name of the DNS zone that should be used + type: string + managedIdentity: + description: managed identity configuration, can not be used at the same time as clientID, clientSecretSecretRef or tenantID + type: object + properties: + clientID: + description: client ID of the managed identity, can not be used at the same time as resourceID + type: string + resourceID: + description: resource ID of the managed identity, can not be used at the same time as clientID + type: string + resourceGroupName: + description: resource group the DNS zone is located in + type: string + subscriptionID: + description: ID of the Azure subscription + type: string + tenantID: + description: when specifying ClientID and ClientSecret then this field is also needed + type: string + cloudDNS: + description: Use the Google Cloud DNS API to manage DNS01 challenge records. + type: object + required: + - project + properties: + hostedZoneName: + description: HostedZoneName is an optional field that tells cert-manager in which Cloud DNS zone the challenge record has to be created. If left empty cert-manager will automatically choose a zone. + type: string + project: + type: string + serviceAccountSecretRef: + description: A reference to a specific 'key' within a Secret resource. In some instances, `key` is a required field. + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + cloudflare: + description: Use the Cloudflare API to manage DNS01 challenge records. + type: object + properties: + apiKeySecretRef: + description: 'API key to use to authenticate with Cloudflare. Note: using an API token to authenticate is now the recommended method as it allows greater control of permissions.' + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + apiTokenSecretRef: + description: API token used to authenticate with Cloudflare. + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + email: + description: Email of the account, only required when using API key based authentication. + type: string + cnameStrategy: + description: CNAMEStrategy configures how the DNS01 provider should handle CNAME records when found in DNS zones. + type: string + enum: + - None + - Follow + digitalocean: + description: Use the DigitalOcean DNS API to manage DNS01 challenge records. + type: object + required: + - tokenSecretRef + properties: + tokenSecretRef: + description: A reference to a specific 'key' within a Secret resource. In some instances, `key` is a required field. + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + rfc2136: + description: Use RFC2136 ("Dynamic Updates in the Domain Name System") (https://datatracker.ietf.org/doc/rfc2136/) to manage DNS01 challenge records. + type: object + required: + - nameserver + properties: + nameserver: + description: The IP address or hostname of an authoritative DNS server supporting RFC2136 in the form host:port. If the host is an IPv6 address it must be enclosed in square brackets (e.g [2001:db8::1]) ; port is optional. This field is required. + type: string + tsigAlgorithm: + description: 'The TSIG Algorithm configured in the DNS supporting RFC2136. Used only when ``tsigSecretSecretRef`` and ``tsigKeyName`` are defined. Supported values are (case-insensitive): ``HMACMD5`` (default), ``HMACSHA1``, ``HMACSHA256`` or ``HMACSHA512``.' + type: string + tsigKeyName: + description: The TSIG Key name configured in the DNS. If ``tsigSecretSecretRef`` is defined, this field is required. + type: string + tsigSecretSecretRef: + description: The name of the secret containing the TSIG value. If ``tsigKeyName`` is defined, this field is required. + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + route53: + description: Use the AWS Route53 API to manage DNS01 challenge records. + type: object + required: + - region + properties: + accessKeyID: + description: 'The AccessKeyID is used for authentication. Cannot be set when SecretAccessKeyID is set. If neither the Access Key nor Key ID are set, we fall-back to using env vars, shared credentials file or AWS Instance metadata, see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials' + type: string + accessKeyIDSecretRef: + description: 'The SecretAccessKey is used for authentication. If set, pull the AWS access key ID from a key within a Kubernetes Secret. Cannot be set when AccessKeyID is set. If neither the Access Key nor Key ID are set, we fall-back to using env vars, shared credentials file or AWS Instance metadata, see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials' + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + hostedZoneID: + description: If set, the provider will manage only this zone in Route53 and will not do an lookup using the route53:ListHostedZonesByName api call. + type: string + region: + description: Always set the region when using AccessKeyID and SecretAccessKey + type: string + role: + description: Role is a Role ARN which the Route53 provider will assume using either the explicit credentials AccessKeyID/SecretAccessKey or the inferred credentials from environment variables, shared credentials file or AWS Instance metadata + type: string + secretAccessKeySecretRef: + description: 'The SecretAccessKey is used for authentication. If neither the Access Key nor Key ID are set, we fall-back to using env vars, shared credentials file or AWS Instance metadata, see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials' + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + webhook: + description: Configure an external webhook based DNS01 challenge solver to manage DNS01 challenge records. + type: object + required: + - groupName + - solverName + properties: + config: + description: Additional configuration that should be passed to the webhook apiserver when challenges are processed. This can contain arbitrary JSON data. Secret values should not be specified in this stanza. If secret values are needed (e.g. credentials for a DNS service), you should use a SecretKeySelector to reference a Secret resource. For details on the schema of this field, consult the webhook provider implementation's documentation. + x-kubernetes-preserve-unknown-fields: true + groupName: + description: The API group name that should be used when POSTing ChallengePayload resources to the webhook apiserver. This should be the same as the GroupName specified in the webhook provider implementation. + type: string + solverName: + description: The name of the solver to use, as defined in the webhook provider implementation. This will typically be the name of the provider, e.g. 'cloudflare'. + type: string + http01: + description: Configures cert-manager to attempt to complete authorizations by performing the HTTP01 challenge flow. It is not possible to obtain certificates for wildcard domain names (e.g. `*.example.com`) using the HTTP01 challenge mechanism. + type: object + properties: + gatewayHTTPRoute: + description: The Gateway API is a sig-network community API that models service networking in Kubernetes (https://gateway-api.sigs.k8s.io/). The Gateway solver will create HTTPRoutes with the specified labels in the same namespace as the challenge. This solver is experimental, and fields / behaviour may change in the future. + type: object + properties: + labels: + description: Custom labels that will be applied to HTTPRoutes created by cert-manager while solving HTTP-01 challenges. + type: object + additionalProperties: + type: string + parentRefs: + description: 'When solving an HTTP-01 challenge, cert-manager creates an HTTPRoute. cert-manager needs to know which parentRefs should be used when creating the HTTPRoute. Usually, the parentRef references a Gateway. See: https://gateway-api.sigs.k8s.io/api-types/httproute/#attaching-to-gateways' + type: array + items: + description: "ParentReference identifies an API object (usually a Gateway) that can be considered a parent of this resource (usually a route). There are two kinds of parent resources with \"Core\" support: \n * Gateway (Gateway conformance profile) * Service (Mesh conformance profile, experimental, ClusterIP Services only) \n This API may be extended in the future to support additional kinds of parent resources. \n The API object must be valid in the cluster; the Group and Kind must be registered in the cluster for this reference to be valid." + type: object + required: + - name + properties: + group: + description: "Group is the group of the referent. When unspecified, \"gateway.networking.k8s.io\" is inferred. To set the core API group (such as for a \"Service\" kind referent), Group must be explicitly set to \"\" (empty string). \n Support: Core" + type: string + default: gateway.networking.k8s.io + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + kind: + description: "Kind is kind of the referent. \n There are two kinds of parent resources with \"Core\" support: \n * Gateway (Gateway conformance profile) * Service (Mesh conformance profile, experimental, ClusterIP Services only) \n Support for other resources is Implementation-Specific." + type: string + default: Gateway + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + name: + description: "Name is the name of the referent. \n Support: Core" + type: string + maxLength: 253 + minLength: 1 + namespace: + description: "Namespace is the namespace of the referent. When unspecified, this refers to the local namespace of the Route. \n Note that there are specific rules for ParentRefs which cross namespace boundaries. Cross-namespace references are only valid if they are explicitly allowed by something in the namespace they are referring to. For example: Gateway has the AllowedRoutes field, and ReferenceGrant provides a generic way to enable any other kind of cross-namespace reference. \n ParentRefs from a Route to a Service in the same namespace are \"producer\" routes, which apply default routing rules to inbound connections from any namespace to the Service. \n ParentRefs from a Route to a Service in a different namespace are \"consumer\" routes, and these routing rules are only applied to outbound connections originating from the same namespace as the Route, for which the intended destination of the connections are a Service targeted as a ParentRef of the Route. \n Support: Core" + type: string + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + port: + description: "Port is the network port this Route targets. It can be interpreted differently based on the type of parent resource. \n When the parent resource is a Gateway, this targets all listeners listening on the specified port that also support this kind of Route(and select this Route). It's not recommended to set `Port` unless the networking behaviors specified in a Route must apply to a specific port as opposed to a listener(s) whose port(s) may be changed. When both Port and SectionName are specified, the name and port of the selected listener must match both specified values. \n When the parent resource is a Service, this targets a specific port in the Service spec. When both Port (experimental) and SectionName are specified, the name and port of the selected port must match both specified values. \n Implementations MAY choose to support other parent resources. Implementations supporting other types of parent resources MUST clearly document how/if Port is interpreted. \n For the purpose of status, an attachment is considered successful as long as the parent resource accepts it partially. For example, Gateway listeners can restrict which Routes can attach to them by Route kind, namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from the referencing Route, the Route MUST be considered successfully attached. If no Gateway listeners accept attachment from this Route, the Route MUST be considered detached from the Gateway. \n Support: Extended \n " + type: integer + format: int32 + maximum: 65535 + minimum: 1 + sectionName: + description: "SectionName is the name of a section within the target resource. In the following resources, SectionName is interpreted as the following: \n * Gateway: Listener Name. When both Port (experimental) and SectionName are specified, the name and port of the selected listener must match both specified values. * Service: Port Name. When both Port (experimental) and SectionName are specified, the name and port of the selected listener must match both specified values. Note that attaching Routes to Services as Parents is part of experimental Mesh support and is not supported for any other purpose. \n Implementations MAY choose to support attaching Routes to other resources. If that is the case, they MUST clearly document how SectionName is interpreted. \n When unspecified (empty string), this will reference the entire resource. For the purpose of status, an attachment is considered successful if at least one section in the parent resource accepts it. For example, Gateway listeners can restrict which Routes can attach to them by Route kind, namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from the referencing Route, the Route MUST be considered successfully attached. If no Gateway listeners accept attachment from this Route, the Route MUST be considered detached from the Gateway. \n Support: Core" + type: string + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + serviceType: + description: Optional service type for Kubernetes solver service. Supported values are NodePort or ClusterIP. If unset, defaults to NodePort. + type: string + ingress: + description: The ingress based HTTP01 challenge solver will solve challenges by creating or modifying Ingress resources in order to route requests for '/.well-known/acme-challenge/XYZ' to 'challenge solver' pods that are provisioned by cert-manager for each Challenge to be completed. + type: object + properties: + class: + description: This field configures the annotation `kubernetes.io/ingress.class` when creating Ingress resources to solve ACME challenges that use this challenge solver. Only one of `class`, `name` or `ingressClassName` may be specified. + type: string + ingressClassName: + description: This field configures the field `ingressClassName` on the created Ingress resources used to solve ACME challenges that use this challenge solver. This is the recommended way of configuring the ingress class. Only one of `class`, `name` or `ingressClassName` may be specified. + type: string + ingressTemplate: + description: Optional ingress template used to configure the ACME challenge solver ingress used for HTTP01 challenges. + type: object + properties: + metadata: + description: ObjectMeta overrides for the ingress used to solve HTTP01 challenges. Only the 'labels' and 'annotations' fields may be set. If labels or annotations overlap with in-built values, the values here will override the in-built values. + type: object + properties: + annotations: + description: Annotations that should be added to the created ACME HTTP01 solver ingress. + type: object + additionalProperties: + type: string + labels: + description: Labels that should be added to the created ACME HTTP01 solver ingress. + type: object + additionalProperties: + type: string + name: + description: The name of the ingress resource that should have ACME challenge solving routes inserted into it in order to solve HTTP01 challenges. This is typically used in conjunction with ingress controllers like ingress-gce, which maintains a 1:1 mapping between external IPs and ingress resources. Only one of `class`, `name` or `ingressClassName` may be specified. + type: string + podTemplate: + description: Optional pod template used to configure the ACME challenge solver pods used for HTTP01 challenges. + type: object + properties: + metadata: + description: ObjectMeta overrides for the pod used to solve HTTP01 challenges. Only the 'labels' and 'annotations' fields may be set. If labels or annotations overlap with in-built values, the values here will override the in-built values. + type: object + properties: + annotations: + description: Annotations that should be added to the create ACME HTTP01 solver pods. + type: object + additionalProperties: + type: string + labels: + description: Labels that should be added to the created ACME HTTP01 solver pods. + type: object + additionalProperties: + type: string + spec: + description: PodSpec defines overrides for the HTTP01 challenge solver pod. Check ACMEChallengeSolverHTTP01IngressPodSpec to find out currently supported fields. All other fields will be ignored. + type: object + properties: + affinity: + description: If specified, the pod's scheduling constraints + type: object + properties: + nodeAffinity: + description: Describes node affinity scheduling rules for the pod. + type: object + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods to nodes that satisfy the affinity expressions specified by this field, but it may choose a node that violates one or more of the expressions. The node that is most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling affinity expressions, etc.), compute a sum by iterating through the elements of this field and adding "weight" to the sum if the node matches the corresponding matchExpressions; the node(s) with the highest sum are the most preferred. + type: array + items: + description: An empty preferred scheduling term matches all objects with implicit weight 0 (i.e. it's a no-op). A null preferred scheduling term matches no objects (i.e. is also a no-op). + type: object + required: + - preference + - weight + properties: + preference: + description: A node selector term, associated with the corresponding weight. + type: object + properties: + matchExpressions: + description: A list of node selector requirements by node's labels. + type: array + items: + description: A node selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: The label key that the selector applies to. + type: string + operator: + description: Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: 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. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch. + type: array + items: + type: string + matchFields: + description: A list of node selector requirements by node's fields. + type: array + items: + description: A node selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: The label key that the selector applies to. + type: string + operator: + description: Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: 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. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch. + type: array + items: + type: string + x-kubernetes-map-type: atomic + weight: + description: Weight associated with matching the corresponding nodeSelectorTerm, in the range 1-100. + type: integer + format: int32 + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by this field are not met at scheduling time, the pod will not be scheduled onto the node. If the affinity requirements specified by this field cease to be met at some point during pod execution (e.g. due to an update), the system may or may not try to eventually evict the pod from its node. + type: object + required: + - nodeSelectorTerms + properties: + nodeSelectorTerms: + description: Required. A list of node selector terms. The terms are ORed. + type: array + items: + description: A null or empty node selector term matches no objects. The requirements of them are ANDed. The TopologySelectorTerm type implements a subset of the NodeSelectorTerm. + type: object + properties: + matchExpressions: + description: A list of node selector requirements by node's labels. + type: array + items: + description: A node selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: The label key that the selector applies to. + type: string + operator: + description: Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: 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. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch. + type: array + items: + type: string + matchFields: + description: A list of node selector requirements by node's fields. + type: array + items: + description: A node selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: The label key that the selector applies to. + type: string + operator: + description: Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: 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. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch. + type: array + items: + type: string + x-kubernetes-map-type: atomic + x-kubernetes-map-type: atomic + podAffinity: + description: Describes pod affinity scheduling rules (e.g. co-locate this pod in the same node, zone, etc. as some other pod(s)). + type: object + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods to nodes that satisfy the affinity expressions specified by this field, but it may choose a node that violates one or more of the expressions. The node that is most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling affinity expressions, etc.), compute a sum by iterating through the elements of this field and adding "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. + type: array + items: + description: The weights of all of the matched WeightedPodAffinityTerm fields are added per-node to find the most preferred node(s) + type: object + required: + - podAffinityTerm + - weight + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated with the corresponding weight. + type: object + required: + - topologyKey + properties: + labelSelector: + description: A label query over a set of resources, in this case pods. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + matchLabels: + 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 + additionalProperties: + type: string + x-kubernetes-map-type: atomic + namespaceSelector: + description: A label query over the set of namespaces that the term applies to. The term is applied to the union of the namespaces selected by this field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector ({}) matches all namespaces. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + matchLabels: + 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 + additionalProperties: + type: string + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static list of namespace names that the term applies to. The term is applied to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list and null namespaceSelector means "this pod's namespace". + type: array + items: + type: string + topologyKey: + description: This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. Empty topologyKey is not allowed. + type: string + weight: + description: weight associated with matching the corresponding podAffinityTerm, in the range 1-100. + type: integer + format: int32 + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by this field are not met at scheduling time, the pod will not be scheduled onto the node. If the affinity requirements specified by this field cease to be met at some point during pod execution (e.g. due to a pod label update), the system may or may not try to eventually evict the pod from its node. When there are multiple elements, the lists of nodes corresponding to each podAffinityTerm are intersected, i.e. all terms must be satisfied. + type: array + items: + description: Defines a set of pods (namely those matching the labelSelector relative to the given namespace(s)) that this pod should be co-located (affinity) or not co-located (anti-affinity) with, where co-located is defined as running on a node whose value of the label with key matches that of any node on which a pod of the set of pods is running + type: object + required: + - topologyKey + properties: + labelSelector: + description: A label query over a set of resources, in this case pods. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + matchLabels: + 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 + additionalProperties: + type: string + x-kubernetes-map-type: atomic + namespaceSelector: + description: A label query over the set of namespaces that the term applies to. The term is applied to the union of the namespaces selected by this field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector ({}) matches all namespaces. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + matchLabels: + 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 + additionalProperties: + type: string + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static list of namespace names that the term applies to. The term is applied to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list and null namespaceSelector means "this pod's namespace". + type: array + items: + type: string + topologyKey: + description: This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. Empty topologyKey is not allowed. + type: string + podAntiAffinity: + description: Describes pod anti-affinity scheduling rules (e.g. avoid putting this pod in the same node, zone, etc. as some other pod(s)). + type: object + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods to nodes that satisfy the anti-affinity expressions specified by this field, but it may choose a node that violates one or more of the expressions. The node that is most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), compute a sum by iterating through the elements of this field and adding "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. + type: array + items: + description: The weights of all of the matched WeightedPodAffinityTerm fields are added per-node to find the most preferred node(s) + type: object + required: + - podAffinityTerm + - weight + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated with the corresponding weight. + type: object + required: + - topologyKey + properties: + labelSelector: + description: A label query over a set of resources, in this case pods. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + matchLabels: + 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 + additionalProperties: + type: string + x-kubernetes-map-type: atomic + namespaceSelector: + description: A label query over the set of namespaces that the term applies to. The term is applied to the union of the namespaces selected by this field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector ({}) matches all namespaces. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + matchLabels: + 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 + additionalProperties: + type: string + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static list of namespace names that the term applies to. The term is applied to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list and null namespaceSelector means "this pod's namespace". + type: array + items: + type: string + topologyKey: + description: This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. Empty topologyKey is not allowed. + type: string + weight: + description: weight associated with matching the corresponding podAffinityTerm, in the range 1-100. + type: integer + format: int32 + requiredDuringSchedulingIgnoredDuringExecution: + description: If the anti-affinity requirements specified by this field are not met at scheduling time, the pod will not be scheduled onto the node. If the anti-affinity requirements specified by this field cease to be met at some point during pod execution (e.g. due to a pod label update), the system may or may not try to eventually evict the pod from its node. When there are multiple elements, the lists of nodes corresponding to each podAffinityTerm are intersected, i.e. all terms must be satisfied. + type: array + items: + description: Defines a set of pods (namely those matching the labelSelector relative to the given namespace(s)) that this pod should be co-located (affinity) or not co-located (anti-affinity) with, where co-located is defined as running on a node whose value of the label with key matches that of any node on which a pod of the set of pods is running + type: object + required: + - topologyKey + properties: + labelSelector: + description: A label query over a set of resources, in this case pods. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + matchLabels: + 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 + additionalProperties: + type: string + x-kubernetes-map-type: atomic + namespaceSelector: + description: A label query over the set of namespaces that the term applies to. The term is applied to the union of the namespaces selected by this field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector ({}) matches all namespaces. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + matchLabels: + 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 + additionalProperties: + type: string + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static list of namespace names that the term applies to. The term is applied to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list and null namespaceSelector means "this pod's namespace". + type: array + items: + type: string + topologyKey: + description: This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. Empty topologyKey is not allowed. + type: string + imagePullSecrets: + description: If specified, the pod's imagePullSecrets + type: array + items: + description: LocalObjectReference contains enough information to let you locate the referenced object inside the same namespace. + type: object + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + x-kubernetes-map-type: atomic + nodeSelector: + description: 'NodeSelector is a selector which must be true for the pod to fit on a node. Selector which must match a node''s labels for the pod to be scheduled on that node. More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/' + type: object + additionalProperties: + type: string + priorityClassName: + description: If specified, the pod's priorityClassName. + type: string + serviceAccountName: + description: If specified, the pod's service account + type: string + tolerations: + description: If specified, the pod's tolerations. + type: array + items: + description: The pod this Toleration is attached to tolerates any taint that matches the triple using the matching operator . + type: object + 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. + type: integer + format: int64 + 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 + serviceType: + description: Optional service type for Kubernetes solver service. Supported values are NodePort or ClusterIP. If unset, defaults to NodePort. + type: string + selector: + description: Selector selects a set of DNSNames on the Certificate resource that should be solved using this challenge solver. If not specified, the solver will be treated as the 'default' solver with the lowest priority, i.e. if any other solver has a more specific match, it will be used instead. + type: object + properties: + dnsNames: + description: List of DNSNames that this solver will be used to solve. If specified and a match is found, a dnsNames selector will take precedence over a dnsZones selector. If multiple solvers match with the same dnsNames value, the solver with the most matching labels in matchLabels will be selected. If neither has more matches, the solver defined earlier in the list will be selected. + type: array + items: + type: string + dnsZones: + description: List of DNSZones that this solver will be used to solve. The most specific DNS zone match specified here will take precedence over other DNS zone matches, so a solver specifying sys.example.com will be selected over one specifying example.com for the domain www.sys.example.com. If multiple solvers match with the same dnsZones value, the solver with the most matching labels in matchLabels will be selected. If neither has more matches, the solver defined earlier in the list will be selected. + type: array + items: + type: string + matchLabels: + description: A label selector that is used to refine the set of certificate's that this challenge solver will apply to. + type: object + additionalProperties: + type: string + ca: + description: CA configures this issuer to sign certificates using a signing CA keypair stored in a Secret resource. This is used to build internal PKIs that are managed by cert-manager. + type: object + required: + - secretName + properties: + crlDistributionPoints: + description: The CRL distribution points is an X.509 v3 certificate extension which identifies the location of the CRL from which the revocation of this certificate can be checked. If not set, certificates will be issued without distribution points set. + type: array + items: + type: string + ocspServers: + description: The OCSP server list is an X.509 v3 extension that defines a list of URLs of OCSP responders. The OCSP responders can be queried for the revocation status of an issued certificate. If not set, the certificate will be issued with no OCSP servers set. For example, an OCSP server URL could be "http://ocsp.int-x3.letsencrypt.org". + type: array + items: + type: string + secretName: + description: SecretName is the name of the secret used to sign Certificates issued by this Issuer. + type: string + selfSigned: + description: SelfSigned configures this issuer to 'self sign' certificates using the private key used to create the CertificateRequest object. + type: object + properties: + crlDistributionPoints: + description: The CRL distribution points is an X.509 v3 certificate extension which identifies the location of the CRL from which the revocation of this certificate can be checked. If not set certificate will be issued without CDP. Values are strings. + type: array + items: + type: string + vault: + description: Vault configures this issuer to sign certificates using a HashiCorp Vault PKI backend. + type: object + required: + - auth + - path + - server + properties: + auth: + description: Auth configures how cert-manager authenticates with the Vault server. + type: object + properties: + appRole: + description: AppRole authenticates with Vault using the App Role auth mechanism, with the role and secret stored in a Kubernetes Secret resource. + type: object + required: + - path + - roleId + - secretRef + properties: + path: + description: 'Path where the App Role authentication backend is mounted in Vault, e.g: "approle"' + type: string + roleId: + description: RoleID configured in the App Role authentication backend when setting up the authentication backend in Vault. + type: string + secretRef: + description: Reference to a key in a Secret that contains the App Role secret used to authenticate with Vault. The `key` field must be specified and denotes which entry within the Secret resource is used as the app role secret. + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + kubernetes: + description: Kubernetes authenticates with Vault by passing the ServiceAccount token stored in the named Secret resource to the Vault server. + type: object + required: + - role + properties: + mountPath: + description: The Vault mountPath here is the mount path to use when authenticating with Vault. For example, setting a value to `/v1/auth/foo`, will use the path `/v1/auth/foo/login` to authenticate with Vault. If unspecified, the default value "/v1/auth/kubernetes" will be used. + type: string + role: + description: A required field containing the Vault Role to assume. A Role binds a Kubernetes ServiceAccount with a set of Vault policies. + type: string + secretRef: + description: The required Secret field containing a Kubernetes ServiceAccount JWT used for authenticating with Vault. Use of 'ambient credentials' is not supported. + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + serviceAccountRef: + description: A reference to a service account that will be used to request a bound token (also known as "projected token"). Compared to using "secretRef", using this field means that you don't rely on statically bound tokens. To use this field, you must configure an RBAC rule to let cert-manager request a token. + type: object + required: + - name + properties: + name: + description: Name of the ServiceAccount used to request a token. + type: string + tokenSecretRef: + description: TokenSecretRef authenticates with Vault by presenting a token. + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + caBundle: + description: Base64-encoded bundle of PEM CAs which will be used to validate the certificate chain presented by Vault. Only used if using HTTPS to connect to Vault and ignored for HTTP connections. Mutually exclusive with CABundleSecretRef. If neither CABundle nor CABundleSecretRef are defined, the certificate bundle in the cert-manager controller container is used to validate the TLS connection. + type: string + format: byte + caBundleSecretRef: + description: Reference to a Secret containing a bundle of PEM-encoded CAs to use when verifying the certificate chain presented by Vault when using HTTPS. Mutually exclusive with CABundle. If neither CABundle nor CABundleSecretRef are defined, the certificate bundle in the cert-manager controller container is used to validate the TLS connection. If no key for the Secret is specified, cert-manager will default to 'ca.crt'. + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + namespace: + description: 'Name of the vault namespace. Namespaces is a set of features within Vault Enterprise that allows Vault environments to support Secure Multi-tenancy. e.g: "ns1" More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces' + type: string + path: + description: 'Path is the mount path of the Vault PKI backend''s `sign` endpoint, e.g: "my_pki_mount/sign/my-role-name".' + type: string + server: + description: 'Server is the connection address for the Vault server, e.g: "https://vault.example.com:8200".' + type: string + venafi: + description: Venafi configures this issuer to sign certificates using a Venafi TPP or Venafi Cloud policy zone. + type: object + required: + - zone + properties: + cloud: + description: Cloud specifies the Venafi cloud configuration settings. Only one of TPP or Cloud may be specified. + type: object + required: + - apiTokenSecretRef + properties: + apiTokenSecretRef: + description: APITokenSecretRef is a secret key selector for the Venafi Cloud API token. + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + url: + description: URL is the base URL for Venafi Cloud. Defaults to "https://api.venafi.cloud/v1". + type: string + tpp: + description: TPP specifies Trust Protection Platform configuration settings. Only one of TPP or Cloud may be specified. + type: object + required: + - credentialsRef + - url + properties: + caBundle: + description: Base64-encoded bundle of PEM CAs which will be used to validate the certificate chain presented by the TPP server. Only used if using HTTPS; ignored for HTTP. If undefined, the certificate bundle in the cert-manager controller container is used to validate the chain. + type: string + format: byte + credentialsRef: + description: CredentialsRef is a reference to a Secret containing the username and password for the TPP server. The secret must contain two keys, 'username' and 'password'. + type: object + required: + - name + properties: + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + url: + description: 'URL is the base URL for the vedsdk endpoint of the Venafi TPP instance, for example: "https://tpp.example.com/vedsdk".' + type: string + zone: + description: Zone is the Venafi Policy Zone to use for this issuer. All requests made to the Venafi platform will be restricted by the named zone policy. This field is required. + type: string + status: + description: Status of the Issuer. This is set and managed automatically. + type: object + properties: + acme: + description: ACME specific status options. This field should only be set if the Issuer is configured to use an ACME server to issue certificates. + type: object + properties: + lastPrivateKeyHash: + description: LastPrivateKeyHash is a hash of the private key associated with the latest registered ACME account, in order to track changes made to registered account associated with the Issuer + type: string + lastRegisteredEmail: + description: LastRegisteredEmail is the email associated with the latest registered ACME account, in order to track changes made to registered account associated with the Issuer + type: string + uri: + description: URI is the unique account identifier, which can also be used to retrieve account details from the CA + type: string + conditions: + description: List of status conditions to indicate the status of a CertificateRequest. Known condition types are `Ready`. + type: array + items: + description: IssuerCondition contains condition information for an Issuer. + type: object + required: + - status + - type + properties: + lastTransitionTime: + description: LastTransitionTime is the timestamp corresponding to the last status change of this condition. + type: string + format: date-time + message: + description: Message is a human readable description of the details of the last transition, complementing reason. + type: string + observedGeneration: + description: If set, this represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.condition[x].observedGeneration is 9, the condition is out of date with respect to the current state of the Issuer. + type: integer + format: int64 + reason: + description: Reason is a brief machine readable explanation for the condition's last transition. + type: string + status: + description: Status of the condition, one of (`True`, `False`, `Unknown`). + type: string + enum: + - "True" + - "False" + - Unknown + type: + description: Type of the condition, known values are (`Ready`). + type: string + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + served: true + storage: true +--- +# Source: cert-manager/templates/crds.yaml +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: orders.acme.cert-manager.io + labels: + app: 'cert-manager' + app.kubernetes.io/name: 'cert-manager' + app.kubernetes.io/instance: 'cert-manager' + # Generated labels + app.kubernetes.io/version: "v1.13.2" +spec: + group: acme.cert-manager.io + names: + kind: Order + listKind: OrderList + plural: orders + singular: order + categories: + - cert-manager + - cert-manager-acme + scope: Namespaced + versions: + - name: v1 + subresources: + status: {} + additionalPrinterColumns: + - jsonPath: .status.state + name: State + type: string + - jsonPath: .spec.issuerRef.name + name: Issuer + priority: 1 + type: string + - jsonPath: .status.reason + name: Reason + priority: 1 + type: string + - jsonPath: .metadata.creationTimestamp + description: CreationTimestamp is a timestamp representing the server time when this object was created. It is not guaranteed to be set in happens-before order across separate operations. Clients may not set this value. It is represented in RFC3339 form and is in UTC. + name: Age + type: date + schema: + openAPIV3Schema: + description: Order is a type to represent an Order with an ACME server + type: object + required: + - metadata + - spec + 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: + type: object + required: + - issuerRef + - request + properties: + commonName: + description: CommonName is the common name as specified on the DER encoded CSR. If specified, this value must also be present in `dnsNames` or `ipAddresses`. This field must match the corresponding field on the DER encoded CSR. + type: string + dnsNames: + description: DNSNames is a list of DNS names that should be included as part of the Order validation process. This field must match the corresponding field on the DER encoded CSR. + type: array + items: + type: string + duration: + description: Duration is the duration for the not after date for the requested certificate. this is set on order creation as pe the ACME spec. + type: string + ipAddresses: + description: IPAddresses is a list of IP addresses that should be included as part of the Order validation process. This field must match the corresponding field on the DER encoded CSR. + type: array + items: + type: string + issuerRef: + description: IssuerRef references a properly configured ACME-type Issuer which should be used to create this Order. If the Issuer does not exist, processing will be retried. If the Issuer is not an 'ACME' Issuer, an error will be returned and the Order will be marked as failed. + type: object + required: + - name + properties: + group: + description: Group of the resource being referred to. + type: string + kind: + description: Kind of the resource being referred to. + type: string + name: + description: Name of the resource being referred to. + type: string + request: + description: Certificate signing request bytes in DER encoding. This will be used when finalizing the order. This field must be set on the order. + type: string + format: byte + status: + type: object + properties: + authorizations: + description: Authorizations contains data returned from the ACME server on what authorizations must be completed in order to validate the DNS names specified on the Order. + type: array + items: + description: ACMEAuthorization contains data returned from the ACME server on an authorization that must be completed in order validate a DNS name on an ACME Order resource. + type: object + required: + - url + properties: + challenges: + description: Challenges specifies the challenge types offered by the ACME server. One of these challenge types will be selected when validating the DNS name and an appropriate Challenge resource will be created to perform the ACME challenge process. + type: array + items: + description: Challenge specifies a challenge offered by the ACME server for an Order. An appropriate Challenge resource can be created to perform the ACME challenge process. + type: object + required: + - token + - type + - url + properties: + token: + description: Token is the token that must be presented for this challenge. This is used to compute the 'key' that must also be presented. + type: string + type: + description: Type is the type of challenge being offered, e.g. 'http-01', 'dns-01', 'tls-sni-01', etc. This is the raw value retrieved from the ACME server. Only 'http-01' and 'dns-01' are supported by cert-manager, other values will be ignored. + type: string + url: + description: URL is the URL of this challenge. It can be used to retrieve additional metadata about the Challenge from the ACME server. + type: string + identifier: + description: Identifier is the DNS name to be validated as part of this authorization + type: string + initialState: + description: InitialState is the initial state of the ACME authorization when first fetched from the ACME server. If an Authorization is already 'valid', the Order controller will not create a Challenge resource for the authorization. This will occur when working with an ACME server that enables 'authz reuse' (such as Let's Encrypt's production endpoint). If not set and 'identifier' is set, the state is assumed to be pending and a Challenge will be created. + type: string + enum: + - valid + - ready + - pending + - processing + - invalid + - expired + - errored + url: + description: URL is the URL of the Authorization that must be completed + type: string + wildcard: + description: Wildcard will be true if this authorization is for a wildcard DNS name. If this is true, the identifier will be the *non-wildcard* version of the DNS name. For example, if '*.example.com' is the DNS name being validated, this field will be 'true' and the 'identifier' field will be 'example.com'. + type: boolean + certificate: + description: Certificate is a copy of the PEM encoded certificate for this Order. This field will be populated after the order has been successfully finalized with the ACME server, and the order has transitioned to the 'valid' state. + type: string + format: byte + failureTime: + description: FailureTime stores the time that this order failed. This is used to influence garbage collection and back-off. + type: string + format: date-time + finalizeURL: + description: FinalizeURL of the Order. This is used to obtain certificates for this order once it has been completed. + type: string + reason: + description: Reason optionally provides more information about a why the order is in the current state. + type: string + state: + description: State contains the current state of this Order resource. States 'success' and 'expired' are 'final' + type: string + enum: + - valid + - ready + - pending + - processing + - invalid + - expired + - errored + url: + description: URL of the Order. This will initially be empty when the resource is first created. The Order controller will populate this field when the Order is first processed. This field will be immutable after it is initially set. + type: string + served: true + storage: true diff --git a/packages/system/capi-operator/charts/cluster-api-operator/templates/_helpers.tpl b/packages/system/capi-operator/charts/cluster-api-operator/templates/_helpers.tpl new file mode 100644 index 00000000..a4c8b733 --- /dev/null +++ b/packages/system/capi-operator/charts/cluster-api-operator/templates/_helpers.tpl @@ -0,0 +1,24 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "capi-operator.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | 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). +*/}} +{{- define "capi-operator.fullname" -}} +{{- if .Values.fullnameOverride -}} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- if contains $name .Release.Name -}} +{{- .Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} diff --git a/packages/system/capi-operator/charts/cluster-api-operator/templates/addon.yaml b/packages/system/capi-operator/charts/cluster-api-operator/templates/addon.yaml new file mode 100644 index 00000000..a4acb740 --- /dev/null +++ b/packages/system/capi-operator/charts/cluster-api-operator/templates/addon.yaml @@ -0,0 +1,54 @@ +# Addon provider +{{- if .Values.addon }} +{{- $addons := split ";" .Values.addon }} +{{- $addonNamespace := "" }} +{{- $addonName := "" }} +{{- $addonVersion := "" }} +{{- range $addon := $addons }} +{{- $addonArgs := split ":" $addon }} +{{- $addonArgsLen := len $addonArgs }} +{{- if eq $addonArgsLen 3 }} + {{- $addonNamespace = $addonArgs._0 }} + {{- $addonName = $addonArgs._1 }} + {{- $addonVersion = $addonArgs._2 }} +{{- else if eq $addonArgsLen 2 }} + {{- $addonNamespace = print $addonArgs._0 "-addon-system" }} + {{- $addonName = $addonArgs._0 }} + {{- $addonVersion = $addonArgs._1 }} +{{- else if eq $addonArgsLen 1 }} + {{- $addonNamespace = print $addonArgs._0 "-addon-system" }} + {{- $addonName = $addonArgs._0 }} +{{- else }} + {{- fail "addon provider argument should have the following format helm:v1.0.0 or mynamespace:helm:v1.0.0" }} +{{- end }} +--- +apiVersion: v1 +kind: Namespace +metadata: + annotations: + "helm.sh/hook": "post-install" + "helm.sh/hook-weight": "1" + name: {{ $addonNamespace }} +--- +apiVersion: operator.cluster.x-k8s.io/v1alpha2 +kind: AddonProvider +metadata: + name: {{ $addonName }} + namespace: {{ $addonNamespace }} + annotations: + "helm.sh/hook": "post-install" + "helm.sh/hook-weight": "2" +{{- if or $addonVersion $.Values.secretName }} +spec: +{{- end}} +{{- if $addonVersion }} + version: {{ $addonVersion }} +{{- end }} +{{- if $.Values.secretName }} + secretName: {{ $.Values.secretName }} +{{- end }} +{{- if $.Values.secretNamespace }} + secretNamespace: {{ $.Values.secretNamespace }} +{{- end }} +{{- end }} +{{- end }} diff --git a/packages/system/capi-operator/charts/cluster-api-operator/templates/bootstrap.yaml b/packages/system/capi-operator/charts/cluster-api-operator/templates/bootstrap.yaml new file mode 100644 index 00000000..a1634ee8 --- /dev/null +++ b/packages/system/capi-operator/charts/cluster-api-operator/templates/bootstrap.yaml @@ -0,0 +1,55 @@ +# Bootstrap provider +{{- if .Values.bootstrap }} +{{- $bootstraps := split ";" .Values.bootstrap }} +{{- $bootstrapNamespace := "" }} +{{- $bootstrapName := "" }} +{{- $bootstrapVersion := "" }} +{{- range $bootstrap := $bootstraps }} +{{- $bootstrapArgs := split ":" $bootstrap }} +{{- $bootstrapArgsLen := len $bootstrapArgs }} +{{- if eq $bootstrapArgsLen 3 }} + {{- $bootstrapNamespace = $bootstrapArgs._0 }} + {{- $bootstrapName = $bootstrapArgs._1 }} + {{- $bootstrapVersion = $bootstrapArgs._2 }} +{{- else if eq $bootstrapArgsLen 2 }} + {{- $bootstrapNamespace = print $bootstrapArgs._0 "-bootstrap-system" }} + {{- $bootstrapName = $bootstrapArgs._0 }} + {{- $bootstrapVersion = $bootstrapArgs._1 }} +{{- else if eq $bootstrapArgsLen 1 }} + {{- $bootstrapNamespace = print $bootstrapArgs._0 "-bootstrap-system" }} + {{- $bootstrapName = $bootstrapArgs._0 }} +{{- else }} + {{- fail "bootstrap provider argument should have the following format kubeadm:v1.0.0 or mynamespace:kubeadm:v1.0.0" }} +{{- end }} +--- +apiVersion: v1 +kind: Namespace +metadata: + annotations: + "helm.sh/hook": "post-install" + "helm.sh/hook-weight": "1" + name: {{ $bootstrapNamespace }} +--- +apiVersion: operator.cluster.x-k8s.io/v1alpha2 +kind: BootstrapProvider +metadata: + name: {{ $bootstrapName }} + namespace: {{ $bootstrapNamespace }} + annotations: + "helm.sh/hook": "post-install" + "helm.sh/hook-weight": "2" +{{- if or $bootstrapVersion $.Values.configSecret.name }} +spec: +{{- end}} +{{- if $bootstrapVersion }} + version: {{ $bootstrapVersion }} +{{- end }} +{{- if $.Values.configSecret.name }} + configSecret: + name: {{ $.Values.configSecret.name }} + {{- if $.Values.configSecret.namespace }} + namespace: {{ $.Values.configSecret.namespace }} + {{- end }} +{{- end }} +{{- end }} +{{- end }} diff --git a/packages/system/capi-operator/charts/cluster-api-operator/templates/cert-manager.namespace.yaml b/packages/system/capi-operator/charts/cluster-api-operator/templates/cert-manager.namespace.yaml new file mode 100644 index 00000000..4a5fc8d3 --- /dev/null +++ b/packages/system/capi-operator/charts/cluster-api-operator/templates/cert-manager.namespace.yaml @@ -0,0 +1,8 @@ +{{- if index .Values "cert-manager" "enabled" }} +apiVersion: v1 +kind: Namespace +metadata: + annotations: + "helm.sh/hook": "pre-install" + name: {{ index .Values "cert-manager" "namespace" }} +{{- end }} diff --git a/packages/system/capi-operator/charts/cluster-api-operator/templates/control-plane.yaml b/packages/system/capi-operator/charts/cluster-api-operator/templates/control-plane.yaml new file mode 100644 index 00000000..b7cec76d --- /dev/null +++ b/packages/system/capi-operator/charts/cluster-api-operator/templates/control-plane.yaml @@ -0,0 +1,55 @@ +# Control plane provider +{{- if .Values.controlPlane }} +{{- $controlPlanes := split ";" .Values.controlPlane }} +{{- $controlPlaneNamespace := "" }} +{{- $controlPlaneName := "" }} +{{- $controlPlaneVersion := "" }} +{{- range $controlPlane := $controlPlanes }} +{{- $controlPlaneArgs := split ":" $controlPlane }} +{{- $controlPlaneArgsLen := len $controlPlaneArgs }} +{{- if eq $controlPlaneArgsLen 3 }} + {{- $controlPlaneNamespace = $controlPlaneArgs._0 }} + {{- $controlPlaneName = $controlPlaneArgs._1 }} + {{- $controlPlaneVersion = $controlPlaneArgs._2 }} +{{- else if eq $controlPlaneArgsLen 2 }} + {{- $controlPlaneNamespace = print $controlPlaneArgs._0 "-control-plane-system" }} + {{- $controlPlaneName = $controlPlaneArgs._0 }} + {{- $controlPlaneVersion = $controlPlaneArgs._1 }} +{{- else if eq $controlPlaneArgsLen 1 }} + {{- $controlPlaneNamespace = print $controlPlaneArgs._0 "-control-plane-system" }} + {{- $controlPlaneName = $controlPlaneArgs._0 }} +{{- else }} + {{- fail "controlplane provider argument should have the following format kubeadm:v1.0.0 or mynamespace:kubeadm:v1.0.0" }} +{{- end }} +--- +apiVersion: v1 +kind: Namespace +metadata: + annotations: + "helm.sh/hook": "post-install" + "helm.sh/hook-weight": "1" + name: {{ $controlPlaneNamespace }} +--- +apiVersion: operator.cluster.x-k8s.io/v1alpha2 +kind: ControlPlaneProvider +metadata: + name: {{ $controlPlaneName }} + namespace: {{ $controlPlaneNamespace }} + annotations: + "helm.sh/hook": "post-install" + "helm.sh/hook-weight": "2" +{{- if or $controlPlaneVersion $.Values.configSecret.name }} +spec: +{{- end}} +{{- if $controlPlaneVersion }} + version: {{ $controlPlaneVersion }} +{{- end }} +{{- if $.Values.configSecret.name }} + configSecret: + name: {{ $.Values.configSecret.name }} + {{- if $.Values.configSecret.namespace }} + namespace: {{ $.Values.configSecret.namespace }} + {{- end }} +{{- end }} +{{- end }} +{{- end }} diff --git a/packages/system/capi-operator/charts/cluster-api-operator/templates/core-conditions.yaml b/packages/system/capi-operator/charts/cluster-api-operator/templates/core-conditions.yaml new file mode 100644 index 00000000..7bba5953 --- /dev/null +++ b/packages/system/capi-operator/charts/cluster-api-operator/templates/core-conditions.yaml @@ -0,0 +1,31 @@ +{{- if or .Values.addon .Values.bootstrap .Values.controlPlane .Values.infrastructure }} +# Deploy core components if not specified +{{- if not .Values.core }} +--- +apiVersion: v1 +kind: Namespace +metadata: + annotations: + "helm.sh/hook": "post-install" + "helm.sh/hook-weight": "1" + name: capi-system +--- +apiVersion: operator.cluster.x-k8s.io/v1alpha2 +kind: CoreProvider +metadata: + name: cluster-api + namespace: capi-system + annotations: + "helm.sh/hook": "post-install" + "helm.sh/hook-weight": "2" +{{- with .Values.configSecret }} +spec: + configSecret: + name: {{ .name }} + {{- if .namespace }} + namespace: {{ .namespace }} + {{- end }} +{{- end }} +{{- end }} +{{- end }} + diff --git a/packages/system/capi-operator/charts/cluster-api-operator/templates/core.yaml b/packages/system/capi-operator/charts/cluster-api-operator/templates/core.yaml new file mode 100644 index 00000000..260efb59 --- /dev/null +++ b/packages/system/capi-operator/charts/cluster-api-operator/templates/core.yaml @@ -0,0 +1,53 @@ +# Core provider +{{- if .Values.core }} +{{- $coreArgs := split ":" .Values.core }} +{{- $coreArgsLen := len $coreArgs }} +{{- $coreVersion := "" }} +{{- $coreNamespace := "" }} +{{- $coreName := "" }} +{{- $coreVersion := "" }} +{{- if eq $coreArgsLen 3 }} + {{- $coreNamespace = $coreArgs._0 }} + {{- $coreName = $coreArgs._1 }} + {{- $coreVersion = $coreArgs._2 }} +{{- else if eq $coreArgsLen 2 }} + {{- $coreNamespace = "capi-system" }} + {{- $coreName = $coreArgs._0 }} + {{- $coreVersion = $coreArgs._1 }} +{{- else if eq $coreArgsLen 1 }} + {{- $coreNamespace = "capi-system" }} + {{- $coreName = $coreArgs._0 }} +{{- else }} + {{- fail "core provider argument should have the following format cluster-api:v1.0.0 or mynamespace:cluster-api:v1.0.0" }} +{{- end }} +--- +apiVersion: v1 +kind: Namespace +metadata: + annotations: + "helm.sh/hook": "post-install" + "helm.sh/hook-weight": "1" + name: {{ $coreNamespace }} +--- +apiVersion: operator.cluster.x-k8s.io/v1alpha2 +kind: CoreProvider +metadata: + name: {{ $coreName }} + namespace: {{ $coreNamespace }} + annotations: + "helm.sh/hook": "post-install" + "helm.sh/hook-weight": "2" +{{- if or $coreVersion $.Values.configSecret.name }} +spec: +{{- end}} +{{- if $coreVersion }} + version: {{ $coreVersion }} +{{- end }} +{{- if $.Values.configSecret.name }} + configSecret: + name: {{ $.Values.configSecret.name }} + {{- if $.Values.configSecret.namespace }} + namespace: {{ $.Values.configSecret.namespace }} + {{- end }} +{{- end }} +{{- end }} diff --git a/packages/system/capi-operator/charts/cluster-api-operator/templates/deployment.yaml b/packages/system/capi-operator/charts/cluster-api-operator/templates/deployment.yaml new file mode 100644 index 00000000..806d0b1c --- /dev/null +++ b/packages/system/capi-operator/charts/cluster-api-operator/templates/deployment.yaml @@ -0,0 +1,137 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ template "capi-operator.fullname" . }} + namespace: '{{ .Release.Namespace }}' + labels: + app: {{ template "capi-operator.name" . }} + app.kubernetes.io/name: {{ template "capi-operator.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "controller" + control-plane: controller-manager + clusterctl.cluster.x-k8s.io/core: capi-operator + {{- with .Values.deploymentLabels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.deploymentAnnotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + replicas: {{ .Values.replicaCount }} + selector: + matchLabels: + app.kubernetes.io/name: {{ template "capi-operator.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "controller" + control-plane: controller-manager + clusterctl.cluster.x-k8s.io/core: capi-operator + {{- with .Values.strategy }} + strategy: + {{- toYaml . | nindent 4 }} + {{- end }} + template: + metadata: + labels: + app: {{ template "capi-operator.name" . }} + app.kubernetes.io/name: {{ template "capi-operator.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "controller" + control-plane: controller-manager + clusterctl.cluster.x-k8s.io/core: capi-operator + {{- with .Values.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.securityContext }} + securityContext: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - args: + {{- if .Values.logLevel }} + - --v={{ .Values.logLevel }} + {{- end }} + {{- if .Values.healthAddr }} + - --health-addr={{ .Values.healthAddr }} + {{- end }} + {{- if .Values.metricsBindAddr }} + - --metrics-bind-addr={{ .Values.metricsBindAddr }} + {{- end }} + {{- if .Values.diagnosticsAddress }} + - --diagnostics-address={{ .Values.diagnosticsAddress }} + {{- end }} + {{- if .Values.insecureDiagnostics }} + - --insecure-diagnostics={{ .Values.insecureDiagnostics }} + {{- end }} + {{- with .Values.leaderElection }} + - --leader-elect={{ .enabled }} + {{- if .leaseDuration }} + - --leader-elect-lease-duration={{ .leaseDuration }} + {{- end }} + {{- if .renewDeadline }} + - --leader-elect-renew-deadline={{ .renewDeadline }} + {{- end }} + {{- if .retryPeriod }} + - --leader-elect-retry-period={{ .retryPeriod }} + {{- end }} + {{- end }} + command: + - /manager + {{- with .Values.image.manager }} + image: "{{- if .registry -}}{{ .registry }}/{{- end -}}{{ .repository }}{{- if (.digest) -}} @{{ .digest }}{{- else -}}:{{ default $.Chart.AppVersion .tag }} {{- end -}}" + {{- end }} + imagePullPolicy: {{ .Values.image.manager.pullPolicy }} + name: manager + ports: + - containerPort: 9443 + name: webhook-server + protocol: TCP + {{- with .Values.resources.manager }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.containerSecurityContext.manager }} + securityContext: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.volumeMounts.manager }} + volumeMounts: + {{- toYaml . | nindent 12 }} + {{- end }} + terminationGracePeriodSeconds: 10 + {{- with .Values.volumes }} + volumes: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.topologySpreadConstraints }} + topologySpreadConstraints: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.podDnsPolicy }} + dnsPolicy: {{ . }} + {{- end }} + {{- with .Values.podDnsConfig }} + dnsConfig: + {{- toYaml . | nindent 8 }} + {{- end }} diff --git a/packages/system/capi-operator/charts/cluster-api-operator/templates/infra-conditions.yaml b/packages/system/capi-operator/charts/cluster-api-operator/templates/infra-conditions.yaml new file mode 100644 index 00000000..2d1e8cca --- /dev/null +++ b/packages/system/capi-operator/charts/cluster-api-operator/templates/infra-conditions.yaml @@ -0,0 +1,60 @@ +{{- if .Values.infrastructure }} + +# Deploy bootstrap, and infrastructure components if not specified +{{- if not .Values.bootstrap }} +--- +apiVersion: v1 +kind: Namespace +metadata: + annotations: + "helm.sh/hook": "post-install" + "helm.sh/hook-weight": "1" + name: capi-kubeadm-bootstrap-system +--- +apiVersion: operator.cluster.x-k8s.io/v1alpha2 +kind: BootstrapProvider +metadata: + name: kubeadm + namespace: capi-kubeadm-bootstrap-system + annotations: + "helm.sh/hook": "post-install" + "helm.sh/hook-weight": "2" +{{- with .Values.configSecret }} +spec: + configSecret: + name: {{ .name }} + {{- if .namespace }} + namespace: {{ .namespace }} + {{- end }} +{{- end }} +{{- end }} + +{{- if not .Values.controlPlane }} +--- +apiVersion: v1 +kind: Namespace +metadata: + annotations: + "helm.sh/hook": "post-install" + "helm.sh/hook-weight": "1" + name: capi-kubeadm-control-plane-system +--- +apiVersion: operator.cluster.x-k8s.io/v1alpha2 +kind: ControlPlaneProvider +metadata: + name: kubeadm + namespace: capi-kubeadm-control-plane-system + annotations: + "helm.sh/hook": "post-install" + "helm.sh/hook-weight": "2" +{{- with .Values.configSecret }} +spec: + configSecret: + name: {{ .name }} + {{- if .namespace }} + namespace: {{ .namespace }} + {{- end }} +{{- end }} +{{- end }} + +{{- end }} diff --git a/packages/system/capi-operator/charts/cluster-api-operator/templates/infra.yaml b/packages/system/capi-operator/charts/cluster-api-operator/templates/infra.yaml new file mode 100644 index 00000000..e2f8b24b --- /dev/null +++ b/packages/system/capi-operator/charts/cluster-api-operator/templates/infra.yaml @@ -0,0 +1,55 @@ +# Infrastructure providers +{{- if .Values.infrastructure }} +{{- $infrastructures := split ";" .Values.infrastructure }} +{{- $infrastructureNamespace := "" }} +{{- $infrastructureName := "" }} +{{- $infrastructureVersion := "" }} +{{- range $infrastructure := $infrastructures }} +{{- $infrastructureArgs := split ":" $infrastructure }} +{{- $infrastructureArgsLen := len $infrastructureArgs }} +{{- if eq $infrastructureArgsLen 3 }} + {{- $infrastructureNamespace = $infrastructureArgs._0 }} + {{- $infrastructureName = $infrastructureArgs._1 }} + {{- $infrastructureVersion = $infrastructureArgs._2 }} +{{- else if eq $infrastructureArgsLen 2 }} + {{- $infrastructureNamespace = print $infrastructureArgs._0 "-infrastructure-system" }} + {{- $infrastructureName = $infrastructureArgs._0 }} + {{- $infrastructureVersion = $infrastructureArgs._1 }} +{{- else if eq $infrastructureArgsLen 1 }} + {{- $infrastructureNamespace = print $infrastructureArgs._0 "-infrastructure-system" }} + {{- $infrastructureName = $infrastructureArgs._0 }} +{{- else }} + {{- fail "infrastructure provider argument should have the following format aws:v1.0.0 or mynamespace:aws:v1.0.0" }} +{{- end }} +--- +apiVersion: v1 +kind: Namespace +metadata: + annotations: + "helm.sh/hook": "post-install" + "helm.sh/hook-weight": "1" + name: {{ $infrastructureNamespace }} +--- +apiVersion: operator.cluster.x-k8s.io/v1alpha2 +kind: InfrastructureProvider +metadata: + name: {{ $infrastructureName }} + namespace: {{ $infrastructureNamespace }} + annotations: + "helm.sh/hook": "post-install" + "helm.sh/hook-weight": "2" +{{- if or $infrastructureVersion $.Values.configSecret.name }} +spec: +{{- end }} +{{- if $infrastructureVersion }} + version: {{ $infrastructureVersion }} +{{- end }} +{{- if $.Values.configSecret.name }} + configSecret: + name: {{ $.Values.configSecret.name }} + {{- if $.Values.configSecret.namespace }} + namespace: {{ $.Values.configSecret.namespace }} + {{- end }} +{{- end }} +{{- end }} +{{- end }} diff --git a/packages/system/capi-operator/charts/cluster-api-operator/templates/operator-components.yaml b/packages/system/capi-operator/charts/cluster-api-operator/templates/operator-components.yaml new file mode 100644 index 00000000..0e3aaf98 --- /dev/null +++ b/packages/system/capi-operator/charts/cluster-api-operator/templates/operator-components.yaml @@ -0,0 +1,15918 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + cert-manager.io/inject-ca-from: '{{ .Release.Namespace }}/capi-operator-serving-cert' + controller-gen.kubebuilder.io/version: v0.11.4 + labels: + clusterctl.cluster.x-k8s.io/core: capi-operator + name: addonproviders.operator.cluster.x-k8s.io +spec: + conversion: + strategy: Webhook + webhook: + clientConfig: + caBundle: Cg== + service: + name: capi-operator-webhook-service + namespace: '{{ .Release.Namespace }}' + path: /convert + conversionReviewVersions: + - v1 + - v1alpha1 + group: operator.cluster.x-k8s.io + names: + kind: AddonProvider + listKind: AddonProviderList + plural: addonproviders + singular: addonprovider + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .status.installedVersion + name: InstalledVersion + type: string + - jsonPath: .status.conditions[?(@.type=='Ready')].status + name: Ready + type: string + name: v1alpha2 + schema: + openAPIV3Schema: + description: AddonProvider is the Schema for the addonproviders 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: AddonProviderSpec defines the desired state of AddonProvider. + properties: + additionalManifests: + description: AdditionalManifests is reference to configmap that contains + additional manifests that will be applied together with the provider + components. The key for storing these manifests has to be `manifests`. + The manifests are applied only once when a certain release is installed/upgraded. + If namespace is not specified, the namespace of the provider will + be used. There is no validation of the yaml content inside the configmap. + properties: + name: + description: Name defines the name of the configmap. + type: string + namespace: + description: Namespace defines the namespace of the configmap. + type: string + required: + - name + type: object + configSecret: + description: ConfigSecret is the object with name and namespace of + the Secret providing the configuration variables for the current + provider instance, like e.g. credentials. Such configurations will + be used when creating or upgrading provider components. The contents + of the secret will be treated as immutable. If changes need to be + made, a new object can be created and the name should be updated. + The contents should be in the form of key:value. This secret must + be in the same namespace as the provider. + properties: + name: + description: Name defines the name of the secret. + type: string + namespace: + description: Namespace defines the namespace of the secret. + type: string + required: + - name + type: object + deployment: + description: Deployment defines the properties that can be enabled + on the deployment for the provider. + properties: + affinity: + description: If specified, the pod's scheduling constraints + properties: + nodeAffinity: + description: Describes node affinity scheduling rules for + the pod. + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods + to nodes that satisfy the affinity expressions specified + by this field, but it may choose a node that violates + one or more of the expressions. The node that is most + preferred is the one with the greatest sum of weights, + i.e. for each node that meets all of the scheduling + requirements (resource request, requiredDuringScheduling + affinity expressions, etc.), compute a sum by iterating + through the elements of this field and adding "weight" + to the sum if the node matches the corresponding matchExpressions; + the node(s) with the highest sum are the most preferred. + items: + description: An empty preferred scheduling term matches + all objects with implicit weight 0 (i.e. it's a no-op). + A null preferred scheduling term matches no objects + (i.e. is also a no-op). + properties: + preference: + description: A node selector term, associated with + the corresponding weight. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: 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. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: 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. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + x-kubernetes-map-type: atomic + weight: + description: Weight associated with matching the + corresponding nodeSelectorTerm, in the range 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by + this field are not met at scheduling time, the pod will + not be scheduled onto the node. If the affinity requirements + specified by this field cease to be met at some point + during pod execution (e.g. due to an update), the system + may or may not try to eventually evict the pod from + its node. + properties: + nodeSelectorTerms: + description: Required. A list of node selector terms. + The terms are ORed. + items: + description: A null or empty node selector term + matches no objects. The requirements of them are + ANDed. The TopologySelectorTerm type implements + a subset of the NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: 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. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: 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. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + x-kubernetes-map-type: atomic + type: array + required: + - nodeSelectorTerms + type: object + x-kubernetes-map-type: atomic + type: object + podAffinity: + description: Describes pod affinity scheduling rules (e.g. + co-locate this pod in the same node, zone, etc. as some + other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods + to nodes that satisfy the affinity expressions specified + by this field, but it may choose a node that violates + one or more of the expressions. The node that is most + preferred is the one with the greatest sum of weights, + i.e. for each node that meets all of the scheduling + requirements (resource request, requiredDuringScheduling + affinity expressions, etc.), compute a sum by iterating + through the elements of this field and adding "weight" + to the sum if the node has pods which matches the corresponding + podAffinityTerm; the node(s) with the highest sum are + the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by + this field and the ones listed in the namespaces + field. null selector and null or empty namespaces + list means "this pod's namespace". An empty + selector ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. + The term is applied to the union of the namespaces + listed in this field and the ones selected + by namespaceSelector. null or empty namespaces + list and null namespaceSelector means "this + pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the + pods matching the labelSelector in the specified + namespaces, where co-located is defined as + running on a node whose value of the label + with key topologyKey matches that of any node + on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching the + corresponding podAffinityTerm, in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by + this field are not met at scheduling time, the pod will + not be scheduled onto the node. If the affinity requirements + specified by this field cease to be met at some point + during pod execution (e.g. due to a pod label update), + the system may or may not try to eventually evict the + pod from its node. When there are multiple elements, + the lists of nodes corresponding to each podAffinityTerm + are intersected, i.e. all terms must be satisfied. + items: + description: Defines a set of pods (namely those matching + the labelSelector relative to the given namespace(s)) + that this pod should be co-located (affinity) or not + co-located (anti-affinity) with, where co-located + is defined as running on a node whose value of the + label with key matches that of any node + on which a pod of the set of pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by this + field and the ones listed in the namespaces field. + null selector and null or empty namespaces list + means "this pod's namespace". An empty selector + ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. The + term is applied to the union of the namespaces + listed in this field and the ones selected by + namespaceSelector. null or empty namespaces list + and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods + matching the labelSelector in the specified namespaces, + where co-located is defined as running on a node + whose value of the label with key topologyKey + matches that of any node on which any of the selected + pods is running. Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + podAntiAffinity: + description: Describes pod anti-affinity scheduling rules + (e.g. avoid putting this pod in the same node, zone, etc. + as some other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods + to nodes that satisfy the anti-affinity expressions + specified by this field, but it may choose a node that + violates one or more of the expressions. The node that + is most preferred is the one with the greatest sum of + weights, i.e. for each node that meets all of the scheduling + requirements (resource request, requiredDuringScheduling + anti-affinity expressions, etc.), compute a sum by iterating + through the elements of this field and adding "weight" + to the sum if the node has pods which matches the corresponding + podAffinityTerm; the node(s) with the highest sum are + the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by + this field and the ones listed in the namespaces + field. null selector and null or empty namespaces + list means "this pod's namespace". An empty + selector ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. + The term is applied to the union of the namespaces + listed in this field and the ones selected + by namespaceSelector. null or empty namespaces + list and null namespaceSelector means "this + pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the + pods matching the labelSelector in the specified + namespaces, where co-located is defined as + running on a node whose value of the label + with key topologyKey matches that of any node + on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching the + corresponding podAffinityTerm, in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the anti-affinity requirements specified + by this field are not met at scheduling time, the pod + will not be scheduled onto the node. If the anti-affinity + requirements specified by this field cease to be met + at some point during pod execution (e.g. due to a pod + label update), the system may or may not try to eventually + evict the pod from its node. When there are multiple + elements, the lists of nodes corresponding to each podAffinityTerm + are intersected, i.e. all terms must be satisfied. + items: + description: Defines a set of pods (namely those matching + the labelSelector relative to the given namespace(s)) + that this pod should be co-located (affinity) or not + co-located (anti-affinity) with, where co-located + is defined as running on a node whose value of the + label with key matches that of any node + on which a pod of the set of pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by this + field and the ones listed in the namespaces field. + null selector and null or empty namespaces list + means "this pod's namespace". An empty selector + ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. The + term is applied to the union of the namespaces + listed in this field and the ones selected by + namespaceSelector. null or empty namespaces list + and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods + matching the labelSelector in the specified namespaces, + where co-located is defined as running on a node + whose value of the label with key topologyKey + matches that of any node on which any of the selected + pods is running. Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + type: object + containers: + description: List of containers specified in the Deployment + items: + description: ContainerSpec defines the properties available + to override for each container in a provider deployment such + as Image and Args to the container’s entrypoint. + properties: + args: + additionalProperties: + type: string + description: Args represents extra provider specific flags + that are not encoded as fields in this API. Explicit controller + manager properties defined in the `Provider.ManagerSpec` + will have higher precedence than those defined in `ContainerSpec.Args`. + For example, `ManagerSpec.SyncPeriod` will be used instead + of the container arg `--sync-period` if both are defined. + The same holds for `ManagerSpec.FeatureGates` and `--feature-gates`. + type: object + command: + description: Command allows override container's entrypoint + array. + items: + type: string + type: array + env: + description: List of environment variables to set in the + container. + 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: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + 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: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + 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 + imageUrl: + description: Container Image URL + type: string + name: + description: Name of the container. Cannot be updated. + type: string + resources: + description: Compute resources required by this container. + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. \n 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 + 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 + required: + - name + type: object + type: array + imagePullSecrets: + description: List of image pull secrets specified in the Deployment + items: + description: LocalObjectReference contains enough information + to let you locate the referenced object inside the same namespace. + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + x-kubernetes-map-type: atomic + type: array + nodeSelector: + additionalProperties: + type: string + description: 'NodeSelector is a selector which must be true for + the pod to fit on a node. Selector which must match a node''s + labels for the pod to be scheduled on that node. More info: + https://kubernetes.io/docs/concepts/configuration/assign-pod-node/' + type: object + replicas: + description: Number of desired pods. This is a pointer to distinguish + between explicit zero and not specified. Defaults to 1. + minimum: 0 + type: integer + serviceAccountName: + description: If specified, the pod's service account + type: string + tolerations: + description: If specified, the pod's tolerations. + 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 + type: object + fetchConfig: + description: FetchConfig determines how the operator will fetch the + components and metadata for the provider. If nil, the operator will + try to fetch components according to default embedded fetch configuration + for the given kind and `ObjectMeta.Name`. For example, the infrastructure + name `aws` will fetch artifacts from https://github.com/kubernetes-sigs/cluster-api-provider-aws/releases. + properties: + selector: + description: 'Selector to be used for fetching provider’s components + and metadata from ConfigMaps stored inside the cluster. Each + ConfigMap is expected to contain components and metadata for + a specific version only. Note: the name of the ConfigMap should + be set to the version or to override this add a label like the + following: provider.cluster.x-k8s.io/version=v1.4.3' + 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 + required: + - key + - operator + type: object + type: array + 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 + url: + description: URL to be used for fetching the provider’s components + and metadata from a remote Github repository. For example, https://github.com/{owner}/{repository}/releases + You must set `providerSpec.Version` field for operator to pick + up desired version of the release from GitHub. + type: string + type: object + manager: + description: Manager defines the properties that can be enabled on + the controller manager for the provider. + properties: + cacheNamespace: + description: "CacheNamespace if specified restricts the manager's + cache to watch objects in the desired namespace Defaults to + all namespaces \n Note: If a namespace is specified, controllers + can still Watch for a cluster-scoped resource (e.g Node). For + namespaced resources the cache will only hold objects from the + desired namespace." + type: string + controller: + description: Controller contains global configuration options + for controllers registered within this manager. + properties: + cacheSyncTimeout: + description: CacheSyncTimeout refers to the time limit set + to wait for syncing caches. Defaults to 2 minutes if not + set. + format: int64 + type: integer + groupKindConcurrency: + additionalProperties: + type: integer + description: "GroupKindConcurrency is a map from a Kind to + the number of concurrent reconciliation allowed for that + controller. \n When a controller is registered within this + manager using the builder utilities, users have to specify + the type the controller reconciles in the For(...) call. + If the object's kind passed matches one of the keys in this + map, the concurrency for that controller is set to the number + specified. \n The key is expected to be consistent in form + with GroupKind.String(), e.g. ReplicaSet in apps group (regardless + of version) would be `ReplicaSet.apps`." + type: object + recoverPanic: + description: RecoverPanic indicates if panics should be recovered. + type: boolean + type: object + featureGates: + additionalProperties: + type: boolean + description: FeatureGates define provider specific feature flags + that will be passed in as container args to the provider's controller + manager. Controller Manager flag is --feature-gates. + type: object + gracefulShutDown: + description: GracefulShutdownTimeout is the duration given to + runnable to stop before the manager actually returns on stop. + To disable graceful shutdown, set to time.Duration(0) To use + graceful shutdown without timeout, set to a negative duration, + e.G. time.Duration(-1) The graceful shutdown is skipped for + safety reasons in case the leader election lease is lost. + type: string + health: + description: Health contains the controller health configuration + properties: + healthProbeBindAddress: + description: HealthProbeBindAddress is the TCP address that + the controller should bind to for serving health probes + It can be set to "0" or "" to disable serving the health + probe. + type: string + livenessEndpointName: + description: LivenessEndpointName, defaults to "healthz" + type: string + readinessEndpointName: + description: ReadinessEndpointName, defaults to "readyz" + type: string + type: object + leaderElection: + description: LeaderElection is the LeaderElection config to be + used when configuring the manager.Manager leader election + properties: + leaderElect: + description: leaderElect enables a leader election client + to gain leadership before executing the main loop. Enable + this when running replicated components for high availability. + type: boolean + leaseDuration: + description: leaseDuration is the duration that non-leader + candidates will wait after observing a leadership renewal + until attempting to acquire leadership of a led but unrenewed + leader slot. This is effectively the maximum duration that + a leader can be stopped before it is replaced by another + candidate. This is only applicable if leader election is + enabled. + type: string + renewDeadline: + description: renewDeadline is the interval between attempts + by the acting master to renew a leadership slot before it + stops leading. This must be less than or equal to the lease + duration. This is only applicable if leader election is + enabled. + type: string + resourceLock: + description: resourceLock indicates the resource object type + that will be used to lock during leader election cycles. + type: string + resourceName: + description: resourceName indicates the name of resource object + that will be used to lock during leader election cycles. + type: string + resourceNamespace: + description: resourceName indicates the namespace of resource + object that will be used to lock during leader election + cycles. + type: string + retryPeriod: + description: retryPeriod is the duration the clients should + wait between attempting acquisition and renewal of a leadership. + This is only applicable if leader election is enabled. + type: string + required: + - leaderElect + - leaseDuration + - renewDeadline + - resourceLock + - resourceName + - resourceNamespace + - retryPeriod + type: object + maxConcurrentReconciles: + description: MaxConcurrentReconciles is the maximum number of + concurrent Reconciles which can be run. + minimum: 1 + type: integer + metrics: + description: Metrics contains thw controller metrics configuration + properties: + bindAddress: + description: BindAddress is the TCP address that the controller + should bind to for serving prometheus metrics. It can be + set to "0" to disable the metrics serving. + type: string + type: object + profilerAddress: + description: ProfilerAddress defines the bind address to expose + the pprof profiler (e.g. localhost:6060). Default empty, meaning + the profiler is disabled. Controller Manager flag is --profiler-address. + type: string + syncPeriod: + description: SyncPeriod determines the minimum frequency at which + watched resources are reconciled. A lower period will correct + entropy more quickly, but reduce responsiveness to change if + there are many watched resources. Change this value only if + you know what you are doing. Defaults to 10 hours if unset. + there will a 10 percent jitter between the SyncPeriod of all + controllers so that all controllers will not send list requests + simultaneously. + type: string + verbosity: + default: 1 + description: Verbosity set the logs verbosity. Defaults to 1. + Controller Manager flag is --verbosity. + minimum: 0 + type: integer + webhook: + description: Webhook contains the controllers webhook configuration + properties: + certDir: + description: CertDir is the directory that contains the server + key and certificate. if not set, webhook server would look + up the server key and certificate in {TempDir}/k8s-webhook-server/serving-certs. + The server key and certificate must be named tls.key and + tls.crt, respectively. + type: string + host: + description: Host is the hostname that the webhook server + binds to. It is used to set webhook.Server.Host. + type: string + port: + description: Port is the port that the webhook server serves + at. It is used to set webhook.Server.Port. + type: integer + type: object + type: object + manifestPatches: + description: ManifestPatches are applied to rendered provider manifests + to customize the provider manifests. Patches are applied in the + order they are specified. The `kind` field must match the target + object, and if `apiVersion` is specified it will only be applied + to matching objects. This should be an inline yaml blob-string https://datatracker.ietf.org/doc/html/rfc7396 + items: + type: string + type: array + version: + description: Version indicates the provider version. + type: string + type: object + status: + description: AddonProviderStatus defines the observed state of AddonProvider. + properties: + conditions: + description: Conditions define the current service state of the provider. + items: + description: Condition defines an observation of a Cluster API resource + operational state. + properties: + lastTransitionTime: + description: 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: A human readable message indicating details about + the transition. This field may be empty. + type: string + reason: + description: The reason for the condition's last transition + in CamelCase. The specific API may choose whether or not this + field is considered a guaranteed API. This field may not be + empty. + type: string + severity: + description: Severity provides an explicit classification of + Reason code, so the users or machines can immediately understand + the current situation and act accordingly. The Severity field + MUST be set only when Status=False. + type: string + status: + description: Status of the condition, one of 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. + type: string + required: + - lastTransitionTime + - status + - type + type: object + type: array + contract: + description: Contract will contain the core provider contract that + the provider is abiding by, like e.g. v1alpha4. + type: string + installedVersion: + description: InstalledVersion is the version of the provider that + is installed. + type: string + observedGeneration: + description: ObservedGeneration is the latest generation observed + by the controller. + format: int64 + type: integer + type: object + type: object + served: true + storage: true + subresources: + status: {} +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + cert-manager.io/inject-ca-from: '{{ .Release.Namespace }}/capi-operator-serving-cert' + controller-gen.kubebuilder.io/version: v0.11.4 + labels: + clusterctl.cluster.x-k8s.io/core: capi-operator + name: bootstrapproviders.operator.cluster.x-k8s.io +spec: + conversion: + strategy: Webhook + webhook: + clientConfig: + caBundle: Cg== + service: + name: capi-operator-webhook-service + namespace: '{{ .Release.Namespace }}' + path: /convert + conversionReviewVersions: + - v1 + - v1alpha1 + group: operator.cluster.x-k8s.io + names: + kind: BootstrapProvider + listKind: BootstrapProviderList + plural: bootstrapproviders + singular: bootstrapprovider + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .status.installedVersion + name: InstalledVersion + type: string + - jsonPath: .status.conditions[?(@.type=='Ready')].status + name: Ready + type: string + name: v1alpha1 + schema: + openAPIV3Schema: + description: BootstrapProvider is the Schema for the bootstrapproviders 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: BootstrapProviderSpec defines the desired state of BootstrapProvider. + properties: + additionalManifests: + description: AdditionalManifests is reference to configmap that contains + additional manifests that will be applied together with the provider + components. The key for storing these manifests has to be `manifests`. + The manifests are applied only once when a certain release is installed/upgraded. + If namespace is not specified, the namespace of the provider will + be used. There is no validation of the yaml content inside the configmap. + properties: + name: + description: Name defines the name of the configmap. + type: string + namespace: + description: Namespace defines the namespace of the configmap. + type: string + required: + - name + type: object + deployment: + description: Deployment defines the properties that can be enabled + on the deployment for the provider. + properties: + affinity: + description: If specified, the pod's scheduling constraints + properties: + nodeAffinity: + description: Describes node affinity scheduling rules for + the pod. + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods + to nodes that satisfy the affinity expressions specified + by this field, but it may choose a node that violates + one or more of the expressions. The node that is most + preferred is the one with the greatest sum of weights, + i.e. for each node that meets all of the scheduling + requirements (resource request, requiredDuringScheduling + affinity expressions, etc.), compute a sum by iterating + through the elements of this field and adding "weight" + to the sum if the node matches the corresponding matchExpressions; + the node(s) with the highest sum are the most preferred. + items: + description: An empty preferred scheduling term matches + all objects with implicit weight 0 (i.e. it's a no-op). + A null preferred scheduling term matches no objects + (i.e. is also a no-op). + properties: + preference: + description: A node selector term, associated with + the corresponding weight. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: 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. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: 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. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + x-kubernetes-map-type: atomic + weight: + description: Weight associated with matching the + corresponding nodeSelectorTerm, in the range 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by + this field are not met at scheduling time, the pod will + not be scheduled onto the node. If the affinity requirements + specified by this field cease to be met at some point + during pod execution (e.g. due to an update), the system + may or may not try to eventually evict the pod from + its node. + properties: + nodeSelectorTerms: + description: Required. A list of node selector terms. + The terms are ORed. + items: + description: A null or empty node selector term + matches no objects. The requirements of them are + ANDed. The TopologySelectorTerm type implements + a subset of the NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: 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. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: 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. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + x-kubernetes-map-type: atomic + type: array + required: + - nodeSelectorTerms + type: object + x-kubernetes-map-type: atomic + type: object + podAffinity: + description: Describes pod affinity scheduling rules (e.g. + co-locate this pod in the same node, zone, etc. as some + other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods + to nodes that satisfy the affinity expressions specified + by this field, but it may choose a node that violates + one or more of the expressions. The node that is most + preferred is the one with the greatest sum of weights, + i.e. for each node that meets all of the scheduling + requirements (resource request, requiredDuringScheduling + affinity expressions, etc.), compute a sum by iterating + through the elements of this field and adding "weight" + to the sum if the node has pods which matches the corresponding + podAffinityTerm; the node(s) with the highest sum are + the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by + this field and the ones listed in the namespaces + field. null selector and null or empty namespaces + list means "this pod's namespace". An empty + selector ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. + The term is applied to the union of the namespaces + listed in this field and the ones selected + by namespaceSelector. null or empty namespaces + list and null namespaceSelector means "this + pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the + pods matching the labelSelector in the specified + namespaces, where co-located is defined as + running on a node whose value of the label + with key topologyKey matches that of any node + on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching the + corresponding podAffinityTerm, in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by + this field are not met at scheduling time, the pod will + not be scheduled onto the node. If the affinity requirements + specified by this field cease to be met at some point + during pod execution (e.g. due to a pod label update), + the system may or may not try to eventually evict the + pod from its node. When there are multiple elements, + the lists of nodes corresponding to each podAffinityTerm + are intersected, i.e. all terms must be satisfied. + items: + description: Defines a set of pods (namely those matching + the labelSelector relative to the given namespace(s)) + that this pod should be co-located (affinity) or not + co-located (anti-affinity) with, where co-located + is defined as running on a node whose value of the + label with key matches that of any node + on which a pod of the set of pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by this + field and the ones listed in the namespaces field. + null selector and null or empty namespaces list + means "this pod's namespace". An empty selector + ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. The + term is applied to the union of the namespaces + listed in this field and the ones selected by + namespaceSelector. null or empty namespaces list + and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods + matching the labelSelector in the specified namespaces, + where co-located is defined as running on a node + whose value of the label with key topologyKey + matches that of any node on which any of the selected + pods is running. Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + podAntiAffinity: + description: Describes pod anti-affinity scheduling rules + (e.g. avoid putting this pod in the same node, zone, etc. + as some other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods + to nodes that satisfy the anti-affinity expressions + specified by this field, but it may choose a node that + violates one or more of the expressions. The node that + is most preferred is the one with the greatest sum of + weights, i.e. for each node that meets all of the scheduling + requirements (resource request, requiredDuringScheduling + anti-affinity expressions, etc.), compute a sum by iterating + through the elements of this field and adding "weight" + to the sum if the node has pods which matches the corresponding + podAffinityTerm; the node(s) with the highest sum are + the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by + this field and the ones listed in the namespaces + field. null selector and null or empty namespaces + list means "this pod's namespace". An empty + selector ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. + The term is applied to the union of the namespaces + listed in this field and the ones selected + by namespaceSelector. null or empty namespaces + list and null namespaceSelector means "this + pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the + pods matching the labelSelector in the specified + namespaces, where co-located is defined as + running on a node whose value of the label + with key topologyKey matches that of any node + on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching the + corresponding podAffinityTerm, in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the anti-affinity requirements specified + by this field are not met at scheduling time, the pod + will not be scheduled onto the node. If the anti-affinity + requirements specified by this field cease to be met + at some point during pod execution (e.g. due to a pod + label update), the system may or may not try to eventually + evict the pod from its node. When there are multiple + elements, the lists of nodes corresponding to each podAffinityTerm + are intersected, i.e. all terms must be satisfied. + items: + description: Defines a set of pods (namely those matching + the labelSelector relative to the given namespace(s)) + that this pod should be co-located (affinity) or not + co-located (anti-affinity) with, where co-located + is defined as running on a node whose value of the + label with key matches that of any node + on which a pod of the set of pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by this + field and the ones listed in the namespaces field. + null selector and null or empty namespaces list + means "this pod's namespace". An empty selector + ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. The + term is applied to the union of the namespaces + listed in this field and the ones selected by + namespaceSelector. null or empty namespaces list + and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods + matching the labelSelector in the specified namespaces, + where co-located is defined as running on a node + whose value of the label with key topologyKey + matches that of any node on which any of the selected + pods is running. Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + type: object + containers: + description: List of containers specified in the Deployment + items: + description: ContainerSpec defines the properties available + to override for each container in a provider deployment such + as Image and Args to the container’s entrypoint. + properties: + args: + additionalProperties: + type: string + description: Args represents extra provider specific flags + that are not encoded as fields in this API. Explicit controller + manager properties defined in the `Provider.ManagerSpec` + will have higher precedence than those defined in `ContainerSpec.Args`. + For example, `ManagerSpec.SyncPeriod` will be used instead + of the container arg `--sync-period` if both are defined. + The same holds for `ManagerSpec.FeatureGates` and `--feature-gates`. + type: object + command: + description: Command allows override container's entrypoint + array. + items: + type: string + type: array + env: + description: List of environment variables to set in the + container. + 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: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + 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: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + 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: Container Image Name + properties: + name: + description: Name allows to specify a name for the image. + type: string + repository: + description: Repository sets the container registry + to pull images from. + type: string + tag: + description: Tag allows to specify a tag for the image. + type: string + type: object + name: + description: Name of the container. Cannot be updated. + type: string + resources: + description: Compute resources required by this container. + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. \n 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 + 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 + required: + - name + type: object + type: array + imagePullSecrets: + description: List of image pull secrets specified in the Deployment + items: + description: LocalObjectReference contains enough information + to let you locate the referenced object inside the same namespace. + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + x-kubernetes-map-type: atomic + type: array + nodeSelector: + additionalProperties: + type: string + description: 'NodeSelector is a selector which must be true for + the pod to fit on a node. Selector which must match a node''s + labels for the pod to be scheduled on that node. More info: + https://kubernetes.io/docs/concepts/configuration/assign-pod-node/' + type: object + replicas: + description: Number of desired pods. This is a pointer to distinguish + between explicit zero and not specified. Defaults to 1. + minimum: 0 + type: integer + serviceAccountName: + description: If specified, the pod's service account + type: string + tolerations: + description: If specified, the pod's tolerations. + 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 + type: object + fetchConfig: + description: FetchConfig determines how the operator will fetch the + components and metadata for the provider. If nil, the operator will + try to fetch components according to default embedded fetch configuration + for the given kind and `ObjectMeta.Name`. For example, the infrastructure + name `aws` will fetch artifacts from https://github.com/kubernetes-sigs/cluster-api-provider-aws/releases. + properties: + selector: + description: 'Selector to be used for fetching provider’s components + and metadata from ConfigMaps stored inside the cluster. Each + ConfigMap is expected to contain components and metadata for + a specific version only. Note: the name of the ConfigMap should + be set to the version or to override this add a label like the + following: provider.cluster.x-k8s.io/version=v1.4.3' + 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 + required: + - key + - operator + type: object + type: array + 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 + url: + description: URL to be used for fetching the provider’s components + and metadata from a remote Github repository. For example, https://github.com/{owner}/{repository}/releases + You must set `providerSpec.Version` field for operator to pick + up desired version of the release from GitHub. + type: string + type: object + manager: + description: Manager defines the properties that can be enabled on + the controller manager for the provider. + properties: + cacheNamespace: + description: "CacheNamespace if specified restricts the manager's + cache to watch objects in the desired namespace Defaults to + all namespaces \n Note: If a namespace is specified, controllers + can still Watch for a cluster-scoped resource (e.g Node). For + namespaced resources the cache will only hold objects from the + desired namespace." + type: string + controller: + description: Controller contains global configuration options + for controllers registered within this manager. + properties: + cacheSyncTimeout: + description: CacheSyncTimeout refers to the time limit set + to wait for syncing caches. Defaults to 2 minutes if not + set. + format: int64 + type: integer + groupKindConcurrency: + additionalProperties: + type: integer + description: "GroupKindConcurrency is a map from a Kind to + the number of concurrent reconciliation allowed for that + controller. \n When a controller is registered within this + manager using the builder utilities, users have to specify + the type the controller reconciles in the For(...) call. + If the object's kind passed matches one of the keys in this + map, the concurrency for that controller is set to the number + specified. \n The key is expected to be consistent in form + with GroupKind.String(), e.g. ReplicaSet in apps group (regardless + of version) would be `ReplicaSet.apps`." + type: object + recoverPanic: + description: RecoverPanic indicates if panics should be recovered. + type: boolean + type: object + featureGates: + additionalProperties: + type: boolean + description: FeatureGates define provider specific feature flags + that will be passed in as container args to the provider's controller + manager. Controller Manager flag is --feature-gates. + type: object + gracefulShutDown: + description: GracefulShutdownTimeout is the duration given to + runnable to stop before the manager actually returns on stop. + To disable graceful shutdown, set to time.Duration(0) To use + graceful shutdown without timeout, set to a negative duration, + e.G. time.Duration(-1) The graceful shutdown is skipped for + safety reasons in case the leader election lease is lost. + type: string + health: + description: Health contains the controller health configuration + properties: + healthProbeBindAddress: + description: HealthProbeBindAddress is the TCP address that + the controller should bind to for serving health probes + It can be set to "0" or "" to disable serving the health + probe. + type: string + livenessEndpointName: + description: LivenessEndpointName, defaults to "healthz" + type: string + readinessEndpointName: + description: ReadinessEndpointName, defaults to "readyz" + type: string + type: object + leaderElection: + description: LeaderElection is the LeaderElection config to be + used when configuring the manager.Manager leader election + properties: + leaderElect: + description: leaderElect enables a leader election client + to gain leadership before executing the main loop. Enable + this when running replicated components for high availability. + type: boolean + leaseDuration: + description: leaseDuration is the duration that non-leader + candidates will wait after observing a leadership renewal + until attempting to acquire leadership of a led but unrenewed + leader slot. This is effectively the maximum duration that + a leader can be stopped before it is replaced by another + candidate. This is only applicable if leader election is + enabled. + type: string + renewDeadline: + description: renewDeadline is the interval between attempts + by the acting master to renew a leadership slot before it + stops leading. This must be less than or equal to the lease + duration. This is only applicable if leader election is + enabled. + type: string + resourceLock: + description: resourceLock indicates the resource object type + that will be used to lock during leader election cycles. + type: string + resourceName: + description: resourceName indicates the name of resource object + that will be used to lock during leader election cycles. + type: string + resourceNamespace: + description: resourceName indicates the namespace of resource + object that will be used to lock during leader election + cycles. + type: string + retryPeriod: + description: retryPeriod is the duration the clients should + wait between attempting acquisition and renewal of a leadership. + This is only applicable if leader election is enabled. + type: string + required: + - leaderElect + - leaseDuration + - renewDeadline + - resourceLock + - resourceName + - resourceNamespace + - retryPeriod + type: object + maxConcurrentReconciles: + description: MaxConcurrentReconciles is the maximum number of + concurrent Reconciles which can be run. + minimum: 1 + type: integer + metrics: + description: Metrics contains the controller metrics configuration + properties: + bindAddress: + description: BindAddress is the TCP address that the controller + should bind to for serving prometheus metrics. It can be + set to "0" to disable the metrics serving. + type: string + type: object + profilerAddress: + description: ProfilerAddress defines the bind address to expose + the pprof profiler (e.g. localhost:6060). Default empty, meaning + the profiler is disabled. Controller Manager flag is --profiler-address. + type: string + syncPeriod: + description: SyncPeriod determines the minimum frequency at which + watched resources are reconciled. A lower period will correct + entropy more quickly, but reduce responsiveness to change if + there are many watched resources. Change this value only if + you know what you are doing. Defaults to 10 hours if unset. + there will a 10 percent jitter between the SyncPeriod of all + controllers so that all controllers will not send list requests + simultaneously. + type: string + verbosity: + default: 1 + description: Verbosity set the logs verbosity. Defaults to 1. + Controller Manager flag is --verbosity. + minimum: 0 + type: integer + webhook: + description: Webhook contains the controllers webhook configuration + properties: + certDir: + description: CertDir is the directory that contains the server + key and certificate. if not set, webhook server would look + up the server key and certificate in {TempDir}/k8s-webhook-server/serving-certs. + The server key and certificate must be named tls.key and + tls.crt, respectively. + type: string + host: + description: Host is the hostname that the webhook server + binds to. It is used to set webhook.Server.Host. + type: string + port: + description: Port is the port that the webhook server serves + at. It is used to set webhook.Server.Port. + type: integer + type: object + type: object + secretName: + description: SecretName is the name of the Secret providing the configuration + variables for the current provider instance, like e.g. credentials. + Such configurations will be used when creating or upgrading provider + components. The contents of the secret will be treated as immutable. + If changes need to be made, a new object can be created and the + name should be updated. The contents should be in the form of key:value. + This secret must be in the same namespace as the provider. + type: string + secretNamespace: + description: SecretNamespace is the namespace of the Secret providing + the configuration variables. If not specified, the namespace of + the provider will be used. + type: string + version: + description: Version indicates the provider version. + type: string + type: object + status: + description: BootstrapProviderStatus defines the observed state of BootstrapProvider. + properties: + conditions: + description: Conditions define the current service state of the provider. + items: + description: Condition defines an observation of a Cluster API resource + operational state. + properties: + lastTransitionTime: + description: 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: A human readable message indicating details about + the transition. This field may be empty. + type: string + reason: + description: The reason for the condition's last transition + in CamelCase. The specific API may choose whether or not this + field is considered a guaranteed API. This field may not be + empty. + type: string + severity: + description: Severity provides an explicit classification of + Reason code, so the users or machines can immediately understand + the current situation and act accordingly. The Severity field + MUST be set only when Status=False. + type: string + status: + description: Status of the condition, one of 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. + type: string + required: + - lastTransitionTime + - status + - type + type: object + type: array + contract: + description: Contract will contain the core provider contract that + the provider is abiding by, like e.g. v1alpha4. + type: string + installedVersion: + description: InstalledVersion is the version of the provider that + is installed. + type: string + observedGeneration: + description: ObservedGeneration is the latest generation observed + by the controller. + format: int64 + type: integer + type: object + type: object + served: true + storage: false + subresources: + status: {} + - additionalPrinterColumns: + - jsonPath: .status.installedVersion + name: InstalledVersion + type: string + - jsonPath: .status.conditions[?(@.type=='Ready')].status + name: Ready + type: string + name: v1alpha2 + schema: + openAPIV3Schema: + description: BootstrapProvider is the Schema for the bootstrapproviders 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: BootstrapProviderSpec defines the desired state of BootstrapProvider. + properties: + additionalManifests: + description: AdditionalManifests is reference to configmap that contains + additional manifests that will be applied together with the provider + components. The key for storing these manifests has to be `manifests`. + The manifests are applied only once when a certain release is installed/upgraded. + If namespace is not specified, the namespace of the provider will + be used. There is no validation of the yaml content inside the configmap. + properties: + name: + description: Name defines the name of the configmap. + type: string + namespace: + description: Namespace defines the namespace of the configmap. + type: string + required: + - name + type: object + configSecret: + description: ConfigSecret is the object with name and namespace of + the Secret providing the configuration variables for the current + provider instance, like e.g. credentials. Such configurations will + be used when creating or upgrading provider components. The contents + of the secret will be treated as immutable. If changes need to be + made, a new object can be created and the name should be updated. + The contents should be in the form of key:value. This secret must + be in the same namespace as the provider. + properties: + name: + description: Name defines the name of the secret. + type: string + namespace: + description: Namespace defines the namespace of the secret. + type: string + required: + - name + type: object + deployment: + description: Deployment defines the properties that can be enabled + on the deployment for the provider. + properties: + affinity: + description: If specified, the pod's scheduling constraints + properties: + nodeAffinity: + description: Describes node affinity scheduling rules for + the pod. + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods + to nodes that satisfy the affinity expressions specified + by this field, but it may choose a node that violates + one or more of the expressions. The node that is most + preferred is the one with the greatest sum of weights, + i.e. for each node that meets all of the scheduling + requirements (resource request, requiredDuringScheduling + affinity expressions, etc.), compute a sum by iterating + through the elements of this field and adding "weight" + to the sum if the node matches the corresponding matchExpressions; + the node(s) with the highest sum are the most preferred. + items: + description: An empty preferred scheduling term matches + all objects with implicit weight 0 (i.e. it's a no-op). + A null preferred scheduling term matches no objects + (i.e. is also a no-op). + properties: + preference: + description: A node selector term, associated with + the corresponding weight. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: 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. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: 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. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + x-kubernetes-map-type: atomic + weight: + description: Weight associated with matching the + corresponding nodeSelectorTerm, in the range 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by + this field are not met at scheduling time, the pod will + not be scheduled onto the node. If the affinity requirements + specified by this field cease to be met at some point + during pod execution (e.g. due to an update), the system + may or may not try to eventually evict the pod from + its node. + properties: + nodeSelectorTerms: + description: Required. A list of node selector terms. + The terms are ORed. + items: + description: A null or empty node selector term + matches no objects. The requirements of them are + ANDed. The TopologySelectorTerm type implements + a subset of the NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: 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. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: 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. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + x-kubernetes-map-type: atomic + type: array + required: + - nodeSelectorTerms + type: object + x-kubernetes-map-type: atomic + type: object + podAffinity: + description: Describes pod affinity scheduling rules (e.g. + co-locate this pod in the same node, zone, etc. as some + other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods + to nodes that satisfy the affinity expressions specified + by this field, but it may choose a node that violates + one or more of the expressions. The node that is most + preferred is the one with the greatest sum of weights, + i.e. for each node that meets all of the scheduling + requirements (resource request, requiredDuringScheduling + affinity expressions, etc.), compute a sum by iterating + through the elements of this field and adding "weight" + to the sum if the node has pods which matches the corresponding + podAffinityTerm; the node(s) with the highest sum are + the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by + this field and the ones listed in the namespaces + field. null selector and null or empty namespaces + list means "this pod's namespace". An empty + selector ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. + The term is applied to the union of the namespaces + listed in this field and the ones selected + by namespaceSelector. null or empty namespaces + list and null namespaceSelector means "this + pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the + pods matching the labelSelector in the specified + namespaces, where co-located is defined as + running on a node whose value of the label + with key topologyKey matches that of any node + on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching the + corresponding podAffinityTerm, in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by + this field are not met at scheduling time, the pod will + not be scheduled onto the node. If the affinity requirements + specified by this field cease to be met at some point + during pod execution (e.g. due to a pod label update), + the system may or may not try to eventually evict the + pod from its node. When there are multiple elements, + the lists of nodes corresponding to each podAffinityTerm + are intersected, i.e. all terms must be satisfied. + items: + description: Defines a set of pods (namely those matching + the labelSelector relative to the given namespace(s)) + that this pod should be co-located (affinity) or not + co-located (anti-affinity) with, where co-located + is defined as running on a node whose value of the + label with key matches that of any node + on which a pod of the set of pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by this + field and the ones listed in the namespaces field. + null selector and null or empty namespaces list + means "this pod's namespace". An empty selector + ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. The + term is applied to the union of the namespaces + listed in this field and the ones selected by + namespaceSelector. null or empty namespaces list + and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods + matching the labelSelector in the specified namespaces, + where co-located is defined as running on a node + whose value of the label with key topologyKey + matches that of any node on which any of the selected + pods is running. Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + podAntiAffinity: + description: Describes pod anti-affinity scheduling rules + (e.g. avoid putting this pod in the same node, zone, etc. + as some other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods + to nodes that satisfy the anti-affinity expressions + specified by this field, but it may choose a node that + violates one or more of the expressions. The node that + is most preferred is the one with the greatest sum of + weights, i.e. for each node that meets all of the scheduling + requirements (resource request, requiredDuringScheduling + anti-affinity expressions, etc.), compute a sum by iterating + through the elements of this field and adding "weight" + to the sum if the node has pods which matches the corresponding + podAffinityTerm; the node(s) with the highest sum are + the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by + this field and the ones listed in the namespaces + field. null selector and null or empty namespaces + list means "this pod's namespace". An empty + selector ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. + The term is applied to the union of the namespaces + listed in this field and the ones selected + by namespaceSelector. null or empty namespaces + list and null namespaceSelector means "this + pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the + pods matching the labelSelector in the specified + namespaces, where co-located is defined as + running on a node whose value of the label + with key topologyKey matches that of any node + on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching the + corresponding podAffinityTerm, in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the anti-affinity requirements specified + by this field are not met at scheduling time, the pod + will not be scheduled onto the node. If the anti-affinity + requirements specified by this field cease to be met + at some point during pod execution (e.g. due to a pod + label update), the system may or may not try to eventually + evict the pod from its node. When there are multiple + elements, the lists of nodes corresponding to each podAffinityTerm + are intersected, i.e. all terms must be satisfied. + items: + description: Defines a set of pods (namely those matching + the labelSelector relative to the given namespace(s)) + that this pod should be co-located (affinity) or not + co-located (anti-affinity) with, where co-located + is defined as running on a node whose value of the + label with key matches that of any node + on which a pod of the set of pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by this + field and the ones listed in the namespaces field. + null selector and null or empty namespaces list + means "this pod's namespace". An empty selector + ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. The + term is applied to the union of the namespaces + listed in this field and the ones selected by + namespaceSelector. null or empty namespaces list + and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods + matching the labelSelector in the specified namespaces, + where co-located is defined as running on a node + whose value of the label with key topologyKey + matches that of any node on which any of the selected + pods is running. Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + type: object + containers: + description: List of containers specified in the Deployment + items: + description: ContainerSpec defines the properties available + to override for each container in a provider deployment such + as Image and Args to the container’s entrypoint. + properties: + args: + additionalProperties: + type: string + description: Args represents extra provider specific flags + that are not encoded as fields in this API. Explicit controller + manager properties defined in the `Provider.ManagerSpec` + will have higher precedence than those defined in `ContainerSpec.Args`. + For example, `ManagerSpec.SyncPeriod` will be used instead + of the container arg `--sync-period` if both are defined. + The same holds for `ManagerSpec.FeatureGates` and `--feature-gates`. + type: object + command: + description: Command allows override container's entrypoint + array. + items: + type: string + type: array + env: + description: List of environment variables to set in the + container. + 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: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + 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: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + 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 + imageUrl: + description: Container Image URL + type: string + name: + description: Name of the container. Cannot be updated. + type: string + resources: + description: Compute resources required by this container. + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. \n 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 + 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 + required: + - name + type: object + type: array + imagePullSecrets: + description: List of image pull secrets specified in the Deployment + items: + description: LocalObjectReference contains enough information + to let you locate the referenced object inside the same namespace. + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + x-kubernetes-map-type: atomic + type: array + nodeSelector: + additionalProperties: + type: string + description: 'NodeSelector is a selector which must be true for + the pod to fit on a node. Selector which must match a node''s + labels for the pod to be scheduled on that node. More info: + https://kubernetes.io/docs/concepts/configuration/assign-pod-node/' + type: object + replicas: + description: Number of desired pods. This is a pointer to distinguish + between explicit zero and not specified. Defaults to 1. + minimum: 0 + type: integer + serviceAccountName: + description: If specified, the pod's service account + type: string + tolerations: + description: If specified, the pod's tolerations. + 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 + type: object + fetchConfig: + description: FetchConfig determines how the operator will fetch the + components and metadata for the provider. If nil, the operator will + try to fetch components according to default embedded fetch configuration + for the given kind and `ObjectMeta.Name`. For example, the infrastructure + name `aws` will fetch artifacts from https://github.com/kubernetes-sigs/cluster-api-provider-aws/releases. + properties: + selector: + description: 'Selector to be used for fetching provider’s components + and metadata from ConfigMaps stored inside the cluster. Each + ConfigMap is expected to contain components and metadata for + a specific version only. Note: the name of the ConfigMap should + be set to the version or to override this add a label like the + following: provider.cluster.x-k8s.io/version=v1.4.3' + 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 + required: + - key + - operator + type: object + type: array + 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 + url: + description: URL to be used for fetching the provider’s components + and metadata from a remote Github repository. For example, https://github.com/{owner}/{repository}/releases + You must set `providerSpec.Version` field for operator to pick + up desired version of the release from GitHub. + type: string + type: object + manager: + description: Manager defines the properties that can be enabled on + the controller manager for the provider. + properties: + cacheNamespace: + description: "CacheNamespace if specified restricts the manager's + cache to watch objects in the desired namespace Defaults to + all namespaces \n Note: If a namespace is specified, controllers + can still Watch for a cluster-scoped resource (e.g Node). For + namespaced resources the cache will only hold objects from the + desired namespace." + type: string + controller: + description: Controller contains global configuration options + for controllers registered within this manager. + properties: + cacheSyncTimeout: + description: CacheSyncTimeout refers to the time limit set + to wait for syncing caches. Defaults to 2 minutes if not + set. + format: int64 + type: integer + groupKindConcurrency: + additionalProperties: + type: integer + description: "GroupKindConcurrency is a map from a Kind to + the number of concurrent reconciliation allowed for that + controller. \n When a controller is registered within this + manager using the builder utilities, users have to specify + the type the controller reconciles in the For(...) call. + If the object's kind passed matches one of the keys in this + map, the concurrency for that controller is set to the number + specified. \n The key is expected to be consistent in form + with GroupKind.String(), e.g. ReplicaSet in apps group (regardless + of version) would be `ReplicaSet.apps`." + type: object + recoverPanic: + description: RecoverPanic indicates if panics should be recovered. + type: boolean + type: object + featureGates: + additionalProperties: + type: boolean + description: FeatureGates define provider specific feature flags + that will be passed in as container args to the provider's controller + manager. Controller Manager flag is --feature-gates. + type: object + gracefulShutDown: + description: GracefulShutdownTimeout is the duration given to + runnable to stop before the manager actually returns on stop. + To disable graceful shutdown, set to time.Duration(0) To use + graceful shutdown without timeout, set to a negative duration, + e.G. time.Duration(-1) The graceful shutdown is skipped for + safety reasons in case the leader election lease is lost. + type: string + health: + description: Health contains the controller health configuration + properties: + healthProbeBindAddress: + description: HealthProbeBindAddress is the TCP address that + the controller should bind to for serving health probes + It can be set to "0" or "" to disable serving the health + probe. + type: string + livenessEndpointName: + description: LivenessEndpointName, defaults to "healthz" + type: string + readinessEndpointName: + description: ReadinessEndpointName, defaults to "readyz" + type: string + type: object + leaderElection: + description: LeaderElection is the LeaderElection config to be + used when configuring the manager.Manager leader election + properties: + leaderElect: + description: leaderElect enables a leader election client + to gain leadership before executing the main loop. Enable + this when running replicated components for high availability. + type: boolean + leaseDuration: + description: leaseDuration is the duration that non-leader + candidates will wait after observing a leadership renewal + until attempting to acquire leadership of a led but unrenewed + leader slot. This is effectively the maximum duration that + a leader can be stopped before it is replaced by another + candidate. This is only applicable if leader election is + enabled. + type: string + renewDeadline: + description: renewDeadline is the interval between attempts + by the acting master to renew a leadership slot before it + stops leading. This must be less than or equal to the lease + duration. This is only applicable if leader election is + enabled. + type: string + resourceLock: + description: resourceLock indicates the resource object type + that will be used to lock during leader election cycles. + type: string + resourceName: + description: resourceName indicates the name of resource object + that will be used to lock during leader election cycles. + type: string + resourceNamespace: + description: resourceName indicates the namespace of resource + object that will be used to lock during leader election + cycles. + type: string + retryPeriod: + description: retryPeriod is the duration the clients should + wait between attempting acquisition and renewal of a leadership. + This is only applicable if leader election is enabled. + type: string + required: + - leaderElect + - leaseDuration + - renewDeadline + - resourceLock + - resourceName + - resourceNamespace + - retryPeriod + type: object + maxConcurrentReconciles: + description: MaxConcurrentReconciles is the maximum number of + concurrent Reconciles which can be run. + minimum: 1 + type: integer + metrics: + description: Metrics contains thw controller metrics configuration + properties: + bindAddress: + description: BindAddress is the TCP address that the controller + should bind to for serving prometheus metrics. It can be + set to "0" to disable the metrics serving. + type: string + type: object + profilerAddress: + description: ProfilerAddress defines the bind address to expose + the pprof profiler (e.g. localhost:6060). Default empty, meaning + the profiler is disabled. Controller Manager flag is --profiler-address. + type: string + syncPeriod: + description: SyncPeriod determines the minimum frequency at which + watched resources are reconciled. A lower period will correct + entropy more quickly, but reduce responsiveness to change if + there are many watched resources. Change this value only if + you know what you are doing. Defaults to 10 hours if unset. + there will a 10 percent jitter between the SyncPeriod of all + controllers so that all controllers will not send list requests + simultaneously. + type: string + verbosity: + default: 1 + description: Verbosity set the logs verbosity. Defaults to 1. + Controller Manager flag is --verbosity. + minimum: 0 + type: integer + webhook: + description: Webhook contains the controllers webhook configuration + properties: + certDir: + description: CertDir is the directory that contains the server + key and certificate. if not set, webhook server would look + up the server key and certificate in {TempDir}/k8s-webhook-server/serving-certs. + The server key and certificate must be named tls.key and + tls.crt, respectively. + type: string + host: + description: Host is the hostname that the webhook server + binds to. It is used to set webhook.Server.Host. + type: string + port: + description: Port is the port that the webhook server serves + at. It is used to set webhook.Server.Port. + type: integer + type: object + type: object + manifestPatches: + description: ManifestPatches are applied to rendered provider manifests + to customize the provider manifests. Patches are applied in the + order they are specified. The `kind` field must match the target + object, and if `apiVersion` is specified it will only be applied + to matching objects. This should be an inline yaml blob-string https://datatracker.ietf.org/doc/html/rfc7396 + items: + type: string + type: array + version: + description: Version indicates the provider version. + type: string + type: object + status: + description: BootstrapProviderStatus defines the observed state of BootstrapProvider. + properties: + conditions: + description: Conditions define the current service state of the provider. + items: + description: Condition defines an observation of a Cluster API resource + operational state. + properties: + lastTransitionTime: + description: 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: A human readable message indicating details about + the transition. This field may be empty. + type: string + reason: + description: The reason for the condition's last transition + in CamelCase. The specific API may choose whether or not this + field is considered a guaranteed API. This field may not be + empty. + type: string + severity: + description: Severity provides an explicit classification of + Reason code, so the users or machines can immediately understand + the current situation and act accordingly. The Severity field + MUST be set only when Status=False. + type: string + status: + description: Status of the condition, one of 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. + type: string + required: + - lastTransitionTime + - status + - type + type: object + type: array + contract: + description: Contract will contain the core provider contract that + the provider is abiding by, like e.g. v1alpha4. + type: string + installedVersion: + description: InstalledVersion is the version of the provider that + is installed. + type: string + observedGeneration: + description: ObservedGeneration is the latest generation observed + by the controller. + format: int64 + type: integer + type: object + type: object + served: true + storage: true + subresources: + status: {} +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + cert-manager.io/inject-ca-from: '{{ .Release.Namespace }}/capi-operator-serving-cert' + controller-gen.kubebuilder.io/version: v0.11.4 + labels: + clusterctl.cluster.x-k8s.io/core: capi-operator + name: controlplaneproviders.operator.cluster.x-k8s.io +spec: + conversion: + strategy: Webhook + webhook: + clientConfig: + caBundle: Cg== + service: + name: capi-operator-webhook-service + namespace: '{{ .Release.Namespace }}' + path: /convert + conversionReviewVersions: + - v1 + - v1alpha1 + group: operator.cluster.x-k8s.io + names: + kind: ControlPlaneProvider + listKind: ControlPlaneProviderList + plural: controlplaneproviders + singular: controlplaneprovider + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .status.installedVersion + name: InstalledVersion + type: string + - jsonPath: .status.conditions[?(@.type=='Ready')].status + name: Ready + type: string + name: v1alpha1 + schema: + openAPIV3Schema: + description: ControlPlaneProvider is the Schema for the controlplaneproviders + 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: ControlPlaneProviderSpec defines the desired state of ControlPlaneProvider. + properties: + additionalManifests: + description: AdditionalManifests is reference to configmap that contains + additional manifests that will be applied together with the provider + components. The key for storing these manifests has to be `manifests`. + The manifests are applied only once when a certain release is installed/upgraded. + If namespace is not specified, the namespace of the provider will + be used. There is no validation of the yaml content inside the configmap. + properties: + name: + description: Name defines the name of the configmap. + type: string + namespace: + description: Namespace defines the namespace of the configmap. + type: string + required: + - name + type: object + deployment: + description: Deployment defines the properties that can be enabled + on the deployment for the provider. + properties: + affinity: + description: If specified, the pod's scheduling constraints + properties: + nodeAffinity: + description: Describes node affinity scheduling rules for + the pod. + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods + to nodes that satisfy the affinity expressions specified + by this field, but it may choose a node that violates + one or more of the expressions. The node that is most + preferred is the one with the greatest sum of weights, + i.e. for each node that meets all of the scheduling + requirements (resource request, requiredDuringScheduling + affinity expressions, etc.), compute a sum by iterating + through the elements of this field and adding "weight" + to the sum if the node matches the corresponding matchExpressions; + the node(s) with the highest sum are the most preferred. + items: + description: An empty preferred scheduling term matches + all objects with implicit weight 0 (i.e. it's a no-op). + A null preferred scheduling term matches no objects + (i.e. is also a no-op). + properties: + preference: + description: A node selector term, associated with + the corresponding weight. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: 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. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: 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. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + x-kubernetes-map-type: atomic + weight: + description: Weight associated with matching the + corresponding nodeSelectorTerm, in the range 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by + this field are not met at scheduling time, the pod will + not be scheduled onto the node. If the affinity requirements + specified by this field cease to be met at some point + during pod execution (e.g. due to an update), the system + may or may not try to eventually evict the pod from + its node. + properties: + nodeSelectorTerms: + description: Required. A list of node selector terms. + The terms are ORed. + items: + description: A null or empty node selector term + matches no objects. The requirements of them are + ANDed. The TopologySelectorTerm type implements + a subset of the NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: 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. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: 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. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + x-kubernetes-map-type: atomic + type: array + required: + - nodeSelectorTerms + type: object + x-kubernetes-map-type: atomic + type: object + podAffinity: + description: Describes pod affinity scheduling rules (e.g. + co-locate this pod in the same node, zone, etc. as some + other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods + to nodes that satisfy the affinity expressions specified + by this field, but it may choose a node that violates + one or more of the expressions. The node that is most + preferred is the one with the greatest sum of weights, + i.e. for each node that meets all of the scheduling + requirements (resource request, requiredDuringScheduling + affinity expressions, etc.), compute a sum by iterating + through the elements of this field and adding "weight" + to the sum if the node has pods which matches the corresponding + podAffinityTerm; the node(s) with the highest sum are + the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by + this field and the ones listed in the namespaces + field. null selector and null or empty namespaces + list means "this pod's namespace". An empty + selector ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. + The term is applied to the union of the namespaces + listed in this field and the ones selected + by namespaceSelector. null or empty namespaces + list and null namespaceSelector means "this + pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the + pods matching the labelSelector in the specified + namespaces, where co-located is defined as + running on a node whose value of the label + with key topologyKey matches that of any node + on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching the + corresponding podAffinityTerm, in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by + this field are not met at scheduling time, the pod will + not be scheduled onto the node. If the affinity requirements + specified by this field cease to be met at some point + during pod execution (e.g. due to a pod label update), + the system may or may not try to eventually evict the + pod from its node. When there are multiple elements, + the lists of nodes corresponding to each podAffinityTerm + are intersected, i.e. all terms must be satisfied. + items: + description: Defines a set of pods (namely those matching + the labelSelector relative to the given namespace(s)) + that this pod should be co-located (affinity) or not + co-located (anti-affinity) with, where co-located + is defined as running on a node whose value of the + label with key matches that of any node + on which a pod of the set of pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by this + field and the ones listed in the namespaces field. + null selector and null or empty namespaces list + means "this pod's namespace". An empty selector + ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. The + term is applied to the union of the namespaces + listed in this field and the ones selected by + namespaceSelector. null or empty namespaces list + and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods + matching the labelSelector in the specified namespaces, + where co-located is defined as running on a node + whose value of the label with key topologyKey + matches that of any node on which any of the selected + pods is running. Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + podAntiAffinity: + description: Describes pod anti-affinity scheduling rules + (e.g. avoid putting this pod in the same node, zone, etc. + as some other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods + to nodes that satisfy the anti-affinity expressions + specified by this field, but it may choose a node that + violates one or more of the expressions. The node that + is most preferred is the one with the greatest sum of + weights, i.e. for each node that meets all of the scheduling + requirements (resource request, requiredDuringScheduling + anti-affinity expressions, etc.), compute a sum by iterating + through the elements of this field and adding "weight" + to the sum if the node has pods which matches the corresponding + podAffinityTerm; the node(s) with the highest sum are + the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by + this field and the ones listed in the namespaces + field. null selector and null or empty namespaces + list means "this pod's namespace". An empty + selector ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. + The term is applied to the union of the namespaces + listed in this field and the ones selected + by namespaceSelector. null or empty namespaces + list and null namespaceSelector means "this + pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the + pods matching the labelSelector in the specified + namespaces, where co-located is defined as + running on a node whose value of the label + with key topologyKey matches that of any node + on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching the + corresponding podAffinityTerm, in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the anti-affinity requirements specified + by this field are not met at scheduling time, the pod + will not be scheduled onto the node. If the anti-affinity + requirements specified by this field cease to be met + at some point during pod execution (e.g. due to a pod + label update), the system may or may not try to eventually + evict the pod from its node. When there are multiple + elements, the lists of nodes corresponding to each podAffinityTerm + are intersected, i.e. all terms must be satisfied. + items: + description: Defines a set of pods (namely those matching + the labelSelector relative to the given namespace(s)) + that this pod should be co-located (affinity) or not + co-located (anti-affinity) with, where co-located + is defined as running on a node whose value of the + label with key matches that of any node + on which a pod of the set of pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by this + field and the ones listed in the namespaces field. + null selector and null or empty namespaces list + means "this pod's namespace". An empty selector + ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. The + term is applied to the union of the namespaces + listed in this field and the ones selected by + namespaceSelector. null or empty namespaces list + and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods + matching the labelSelector in the specified namespaces, + where co-located is defined as running on a node + whose value of the label with key topologyKey + matches that of any node on which any of the selected + pods is running. Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + type: object + containers: + description: List of containers specified in the Deployment + items: + description: ContainerSpec defines the properties available + to override for each container in a provider deployment such + as Image and Args to the container’s entrypoint. + properties: + args: + additionalProperties: + type: string + description: Args represents extra provider specific flags + that are not encoded as fields in this API. Explicit controller + manager properties defined in the `Provider.ManagerSpec` + will have higher precedence than those defined in `ContainerSpec.Args`. + For example, `ManagerSpec.SyncPeriod` will be used instead + of the container arg `--sync-period` if both are defined. + The same holds for `ManagerSpec.FeatureGates` and `--feature-gates`. + type: object + command: + description: Command allows override container's entrypoint + array. + items: + type: string + type: array + env: + description: List of environment variables to set in the + container. + 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: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + 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: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + 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: Container Image Name + properties: + name: + description: Name allows to specify a name for the image. + type: string + repository: + description: Repository sets the container registry + to pull images from. + type: string + tag: + description: Tag allows to specify a tag for the image. + type: string + type: object + name: + description: Name of the container. Cannot be updated. + type: string + resources: + description: Compute resources required by this container. + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. \n 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 + 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 + required: + - name + type: object + type: array + imagePullSecrets: + description: List of image pull secrets specified in the Deployment + items: + description: LocalObjectReference contains enough information + to let you locate the referenced object inside the same namespace. + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + x-kubernetes-map-type: atomic + type: array + nodeSelector: + additionalProperties: + type: string + description: 'NodeSelector is a selector which must be true for + the pod to fit on a node. Selector which must match a node''s + labels for the pod to be scheduled on that node. More info: + https://kubernetes.io/docs/concepts/configuration/assign-pod-node/' + type: object + replicas: + description: Number of desired pods. This is a pointer to distinguish + between explicit zero and not specified. Defaults to 1. + minimum: 0 + type: integer + serviceAccountName: + description: If specified, the pod's service account + type: string + tolerations: + description: If specified, the pod's tolerations. + 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 + type: object + fetchConfig: + description: FetchConfig determines how the operator will fetch the + components and metadata for the provider. If nil, the operator will + try to fetch components according to default embedded fetch configuration + for the given kind and `ObjectMeta.Name`. For example, the infrastructure + name `aws` will fetch artifacts from https://github.com/kubernetes-sigs/cluster-api-provider-aws/releases. + properties: + selector: + description: 'Selector to be used for fetching provider’s components + and metadata from ConfigMaps stored inside the cluster. Each + ConfigMap is expected to contain components and metadata for + a specific version only. Note: the name of the ConfigMap should + be set to the version or to override this add a label like the + following: provider.cluster.x-k8s.io/version=v1.4.3' + 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 + required: + - key + - operator + type: object + type: array + 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 + url: + description: URL to be used for fetching the provider’s components + and metadata from a remote Github repository. For example, https://github.com/{owner}/{repository}/releases + You must set `providerSpec.Version` field for operator to pick + up desired version of the release from GitHub. + type: string + type: object + manager: + description: Manager defines the properties that can be enabled on + the controller manager for the provider. + properties: + cacheNamespace: + description: "CacheNamespace if specified restricts the manager's + cache to watch objects in the desired namespace Defaults to + all namespaces \n Note: If a namespace is specified, controllers + can still Watch for a cluster-scoped resource (e.g Node). For + namespaced resources the cache will only hold objects from the + desired namespace." + type: string + controller: + description: Controller contains global configuration options + for controllers registered within this manager. + properties: + cacheSyncTimeout: + description: CacheSyncTimeout refers to the time limit set + to wait for syncing caches. Defaults to 2 minutes if not + set. + format: int64 + type: integer + groupKindConcurrency: + additionalProperties: + type: integer + description: "GroupKindConcurrency is a map from a Kind to + the number of concurrent reconciliation allowed for that + controller. \n When a controller is registered within this + manager using the builder utilities, users have to specify + the type the controller reconciles in the For(...) call. + If the object's kind passed matches one of the keys in this + map, the concurrency for that controller is set to the number + specified. \n The key is expected to be consistent in form + with GroupKind.String(), e.g. ReplicaSet in apps group (regardless + of version) would be `ReplicaSet.apps`." + type: object + recoverPanic: + description: RecoverPanic indicates if panics should be recovered. + type: boolean + type: object + featureGates: + additionalProperties: + type: boolean + description: FeatureGates define provider specific feature flags + that will be passed in as container args to the provider's controller + manager. Controller Manager flag is --feature-gates. + type: object + gracefulShutDown: + description: GracefulShutdownTimeout is the duration given to + runnable to stop before the manager actually returns on stop. + To disable graceful shutdown, set to time.Duration(0) To use + graceful shutdown without timeout, set to a negative duration, + e.G. time.Duration(-1) The graceful shutdown is skipped for + safety reasons in case the leader election lease is lost. + type: string + health: + description: Health contains the controller health configuration + properties: + healthProbeBindAddress: + description: HealthProbeBindAddress is the TCP address that + the controller should bind to for serving health probes + It can be set to "0" or "" to disable serving the health + probe. + type: string + livenessEndpointName: + description: LivenessEndpointName, defaults to "healthz" + type: string + readinessEndpointName: + description: ReadinessEndpointName, defaults to "readyz" + type: string + type: object + leaderElection: + description: LeaderElection is the LeaderElection config to be + used when configuring the manager.Manager leader election + properties: + leaderElect: + description: leaderElect enables a leader election client + to gain leadership before executing the main loop. Enable + this when running replicated components for high availability. + type: boolean + leaseDuration: + description: leaseDuration is the duration that non-leader + candidates will wait after observing a leadership renewal + until attempting to acquire leadership of a led but unrenewed + leader slot. This is effectively the maximum duration that + a leader can be stopped before it is replaced by another + candidate. This is only applicable if leader election is + enabled. + type: string + renewDeadline: + description: renewDeadline is the interval between attempts + by the acting master to renew a leadership slot before it + stops leading. This must be less than or equal to the lease + duration. This is only applicable if leader election is + enabled. + type: string + resourceLock: + description: resourceLock indicates the resource object type + that will be used to lock during leader election cycles. + type: string + resourceName: + description: resourceName indicates the name of resource object + that will be used to lock during leader election cycles. + type: string + resourceNamespace: + description: resourceName indicates the namespace of resource + object that will be used to lock during leader election + cycles. + type: string + retryPeriod: + description: retryPeriod is the duration the clients should + wait between attempting acquisition and renewal of a leadership. + This is only applicable if leader election is enabled. + type: string + required: + - leaderElect + - leaseDuration + - renewDeadline + - resourceLock + - resourceName + - resourceNamespace + - retryPeriod + type: object + maxConcurrentReconciles: + description: MaxConcurrentReconciles is the maximum number of + concurrent Reconciles which can be run. + minimum: 1 + type: integer + metrics: + description: Metrics contains the controller metrics configuration + properties: + bindAddress: + description: BindAddress is the TCP address that the controller + should bind to for serving prometheus metrics. It can be + set to "0" to disable the metrics serving. + type: string + type: object + profilerAddress: + description: ProfilerAddress defines the bind address to expose + the pprof profiler (e.g. localhost:6060). Default empty, meaning + the profiler is disabled. Controller Manager flag is --profiler-address. + type: string + syncPeriod: + description: SyncPeriod determines the minimum frequency at which + watched resources are reconciled. A lower period will correct + entropy more quickly, but reduce responsiveness to change if + there are many watched resources. Change this value only if + you know what you are doing. Defaults to 10 hours if unset. + there will a 10 percent jitter between the SyncPeriod of all + controllers so that all controllers will not send list requests + simultaneously. + type: string + verbosity: + default: 1 + description: Verbosity set the logs verbosity. Defaults to 1. + Controller Manager flag is --verbosity. + minimum: 0 + type: integer + webhook: + description: Webhook contains the controllers webhook configuration + properties: + certDir: + description: CertDir is the directory that contains the server + key and certificate. if not set, webhook server would look + up the server key and certificate in {TempDir}/k8s-webhook-server/serving-certs. + The server key and certificate must be named tls.key and + tls.crt, respectively. + type: string + host: + description: Host is the hostname that the webhook server + binds to. It is used to set webhook.Server.Host. + type: string + port: + description: Port is the port that the webhook server serves + at. It is used to set webhook.Server.Port. + type: integer + type: object + type: object + secretName: + description: SecretName is the name of the Secret providing the configuration + variables for the current provider instance, like e.g. credentials. + Such configurations will be used when creating or upgrading provider + components. The contents of the secret will be treated as immutable. + If changes need to be made, a new object can be created and the + name should be updated. The contents should be in the form of key:value. + This secret must be in the same namespace as the provider. + type: string + secretNamespace: + description: SecretNamespace is the namespace of the Secret providing + the configuration variables. If not specified, the namespace of + the provider will be used. + type: string + version: + description: Version indicates the provider version. + type: string + type: object + status: + description: ControlPlaneProviderStatus defines the observed state of + ControlPlaneProvider. + properties: + conditions: + description: Conditions define the current service state of the provider. + items: + description: Condition defines an observation of a Cluster API resource + operational state. + properties: + lastTransitionTime: + description: 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: A human readable message indicating details about + the transition. This field may be empty. + type: string + reason: + description: The reason for the condition's last transition + in CamelCase. The specific API may choose whether or not this + field is considered a guaranteed API. This field may not be + empty. + type: string + severity: + description: Severity provides an explicit classification of + Reason code, so the users or machines can immediately understand + the current situation and act accordingly. The Severity field + MUST be set only when Status=False. + type: string + status: + description: Status of the condition, one of 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. + type: string + required: + - lastTransitionTime + - status + - type + type: object + type: array + contract: + description: Contract will contain the core provider contract that + the provider is abiding by, like e.g. v1alpha4. + type: string + installedVersion: + description: InstalledVersion is the version of the provider that + is installed. + type: string + observedGeneration: + description: ObservedGeneration is the latest generation observed + by the controller. + format: int64 + type: integer + type: object + type: object + served: true + storage: false + subresources: + status: {} + - additionalPrinterColumns: + - jsonPath: .status.installedVersion + name: InstalledVersion + type: string + - jsonPath: .status.conditions[?(@.type=='Ready')].status + name: Ready + type: string + name: v1alpha2 + schema: + openAPIV3Schema: + description: ControlPlaneProvider is the Schema for the controlplaneproviders + 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: ControlPlaneProviderSpec defines the desired state of ControlPlaneProvider. + properties: + additionalManifests: + description: AdditionalManifests is reference to configmap that contains + additional manifests that will be applied together with the provider + components. The key for storing these manifests has to be `manifests`. + The manifests are applied only once when a certain release is installed/upgraded. + If namespace is not specified, the namespace of the provider will + be used. There is no validation of the yaml content inside the configmap. + properties: + name: + description: Name defines the name of the configmap. + type: string + namespace: + description: Namespace defines the namespace of the configmap. + type: string + required: + - name + type: object + configSecret: + description: ConfigSecret is the object with name and namespace of + the Secret providing the configuration variables for the current + provider instance, like e.g. credentials. Such configurations will + be used when creating or upgrading provider components. The contents + of the secret will be treated as immutable. If changes need to be + made, a new object can be created and the name should be updated. + The contents should be in the form of key:value. This secret must + be in the same namespace as the provider. + properties: + name: + description: Name defines the name of the secret. + type: string + namespace: + description: Namespace defines the namespace of the secret. + type: string + required: + - name + type: object + deployment: + description: Deployment defines the properties that can be enabled + on the deployment for the provider. + properties: + affinity: + description: If specified, the pod's scheduling constraints + properties: + nodeAffinity: + description: Describes node affinity scheduling rules for + the pod. + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods + to nodes that satisfy the affinity expressions specified + by this field, but it may choose a node that violates + one or more of the expressions. The node that is most + preferred is the one with the greatest sum of weights, + i.e. for each node that meets all of the scheduling + requirements (resource request, requiredDuringScheduling + affinity expressions, etc.), compute a sum by iterating + through the elements of this field and adding "weight" + to the sum if the node matches the corresponding matchExpressions; + the node(s) with the highest sum are the most preferred. + items: + description: An empty preferred scheduling term matches + all objects with implicit weight 0 (i.e. it's a no-op). + A null preferred scheduling term matches no objects + (i.e. is also a no-op). + properties: + preference: + description: A node selector term, associated with + the corresponding weight. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: 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. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: 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. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + x-kubernetes-map-type: atomic + weight: + description: Weight associated with matching the + corresponding nodeSelectorTerm, in the range 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by + this field are not met at scheduling time, the pod will + not be scheduled onto the node. If the affinity requirements + specified by this field cease to be met at some point + during pod execution (e.g. due to an update), the system + may or may not try to eventually evict the pod from + its node. + properties: + nodeSelectorTerms: + description: Required. A list of node selector terms. + The terms are ORed. + items: + description: A null or empty node selector term + matches no objects. The requirements of them are + ANDed. The TopologySelectorTerm type implements + a subset of the NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: 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. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: 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. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + x-kubernetes-map-type: atomic + type: array + required: + - nodeSelectorTerms + type: object + x-kubernetes-map-type: atomic + type: object + podAffinity: + description: Describes pod affinity scheduling rules (e.g. + co-locate this pod in the same node, zone, etc. as some + other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods + to nodes that satisfy the affinity expressions specified + by this field, but it may choose a node that violates + one or more of the expressions. The node that is most + preferred is the one with the greatest sum of weights, + i.e. for each node that meets all of the scheduling + requirements (resource request, requiredDuringScheduling + affinity expressions, etc.), compute a sum by iterating + through the elements of this field and adding "weight" + to the sum if the node has pods which matches the corresponding + podAffinityTerm; the node(s) with the highest sum are + the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by + this field and the ones listed in the namespaces + field. null selector and null or empty namespaces + list means "this pod's namespace". An empty + selector ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. + The term is applied to the union of the namespaces + listed in this field and the ones selected + by namespaceSelector. null or empty namespaces + list and null namespaceSelector means "this + pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the + pods matching the labelSelector in the specified + namespaces, where co-located is defined as + running on a node whose value of the label + with key topologyKey matches that of any node + on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching the + corresponding podAffinityTerm, in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by + this field are not met at scheduling time, the pod will + not be scheduled onto the node. If the affinity requirements + specified by this field cease to be met at some point + during pod execution (e.g. due to a pod label update), + the system may or may not try to eventually evict the + pod from its node. When there are multiple elements, + the lists of nodes corresponding to each podAffinityTerm + are intersected, i.e. all terms must be satisfied. + items: + description: Defines a set of pods (namely those matching + the labelSelector relative to the given namespace(s)) + that this pod should be co-located (affinity) or not + co-located (anti-affinity) with, where co-located + is defined as running on a node whose value of the + label with key matches that of any node + on which a pod of the set of pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by this + field and the ones listed in the namespaces field. + null selector and null or empty namespaces list + means "this pod's namespace". An empty selector + ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. The + term is applied to the union of the namespaces + listed in this field and the ones selected by + namespaceSelector. null or empty namespaces list + and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods + matching the labelSelector in the specified namespaces, + where co-located is defined as running on a node + whose value of the label with key topologyKey + matches that of any node on which any of the selected + pods is running. Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + podAntiAffinity: + description: Describes pod anti-affinity scheduling rules + (e.g. avoid putting this pod in the same node, zone, etc. + as some other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods + to nodes that satisfy the anti-affinity expressions + specified by this field, but it may choose a node that + violates one or more of the expressions. The node that + is most preferred is the one with the greatest sum of + weights, i.e. for each node that meets all of the scheduling + requirements (resource request, requiredDuringScheduling + anti-affinity expressions, etc.), compute a sum by iterating + through the elements of this field and adding "weight" + to the sum if the node has pods which matches the corresponding + podAffinityTerm; the node(s) with the highest sum are + the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by + this field and the ones listed in the namespaces + field. null selector and null or empty namespaces + list means "this pod's namespace". An empty + selector ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. + The term is applied to the union of the namespaces + listed in this field and the ones selected + by namespaceSelector. null or empty namespaces + list and null namespaceSelector means "this + pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the + pods matching the labelSelector in the specified + namespaces, where co-located is defined as + running on a node whose value of the label + with key topologyKey matches that of any node + on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching the + corresponding podAffinityTerm, in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the anti-affinity requirements specified + by this field are not met at scheduling time, the pod + will not be scheduled onto the node. If the anti-affinity + requirements specified by this field cease to be met + at some point during pod execution (e.g. due to a pod + label update), the system may or may not try to eventually + evict the pod from its node. When there are multiple + elements, the lists of nodes corresponding to each podAffinityTerm + are intersected, i.e. all terms must be satisfied. + items: + description: Defines a set of pods (namely those matching + the labelSelector relative to the given namespace(s)) + that this pod should be co-located (affinity) or not + co-located (anti-affinity) with, where co-located + is defined as running on a node whose value of the + label with key matches that of any node + on which a pod of the set of pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by this + field and the ones listed in the namespaces field. + null selector and null or empty namespaces list + means "this pod's namespace". An empty selector + ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. The + term is applied to the union of the namespaces + listed in this field and the ones selected by + namespaceSelector. null or empty namespaces list + and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods + matching the labelSelector in the specified namespaces, + where co-located is defined as running on a node + whose value of the label with key topologyKey + matches that of any node on which any of the selected + pods is running. Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + type: object + containers: + description: List of containers specified in the Deployment + items: + description: ContainerSpec defines the properties available + to override for each container in a provider deployment such + as Image and Args to the container’s entrypoint. + properties: + args: + additionalProperties: + type: string + description: Args represents extra provider specific flags + that are not encoded as fields in this API. Explicit controller + manager properties defined in the `Provider.ManagerSpec` + will have higher precedence than those defined in `ContainerSpec.Args`. + For example, `ManagerSpec.SyncPeriod` will be used instead + of the container arg `--sync-period` if both are defined. + The same holds for `ManagerSpec.FeatureGates` and `--feature-gates`. + type: object + command: + description: Command allows override container's entrypoint + array. + items: + type: string + type: array + env: + description: List of environment variables to set in the + container. + 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: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + 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: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + 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 + imageUrl: + description: Container Image URL + type: string + name: + description: Name of the container. Cannot be updated. + type: string + resources: + description: Compute resources required by this container. + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. \n 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 + 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 + required: + - name + type: object + type: array + imagePullSecrets: + description: List of image pull secrets specified in the Deployment + items: + description: LocalObjectReference contains enough information + to let you locate the referenced object inside the same namespace. + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + x-kubernetes-map-type: atomic + type: array + nodeSelector: + additionalProperties: + type: string + description: 'NodeSelector is a selector which must be true for + the pod to fit on a node. Selector which must match a node''s + labels for the pod to be scheduled on that node. More info: + https://kubernetes.io/docs/concepts/configuration/assign-pod-node/' + type: object + replicas: + description: Number of desired pods. This is a pointer to distinguish + between explicit zero and not specified. Defaults to 1. + minimum: 0 + type: integer + serviceAccountName: + description: If specified, the pod's service account + type: string + tolerations: + description: If specified, the pod's tolerations. + 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 + type: object + fetchConfig: + description: FetchConfig determines how the operator will fetch the + components and metadata for the provider. If nil, the operator will + try to fetch components according to default embedded fetch configuration + for the given kind and `ObjectMeta.Name`. For example, the infrastructure + name `aws` will fetch artifacts from https://github.com/kubernetes-sigs/cluster-api-provider-aws/releases. + properties: + selector: + description: 'Selector to be used for fetching provider’s components + and metadata from ConfigMaps stored inside the cluster. Each + ConfigMap is expected to contain components and metadata for + a specific version only. Note: the name of the ConfigMap should + be set to the version or to override this add a label like the + following: provider.cluster.x-k8s.io/version=v1.4.3' + 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 + required: + - key + - operator + type: object + type: array + 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 + url: + description: URL to be used for fetching the provider’s components + and metadata from a remote Github repository. For example, https://github.com/{owner}/{repository}/releases + You must set `providerSpec.Version` field for operator to pick + up desired version of the release from GitHub. + type: string + type: object + manager: + description: Manager defines the properties that can be enabled on + the controller manager for the provider. + properties: + cacheNamespace: + description: "CacheNamespace if specified restricts the manager's + cache to watch objects in the desired namespace Defaults to + all namespaces \n Note: If a namespace is specified, controllers + can still Watch for a cluster-scoped resource (e.g Node). For + namespaced resources the cache will only hold objects from the + desired namespace." + type: string + controller: + description: Controller contains global configuration options + for controllers registered within this manager. + properties: + cacheSyncTimeout: + description: CacheSyncTimeout refers to the time limit set + to wait for syncing caches. Defaults to 2 minutes if not + set. + format: int64 + type: integer + groupKindConcurrency: + additionalProperties: + type: integer + description: "GroupKindConcurrency is a map from a Kind to + the number of concurrent reconciliation allowed for that + controller. \n When a controller is registered within this + manager using the builder utilities, users have to specify + the type the controller reconciles in the For(...) call. + If the object's kind passed matches one of the keys in this + map, the concurrency for that controller is set to the number + specified. \n The key is expected to be consistent in form + with GroupKind.String(), e.g. ReplicaSet in apps group (regardless + of version) would be `ReplicaSet.apps`." + type: object + recoverPanic: + description: RecoverPanic indicates if panics should be recovered. + type: boolean + type: object + featureGates: + additionalProperties: + type: boolean + description: FeatureGates define provider specific feature flags + that will be passed in as container args to the provider's controller + manager. Controller Manager flag is --feature-gates. + type: object + gracefulShutDown: + description: GracefulShutdownTimeout is the duration given to + runnable to stop before the manager actually returns on stop. + To disable graceful shutdown, set to time.Duration(0) To use + graceful shutdown without timeout, set to a negative duration, + e.G. time.Duration(-1) The graceful shutdown is skipped for + safety reasons in case the leader election lease is lost. + type: string + health: + description: Health contains the controller health configuration + properties: + healthProbeBindAddress: + description: HealthProbeBindAddress is the TCP address that + the controller should bind to for serving health probes + It can be set to "0" or "" to disable serving the health + probe. + type: string + livenessEndpointName: + description: LivenessEndpointName, defaults to "healthz" + type: string + readinessEndpointName: + description: ReadinessEndpointName, defaults to "readyz" + type: string + type: object + leaderElection: + description: LeaderElection is the LeaderElection config to be + used when configuring the manager.Manager leader election + properties: + leaderElect: + description: leaderElect enables a leader election client + to gain leadership before executing the main loop. Enable + this when running replicated components for high availability. + type: boolean + leaseDuration: + description: leaseDuration is the duration that non-leader + candidates will wait after observing a leadership renewal + until attempting to acquire leadership of a led but unrenewed + leader slot. This is effectively the maximum duration that + a leader can be stopped before it is replaced by another + candidate. This is only applicable if leader election is + enabled. + type: string + renewDeadline: + description: renewDeadline is the interval between attempts + by the acting master to renew a leadership slot before it + stops leading. This must be less than or equal to the lease + duration. This is only applicable if leader election is + enabled. + type: string + resourceLock: + description: resourceLock indicates the resource object type + that will be used to lock during leader election cycles. + type: string + resourceName: + description: resourceName indicates the name of resource object + that will be used to lock during leader election cycles. + type: string + resourceNamespace: + description: resourceName indicates the namespace of resource + object that will be used to lock during leader election + cycles. + type: string + retryPeriod: + description: retryPeriod is the duration the clients should + wait between attempting acquisition and renewal of a leadership. + This is only applicable if leader election is enabled. + type: string + required: + - leaderElect + - leaseDuration + - renewDeadline + - resourceLock + - resourceName + - resourceNamespace + - retryPeriod + type: object + maxConcurrentReconciles: + description: MaxConcurrentReconciles is the maximum number of + concurrent Reconciles which can be run. + minimum: 1 + type: integer + metrics: + description: Metrics contains thw controller metrics configuration + properties: + bindAddress: + description: BindAddress is the TCP address that the controller + should bind to for serving prometheus metrics. It can be + set to "0" to disable the metrics serving. + type: string + type: object + profilerAddress: + description: ProfilerAddress defines the bind address to expose + the pprof profiler (e.g. localhost:6060). Default empty, meaning + the profiler is disabled. Controller Manager flag is --profiler-address. + type: string + syncPeriod: + description: SyncPeriod determines the minimum frequency at which + watched resources are reconciled. A lower period will correct + entropy more quickly, but reduce responsiveness to change if + there are many watched resources. Change this value only if + you know what you are doing. Defaults to 10 hours if unset. + there will a 10 percent jitter between the SyncPeriod of all + controllers so that all controllers will not send list requests + simultaneously. + type: string + verbosity: + default: 1 + description: Verbosity set the logs verbosity. Defaults to 1. + Controller Manager flag is --verbosity. + minimum: 0 + type: integer + webhook: + description: Webhook contains the controllers webhook configuration + properties: + certDir: + description: CertDir is the directory that contains the server + key and certificate. if not set, webhook server would look + up the server key and certificate in {TempDir}/k8s-webhook-server/serving-certs. + The server key and certificate must be named tls.key and + tls.crt, respectively. + type: string + host: + description: Host is the hostname that the webhook server + binds to. It is used to set webhook.Server.Host. + type: string + port: + description: Port is the port that the webhook server serves + at. It is used to set webhook.Server.Port. + type: integer + type: object + type: object + manifestPatches: + description: ManifestPatches are applied to rendered provider manifests + to customize the provider manifests. Patches are applied in the + order they are specified. The `kind` field must match the target + object, and if `apiVersion` is specified it will only be applied + to matching objects. This should be an inline yaml blob-string https://datatracker.ietf.org/doc/html/rfc7396 + items: + type: string + type: array + version: + description: Version indicates the provider version. + type: string + type: object + status: + description: ControlPlaneProviderStatus defines the observed state of + ControlPlaneProvider. + properties: + conditions: + description: Conditions define the current service state of the provider. + items: + description: Condition defines an observation of a Cluster API resource + operational state. + properties: + lastTransitionTime: + description: 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: A human readable message indicating details about + the transition. This field may be empty. + type: string + reason: + description: The reason for the condition's last transition + in CamelCase. The specific API may choose whether or not this + field is considered a guaranteed API. This field may not be + empty. + type: string + severity: + description: Severity provides an explicit classification of + Reason code, so the users or machines can immediately understand + the current situation and act accordingly. The Severity field + MUST be set only when Status=False. + type: string + status: + description: Status of the condition, one of 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. + type: string + required: + - lastTransitionTime + - status + - type + type: object + type: array + contract: + description: Contract will contain the core provider contract that + the provider is abiding by, like e.g. v1alpha4. + type: string + installedVersion: + description: InstalledVersion is the version of the provider that + is installed. + type: string + observedGeneration: + description: ObservedGeneration is the latest generation observed + by the controller. + format: int64 + type: integer + type: object + type: object + served: true + storage: true + subresources: + status: {} +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + cert-manager.io/inject-ca-from: '{{ .Release.Namespace }}/capi-operator-serving-cert' + controller-gen.kubebuilder.io/version: v0.11.4 + labels: + clusterctl.cluster.x-k8s.io/core: capi-operator + name: coreproviders.operator.cluster.x-k8s.io +spec: + conversion: + strategy: Webhook + webhook: + clientConfig: + caBundle: Cg== + service: + name: capi-operator-webhook-service + namespace: '{{ .Release.Namespace }}' + path: /convert + conversionReviewVersions: + - v1 + - v1alpha1 + group: operator.cluster.x-k8s.io + names: + kind: CoreProvider + listKind: CoreProviderList + plural: coreproviders + singular: coreprovider + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .status.installedVersion + name: InstalledVersion + type: string + - jsonPath: .status.conditions[?(@.type=='Ready')].status + name: Ready + type: string + name: v1alpha1 + schema: + openAPIV3Schema: + description: CoreProvider is the Schema for the coreproviders 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: CoreProviderSpec defines the desired state of CoreProvider. + properties: + additionalManifests: + description: AdditionalManifests is reference to configmap that contains + additional manifests that will be applied together with the provider + components. The key for storing these manifests has to be `manifests`. + The manifests are applied only once when a certain release is installed/upgraded. + If namespace is not specified, the namespace of the provider will + be used. There is no validation of the yaml content inside the configmap. + properties: + name: + description: Name defines the name of the configmap. + type: string + namespace: + description: Namespace defines the namespace of the configmap. + type: string + required: + - name + type: object + deployment: + description: Deployment defines the properties that can be enabled + on the deployment for the provider. + properties: + affinity: + description: If specified, the pod's scheduling constraints + properties: + nodeAffinity: + description: Describes node affinity scheduling rules for + the pod. + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods + to nodes that satisfy the affinity expressions specified + by this field, but it may choose a node that violates + one or more of the expressions. The node that is most + preferred is the one with the greatest sum of weights, + i.e. for each node that meets all of the scheduling + requirements (resource request, requiredDuringScheduling + affinity expressions, etc.), compute a sum by iterating + through the elements of this field and adding "weight" + to the sum if the node matches the corresponding matchExpressions; + the node(s) with the highest sum are the most preferred. + items: + description: An empty preferred scheduling term matches + all objects with implicit weight 0 (i.e. it's a no-op). + A null preferred scheduling term matches no objects + (i.e. is also a no-op). + properties: + preference: + description: A node selector term, associated with + the corresponding weight. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: 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. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: 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. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + x-kubernetes-map-type: atomic + weight: + description: Weight associated with matching the + corresponding nodeSelectorTerm, in the range 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by + this field are not met at scheduling time, the pod will + not be scheduled onto the node. If the affinity requirements + specified by this field cease to be met at some point + during pod execution (e.g. due to an update), the system + may or may not try to eventually evict the pod from + its node. + properties: + nodeSelectorTerms: + description: Required. A list of node selector terms. + The terms are ORed. + items: + description: A null or empty node selector term + matches no objects. The requirements of them are + ANDed. The TopologySelectorTerm type implements + a subset of the NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: 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. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: 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. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + x-kubernetes-map-type: atomic + type: array + required: + - nodeSelectorTerms + type: object + x-kubernetes-map-type: atomic + type: object + podAffinity: + description: Describes pod affinity scheduling rules (e.g. + co-locate this pod in the same node, zone, etc. as some + other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods + to nodes that satisfy the affinity expressions specified + by this field, but it may choose a node that violates + one or more of the expressions. The node that is most + preferred is the one with the greatest sum of weights, + i.e. for each node that meets all of the scheduling + requirements (resource request, requiredDuringScheduling + affinity expressions, etc.), compute a sum by iterating + through the elements of this field and adding "weight" + to the sum if the node has pods which matches the corresponding + podAffinityTerm; the node(s) with the highest sum are + the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by + this field and the ones listed in the namespaces + field. null selector and null or empty namespaces + list means "this pod's namespace". An empty + selector ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. + The term is applied to the union of the namespaces + listed in this field and the ones selected + by namespaceSelector. null or empty namespaces + list and null namespaceSelector means "this + pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the + pods matching the labelSelector in the specified + namespaces, where co-located is defined as + running on a node whose value of the label + with key topologyKey matches that of any node + on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching the + corresponding podAffinityTerm, in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by + this field are not met at scheduling time, the pod will + not be scheduled onto the node. If the affinity requirements + specified by this field cease to be met at some point + during pod execution (e.g. due to a pod label update), + the system may or may not try to eventually evict the + pod from its node. When there are multiple elements, + the lists of nodes corresponding to each podAffinityTerm + are intersected, i.e. all terms must be satisfied. + items: + description: Defines a set of pods (namely those matching + the labelSelector relative to the given namespace(s)) + that this pod should be co-located (affinity) or not + co-located (anti-affinity) with, where co-located + is defined as running on a node whose value of the + label with key matches that of any node + on which a pod of the set of pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by this + field and the ones listed in the namespaces field. + null selector and null or empty namespaces list + means "this pod's namespace". An empty selector + ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. The + term is applied to the union of the namespaces + listed in this field and the ones selected by + namespaceSelector. null or empty namespaces list + and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods + matching the labelSelector in the specified namespaces, + where co-located is defined as running on a node + whose value of the label with key topologyKey + matches that of any node on which any of the selected + pods is running. Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + podAntiAffinity: + description: Describes pod anti-affinity scheduling rules + (e.g. avoid putting this pod in the same node, zone, etc. + as some other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods + to nodes that satisfy the anti-affinity expressions + specified by this field, but it may choose a node that + violates one or more of the expressions. The node that + is most preferred is the one with the greatest sum of + weights, i.e. for each node that meets all of the scheduling + requirements (resource request, requiredDuringScheduling + anti-affinity expressions, etc.), compute a sum by iterating + through the elements of this field and adding "weight" + to the sum if the node has pods which matches the corresponding + podAffinityTerm; the node(s) with the highest sum are + the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by + this field and the ones listed in the namespaces + field. null selector and null or empty namespaces + list means "this pod's namespace". An empty + selector ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. + The term is applied to the union of the namespaces + listed in this field and the ones selected + by namespaceSelector. null or empty namespaces + list and null namespaceSelector means "this + pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the + pods matching the labelSelector in the specified + namespaces, where co-located is defined as + running on a node whose value of the label + with key topologyKey matches that of any node + on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching the + corresponding podAffinityTerm, in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the anti-affinity requirements specified + by this field are not met at scheduling time, the pod + will not be scheduled onto the node. If the anti-affinity + requirements specified by this field cease to be met + at some point during pod execution (e.g. due to a pod + label update), the system may or may not try to eventually + evict the pod from its node. When there are multiple + elements, the lists of nodes corresponding to each podAffinityTerm + are intersected, i.e. all terms must be satisfied. + items: + description: Defines a set of pods (namely those matching + the labelSelector relative to the given namespace(s)) + that this pod should be co-located (affinity) or not + co-located (anti-affinity) with, where co-located + is defined as running on a node whose value of the + label with key matches that of any node + on which a pod of the set of pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by this + field and the ones listed in the namespaces field. + null selector and null or empty namespaces list + means "this pod's namespace". An empty selector + ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. The + term is applied to the union of the namespaces + listed in this field and the ones selected by + namespaceSelector. null or empty namespaces list + and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods + matching the labelSelector in the specified namespaces, + where co-located is defined as running on a node + whose value of the label with key topologyKey + matches that of any node on which any of the selected + pods is running. Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + type: object + containers: + description: List of containers specified in the Deployment + items: + description: ContainerSpec defines the properties available + to override for each container in a provider deployment such + as Image and Args to the container’s entrypoint. + properties: + args: + additionalProperties: + type: string + description: Args represents extra provider specific flags + that are not encoded as fields in this API. Explicit controller + manager properties defined in the `Provider.ManagerSpec` + will have higher precedence than those defined in `ContainerSpec.Args`. + For example, `ManagerSpec.SyncPeriod` will be used instead + of the container arg `--sync-period` if both are defined. + The same holds for `ManagerSpec.FeatureGates` and `--feature-gates`. + type: object + command: + description: Command allows override container's entrypoint + array. + items: + type: string + type: array + env: + description: List of environment variables to set in the + container. + 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: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + 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: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + 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: Container Image Name + properties: + name: + description: Name allows to specify a name for the image. + type: string + repository: + description: Repository sets the container registry + to pull images from. + type: string + tag: + description: Tag allows to specify a tag for the image. + type: string + type: object + name: + description: Name of the container. Cannot be updated. + type: string + resources: + description: Compute resources required by this container. + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. \n 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 + 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 + required: + - name + type: object + type: array + imagePullSecrets: + description: List of image pull secrets specified in the Deployment + items: + description: LocalObjectReference contains enough information + to let you locate the referenced object inside the same namespace. + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + x-kubernetes-map-type: atomic + type: array + nodeSelector: + additionalProperties: + type: string + description: 'NodeSelector is a selector which must be true for + the pod to fit on a node. Selector which must match a node''s + labels for the pod to be scheduled on that node. More info: + https://kubernetes.io/docs/concepts/configuration/assign-pod-node/' + type: object + replicas: + description: Number of desired pods. This is a pointer to distinguish + between explicit zero and not specified. Defaults to 1. + minimum: 0 + type: integer + serviceAccountName: + description: If specified, the pod's service account + type: string + tolerations: + description: If specified, the pod's tolerations. + 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 + type: object + fetchConfig: + description: FetchConfig determines how the operator will fetch the + components and metadata for the provider. If nil, the operator will + try to fetch components according to default embedded fetch configuration + for the given kind and `ObjectMeta.Name`. For example, the infrastructure + name `aws` will fetch artifacts from https://github.com/kubernetes-sigs/cluster-api-provider-aws/releases. + properties: + selector: + description: 'Selector to be used for fetching provider’s components + and metadata from ConfigMaps stored inside the cluster. Each + ConfigMap is expected to contain components and metadata for + a specific version only. Note: the name of the ConfigMap should + be set to the version or to override this add a label like the + following: provider.cluster.x-k8s.io/version=v1.4.3' + 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 + required: + - key + - operator + type: object + type: array + 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 + url: + description: URL to be used for fetching the provider’s components + and metadata from a remote Github repository. For example, https://github.com/{owner}/{repository}/releases + You must set `providerSpec.Version` field for operator to pick + up desired version of the release from GitHub. + type: string + type: object + manager: + description: Manager defines the properties that can be enabled on + the controller manager for the provider. + properties: + cacheNamespace: + description: "CacheNamespace if specified restricts the manager's + cache to watch objects in the desired namespace Defaults to + all namespaces \n Note: If a namespace is specified, controllers + can still Watch for a cluster-scoped resource (e.g Node). For + namespaced resources the cache will only hold objects from the + desired namespace." + type: string + controller: + description: Controller contains global configuration options + for controllers registered within this manager. + properties: + cacheSyncTimeout: + description: CacheSyncTimeout refers to the time limit set + to wait for syncing caches. Defaults to 2 minutes if not + set. + format: int64 + type: integer + groupKindConcurrency: + additionalProperties: + type: integer + description: "GroupKindConcurrency is a map from a Kind to + the number of concurrent reconciliation allowed for that + controller. \n When a controller is registered within this + manager using the builder utilities, users have to specify + the type the controller reconciles in the For(...) call. + If the object's kind passed matches one of the keys in this + map, the concurrency for that controller is set to the number + specified. \n The key is expected to be consistent in form + with GroupKind.String(), e.g. ReplicaSet in apps group (regardless + of version) would be `ReplicaSet.apps`." + type: object + recoverPanic: + description: RecoverPanic indicates if panics should be recovered. + type: boolean + type: object + featureGates: + additionalProperties: + type: boolean + description: FeatureGates define provider specific feature flags + that will be passed in as container args to the provider's controller + manager. Controller Manager flag is --feature-gates. + type: object + gracefulShutDown: + description: GracefulShutdownTimeout is the duration given to + runnable to stop before the manager actually returns on stop. + To disable graceful shutdown, set to time.Duration(0) To use + graceful shutdown without timeout, set to a negative duration, + e.G. time.Duration(-1) The graceful shutdown is skipped for + safety reasons in case the leader election lease is lost. + type: string + health: + description: Health contains the controller health configuration + properties: + healthProbeBindAddress: + description: HealthProbeBindAddress is the TCP address that + the controller should bind to for serving health probes + It can be set to "0" or "" to disable serving the health + probe. + type: string + livenessEndpointName: + description: LivenessEndpointName, defaults to "healthz" + type: string + readinessEndpointName: + description: ReadinessEndpointName, defaults to "readyz" + type: string + type: object + leaderElection: + description: LeaderElection is the LeaderElection config to be + used when configuring the manager.Manager leader election + properties: + leaderElect: + description: leaderElect enables a leader election client + to gain leadership before executing the main loop. Enable + this when running replicated components for high availability. + type: boolean + leaseDuration: + description: leaseDuration is the duration that non-leader + candidates will wait after observing a leadership renewal + until attempting to acquire leadership of a led but unrenewed + leader slot. This is effectively the maximum duration that + a leader can be stopped before it is replaced by another + candidate. This is only applicable if leader election is + enabled. + type: string + renewDeadline: + description: renewDeadline is the interval between attempts + by the acting master to renew a leadership slot before it + stops leading. This must be less than or equal to the lease + duration. This is only applicable if leader election is + enabled. + type: string + resourceLock: + description: resourceLock indicates the resource object type + that will be used to lock during leader election cycles. + type: string + resourceName: + description: resourceName indicates the name of resource object + that will be used to lock during leader election cycles. + type: string + resourceNamespace: + description: resourceName indicates the namespace of resource + object that will be used to lock during leader election + cycles. + type: string + retryPeriod: + description: retryPeriod is the duration the clients should + wait between attempting acquisition and renewal of a leadership. + This is only applicable if leader election is enabled. + type: string + required: + - leaderElect + - leaseDuration + - renewDeadline + - resourceLock + - resourceName + - resourceNamespace + - retryPeriod + type: object + maxConcurrentReconciles: + description: MaxConcurrentReconciles is the maximum number of + concurrent Reconciles which can be run. + minimum: 1 + type: integer + metrics: + description: Metrics contains the controller metrics configuration + properties: + bindAddress: + description: BindAddress is the TCP address that the controller + should bind to for serving prometheus metrics. It can be + set to "0" to disable the metrics serving. + type: string + type: object + profilerAddress: + description: ProfilerAddress defines the bind address to expose + the pprof profiler (e.g. localhost:6060). Default empty, meaning + the profiler is disabled. Controller Manager flag is --profiler-address. + type: string + syncPeriod: + description: SyncPeriod determines the minimum frequency at which + watched resources are reconciled. A lower period will correct + entropy more quickly, but reduce responsiveness to change if + there are many watched resources. Change this value only if + you know what you are doing. Defaults to 10 hours if unset. + there will a 10 percent jitter between the SyncPeriod of all + controllers so that all controllers will not send list requests + simultaneously. + type: string + verbosity: + default: 1 + description: Verbosity set the logs verbosity. Defaults to 1. + Controller Manager flag is --verbosity. + minimum: 0 + type: integer + webhook: + description: Webhook contains the controllers webhook configuration + properties: + certDir: + description: CertDir is the directory that contains the server + key and certificate. if not set, webhook server would look + up the server key and certificate in {TempDir}/k8s-webhook-server/serving-certs. + The server key and certificate must be named tls.key and + tls.crt, respectively. + type: string + host: + description: Host is the hostname that the webhook server + binds to. It is used to set webhook.Server.Host. + type: string + port: + description: Port is the port that the webhook server serves + at. It is used to set webhook.Server.Port. + type: integer + type: object + type: object + secretName: + description: SecretName is the name of the Secret providing the configuration + variables for the current provider instance, like e.g. credentials. + Such configurations will be used when creating or upgrading provider + components. The contents of the secret will be treated as immutable. + If changes need to be made, a new object can be created and the + name should be updated. The contents should be in the form of key:value. + This secret must be in the same namespace as the provider. + type: string + secretNamespace: + description: SecretNamespace is the namespace of the Secret providing + the configuration variables. If not specified, the namespace of + the provider will be used. + type: string + version: + description: Version indicates the provider version. + type: string + type: object + status: + description: CoreProviderStatus defines the observed state of CoreProvider. + properties: + conditions: + description: Conditions define the current service state of the provider. + items: + description: Condition defines an observation of a Cluster API resource + operational state. + properties: + lastTransitionTime: + description: 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: A human readable message indicating details about + the transition. This field may be empty. + type: string + reason: + description: The reason for the condition's last transition + in CamelCase. The specific API may choose whether or not this + field is considered a guaranteed API. This field may not be + empty. + type: string + severity: + description: Severity provides an explicit classification of + Reason code, so the users or machines can immediately understand + the current situation and act accordingly. The Severity field + MUST be set only when Status=False. + type: string + status: + description: Status of the condition, one of 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. + type: string + required: + - lastTransitionTime + - status + - type + type: object + type: array + contract: + description: Contract will contain the core provider contract that + the provider is abiding by, like e.g. v1alpha4. + type: string + installedVersion: + description: InstalledVersion is the version of the provider that + is installed. + type: string + observedGeneration: + description: ObservedGeneration is the latest generation observed + by the controller. + format: int64 + type: integer + type: object + type: object + served: true + storage: false + subresources: + status: {} + - additionalPrinterColumns: + - jsonPath: .status.installedVersion + name: InstalledVersion + type: string + - jsonPath: .status.conditions[?(@.type=='Ready')].status + name: Ready + type: string + name: v1alpha2 + schema: + openAPIV3Schema: + description: CoreProvider is the Schema for the coreproviders 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: CoreProviderSpec defines the desired state of CoreProvider. + properties: + additionalManifests: + description: AdditionalManifests is reference to configmap that contains + additional manifests that will be applied together with the provider + components. The key for storing these manifests has to be `manifests`. + The manifests are applied only once when a certain release is installed/upgraded. + If namespace is not specified, the namespace of the provider will + be used. There is no validation of the yaml content inside the configmap. + properties: + name: + description: Name defines the name of the configmap. + type: string + namespace: + description: Namespace defines the namespace of the configmap. + type: string + required: + - name + type: object + configSecret: + description: ConfigSecret is the object with name and namespace of + the Secret providing the configuration variables for the current + provider instance, like e.g. credentials. Such configurations will + be used when creating or upgrading provider components. The contents + of the secret will be treated as immutable. If changes need to be + made, a new object can be created and the name should be updated. + The contents should be in the form of key:value. This secret must + be in the same namespace as the provider. + properties: + name: + description: Name defines the name of the secret. + type: string + namespace: + description: Namespace defines the namespace of the secret. + type: string + required: + - name + type: object + deployment: + description: Deployment defines the properties that can be enabled + on the deployment for the provider. + properties: + affinity: + description: If specified, the pod's scheduling constraints + properties: + nodeAffinity: + description: Describes node affinity scheduling rules for + the pod. + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods + to nodes that satisfy the affinity expressions specified + by this field, but it may choose a node that violates + one or more of the expressions. The node that is most + preferred is the one with the greatest sum of weights, + i.e. for each node that meets all of the scheduling + requirements (resource request, requiredDuringScheduling + affinity expressions, etc.), compute a sum by iterating + through the elements of this field and adding "weight" + to the sum if the node matches the corresponding matchExpressions; + the node(s) with the highest sum are the most preferred. + items: + description: An empty preferred scheduling term matches + all objects with implicit weight 0 (i.e. it's a no-op). + A null preferred scheduling term matches no objects + (i.e. is also a no-op). + properties: + preference: + description: A node selector term, associated with + the corresponding weight. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: 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. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: 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. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + x-kubernetes-map-type: atomic + weight: + description: Weight associated with matching the + corresponding nodeSelectorTerm, in the range 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by + this field are not met at scheduling time, the pod will + not be scheduled onto the node. If the affinity requirements + specified by this field cease to be met at some point + during pod execution (e.g. due to an update), the system + may or may not try to eventually evict the pod from + its node. + properties: + nodeSelectorTerms: + description: Required. A list of node selector terms. + The terms are ORed. + items: + description: A null or empty node selector term + matches no objects. The requirements of them are + ANDed. The TopologySelectorTerm type implements + a subset of the NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: 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. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: 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. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + x-kubernetes-map-type: atomic + type: array + required: + - nodeSelectorTerms + type: object + x-kubernetes-map-type: atomic + type: object + podAffinity: + description: Describes pod affinity scheduling rules (e.g. + co-locate this pod in the same node, zone, etc. as some + other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods + to nodes that satisfy the affinity expressions specified + by this field, but it may choose a node that violates + one or more of the expressions. The node that is most + preferred is the one with the greatest sum of weights, + i.e. for each node that meets all of the scheduling + requirements (resource request, requiredDuringScheduling + affinity expressions, etc.), compute a sum by iterating + through the elements of this field and adding "weight" + to the sum if the node has pods which matches the corresponding + podAffinityTerm; the node(s) with the highest sum are + the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by + this field and the ones listed in the namespaces + field. null selector and null or empty namespaces + list means "this pod's namespace". An empty + selector ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. + The term is applied to the union of the namespaces + listed in this field and the ones selected + by namespaceSelector. null or empty namespaces + list and null namespaceSelector means "this + pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the + pods matching the labelSelector in the specified + namespaces, where co-located is defined as + running on a node whose value of the label + with key topologyKey matches that of any node + on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching the + corresponding podAffinityTerm, in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by + this field are not met at scheduling time, the pod will + not be scheduled onto the node. If the affinity requirements + specified by this field cease to be met at some point + during pod execution (e.g. due to a pod label update), + the system may or may not try to eventually evict the + pod from its node. When there are multiple elements, + the lists of nodes corresponding to each podAffinityTerm + are intersected, i.e. all terms must be satisfied. + items: + description: Defines a set of pods (namely those matching + the labelSelector relative to the given namespace(s)) + that this pod should be co-located (affinity) or not + co-located (anti-affinity) with, where co-located + is defined as running on a node whose value of the + label with key matches that of any node + on which a pod of the set of pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by this + field and the ones listed in the namespaces field. + null selector and null or empty namespaces list + means "this pod's namespace". An empty selector + ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. The + term is applied to the union of the namespaces + listed in this field and the ones selected by + namespaceSelector. null or empty namespaces list + and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods + matching the labelSelector in the specified namespaces, + where co-located is defined as running on a node + whose value of the label with key topologyKey + matches that of any node on which any of the selected + pods is running. Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + podAntiAffinity: + description: Describes pod anti-affinity scheduling rules + (e.g. avoid putting this pod in the same node, zone, etc. + as some other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods + to nodes that satisfy the anti-affinity expressions + specified by this field, but it may choose a node that + violates one or more of the expressions. The node that + is most preferred is the one with the greatest sum of + weights, i.e. for each node that meets all of the scheduling + requirements (resource request, requiredDuringScheduling + anti-affinity expressions, etc.), compute a sum by iterating + through the elements of this field and adding "weight" + to the sum if the node has pods which matches the corresponding + podAffinityTerm; the node(s) with the highest sum are + the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by + this field and the ones listed in the namespaces + field. null selector and null or empty namespaces + list means "this pod's namespace". An empty + selector ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. + The term is applied to the union of the namespaces + listed in this field and the ones selected + by namespaceSelector. null or empty namespaces + list and null namespaceSelector means "this + pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the + pods matching the labelSelector in the specified + namespaces, where co-located is defined as + running on a node whose value of the label + with key topologyKey matches that of any node + on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching the + corresponding podAffinityTerm, in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the anti-affinity requirements specified + by this field are not met at scheduling time, the pod + will not be scheduled onto the node. If the anti-affinity + requirements specified by this field cease to be met + at some point during pod execution (e.g. due to a pod + label update), the system may or may not try to eventually + evict the pod from its node. When there are multiple + elements, the lists of nodes corresponding to each podAffinityTerm + are intersected, i.e. all terms must be satisfied. + items: + description: Defines a set of pods (namely those matching + the labelSelector relative to the given namespace(s)) + that this pod should be co-located (affinity) or not + co-located (anti-affinity) with, where co-located + is defined as running on a node whose value of the + label with key matches that of any node + on which a pod of the set of pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by this + field and the ones listed in the namespaces field. + null selector and null or empty namespaces list + means "this pod's namespace". An empty selector + ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. The + term is applied to the union of the namespaces + listed in this field and the ones selected by + namespaceSelector. null or empty namespaces list + and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods + matching the labelSelector in the specified namespaces, + where co-located is defined as running on a node + whose value of the label with key topologyKey + matches that of any node on which any of the selected + pods is running. Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + type: object + containers: + description: List of containers specified in the Deployment + items: + description: ContainerSpec defines the properties available + to override for each container in a provider deployment such + as Image and Args to the container’s entrypoint. + properties: + args: + additionalProperties: + type: string + description: Args represents extra provider specific flags + that are not encoded as fields in this API. Explicit controller + manager properties defined in the `Provider.ManagerSpec` + will have higher precedence than those defined in `ContainerSpec.Args`. + For example, `ManagerSpec.SyncPeriod` will be used instead + of the container arg `--sync-period` if both are defined. + The same holds for `ManagerSpec.FeatureGates` and `--feature-gates`. + type: object + command: + description: Command allows override container's entrypoint + array. + items: + type: string + type: array + env: + description: List of environment variables to set in the + container. + 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: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + 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: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + 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 + imageUrl: + description: Container Image URL + type: string + name: + description: Name of the container. Cannot be updated. + type: string + resources: + description: Compute resources required by this container. + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. \n 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 + 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 + required: + - name + type: object + type: array + imagePullSecrets: + description: List of image pull secrets specified in the Deployment + items: + description: LocalObjectReference contains enough information + to let you locate the referenced object inside the same namespace. + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + x-kubernetes-map-type: atomic + type: array + nodeSelector: + additionalProperties: + type: string + description: 'NodeSelector is a selector which must be true for + the pod to fit on a node. Selector which must match a node''s + labels for the pod to be scheduled on that node. More info: + https://kubernetes.io/docs/concepts/configuration/assign-pod-node/' + type: object + replicas: + description: Number of desired pods. This is a pointer to distinguish + between explicit zero and not specified. Defaults to 1. + minimum: 0 + type: integer + serviceAccountName: + description: If specified, the pod's service account + type: string + tolerations: + description: If specified, the pod's tolerations. + 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 + type: object + fetchConfig: + description: FetchConfig determines how the operator will fetch the + components and metadata for the provider. If nil, the operator will + try to fetch components according to default embedded fetch configuration + for the given kind and `ObjectMeta.Name`. For example, the infrastructure + name `aws` will fetch artifacts from https://github.com/kubernetes-sigs/cluster-api-provider-aws/releases. + properties: + selector: + description: 'Selector to be used for fetching provider’s components + and metadata from ConfigMaps stored inside the cluster. Each + ConfigMap is expected to contain components and metadata for + a specific version only. Note: the name of the ConfigMap should + be set to the version or to override this add a label like the + following: provider.cluster.x-k8s.io/version=v1.4.3' + 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 + required: + - key + - operator + type: object + type: array + 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 + url: + description: URL to be used for fetching the provider’s components + and metadata from a remote Github repository. For example, https://github.com/{owner}/{repository}/releases + You must set `providerSpec.Version` field for operator to pick + up desired version of the release from GitHub. + type: string + type: object + manager: + description: Manager defines the properties that can be enabled on + the controller manager for the provider. + properties: + cacheNamespace: + description: "CacheNamespace if specified restricts the manager's + cache to watch objects in the desired namespace Defaults to + all namespaces \n Note: If a namespace is specified, controllers + can still Watch for a cluster-scoped resource (e.g Node). For + namespaced resources the cache will only hold objects from the + desired namespace." + type: string + controller: + description: Controller contains global configuration options + for controllers registered within this manager. + properties: + cacheSyncTimeout: + description: CacheSyncTimeout refers to the time limit set + to wait for syncing caches. Defaults to 2 minutes if not + set. + format: int64 + type: integer + groupKindConcurrency: + additionalProperties: + type: integer + description: "GroupKindConcurrency is a map from a Kind to + the number of concurrent reconciliation allowed for that + controller. \n When a controller is registered within this + manager using the builder utilities, users have to specify + the type the controller reconciles in the For(...) call. + If the object's kind passed matches one of the keys in this + map, the concurrency for that controller is set to the number + specified. \n The key is expected to be consistent in form + with GroupKind.String(), e.g. ReplicaSet in apps group (regardless + of version) would be `ReplicaSet.apps`." + type: object + recoverPanic: + description: RecoverPanic indicates if panics should be recovered. + type: boolean + type: object + featureGates: + additionalProperties: + type: boolean + description: FeatureGates define provider specific feature flags + that will be passed in as container args to the provider's controller + manager. Controller Manager flag is --feature-gates. + type: object + gracefulShutDown: + description: GracefulShutdownTimeout is the duration given to + runnable to stop before the manager actually returns on stop. + To disable graceful shutdown, set to time.Duration(0) To use + graceful shutdown without timeout, set to a negative duration, + e.G. time.Duration(-1) The graceful shutdown is skipped for + safety reasons in case the leader election lease is lost. + type: string + health: + description: Health contains the controller health configuration + properties: + healthProbeBindAddress: + description: HealthProbeBindAddress is the TCP address that + the controller should bind to for serving health probes + It can be set to "0" or "" to disable serving the health + probe. + type: string + livenessEndpointName: + description: LivenessEndpointName, defaults to "healthz" + type: string + readinessEndpointName: + description: ReadinessEndpointName, defaults to "readyz" + type: string + type: object + leaderElection: + description: LeaderElection is the LeaderElection config to be + used when configuring the manager.Manager leader election + properties: + leaderElect: + description: leaderElect enables a leader election client + to gain leadership before executing the main loop. Enable + this when running replicated components for high availability. + type: boolean + leaseDuration: + description: leaseDuration is the duration that non-leader + candidates will wait after observing a leadership renewal + until attempting to acquire leadership of a led but unrenewed + leader slot. This is effectively the maximum duration that + a leader can be stopped before it is replaced by another + candidate. This is only applicable if leader election is + enabled. + type: string + renewDeadline: + description: renewDeadline is the interval between attempts + by the acting master to renew a leadership slot before it + stops leading. This must be less than or equal to the lease + duration. This is only applicable if leader election is + enabled. + type: string + resourceLock: + description: resourceLock indicates the resource object type + that will be used to lock during leader election cycles. + type: string + resourceName: + description: resourceName indicates the name of resource object + that will be used to lock during leader election cycles. + type: string + resourceNamespace: + description: resourceName indicates the namespace of resource + object that will be used to lock during leader election + cycles. + type: string + retryPeriod: + description: retryPeriod is the duration the clients should + wait between attempting acquisition and renewal of a leadership. + This is only applicable if leader election is enabled. + type: string + required: + - leaderElect + - leaseDuration + - renewDeadline + - resourceLock + - resourceName + - resourceNamespace + - retryPeriod + type: object + maxConcurrentReconciles: + description: MaxConcurrentReconciles is the maximum number of + concurrent Reconciles which can be run. + minimum: 1 + type: integer + metrics: + description: Metrics contains thw controller metrics configuration + properties: + bindAddress: + description: BindAddress is the TCP address that the controller + should bind to for serving prometheus metrics. It can be + set to "0" to disable the metrics serving. + type: string + type: object + profilerAddress: + description: ProfilerAddress defines the bind address to expose + the pprof profiler (e.g. localhost:6060). Default empty, meaning + the profiler is disabled. Controller Manager flag is --profiler-address. + type: string + syncPeriod: + description: SyncPeriod determines the minimum frequency at which + watched resources are reconciled. A lower period will correct + entropy more quickly, but reduce responsiveness to change if + there are many watched resources. Change this value only if + you know what you are doing. Defaults to 10 hours if unset. + there will a 10 percent jitter between the SyncPeriod of all + controllers so that all controllers will not send list requests + simultaneously. + type: string + verbosity: + default: 1 + description: Verbosity set the logs verbosity. Defaults to 1. + Controller Manager flag is --verbosity. + minimum: 0 + type: integer + webhook: + description: Webhook contains the controllers webhook configuration + properties: + certDir: + description: CertDir is the directory that contains the server + key and certificate. if not set, webhook server would look + up the server key and certificate in {TempDir}/k8s-webhook-server/serving-certs. + The server key and certificate must be named tls.key and + tls.crt, respectively. + type: string + host: + description: Host is the hostname that the webhook server + binds to. It is used to set webhook.Server.Host. + type: string + port: + description: Port is the port that the webhook server serves + at. It is used to set webhook.Server.Port. + type: integer + type: object + type: object + manifestPatches: + description: ManifestPatches are applied to rendered provider manifests + to customize the provider manifests. Patches are applied in the + order they are specified. The `kind` field must match the target + object, and if `apiVersion` is specified it will only be applied + to matching objects. This should be an inline yaml blob-string https://datatracker.ietf.org/doc/html/rfc7396 + items: + type: string + type: array + version: + description: Version indicates the provider version. + type: string + type: object + status: + description: CoreProviderStatus defines the observed state of CoreProvider. + properties: + conditions: + description: Conditions define the current service state of the provider. + items: + description: Condition defines an observation of a Cluster API resource + operational state. + properties: + lastTransitionTime: + description: 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: A human readable message indicating details about + the transition. This field may be empty. + type: string + reason: + description: The reason for the condition's last transition + in CamelCase. The specific API may choose whether or not this + field is considered a guaranteed API. This field may not be + empty. + type: string + severity: + description: Severity provides an explicit classification of + Reason code, so the users or machines can immediately understand + the current situation and act accordingly. The Severity field + MUST be set only when Status=False. + type: string + status: + description: Status of the condition, one of 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. + type: string + required: + - lastTransitionTime + - status + - type + type: object + type: array + contract: + description: Contract will contain the core provider contract that + the provider is abiding by, like e.g. v1alpha4. + type: string + installedVersion: + description: InstalledVersion is the version of the provider that + is installed. + type: string + observedGeneration: + description: ObservedGeneration is the latest generation observed + by the controller. + format: int64 + type: integer + type: object + type: object + served: true + storage: true + subresources: + status: {} +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + cert-manager.io/inject-ca-from: '{{ .Release.Namespace }}/capi-operator-serving-cert' + controller-gen.kubebuilder.io/version: v0.11.4 + labels: + clusterctl.cluster.x-k8s.io/core: capi-operator + name: infrastructureproviders.operator.cluster.x-k8s.io +spec: + conversion: + strategy: Webhook + webhook: + clientConfig: + caBundle: Cg== + service: + name: capi-operator-webhook-service + namespace: '{{ .Release.Namespace }}' + path: /convert + conversionReviewVersions: + - v1 + - v1alpha1 + group: operator.cluster.x-k8s.io + names: + kind: InfrastructureProvider + listKind: InfrastructureProviderList + plural: infrastructureproviders + singular: infrastructureprovider + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .status.installedVersion + name: InstalledVersion + type: string + - jsonPath: .status.conditions[?(@.type=='Ready')].status + name: Ready + type: string + name: v1alpha1 + schema: + openAPIV3Schema: + description: InfrastructureProvider is the Schema for the infrastructureproviders + 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: InfrastructureProviderSpec defines the desired state of InfrastructureProvider. + properties: + additionalManifests: + description: AdditionalManifests is reference to configmap that contains + additional manifests that will be applied together with the provider + components. The key for storing these manifests has to be `manifests`. + The manifests are applied only once when a certain release is installed/upgraded. + If namespace is not specified, the namespace of the provider will + be used. There is no validation of the yaml content inside the configmap. + properties: + name: + description: Name defines the name of the configmap. + type: string + namespace: + description: Namespace defines the namespace of the configmap. + type: string + required: + - name + type: object + deployment: + description: Deployment defines the properties that can be enabled + on the deployment for the provider. + properties: + affinity: + description: If specified, the pod's scheduling constraints + properties: + nodeAffinity: + description: Describes node affinity scheduling rules for + the pod. + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods + to nodes that satisfy the affinity expressions specified + by this field, but it may choose a node that violates + one or more of the expressions. The node that is most + preferred is the one with the greatest sum of weights, + i.e. for each node that meets all of the scheduling + requirements (resource request, requiredDuringScheduling + affinity expressions, etc.), compute a sum by iterating + through the elements of this field and adding "weight" + to the sum if the node matches the corresponding matchExpressions; + the node(s) with the highest sum are the most preferred. + items: + description: An empty preferred scheduling term matches + all objects with implicit weight 0 (i.e. it's a no-op). + A null preferred scheduling term matches no objects + (i.e. is also a no-op). + properties: + preference: + description: A node selector term, associated with + the corresponding weight. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: 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. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: 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. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + x-kubernetes-map-type: atomic + weight: + description: Weight associated with matching the + corresponding nodeSelectorTerm, in the range 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by + this field are not met at scheduling time, the pod will + not be scheduled onto the node. If the affinity requirements + specified by this field cease to be met at some point + during pod execution (e.g. due to an update), the system + may or may not try to eventually evict the pod from + its node. + properties: + nodeSelectorTerms: + description: Required. A list of node selector terms. + The terms are ORed. + items: + description: A null or empty node selector term + matches no objects. The requirements of them are + ANDed. The TopologySelectorTerm type implements + a subset of the NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: 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. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: 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. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + x-kubernetes-map-type: atomic + type: array + required: + - nodeSelectorTerms + type: object + x-kubernetes-map-type: atomic + type: object + podAffinity: + description: Describes pod affinity scheduling rules (e.g. + co-locate this pod in the same node, zone, etc. as some + other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods + to nodes that satisfy the affinity expressions specified + by this field, but it may choose a node that violates + one or more of the expressions. The node that is most + preferred is the one with the greatest sum of weights, + i.e. for each node that meets all of the scheduling + requirements (resource request, requiredDuringScheduling + affinity expressions, etc.), compute a sum by iterating + through the elements of this field and adding "weight" + to the sum if the node has pods which matches the corresponding + podAffinityTerm; the node(s) with the highest sum are + the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by + this field and the ones listed in the namespaces + field. null selector and null or empty namespaces + list means "this pod's namespace". An empty + selector ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. + The term is applied to the union of the namespaces + listed in this field and the ones selected + by namespaceSelector. null or empty namespaces + list and null namespaceSelector means "this + pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the + pods matching the labelSelector in the specified + namespaces, where co-located is defined as + running on a node whose value of the label + with key topologyKey matches that of any node + on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching the + corresponding podAffinityTerm, in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by + this field are not met at scheduling time, the pod will + not be scheduled onto the node. If the affinity requirements + specified by this field cease to be met at some point + during pod execution (e.g. due to a pod label update), + the system may or may not try to eventually evict the + pod from its node. When there are multiple elements, + the lists of nodes corresponding to each podAffinityTerm + are intersected, i.e. all terms must be satisfied. + items: + description: Defines a set of pods (namely those matching + the labelSelector relative to the given namespace(s)) + that this pod should be co-located (affinity) or not + co-located (anti-affinity) with, where co-located + is defined as running on a node whose value of the + label with key matches that of any node + on which a pod of the set of pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by this + field and the ones listed in the namespaces field. + null selector and null or empty namespaces list + means "this pod's namespace". An empty selector + ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. The + term is applied to the union of the namespaces + listed in this field and the ones selected by + namespaceSelector. null or empty namespaces list + and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods + matching the labelSelector in the specified namespaces, + where co-located is defined as running on a node + whose value of the label with key topologyKey + matches that of any node on which any of the selected + pods is running. Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + podAntiAffinity: + description: Describes pod anti-affinity scheduling rules + (e.g. avoid putting this pod in the same node, zone, etc. + as some other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods + to nodes that satisfy the anti-affinity expressions + specified by this field, but it may choose a node that + violates one or more of the expressions. The node that + is most preferred is the one with the greatest sum of + weights, i.e. for each node that meets all of the scheduling + requirements (resource request, requiredDuringScheduling + anti-affinity expressions, etc.), compute a sum by iterating + through the elements of this field and adding "weight" + to the sum if the node has pods which matches the corresponding + podAffinityTerm; the node(s) with the highest sum are + the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by + this field and the ones listed in the namespaces + field. null selector and null or empty namespaces + list means "this pod's namespace". An empty + selector ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. + The term is applied to the union of the namespaces + listed in this field and the ones selected + by namespaceSelector. null or empty namespaces + list and null namespaceSelector means "this + pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the + pods matching the labelSelector in the specified + namespaces, where co-located is defined as + running on a node whose value of the label + with key topologyKey matches that of any node + on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching the + corresponding podAffinityTerm, in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the anti-affinity requirements specified + by this field are not met at scheduling time, the pod + will not be scheduled onto the node. If the anti-affinity + requirements specified by this field cease to be met + at some point during pod execution (e.g. due to a pod + label update), the system may or may not try to eventually + evict the pod from its node. When there are multiple + elements, the lists of nodes corresponding to each podAffinityTerm + are intersected, i.e. all terms must be satisfied. + items: + description: Defines a set of pods (namely those matching + the labelSelector relative to the given namespace(s)) + that this pod should be co-located (affinity) or not + co-located (anti-affinity) with, where co-located + is defined as running on a node whose value of the + label with key matches that of any node + on which a pod of the set of pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by this + field and the ones listed in the namespaces field. + null selector and null or empty namespaces list + means "this pod's namespace". An empty selector + ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. The + term is applied to the union of the namespaces + listed in this field and the ones selected by + namespaceSelector. null or empty namespaces list + and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods + matching the labelSelector in the specified namespaces, + where co-located is defined as running on a node + whose value of the label with key topologyKey + matches that of any node on which any of the selected + pods is running. Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + type: object + containers: + description: List of containers specified in the Deployment + items: + description: ContainerSpec defines the properties available + to override for each container in a provider deployment such + as Image and Args to the container’s entrypoint. + properties: + args: + additionalProperties: + type: string + description: Args represents extra provider specific flags + that are not encoded as fields in this API. Explicit controller + manager properties defined in the `Provider.ManagerSpec` + will have higher precedence than those defined in `ContainerSpec.Args`. + For example, `ManagerSpec.SyncPeriod` will be used instead + of the container arg `--sync-period` if both are defined. + The same holds for `ManagerSpec.FeatureGates` and `--feature-gates`. + type: object + command: + description: Command allows override container's entrypoint + array. + items: + type: string + type: array + env: + description: List of environment variables to set in the + container. + 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: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + 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: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + 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: Container Image Name + properties: + name: + description: Name allows to specify a name for the image. + type: string + repository: + description: Repository sets the container registry + to pull images from. + type: string + tag: + description: Tag allows to specify a tag for the image. + type: string + type: object + name: + description: Name of the container. Cannot be updated. + type: string + resources: + description: Compute resources required by this container. + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. \n 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 + 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 + required: + - name + type: object + type: array + imagePullSecrets: + description: List of image pull secrets specified in the Deployment + items: + description: LocalObjectReference contains enough information + to let you locate the referenced object inside the same namespace. + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + x-kubernetes-map-type: atomic + type: array + nodeSelector: + additionalProperties: + type: string + description: 'NodeSelector is a selector which must be true for + the pod to fit on a node. Selector which must match a node''s + labels for the pod to be scheduled on that node. More info: + https://kubernetes.io/docs/concepts/configuration/assign-pod-node/' + type: object + replicas: + description: Number of desired pods. This is a pointer to distinguish + between explicit zero and not specified. Defaults to 1. + minimum: 0 + type: integer + serviceAccountName: + description: If specified, the pod's service account + type: string + tolerations: + description: If specified, the pod's tolerations. + 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 + type: object + fetchConfig: + description: FetchConfig determines how the operator will fetch the + components and metadata for the provider. If nil, the operator will + try to fetch components according to default embedded fetch configuration + for the given kind and `ObjectMeta.Name`. For example, the infrastructure + name `aws` will fetch artifacts from https://github.com/kubernetes-sigs/cluster-api-provider-aws/releases. + properties: + selector: + description: 'Selector to be used for fetching provider’s components + and metadata from ConfigMaps stored inside the cluster. Each + ConfigMap is expected to contain components and metadata for + a specific version only. Note: the name of the ConfigMap should + be set to the version or to override this add a label like the + following: provider.cluster.x-k8s.io/version=v1.4.3' + 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 + required: + - key + - operator + type: object + type: array + 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 + url: + description: URL to be used for fetching the provider’s components + and metadata from a remote Github repository. For example, https://github.com/{owner}/{repository}/releases + You must set `providerSpec.Version` field for operator to pick + up desired version of the release from GitHub. + type: string + type: object + manager: + description: Manager defines the properties that can be enabled on + the controller manager for the provider. + properties: + cacheNamespace: + description: "CacheNamespace if specified restricts the manager's + cache to watch objects in the desired namespace Defaults to + all namespaces \n Note: If a namespace is specified, controllers + can still Watch for a cluster-scoped resource (e.g Node). For + namespaced resources the cache will only hold objects from the + desired namespace." + type: string + controller: + description: Controller contains global configuration options + for controllers registered within this manager. + properties: + cacheSyncTimeout: + description: CacheSyncTimeout refers to the time limit set + to wait for syncing caches. Defaults to 2 minutes if not + set. + format: int64 + type: integer + groupKindConcurrency: + additionalProperties: + type: integer + description: "GroupKindConcurrency is a map from a Kind to + the number of concurrent reconciliation allowed for that + controller. \n When a controller is registered within this + manager using the builder utilities, users have to specify + the type the controller reconciles in the For(...) call. + If the object's kind passed matches one of the keys in this + map, the concurrency for that controller is set to the number + specified. \n The key is expected to be consistent in form + with GroupKind.String(), e.g. ReplicaSet in apps group (regardless + of version) would be `ReplicaSet.apps`." + type: object + recoverPanic: + description: RecoverPanic indicates if panics should be recovered. + type: boolean + type: object + featureGates: + additionalProperties: + type: boolean + description: FeatureGates define provider specific feature flags + that will be passed in as container args to the provider's controller + manager. Controller Manager flag is --feature-gates. + type: object + gracefulShutDown: + description: GracefulShutdownTimeout is the duration given to + runnable to stop before the manager actually returns on stop. + To disable graceful shutdown, set to time.Duration(0) To use + graceful shutdown without timeout, set to a negative duration, + e.G. time.Duration(-1) The graceful shutdown is skipped for + safety reasons in case the leader election lease is lost. + type: string + health: + description: Health contains the controller health configuration + properties: + healthProbeBindAddress: + description: HealthProbeBindAddress is the TCP address that + the controller should bind to for serving health probes + It can be set to "0" or "" to disable serving the health + probe. + type: string + livenessEndpointName: + description: LivenessEndpointName, defaults to "healthz" + type: string + readinessEndpointName: + description: ReadinessEndpointName, defaults to "readyz" + type: string + type: object + leaderElection: + description: LeaderElection is the LeaderElection config to be + used when configuring the manager.Manager leader election + properties: + leaderElect: + description: leaderElect enables a leader election client + to gain leadership before executing the main loop. Enable + this when running replicated components for high availability. + type: boolean + leaseDuration: + description: leaseDuration is the duration that non-leader + candidates will wait after observing a leadership renewal + until attempting to acquire leadership of a led but unrenewed + leader slot. This is effectively the maximum duration that + a leader can be stopped before it is replaced by another + candidate. This is only applicable if leader election is + enabled. + type: string + renewDeadline: + description: renewDeadline is the interval between attempts + by the acting master to renew a leadership slot before it + stops leading. This must be less than or equal to the lease + duration. This is only applicable if leader election is + enabled. + type: string + resourceLock: + description: resourceLock indicates the resource object type + that will be used to lock during leader election cycles. + type: string + resourceName: + description: resourceName indicates the name of resource object + that will be used to lock during leader election cycles. + type: string + resourceNamespace: + description: resourceName indicates the namespace of resource + object that will be used to lock during leader election + cycles. + type: string + retryPeriod: + description: retryPeriod is the duration the clients should + wait between attempting acquisition and renewal of a leadership. + This is only applicable if leader election is enabled. + type: string + required: + - leaderElect + - leaseDuration + - renewDeadline + - resourceLock + - resourceName + - resourceNamespace + - retryPeriod + type: object + maxConcurrentReconciles: + description: MaxConcurrentReconciles is the maximum number of + concurrent Reconciles which can be run. + minimum: 1 + type: integer + metrics: + description: Metrics contains the controller metrics configuration + properties: + bindAddress: + description: BindAddress is the TCP address that the controller + should bind to for serving prometheus metrics. It can be + set to "0" to disable the metrics serving. + type: string + type: object + profilerAddress: + description: ProfilerAddress defines the bind address to expose + the pprof profiler (e.g. localhost:6060). Default empty, meaning + the profiler is disabled. Controller Manager flag is --profiler-address. + type: string + syncPeriod: + description: SyncPeriod determines the minimum frequency at which + watched resources are reconciled. A lower period will correct + entropy more quickly, but reduce responsiveness to change if + there are many watched resources. Change this value only if + you know what you are doing. Defaults to 10 hours if unset. + there will a 10 percent jitter between the SyncPeriod of all + controllers so that all controllers will not send list requests + simultaneously. + type: string + verbosity: + default: 1 + description: Verbosity set the logs verbosity. Defaults to 1. + Controller Manager flag is --verbosity. + minimum: 0 + type: integer + webhook: + description: Webhook contains the controllers webhook configuration + properties: + certDir: + description: CertDir is the directory that contains the server + key and certificate. if not set, webhook server would look + up the server key and certificate in {TempDir}/k8s-webhook-server/serving-certs. + The server key and certificate must be named tls.key and + tls.crt, respectively. + type: string + host: + description: Host is the hostname that the webhook server + binds to. It is used to set webhook.Server.Host. + type: string + port: + description: Port is the port that the webhook server serves + at. It is used to set webhook.Server.Port. + type: integer + type: object + type: object + secretName: + description: SecretName is the name of the Secret providing the configuration + variables for the current provider instance, like e.g. credentials. + Such configurations will be used when creating or upgrading provider + components. The contents of the secret will be treated as immutable. + If changes need to be made, a new object can be created and the + name should be updated. The contents should be in the form of key:value. + This secret must be in the same namespace as the provider. + type: string + secretNamespace: + description: SecretNamespace is the namespace of the Secret providing + the configuration variables. If not specified, the namespace of + the provider will be used. + type: string + version: + description: Version indicates the provider version. + type: string + type: object + status: + description: InfrastructureProviderStatus defines the observed state of + InfrastructureProvider. + properties: + conditions: + description: Conditions define the current service state of the provider. + items: + description: Condition defines an observation of a Cluster API resource + operational state. + properties: + lastTransitionTime: + description: 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: A human readable message indicating details about + the transition. This field may be empty. + type: string + reason: + description: The reason for the condition's last transition + in CamelCase. The specific API may choose whether or not this + field is considered a guaranteed API. This field may not be + empty. + type: string + severity: + description: Severity provides an explicit classification of + Reason code, so the users or machines can immediately understand + the current situation and act accordingly. The Severity field + MUST be set only when Status=False. + type: string + status: + description: Status of the condition, one of 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. + type: string + required: + - lastTransitionTime + - status + - type + type: object + type: array + contract: + description: Contract will contain the core provider contract that + the provider is abiding by, like e.g. v1alpha4. + type: string + installedVersion: + description: InstalledVersion is the version of the provider that + is installed. + type: string + observedGeneration: + description: ObservedGeneration is the latest generation observed + by the controller. + format: int64 + type: integer + type: object + type: object + served: true + storage: false + subresources: + status: {} + - additionalPrinterColumns: + - jsonPath: .status.installedVersion + name: InstalledVersion + type: string + - jsonPath: .status.conditions[?(@.type=='Ready')].status + name: Ready + type: string + name: v1alpha2 + schema: + openAPIV3Schema: + description: InfrastructureProvider is the Schema for the infrastructureproviders + 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: InfrastructureProviderSpec defines the desired state of InfrastructureProvider. + properties: + additionalManifests: + description: AdditionalManifests is reference to configmap that contains + additional manifests that will be applied together with the provider + components. The key for storing these manifests has to be `manifests`. + The manifests are applied only once when a certain release is installed/upgraded. + If namespace is not specified, the namespace of the provider will + be used. There is no validation of the yaml content inside the configmap. + properties: + name: + description: Name defines the name of the configmap. + type: string + namespace: + description: Namespace defines the namespace of the configmap. + type: string + required: + - name + type: object + configSecret: + description: ConfigSecret is the object with name and namespace of + the Secret providing the configuration variables for the current + provider instance, like e.g. credentials. Such configurations will + be used when creating or upgrading provider components. The contents + of the secret will be treated as immutable. If changes need to be + made, a new object can be created and the name should be updated. + The contents should be in the form of key:value. This secret must + be in the same namespace as the provider. + properties: + name: + description: Name defines the name of the secret. + type: string + namespace: + description: Namespace defines the namespace of the secret. + type: string + required: + - name + type: object + deployment: + description: Deployment defines the properties that can be enabled + on the deployment for the provider. + properties: + affinity: + description: If specified, the pod's scheduling constraints + properties: + nodeAffinity: + description: Describes node affinity scheduling rules for + the pod. + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods + to nodes that satisfy the affinity expressions specified + by this field, but it may choose a node that violates + one or more of the expressions. The node that is most + preferred is the one with the greatest sum of weights, + i.e. for each node that meets all of the scheduling + requirements (resource request, requiredDuringScheduling + affinity expressions, etc.), compute a sum by iterating + through the elements of this field and adding "weight" + to the sum if the node matches the corresponding matchExpressions; + the node(s) with the highest sum are the most preferred. + items: + description: An empty preferred scheduling term matches + all objects with implicit weight 0 (i.e. it's a no-op). + A null preferred scheduling term matches no objects + (i.e. is also a no-op). + properties: + preference: + description: A node selector term, associated with + the corresponding weight. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: 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. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: 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. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + x-kubernetes-map-type: atomic + weight: + description: Weight associated with matching the + corresponding nodeSelectorTerm, in the range 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by + this field are not met at scheduling time, the pod will + not be scheduled onto the node. If the affinity requirements + specified by this field cease to be met at some point + during pod execution (e.g. due to an update), the system + may or may not try to eventually evict the pod from + its node. + properties: + nodeSelectorTerms: + description: Required. A list of node selector terms. + The terms are ORed. + items: + description: A null or empty node selector term + matches no objects. The requirements of them are + ANDed. The TopologySelectorTerm type implements + a subset of the NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: 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. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: 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. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + x-kubernetes-map-type: atomic + type: array + required: + - nodeSelectorTerms + type: object + x-kubernetes-map-type: atomic + type: object + podAffinity: + description: Describes pod affinity scheduling rules (e.g. + co-locate this pod in the same node, zone, etc. as some + other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods + to nodes that satisfy the affinity expressions specified + by this field, but it may choose a node that violates + one or more of the expressions. The node that is most + preferred is the one with the greatest sum of weights, + i.e. for each node that meets all of the scheduling + requirements (resource request, requiredDuringScheduling + affinity expressions, etc.), compute a sum by iterating + through the elements of this field and adding "weight" + to the sum if the node has pods which matches the corresponding + podAffinityTerm; the node(s) with the highest sum are + the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by + this field and the ones listed in the namespaces + field. null selector and null or empty namespaces + list means "this pod's namespace". An empty + selector ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. + The term is applied to the union of the namespaces + listed in this field and the ones selected + by namespaceSelector. null or empty namespaces + list and null namespaceSelector means "this + pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the + pods matching the labelSelector in the specified + namespaces, where co-located is defined as + running on a node whose value of the label + with key topologyKey matches that of any node + on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching the + corresponding podAffinityTerm, in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by + this field are not met at scheduling time, the pod will + not be scheduled onto the node. If the affinity requirements + specified by this field cease to be met at some point + during pod execution (e.g. due to a pod label update), + the system may or may not try to eventually evict the + pod from its node. When there are multiple elements, + the lists of nodes corresponding to each podAffinityTerm + are intersected, i.e. all terms must be satisfied. + items: + description: Defines a set of pods (namely those matching + the labelSelector relative to the given namespace(s)) + that this pod should be co-located (affinity) or not + co-located (anti-affinity) with, where co-located + is defined as running on a node whose value of the + label with key matches that of any node + on which a pod of the set of pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by this + field and the ones listed in the namespaces field. + null selector and null or empty namespaces list + means "this pod's namespace". An empty selector + ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. The + term is applied to the union of the namespaces + listed in this field and the ones selected by + namespaceSelector. null or empty namespaces list + and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods + matching the labelSelector in the specified namespaces, + where co-located is defined as running on a node + whose value of the label with key topologyKey + matches that of any node on which any of the selected + pods is running. Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + podAntiAffinity: + description: Describes pod anti-affinity scheduling rules + (e.g. avoid putting this pod in the same node, zone, etc. + as some other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods + to nodes that satisfy the anti-affinity expressions + specified by this field, but it may choose a node that + violates one or more of the expressions. The node that + is most preferred is the one with the greatest sum of + weights, i.e. for each node that meets all of the scheduling + requirements (resource request, requiredDuringScheduling + anti-affinity expressions, etc.), compute a sum by iterating + through the elements of this field and adding "weight" + to the sum if the node has pods which matches the corresponding + podAffinityTerm; the node(s) with the highest sum are + the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by + this field and the ones listed in the namespaces + field. null selector and null or empty namespaces + list means "this pod's namespace". An empty + selector ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. + The term is applied to the union of the namespaces + listed in this field and the ones selected + by namespaceSelector. null or empty namespaces + list and null namespaceSelector means "this + pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the + pods matching the labelSelector in the specified + namespaces, where co-located is defined as + running on a node whose value of the label + with key topologyKey matches that of any node + on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching the + corresponding podAffinityTerm, in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the anti-affinity requirements specified + by this field are not met at scheduling time, the pod + will not be scheduled onto the node. If the anti-affinity + requirements specified by this field cease to be met + at some point during pod execution (e.g. due to a pod + label update), the system may or may not try to eventually + evict the pod from its node. When there are multiple + elements, the lists of nodes corresponding to each podAffinityTerm + are intersected, i.e. all terms must be satisfied. + items: + description: Defines a set of pods (namely those matching + the labelSelector relative to the given namespace(s)) + that this pod should be co-located (affinity) or not + co-located (anti-affinity) with, where co-located + is defined as running on a node whose value of the + label with key matches that of any node + on which a pod of the set of pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by this + field and the ones listed in the namespaces field. + null selector and null or empty namespaces list + means "this pod's namespace". An empty selector + ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. The + term is applied to the union of the namespaces + listed in this field and the ones selected by + namespaceSelector. null or empty namespaces list + and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods + matching the labelSelector in the specified namespaces, + where co-located is defined as running on a node + whose value of the label with key topologyKey + matches that of any node on which any of the selected + pods is running. Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + type: object + containers: + description: List of containers specified in the Deployment + items: + description: ContainerSpec defines the properties available + to override for each container in a provider deployment such + as Image and Args to the container’s entrypoint. + properties: + args: + additionalProperties: + type: string + description: Args represents extra provider specific flags + that are not encoded as fields in this API. Explicit controller + manager properties defined in the `Provider.ManagerSpec` + will have higher precedence than those defined in `ContainerSpec.Args`. + For example, `ManagerSpec.SyncPeriod` will be used instead + of the container arg `--sync-period` if both are defined. + The same holds for `ManagerSpec.FeatureGates` and `--feature-gates`. + type: object + command: + description: Command allows override container's entrypoint + array. + items: + type: string + type: array + env: + description: List of environment variables to set in the + container. + 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: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + 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: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + 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 + imageUrl: + description: Container Image URL + type: string + name: + description: Name of the container. Cannot be updated. + type: string + resources: + description: Compute resources required by this container. + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. \n 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 + 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 + required: + - name + type: object + type: array + imagePullSecrets: + description: List of image pull secrets specified in the Deployment + items: + description: LocalObjectReference contains enough information + to let you locate the referenced object inside the same namespace. + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + x-kubernetes-map-type: atomic + type: array + nodeSelector: + additionalProperties: + type: string + description: 'NodeSelector is a selector which must be true for + the pod to fit on a node. Selector which must match a node''s + labels for the pod to be scheduled on that node. More info: + https://kubernetes.io/docs/concepts/configuration/assign-pod-node/' + type: object + replicas: + description: Number of desired pods. This is a pointer to distinguish + between explicit zero and not specified. Defaults to 1. + minimum: 0 + type: integer + serviceAccountName: + description: If specified, the pod's service account + type: string + tolerations: + description: If specified, the pod's tolerations. + 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 + type: object + fetchConfig: + description: FetchConfig determines how the operator will fetch the + components and metadata for the provider. If nil, the operator will + try to fetch components according to default embedded fetch configuration + for the given kind and `ObjectMeta.Name`. For example, the infrastructure + name `aws` will fetch artifacts from https://github.com/kubernetes-sigs/cluster-api-provider-aws/releases. + properties: + selector: + description: 'Selector to be used for fetching provider’s components + and metadata from ConfigMaps stored inside the cluster. Each + ConfigMap is expected to contain components and metadata for + a specific version only. Note: the name of the ConfigMap should + be set to the version or to override this add a label like the + following: provider.cluster.x-k8s.io/version=v1.4.3' + 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 + required: + - key + - operator + type: object + type: array + 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 + url: + description: URL to be used for fetching the provider’s components + and metadata from a remote Github repository. For example, https://github.com/{owner}/{repository}/releases + You must set `providerSpec.Version` field for operator to pick + up desired version of the release from GitHub. + type: string + type: object + manager: + description: Manager defines the properties that can be enabled on + the controller manager for the provider. + properties: + cacheNamespace: + description: "CacheNamespace if specified restricts the manager's + cache to watch objects in the desired namespace Defaults to + all namespaces \n Note: If a namespace is specified, controllers + can still Watch for a cluster-scoped resource (e.g Node). For + namespaced resources the cache will only hold objects from the + desired namespace." + type: string + controller: + description: Controller contains global configuration options + for controllers registered within this manager. + properties: + cacheSyncTimeout: + description: CacheSyncTimeout refers to the time limit set + to wait for syncing caches. Defaults to 2 minutes if not + set. + format: int64 + type: integer + groupKindConcurrency: + additionalProperties: + type: integer + description: "GroupKindConcurrency is a map from a Kind to + the number of concurrent reconciliation allowed for that + controller. \n When a controller is registered within this + manager using the builder utilities, users have to specify + the type the controller reconciles in the For(...) call. + If the object's kind passed matches one of the keys in this + map, the concurrency for that controller is set to the number + specified. \n The key is expected to be consistent in form + with GroupKind.String(), e.g. ReplicaSet in apps group (regardless + of version) would be `ReplicaSet.apps`." + type: object + recoverPanic: + description: RecoverPanic indicates if panics should be recovered. + type: boolean + type: object + featureGates: + additionalProperties: + type: boolean + description: FeatureGates define provider specific feature flags + that will be passed in as container args to the provider's controller + manager. Controller Manager flag is --feature-gates. + type: object + gracefulShutDown: + description: GracefulShutdownTimeout is the duration given to + runnable to stop before the manager actually returns on stop. + To disable graceful shutdown, set to time.Duration(0) To use + graceful shutdown without timeout, set to a negative duration, + e.G. time.Duration(-1) The graceful shutdown is skipped for + safety reasons in case the leader election lease is lost. + type: string + health: + description: Health contains the controller health configuration + properties: + healthProbeBindAddress: + description: HealthProbeBindAddress is the TCP address that + the controller should bind to for serving health probes + It can be set to "0" or "" to disable serving the health + probe. + type: string + livenessEndpointName: + description: LivenessEndpointName, defaults to "healthz" + type: string + readinessEndpointName: + description: ReadinessEndpointName, defaults to "readyz" + type: string + type: object + leaderElection: + description: LeaderElection is the LeaderElection config to be + used when configuring the manager.Manager leader election + properties: + leaderElect: + description: leaderElect enables a leader election client + to gain leadership before executing the main loop. Enable + this when running replicated components for high availability. + type: boolean + leaseDuration: + description: leaseDuration is the duration that non-leader + candidates will wait after observing a leadership renewal + until attempting to acquire leadership of a led but unrenewed + leader slot. This is effectively the maximum duration that + a leader can be stopped before it is replaced by another + candidate. This is only applicable if leader election is + enabled. + type: string + renewDeadline: + description: renewDeadline is the interval between attempts + by the acting master to renew a leadership slot before it + stops leading. This must be less than or equal to the lease + duration. This is only applicable if leader election is + enabled. + type: string + resourceLock: + description: resourceLock indicates the resource object type + that will be used to lock during leader election cycles. + type: string + resourceName: + description: resourceName indicates the name of resource object + that will be used to lock during leader election cycles. + type: string + resourceNamespace: + description: resourceName indicates the namespace of resource + object that will be used to lock during leader election + cycles. + type: string + retryPeriod: + description: retryPeriod is the duration the clients should + wait between attempting acquisition and renewal of a leadership. + This is only applicable if leader election is enabled. + type: string + required: + - leaderElect + - leaseDuration + - renewDeadline + - resourceLock + - resourceName + - resourceNamespace + - retryPeriod + type: object + maxConcurrentReconciles: + description: MaxConcurrentReconciles is the maximum number of + concurrent Reconciles which can be run. + minimum: 1 + type: integer + metrics: + description: Metrics contains thw controller metrics configuration + properties: + bindAddress: + description: BindAddress is the TCP address that the controller + should bind to for serving prometheus metrics. It can be + set to "0" to disable the metrics serving. + type: string + type: object + profilerAddress: + description: ProfilerAddress defines the bind address to expose + the pprof profiler (e.g. localhost:6060). Default empty, meaning + the profiler is disabled. Controller Manager flag is --profiler-address. + type: string + syncPeriod: + description: SyncPeriod determines the minimum frequency at which + watched resources are reconciled. A lower period will correct + entropy more quickly, but reduce responsiveness to change if + there are many watched resources. Change this value only if + you know what you are doing. Defaults to 10 hours if unset. + there will a 10 percent jitter between the SyncPeriod of all + controllers so that all controllers will not send list requests + simultaneously. + type: string + verbosity: + default: 1 + description: Verbosity set the logs verbosity. Defaults to 1. + Controller Manager flag is --verbosity. + minimum: 0 + type: integer + webhook: + description: Webhook contains the controllers webhook configuration + properties: + certDir: + description: CertDir is the directory that contains the server + key and certificate. if not set, webhook server would look + up the server key and certificate in {TempDir}/k8s-webhook-server/serving-certs. + The server key and certificate must be named tls.key and + tls.crt, respectively. + type: string + host: + description: Host is the hostname that the webhook server + binds to. It is used to set webhook.Server.Host. + type: string + port: + description: Port is the port that the webhook server serves + at. It is used to set webhook.Server.Port. + type: integer + type: object + type: object + manifestPatches: + description: ManifestPatches are applied to rendered provider manifests + to customize the provider manifests. Patches are applied in the + order they are specified. The `kind` field must match the target + object, and if `apiVersion` is specified it will only be applied + to matching objects. This should be an inline yaml blob-string https://datatracker.ietf.org/doc/html/rfc7396 + items: + type: string + type: array + version: + description: Version indicates the provider version. + type: string + type: object + status: + description: InfrastructureProviderStatus defines the observed state of + InfrastructureProvider. + properties: + conditions: + description: Conditions define the current service state of the provider. + items: + description: Condition defines an observation of a Cluster API resource + operational state. + properties: + lastTransitionTime: + description: 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: A human readable message indicating details about + the transition. This field may be empty. + type: string + reason: + description: The reason for the condition's last transition + in CamelCase. The specific API may choose whether or not this + field is considered a guaranteed API. This field may not be + empty. + type: string + severity: + description: Severity provides an explicit classification of + Reason code, so the users or machines can immediately understand + the current situation and act accordingly. The Severity field + MUST be set only when Status=False. + type: string + status: + description: Status of the condition, one of 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. + type: string + required: + - lastTransitionTime + - status + - type + type: object + type: array + contract: + description: Contract will contain the core provider contract that + the provider is abiding by, like e.g. v1alpha4. + type: string + installedVersion: + description: InstalledVersion is the version of the provider that + is installed. + type: string + observedGeneration: + description: ObservedGeneration is the latest generation observed + by the controller. + format: int64 + type: integer + type: object + type: object + served: true + storage: true + subresources: + status: {} +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + cert-manager.io/inject-ca-from: '{{ .Release.Namespace }}/capi-operator-serving-cert' + controller-gen.kubebuilder.io/version: v0.11.4 + labels: + clusterctl.cluster.x-k8s.io/core: capi-operator + name: ipamproviders.operator.cluster.x-k8s.io +spec: + conversion: + strategy: Webhook + webhook: + clientConfig: + caBundle: Cg== + service: + name: capi-operator-webhook-service + namespace: '{{ .Release.Namespace }}' + path: /convert + conversionReviewVersions: + - v1 + - v1alpha1 + group: operator.cluster.x-k8s.io + names: + kind: IPAMProvider + listKind: IPAMProviderList + plural: ipamproviders + singular: ipamprovider + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .status.installedVersion + name: InstalledVersion + type: string + - jsonPath: .status.conditions[?(@.type=='Ready')].status + name: Ready + type: string + name: v1alpha2 + schema: + openAPIV3Schema: + description: IPAMProvider is the Schema for the IPAMProviders 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: IPAMProviderSpec defines the desired state of IPAMProvider. + properties: + additionalManifests: + description: AdditionalManifests is reference to configmap that contains + additional manifests that will be applied together with the provider + components. The key for storing these manifests has to be `manifests`. + The manifests are applied only once when a certain release is installed/upgraded. + If namespace is not specified, the namespace of the provider will + be used. There is no validation of the yaml content inside the configmap. + properties: + name: + description: Name defines the name of the configmap. + type: string + namespace: + description: Namespace defines the namespace of the configmap. + type: string + required: + - name + type: object + configSecret: + description: ConfigSecret is the object with name and namespace of + the Secret providing the configuration variables for the current + provider instance, like e.g. credentials. Such configurations will + be used when creating or upgrading provider components. The contents + of the secret will be treated as immutable. If changes need to be + made, a new object can be created and the name should be updated. + The contents should be in the form of key:value. This secret must + be in the same namespace as the provider. + properties: + name: + description: Name defines the name of the secret. + type: string + namespace: + description: Namespace defines the namespace of the secret. + type: string + required: + - name + type: object + deployment: + description: Deployment defines the properties that can be enabled + on the deployment for the provider. + properties: + affinity: + description: If specified, the pod's scheduling constraints + properties: + nodeAffinity: + description: Describes node affinity scheduling rules for + the pod. + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods + to nodes that satisfy the affinity expressions specified + by this field, but it may choose a node that violates + one or more of the expressions. The node that is most + preferred is the one with the greatest sum of weights, + i.e. for each node that meets all of the scheduling + requirements (resource request, requiredDuringScheduling + affinity expressions, etc.), compute a sum by iterating + through the elements of this field and adding "weight" + to the sum if the node matches the corresponding matchExpressions; + the node(s) with the highest sum are the most preferred. + items: + description: An empty preferred scheduling term matches + all objects with implicit weight 0 (i.e. it's a no-op). + A null preferred scheduling term matches no objects + (i.e. is also a no-op). + properties: + preference: + description: A node selector term, associated with + the corresponding weight. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: 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. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: 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. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + x-kubernetes-map-type: atomic + weight: + description: Weight associated with matching the + corresponding nodeSelectorTerm, in the range 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by + this field are not met at scheduling time, the pod will + not be scheduled onto the node. If the affinity requirements + specified by this field cease to be met at some point + during pod execution (e.g. due to an update), the system + may or may not try to eventually evict the pod from + its node. + properties: + nodeSelectorTerms: + description: Required. A list of node selector terms. + The terms are ORed. + items: + description: A null or empty node selector term + matches no objects. The requirements of them are + ANDed. The TopologySelectorTerm type implements + a subset of the NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: 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. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: 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. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + x-kubernetes-map-type: atomic + type: array + required: + - nodeSelectorTerms + type: object + x-kubernetes-map-type: atomic + type: object + podAffinity: + description: Describes pod affinity scheduling rules (e.g. + co-locate this pod in the same node, zone, etc. as some + other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods + to nodes that satisfy the affinity expressions specified + by this field, but it may choose a node that violates + one or more of the expressions. The node that is most + preferred is the one with the greatest sum of weights, + i.e. for each node that meets all of the scheduling + requirements (resource request, requiredDuringScheduling + affinity expressions, etc.), compute a sum by iterating + through the elements of this field and adding "weight" + to the sum if the node has pods which matches the corresponding + podAffinityTerm; the node(s) with the highest sum are + the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by + this field and the ones listed in the namespaces + field. null selector and null or empty namespaces + list means "this pod's namespace". An empty + selector ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. + The term is applied to the union of the namespaces + listed in this field and the ones selected + by namespaceSelector. null or empty namespaces + list and null namespaceSelector means "this + pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the + pods matching the labelSelector in the specified + namespaces, where co-located is defined as + running on a node whose value of the label + with key topologyKey matches that of any node + on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching the + corresponding podAffinityTerm, in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by + this field are not met at scheduling time, the pod will + not be scheduled onto the node. If the affinity requirements + specified by this field cease to be met at some point + during pod execution (e.g. due to a pod label update), + the system may or may not try to eventually evict the + pod from its node. When there are multiple elements, + the lists of nodes corresponding to each podAffinityTerm + are intersected, i.e. all terms must be satisfied. + items: + description: Defines a set of pods (namely those matching + the labelSelector relative to the given namespace(s)) + that this pod should be co-located (affinity) or not + co-located (anti-affinity) with, where co-located + is defined as running on a node whose value of the + label with key matches that of any node + on which a pod of the set of pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by this + field and the ones listed in the namespaces field. + null selector and null or empty namespaces list + means "this pod's namespace". An empty selector + ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. The + term is applied to the union of the namespaces + listed in this field and the ones selected by + namespaceSelector. null or empty namespaces list + and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods + matching the labelSelector in the specified namespaces, + where co-located is defined as running on a node + whose value of the label with key topologyKey + matches that of any node on which any of the selected + pods is running. Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + podAntiAffinity: + description: Describes pod anti-affinity scheduling rules + (e.g. avoid putting this pod in the same node, zone, etc. + as some other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods + to nodes that satisfy the anti-affinity expressions + specified by this field, but it may choose a node that + violates one or more of the expressions. The node that + is most preferred is the one with the greatest sum of + weights, i.e. for each node that meets all of the scheduling + requirements (resource request, requiredDuringScheduling + anti-affinity expressions, etc.), compute a sum by iterating + through the elements of this field and adding "weight" + to the sum if the node has pods which matches the corresponding + podAffinityTerm; the node(s) with the highest sum are + the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by + this field and the ones listed in the namespaces + field. null selector and null or empty namespaces + list means "this pod's namespace". An empty + selector ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. + The term is applied to the union of the namespaces + listed in this field and the ones selected + by namespaceSelector. null or empty namespaces + list and null namespaceSelector means "this + pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the + pods matching the labelSelector in the specified + namespaces, where co-located is defined as + running on a node whose value of the label + with key topologyKey matches that of any node + on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching the + corresponding podAffinityTerm, in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the anti-affinity requirements specified + by this field are not met at scheduling time, the pod + will not be scheduled onto the node. If the anti-affinity + requirements specified by this field cease to be met + at some point during pod execution (e.g. due to a pod + label update), the system may or may not try to eventually + evict the pod from its node. When there are multiple + elements, the lists of nodes corresponding to each podAffinityTerm + are intersected, i.e. all terms must be satisfied. + items: + description: Defines a set of pods (namely those matching + the labelSelector relative to the given namespace(s)) + that this pod should be co-located (affinity) or not + co-located (anti-affinity) with, where co-located + is defined as running on a node whose value of the + label with key matches that of any node + on which a pod of the set of pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by this + field and the ones listed in the namespaces field. + null selector and null or empty namespaces list + means "this pod's namespace". An empty selector + ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. The + term is applied to the union of the namespaces + listed in this field and the ones selected by + namespaceSelector. null or empty namespaces list + and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods + matching the labelSelector in the specified namespaces, + where co-located is defined as running on a node + whose value of the label with key topologyKey + matches that of any node on which any of the selected + pods is running. Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + type: object + containers: + description: List of containers specified in the Deployment + items: + description: ContainerSpec defines the properties available + to override for each container in a provider deployment such + as Image and Args to the container’s entrypoint. + properties: + args: + additionalProperties: + type: string + description: Args represents extra provider specific flags + that are not encoded as fields in this API. Explicit controller + manager properties defined in the `Provider.ManagerSpec` + will have higher precedence than those defined in `ContainerSpec.Args`. + For example, `ManagerSpec.SyncPeriod` will be used instead + of the container arg `--sync-period` if both are defined. + The same holds for `ManagerSpec.FeatureGates` and `--feature-gates`. + type: object + command: + description: Command allows override container's entrypoint + array. + items: + type: string + type: array + env: + description: List of environment variables to set in the + container. + 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: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + 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: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + 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 + imageUrl: + description: Container Image URL + type: string + name: + description: Name of the container. Cannot be updated. + type: string + resources: + description: Compute resources required by this container. + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. \n 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 + 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 + required: + - name + type: object + type: array + imagePullSecrets: + description: List of image pull secrets specified in the Deployment + items: + description: LocalObjectReference contains enough information + to let you locate the referenced object inside the same namespace. + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + x-kubernetes-map-type: atomic + type: array + nodeSelector: + additionalProperties: + type: string + description: 'NodeSelector is a selector which must be true for + the pod to fit on a node. Selector which must match a node''s + labels for the pod to be scheduled on that node. More info: + https://kubernetes.io/docs/concepts/configuration/assign-pod-node/' + type: object + replicas: + description: Number of desired pods. This is a pointer to distinguish + between explicit zero and not specified. Defaults to 1. + minimum: 0 + type: integer + serviceAccountName: + description: If specified, the pod's service account + type: string + tolerations: + description: If specified, the pod's tolerations. + 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 + type: object + fetchConfig: + description: FetchConfig determines how the operator will fetch the + components and metadata for the provider. If nil, the operator will + try to fetch components according to default embedded fetch configuration + for the given kind and `ObjectMeta.Name`. For example, the infrastructure + name `aws` will fetch artifacts from https://github.com/kubernetes-sigs/cluster-api-provider-aws/releases. + properties: + selector: + description: 'Selector to be used for fetching provider’s components + and metadata from ConfigMaps stored inside the cluster. Each + ConfigMap is expected to contain components and metadata for + a specific version only. Note: the name of the ConfigMap should + be set to the version or to override this add a label like the + following: provider.cluster.x-k8s.io/version=v1.4.3' + 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 + required: + - key + - operator + type: object + type: array + 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 + url: + description: URL to be used for fetching the provider’s components + and metadata from a remote Github repository. For example, https://github.com/{owner}/{repository}/releases + You must set `providerSpec.Version` field for operator to pick + up desired version of the release from GitHub. + type: string + type: object + manager: + description: Manager defines the properties that can be enabled on + the controller manager for the provider. + properties: + cacheNamespace: + description: "CacheNamespace if specified restricts the manager's + cache to watch objects in the desired namespace Defaults to + all namespaces \n Note: If a namespace is specified, controllers + can still Watch for a cluster-scoped resource (e.g Node). For + namespaced resources the cache will only hold objects from the + desired namespace." + type: string + controller: + description: Controller contains global configuration options + for controllers registered within this manager. + properties: + cacheSyncTimeout: + description: CacheSyncTimeout refers to the time limit set + to wait for syncing caches. Defaults to 2 minutes if not + set. + format: int64 + type: integer + groupKindConcurrency: + additionalProperties: + type: integer + description: "GroupKindConcurrency is a map from a Kind to + the number of concurrent reconciliation allowed for that + controller. \n When a controller is registered within this + manager using the builder utilities, users have to specify + the type the controller reconciles in the For(...) call. + If the object's kind passed matches one of the keys in this + map, the concurrency for that controller is set to the number + specified. \n The key is expected to be consistent in form + with GroupKind.String(), e.g. ReplicaSet in apps group (regardless + of version) would be `ReplicaSet.apps`." + type: object + recoverPanic: + description: RecoverPanic indicates if panics should be recovered. + type: boolean + type: object + featureGates: + additionalProperties: + type: boolean + description: FeatureGates define provider specific feature flags + that will be passed in as container args to the provider's controller + manager. Controller Manager flag is --feature-gates. + type: object + gracefulShutDown: + description: GracefulShutdownTimeout is the duration given to + runnable to stop before the manager actually returns on stop. + To disable graceful shutdown, set to time.Duration(0) To use + graceful shutdown without timeout, set to a negative duration, + e.G. time.Duration(-1) The graceful shutdown is skipped for + safety reasons in case the leader election lease is lost. + type: string + health: + description: Health contains the controller health configuration + properties: + healthProbeBindAddress: + description: HealthProbeBindAddress is the TCP address that + the controller should bind to for serving health probes + It can be set to "0" or "" to disable serving the health + probe. + type: string + livenessEndpointName: + description: LivenessEndpointName, defaults to "healthz" + type: string + readinessEndpointName: + description: ReadinessEndpointName, defaults to "readyz" + type: string + type: object + leaderElection: + description: LeaderElection is the LeaderElection config to be + used when configuring the manager.Manager leader election + properties: + leaderElect: + description: leaderElect enables a leader election client + to gain leadership before executing the main loop. Enable + this when running replicated components for high availability. + type: boolean + leaseDuration: + description: leaseDuration is the duration that non-leader + candidates will wait after observing a leadership renewal + until attempting to acquire leadership of a led but unrenewed + leader slot. This is effectively the maximum duration that + a leader can be stopped before it is replaced by another + candidate. This is only applicable if leader election is + enabled. + type: string + renewDeadline: + description: renewDeadline is the interval between attempts + by the acting master to renew a leadership slot before it + stops leading. This must be less than or equal to the lease + duration. This is only applicable if leader election is + enabled. + type: string + resourceLock: + description: resourceLock indicates the resource object type + that will be used to lock during leader election cycles. + type: string + resourceName: + description: resourceName indicates the name of resource object + that will be used to lock during leader election cycles. + type: string + resourceNamespace: + description: resourceName indicates the namespace of resource + object that will be used to lock during leader election + cycles. + type: string + retryPeriod: + description: retryPeriod is the duration the clients should + wait between attempting acquisition and renewal of a leadership. + This is only applicable if leader election is enabled. + type: string + required: + - leaderElect + - leaseDuration + - renewDeadline + - resourceLock + - resourceName + - resourceNamespace + - retryPeriod + type: object + maxConcurrentReconciles: + description: MaxConcurrentReconciles is the maximum number of + concurrent Reconciles which can be run. + minimum: 1 + type: integer + metrics: + description: Metrics contains thw controller metrics configuration + properties: + bindAddress: + description: BindAddress is the TCP address that the controller + should bind to for serving prometheus metrics. It can be + set to "0" to disable the metrics serving. + type: string + type: object + profilerAddress: + description: ProfilerAddress defines the bind address to expose + the pprof profiler (e.g. localhost:6060). Default empty, meaning + the profiler is disabled. Controller Manager flag is --profiler-address. + type: string + syncPeriod: + description: SyncPeriod determines the minimum frequency at which + watched resources are reconciled. A lower period will correct + entropy more quickly, but reduce responsiveness to change if + there are many watched resources. Change this value only if + you know what you are doing. Defaults to 10 hours if unset. + there will a 10 percent jitter between the SyncPeriod of all + controllers so that all controllers will not send list requests + simultaneously. + type: string + verbosity: + default: 1 + description: Verbosity set the logs verbosity. Defaults to 1. + Controller Manager flag is --verbosity. + minimum: 0 + type: integer + webhook: + description: Webhook contains the controllers webhook configuration + properties: + certDir: + description: CertDir is the directory that contains the server + key and certificate. if not set, webhook server would look + up the server key and certificate in {TempDir}/k8s-webhook-server/serving-certs. + The server key and certificate must be named tls.key and + tls.crt, respectively. + type: string + host: + description: Host is the hostname that the webhook server + binds to. It is used to set webhook.Server.Host. + type: string + port: + description: Port is the port that the webhook server serves + at. It is used to set webhook.Server.Port. + type: integer + type: object + type: object + manifestPatches: + description: ManifestPatches are applied to rendered provider manifests + to customize the provider manifests. Patches are applied in the + order they are specified. The `kind` field must match the target + object, and if `apiVersion` is specified it will only be applied + to matching objects. This should be an inline yaml blob-string https://datatracker.ietf.org/doc/html/rfc7396 + items: + type: string + type: array + version: + description: Version indicates the provider version. + type: string + type: object + status: + description: IPAMProviderStatus defines the observed state of IPAMProvider. + properties: + conditions: + description: Conditions define the current service state of the provider. + items: + description: Condition defines an observation of a Cluster API resource + operational state. + properties: + lastTransitionTime: + description: 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: A human readable message indicating details about + the transition. This field may be empty. + type: string + reason: + description: The reason for the condition's last transition + in CamelCase. The specific API may choose whether or not this + field is considered a guaranteed API. This field may not be + empty. + type: string + severity: + description: Severity provides an explicit classification of + Reason code, so the users or machines can immediately understand + the current situation and act accordingly. The Severity field + MUST be set only when Status=False. + type: string + status: + description: Status of the condition, one of 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. + type: string + required: + - lastTransitionTime + - status + - type + type: object + type: array + contract: + description: Contract will contain the core provider contract that + the provider is abiding by, like e.g. v1alpha4. + type: string + installedVersion: + description: InstalledVersion is the version of the provider that + is installed. + type: string + observedGeneration: + description: ObservedGeneration is the latest generation observed + by the controller. + format: int64 + type: integer + type: object + type: object + served: true + storage: true + subresources: + status: {} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + labels: + clusterctl.cluster.x-k8s.io/core: capi-operator + name: capi-operator-leader-election-role + namespace: '{{ .Release.Namespace }}' +rules: +- apiGroups: + - "" + resources: + - configmaps + verbs: + - get + - list + - watch + - create + - update + - patch + - delete +- apiGroups: + - "" + resources: + - configmaps/status + verbs: + - get + - update + - patch +- apiGroups: + - "" + resources: + - events + verbs: + - create +- apiGroups: + - coordination.k8s.io + resources: + - leases + verbs: + - get + - list + - watch + - create + - update + - patch + - delete +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + clusterctl.cluster.x-k8s.io/core: capi-operator + name: capi-operator-manager-role +rules: +- apiGroups: + - '*' + resources: + - '*' + verbs: + - '*' +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + labels: + clusterctl.cluster.x-k8s.io/core: capi-operator + name: capi-operator-leader-election-rolebinding + namespace: '{{ .Release.Namespace }}' +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: capi-operator-leader-election-role +subjects: +- kind: ServiceAccount + name: default + namespace: '{{ .Release.Namespace }}' +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + labels: + clusterctl.cluster.x-k8s.io/core: capi-operator + name: capi-operator-manager-rolebinding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: capi-operator-manager-role +subjects: +- kind: ServiceAccount + name: default + namespace: '{{ .Release.Namespace }}' +--- +apiVersion: v1 +kind: Service +metadata: + labels: + clusterctl.cluster.x-k8s.io/core: capi-operator + name: capi-operator-webhook-service + namespace: '{{ .Release.Namespace }}' +spec: + ports: + - port: 443 + targetPort: 9443 + selector: + clusterctl.cluster.x-k8s.io/core: capi-operator + control-plane: controller-manager +--- +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + labels: + clusterctl.cluster.x-k8s.io/core: capi-operator + name: capi-operator-serving-cert + namespace: '{{ .Release.Namespace }}' +spec: + dnsNames: + - capi-operator-webhook-service.{{ .Release.Namespace }}.svc + - capi-operator-webhook-service.{{ .Release.Namespace }}.svc.cluster.local + issuerRef: + kind: Issuer + name: capi-operator-selfsigned-issuer + secretName: capi-operator-webhook-service-cert +--- +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + labels: + clusterctl.cluster.x-k8s.io/core: capi-operator + name: capi-operator-selfsigned-issuer + namespace: '{{ .Release.Namespace }}' +spec: + selfSigned: {} +--- +apiVersion: admissionregistration.k8s.io/v1 +kind: MutatingWebhookConfiguration +metadata: + annotations: + cert-manager.io/inject-ca-from: '{{ .Release.Namespace }}/capi-operator-serving-cert' + labels: + clusterctl.cluster.x-k8s.io/core: capi-operator + name: capi-operator-mutating-webhook-configuration +webhooks: +- admissionReviewVersions: + - v1 + - v1beta1 + clientConfig: + service: + name: capi-operator-webhook-service + namespace: '{{ .Release.Namespace }}' + path: /mutate-operator-cluster-x-k8s-io-v1alpha2-addonprovider + failurePolicy: Fail + matchPolicy: Equivalent + name: vaddonprovider.kb.io + rules: + - apiGroups: + - operator.cluster.x-k8s.io + apiVersions: + - v1alpha2 + operations: + - CREATE + - UPDATE + resources: + - addonproviders + sideEffects: None +- admissionReviewVersions: + - v1 + - v1beta1 + clientConfig: + service: + name: capi-operator-webhook-service + namespace: '{{ .Release.Namespace }}' + path: /mutate-operator-cluster-x-k8s-io-v1alpha2-bootstrapprovider + failurePolicy: Fail + matchPolicy: Equivalent + name: vbootstrapprovider.kb.io + rules: + - apiGroups: + - operator.cluster.x-k8s.io + apiVersions: + - v1alpha2 + operations: + - CREATE + - UPDATE + resources: + - bootstrapproviders + sideEffects: None +- admissionReviewVersions: + - v1 + - v1beta1 + clientConfig: + service: + name: capi-operator-webhook-service + namespace: '{{ .Release.Namespace }}' + path: /mutate-operator-cluster-x-k8s-io-v1alpha2-controlplaneprovider + failurePolicy: Fail + matchPolicy: Equivalent + name: vcontrolplaneprovider.kb.io + rules: + - apiGroups: + - operator.cluster.x-k8s.io + apiVersions: + - v1alpha2 + operations: + - CREATE + - UPDATE + resources: + - controlplaneproviders + sideEffects: None +- admissionReviewVersions: + - v1 + - v1beta1 + clientConfig: + service: + name: capi-operator-webhook-service + namespace: '{{ .Release.Namespace }}' + path: /mutate-operator-cluster-x-k8s-io-v1alpha2-coreprovider + failurePolicy: Fail + matchPolicy: Equivalent + name: vcoreprovider.kb.io + rules: + - apiGroups: + - operator.cluster.x-k8s.io + apiVersions: + - v1alpha2 + operations: + - CREATE + - UPDATE + resources: + - coreproviders + sideEffects: None +- admissionReviewVersions: + - v1 + - v1beta1 + clientConfig: + service: + name: capi-operator-webhook-service + namespace: '{{ .Release.Namespace }}' + path: /mutate-operator-cluster-x-k8s-io-v1alpha2-infrastructureprovider + failurePolicy: Fail + matchPolicy: Equivalent + name: vinfrastructureprovider.kb.io + rules: + - apiGroups: + - operator.cluster.x-k8s.io + apiVersions: + - v1alpha2 + operations: + - CREATE + - UPDATE + resources: + - infrastructureproviders + sideEffects: None +- admissionReviewVersions: + - v1 + - v1beta1 + clientConfig: + service: + name: capi-operator-webhook-service + namespace: '{{ .Release.Namespace }}' + path: /mutate-operator-cluster-x-k8s-io-v1alpha2-ipamprovider + failurePolicy: Fail + matchPolicy: Equivalent + name: vipamprovider.kb.io + rules: + - apiGroups: + - operator.cluster.x-k8s.io + apiVersions: + - v1alpha2 + operations: + - CREATE + - UPDATE + resources: + - ipamproviders + sideEffects: None +--- +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingWebhookConfiguration +metadata: + annotations: + cert-manager.io/inject-ca-from: '{{ .Release.Namespace }}/capi-operator-serving-cert' + labels: + clusterctl.cluster.x-k8s.io/core: capi-operator + name: capi-operator-validating-webhook-configuration +webhooks: +- admissionReviewVersions: + - v1 + - v1beta1 + clientConfig: + service: + name: capi-operator-webhook-service + namespace: '{{ .Release.Namespace }}' + path: /validate-operator-cluster-x-k8s-io-v1alpha2-addonprovider + failurePolicy: Fail + matchPolicy: Equivalent + name: vaddonprovider.kb.io + rules: + - apiGroups: + - operator.cluster.x-k8s.io + apiVersions: + - v1alpha2 + operations: + - CREATE + - UPDATE + resources: + - addonproviders + sideEffects: None +- admissionReviewVersions: + - v1 + - v1beta1 + clientConfig: + service: + name: capi-operator-webhook-service + namespace: '{{ .Release.Namespace }}' + path: /validate-operator-cluster-x-k8s-io-v1alpha2-bootstrapprovider + failurePolicy: Fail + matchPolicy: Equivalent + name: vbootstrapprovider.kb.io + rules: + - apiGroups: + - operator.cluster.x-k8s.io + apiVersions: + - v1alpha2 + operations: + - CREATE + - UPDATE + resources: + - bootstrapproviders + sideEffects: None +- admissionReviewVersions: + - v1 + - v1beta1 + clientConfig: + service: + name: capi-operator-webhook-service + namespace: '{{ .Release.Namespace }}' + path: /validate-operator-cluster-x-k8s-io-v1alpha2-controlplaneprovider + failurePolicy: Fail + matchPolicy: Equivalent + name: vcontrolplaneprovider.kb.io + rules: + - apiGroups: + - operator.cluster.x-k8s.io + apiVersions: + - v1alpha2 + operations: + - CREATE + - UPDATE + resources: + - controlplaneproviders + sideEffects: None +- admissionReviewVersions: + - v1 + - v1beta1 + clientConfig: + service: + name: capi-operator-webhook-service + namespace: '{{ .Release.Namespace }}' + path: /validate-operator-cluster-x-k8s-io-v1alpha2-coreprovider + failurePolicy: Fail + matchPolicy: Equivalent + name: vcoreprovider.kb.io + rules: + - apiGroups: + - operator.cluster.x-k8s.io + apiVersions: + - v1alpha2 + operations: + - CREATE + - UPDATE + resources: + - coreproviders + sideEffects: None +- admissionReviewVersions: + - v1 + - v1beta1 + clientConfig: + service: + name: capi-operator-webhook-service + namespace: '{{ .Release.Namespace }}' + path: /validate-operator-cluster-x-k8s-io-v1alpha2-infrastructureprovider + failurePolicy: Fail + matchPolicy: Equivalent + name: vinfrastructureprovider.kb.io + rules: + - apiGroups: + - operator.cluster.x-k8s.io + apiVersions: + - v1alpha2 + operations: + - CREATE + - UPDATE + resources: + - infrastructureproviders + sideEffects: None +- admissionReviewVersions: + - v1 + - v1beta1 + clientConfig: + service: + name: capi-operator-webhook-service + namespace: '{{ .Release.Namespace }}' + path: /validate-operator-cluster-x-k8s-io-v1alpha2-ipamprovider + failurePolicy: Fail + matchPolicy: Equivalent + name: vipamprovider.kb.io + rules: + - apiGroups: + - operator.cluster.x-k8s.io + apiVersions: + - v1alpha2 + operations: + - CREATE + - UPDATE + resources: + - ipamproviders + sideEffects: None diff --git a/packages/system/capi-operator/charts/cluster-api-operator/values.yaml b/packages/system/capi-operator/charts/cluster-api-operator/values.yaml new file mode 100644 index 00000000..7575c8bd --- /dev/null +++ b/packages/system/capi-operator/charts/cluster-api-operator/values.yaml @@ -0,0 +1,72 @@ +--- +# Cert Manager options +# Full list of supported values is available at https://artifacthub.io/packages/helm/cert-manager/cert-manager +cert-manager: + enabled: false + fullnameOverride: "cert-manager" + namespace: "cert-manager" +# --- +# Cluster API provider options +core: "" +bootstrap: "" +controlPlane: "" +infrastructure: "" +addon: "" +# --- +# Common configuration secret options +configSecret: {} +# --- +# CAPI operator deployment options +logLevel: 2 +replicaCount: 1 +leaderElection: + enabled: true +image: + manager: + repository: registry.k8s.io/capi-operator/cluster-api-operator + tag: v0.8.1 + pullPolicy: IfNotPresent +healthAddr: ":8081" +metricsBindAddr: "127.0.0.1:8080" +diagnosticsAddress: "8443" +insecureDiagnostics: false +imagePullSecrets: {} +resources: + manager: + limits: + cpu: 100m + memory: 150Mi + requests: + cpu: 100m + memory: 100Mi +containerSecurityContext: {} +affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: kubernetes.io/arch + operator: In + values: + - amd64 + - arm64 + - ppc64le + - key: kubernetes.io/os + operator: In + values: + - linux +tolerations: + - effect: NoSchedule + key: node-role.kubernetes.io/master + - effect: NoSchedule + key: node-role.kubernetes.io/control-plane +volumes: + - name: cert + secret: + defaultMode: 420 + secretName: capi-operator-webhook-service-cert +volumeMounts: + manager: + - mountPath: /tmp/k8s-webhook-server/serving-certs + name: cert + readOnly: true diff --git a/packages/system/capi-providers/Chart.yaml b/packages/system/capi-providers/Chart.yaml new file mode 100644 index 00000000..ec1d9406 --- /dev/null +++ b/packages/system/capi-providers/Chart.yaml @@ -0,0 +1,2 @@ +name: cozy-capi-providers +version: 1.0.0 diff --git a/packages/system/capi-providers/Makefile b/packages/system/capi-providers/Makefile new file mode 100644 index 00000000..9dfff074 --- /dev/null +++ b/packages/system/capi-providers/Makefile @@ -0,0 +1,11 @@ +NAME=capi-providers +NAMESPACE=cozy-cluster-api + +show: + helm template --dry-run=server -n $(NAMESPACE) $(NAME) . + +apply: + helm upgrade -i -n $(NAMESPACE) $(NAME) . + +diff: + helm diff upgrade --allow-unreleased --normalize-manifests -n $(NAMESPACE) $(NAME) . diff --git a/packages/system/capi-providers/templates/providers.yaml b/packages/system/capi-providers/templates/providers.yaml new file mode 100644 index 00000000..eff303ec --- /dev/null +++ b/packages/system/capi-providers/templates/providers.yaml @@ -0,0 +1,26 @@ +--- +apiVersion: operator.cluster.x-k8s.io/v1alpha2 +kind: CoreProvider +metadata: + name: cluster-api +--- +apiVersion: operator.cluster.x-k8s.io/v1alpha2 +kind: ControlPlaneProvider +metadata: + name: kamaji +spec: + # fix: https://github.com/clastix/cluster-api-control-plane-provider-kamaji/pull/78 + deployment: + containers: + - name: manager + imageUrl: ghcr.io/kvaps/test:cluster-api-control-plane-provider-kamaji-v0.6.0-fix7 +--- +apiVersion: operator.cluster.x-k8s.io/v1alpha2 +kind: BootstrapProvider +metadata: + name: kubeadm +--- +apiVersion: operator.cluster.x-k8s.io/v1alpha2 +kind: InfrastructureProvider +metadata: + name: kubevirt diff --git a/packages/system/cert-manager-issuers/.helmignore b/packages/system/cert-manager-issuers/.helmignore new file mode 100644 index 00000000..216b462f --- /dev/null +++ b/packages/system/cert-manager-issuers/.helmignore @@ -0,0 +1,2 @@ +images +hack diff --git a/packages/system/cert-manager-issuers/Chart.yaml b/packages/system/cert-manager-issuers/Chart.yaml new file mode 100644 index 00000000..5f968971 --- /dev/null +++ b/packages/system/cert-manager-issuers/Chart.yaml @@ -0,0 +1,2 @@ +name: cozy-cert-manager-issuers +version: 1.0.0 diff --git a/packages/system/cert-manager-issuers/Makefile b/packages/system/cert-manager-issuers/Makefile new file mode 100644 index 00000000..135de3ba --- /dev/null +++ b/packages/system/cert-manager-issuers/Makefile @@ -0,0 +1,11 @@ +NAME=cert-manager-issuers +NAMESPACE=cozy-cert-manager + +show: + helm template --dry-run=server -n $(NAMESPACE) $(NAME) . + +apply: + helm upgrade -i -n $(NAMESPACE) $(NAME) . + +diff: + helm diff upgrade --allow-unreleased --normalize-manifests -n $(NAMESPACE) $(NAME) . diff --git a/packages/system/cert-manager-issuers/templates/cluster-issuers.yaml b/packages/system/cert-manager-issuers/templates/cluster-issuers.yaml new file mode 100644 index 00000000..83f9be1b --- /dev/null +++ b/packages/system/cert-manager-issuers/templates/cluster-issuers.yaml @@ -0,0 +1,28 @@ +apiVersion: cert-manager.io/v1 +kind: ClusterIssuer +metadata: + annotations: + name: letsencrypt-prod +spec: + acme: + privateKeySecretRef: + name: letsencrypt-prod + server: https://acme-v02.api.letsencrypt.org/directory + solvers: + - http01: + ingress: + class: nginx +--- +apiVersion: cert-manager.io/v1 +kind: ClusterIssuer +metadata: + name: letsencrypt-stage +spec: + acme: + privateKeySecretRef: + name: letsencrypt-stage + server: https://acme-staging-v02.api.letsencrypt.org/directory + solvers: + - http01: + ingress: + class: nginx diff --git a/packages/system/cert-manager-issuers/values.yaml b/packages/system/cert-manager-issuers/values.yaml new file mode 100644 index 00000000..0b21fc93 --- /dev/null +++ b/packages/system/cert-manager-issuers/values.yaml @@ -0,0 +1,2 @@ +cert-manager: + installCRDs: true diff --git a/packages/system/cert-manager/.helmignore b/packages/system/cert-manager/.helmignore new file mode 100644 index 00000000..216b462f --- /dev/null +++ b/packages/system/cert-manager/.helmignore @@ -0,0 +1,2 @@ +images +hack diff --git a/packages/system/cert-manager/Chart.yaml b/packages/system/cert-manager/Chart.yaml new file mode 100644 index 00000000..fe2ef8c0 --- /dev/null +++ b/packages/system/cert-manager/Chart.yaml @@ -0,0 +1,2 @@ +name: cozy-cert-manager +version: 1.0.0 diff --git a/packages/system/cert-manager/Makefile b/packages/system/cert-manager/Makefile new file mode 100644 index 00000000..53305d33 --- /dev/null +++ b/packages/system/cert-manager/Makefile @@ -0,0 +1,17 @@ +NAME=cert-manager +NAMESPACE=cozy-cert-manager + +show: + helm template --dry-run=server -n $(NAMESPACE) $(NAME) . + +apply: + helm upgrade -i -n $(NAMESPACE) $(NAME) . + +diff: + helm diff upgrade --allow-unreleased --normalize-manifests -n $(NAMESPACE) $(NAME) . + +update: + rm -rf charts + helm repo add jetstack https://charts.jetstack.io + helm repo update jetstack + helm pull jetstack/cert-manager --untar --untardir charts diff --git a/packages/system/cert-manager/charts/cert-manager/Chart.yaml b/packages/system/cert-manager/charts/cert-manager/Chart.yaml new file mode 100644 index 00000000..a491e9f5 --- /dev/null +++ b/packages/system/cert-manager/charts/cert-manager/Chart.yaml @@ -0,0 +1,24 @@ +annotations: + artifacthub.io/prerelease: "false" + artifacthub.io/signKey: | + fingerprint: 1020CF3C033D4F35BAE1C19E1226061C665DF13E + url: https://cert-manager.io/public-keys/cert-manager-keyring-2021-09-20-1020CF3C033D4F35BAE1C19E1226061C665DF13E.gpg +apiVersion: v1 +appVersion: v1.12.3 +description: A Helm chart for cert-manager +home: https://github.com/cert-manager/cert-manager +icon: https://raw.githubusercontent.com/cert-manager/cert-manager/d53c0b9270f8cd90d908460d69502694e1838f5f/logo/logo-small.png +keywords: +- cert-manager +- kube-lego +- letsencrypt +- tls +kubeVersion: '>= 1.22.0-0' +maintainers: +- email: cert-manager-maintainers@googlegroups.com + name: cert-manager-maintainers + url: https://cert-manager.io +name: cert-manager +sources: +- https://github.com/cert-manager/cert-manager +version: v1.12.3 diff --git a/packages/system/cert-manager/charts/cert-manager/README.md b/packages/system/cert-manager/charts/cert-manager/README.md new file mode 100644 index 00000000..d613a03e --- /dev/null +++ b/packages/system/cert-manager/charts/cert-manager/README.md @@ -0,0 +1,271 @@ +# cert-manager + +cert-manager is a Kubernetes addon to automate the management and issuance of +TLS certificates from various issuing sources. + +It will ensure certificates are valid and up to date periodically, and attempt +to renew certificates at an appropriate time before expiry. + +## Prerequisites + +- Kubernetes 1.20+ + +## Installing the Chart + +Full installation instructions, including details on how to configure extra +functionality in cert-manager can be found in the [installation docs](https://cert-manager.io/docs/installation/kubernetes/). + +Before installing the chart, you must first install the cert-manager CustomResourceDefinition resources. +This is performed in a separate step to allow you to easily uninstall and reinstall cert-manager without deleting your installed custom resources. + +```bash +$ kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.12.3/cert-manager.crds.yaml +``` + +To install the chart with the release name `my-release`: + +```console +## Add the Jetstack Helm repository +$ helm repo add jetstack https://charts.jetstack.io + +## Install the cert-manager helm chart +$ helm install my-release --namespace cert-manager --version v1.12.3 jetstack/cert-manager +``` + +In order to begin issuing certificates, you will need to set up a ClusterIssuer +or Issuer resource (for example, by creating a 'letsencrypt-staging' issuer). + +More information on the different types of issuers and how to configure them +can be found in [our documentation](https://cert-manager.io/docs/configuration/). + +For information on how to configure cert-manager to automatically provision +Certificates for Ingress resources, take a look at the +[Securing Ingresses documentation](https://cert-manager.io/docs/usage/ingress/). + +> **Tip**: List all releases using `helm list` + +## Upgrading the Chart + +Special considerations may be required when upgrading the Helm chart, and these +are documented in our full [upgrading guide](https://cert-manager.io/docs/installation/upgrading/). + +**Please check here before performing upgrades!** + +## Uninstalling the Chart + +To uninstall/delete the `my-release` deployment: + +```console +$ helm delete my-release +``` + +The command removes all the Kubernetes components associated with the chart and deletes the release. + +If you want to completely uninstall cert-manager from your cluster, you will also need to +delete the previously installed CustomResourceDefinition resources: + +```console +$ kubectl delete -f https://github.com/cert-manager/cert-manager/releases/download/v1.12.3/cert-manager.crds.yaml +``` + +## Configuration + +The following table lists the configurable parameters of the cert-manager chart and their default values. + +| Parameter | Description | Default | +| --------- | ----------- | ------- | +| `global.imagePullSecrets` | Reference to one or more secrets to be used when pulling images | `[]` | +| `global.commonLabels` | Labels to apply to all resources | `{}` | +| `global.rbac.create` | If `true`, create and use RBAC resources (includes sub-charts) | `true` | +| `global.priorityClassName`| Priority class name for cert-manager and webhook pods | `""` | +| `global.podSecurityPolicy.enabled` | If `true`, create and use PodSecurityPolicy (includes sub-charts) | `false` | +| `global.podSecurityPolicy.useAppArmor` | If `true`, use Apparmor seccomp profile in PSP | `true` | +| `global.leaderElection.namespace` | Override the namespace used to store the ConfigMap for leader election | `kube-system` | +| `global.leaderElection.leaseDuration` | The duration that non-leader candidates will wait after observing a leadership renewal until attempting to acquire leadership of a led but unrenewed leader slot. This is effectively the maximum duration that a leader can be stopped before it is replaced by another candidate | | +| `global.leaderElection.renewDeadline` | The interval between attempts by the acting master to renew a leadership slot before it stops leading. This must be less than or equal to the lease duration | | +| `global.leaderElection.retryPeriod` | The duration the clients should wait between attempting acquisition and renewal of a leadership | | +| `installCRDs` | If true, CRD resources will be installed as part of the Helm chart. If enabled, when uninstalling CRD resources will be deleted causing all installed custom resources to be DELETED | `false` | +| `image.repository` | Image repository | `quay.io/jetstack/cert-manager-controller` | +| `image.tag` | Image tag | `v1.12.3` | +| `image.pullPolicy` | Image pull policy | `IfNotPresent` | +| `replicaCount` | Number of cert-manager replicas | `1` | +| `clusterResourceNamespace` | Override the namespace used to store DNS provider credentials etc. for ClusterIssuer resources | Same namespace as cert-manager pod | +| `featureGates` | Set of comma-separated key=value pairs that describe feature gates on the controller. Some feature gates may also have to be enabled on other components, and can be set supplying the `feature-gate` flag to `.extraArgs` | `` | +| `extraArgs` | Optional flags for cert-manager | `[]` | +| `extraEnv` | Optional environment variables for cert-manager | `[]` | +| `serviceAccount.create` | If `true`, create a new service account | `true` | +| `serviceAccount.name` | Service account to be used. If not set and `serviceAccount.create` is `true`, a name is generated using the fullname template | | +| `serviceAccount.annotations` | Annotations to add to the service account | | +| `serviceAccount.automountServiceAccountToken` | Automount API credentials for the Service Account | `true` | +| `volumes` | Optional volumes for cert-manager | `[]` | +| `volumeMounts` | Optional volume mounts for cert-manager | `[]` | +| `resources` | CPU/memory resource requests/limits | `{}` | +| `securityContext` | Security context for the controller pod assignment | refer to [Default Security Contexts](#default-security-contexts) | +| `containerSecurityContext` | Security context to be set on the controller component container | refer to [Default Security Contexts](#default-security-contexts) | +| `nodeSelector` | Node labels for pod assignment | `{}` | +| `affinity` | Node affinity for pod assignment | `{}` | +| `tolerations` | Node tolerations for pod assignment | `[]` | +| `topologySpreadConstraints` | Topology spread constraints for pod assignment | `[]` | +| `livenessProbe.enabled` | Enable or disable the liveness probe for the controller container in the controller Pod. See https://cert-manager.io/docs/installation/best-practice/ to learn about when you might want to enable this livenss probe. | `false` | +| `livenessProbe.initialDelaySeconds` | The liveness probe initial delay (in seconds) | `10` | +| `livenessProbe.periodSeconds` | The liveness probe period (in seconds) | `10` | +| `livenessProbe.timeoutSeconds` | The liveness probe timeout (in seconds) | `10` | +| `livenessProbe.periodSeconds` | The liveness probe period (in seconds) | `10` | +| `livenessProbe.successThreshold` | The liveness probe success threshold | `1` | +| `livenessProbe.failureThreshold` | The liveness probe failure threshold | `8` | +| `ingressShim.defaultIssuerName` | Optional default issuer to use for ingress resources | | +| `ingressShim.defaultIssuerKind` | Optional default issuer kind to use for ingress resources | | +| `ingressShim.defaultIssuerGroup` | Optional default issuer group to use for ingress resources | | +| `prometheus.enabled` | Enable Prometheus monitoring | `true` | +| `prometheus.servicemonitor.enabled` | Enable Prometheus Operator ServiceMonitor monitoring | `false` | +| `prometheus.servicemonitor.namespace` | Define namespace where to deploy the ServiceMonitor resource | (namespace where you are deploying) | +| `prometheus.servicemonitor.prometheusInstance` | Prometheus Instance definition | `default` | +| `prometheus.servicemonitor.targetPort` | Prometheus scrape port | `9402` | +| `prometheus.servicemonitor.path` | Prometheus scrape path | `/metrics` | +| `prometheus.servicemonitor.interval` | Prometheus scrape interval | `60s` | +| `prometheus.servicemonitor.labels` | Add custom labels to ServiceMonitor | | +| `prometheus.servicemonitor.scrapeTimeout` | Prometheus scrape timeout | `30s` | +| `prometheus.servicemonitor.honorLabels` | Enable label honoring for metrics scraped by Prometheus (see [Prometheus scrape config docs](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#scrape_config) for details). By setting `honorLabels` to `true`, Prometheus will prefer label contents given by cert-manager on conflicts. Can be used to remove the "exported_namespace" label for example. | `false` | +| `podAnnotations` | Annotations to add to the cert-manager pod | `{}` | +| `deploymentAnnotations` | Annotations to add to the cert-manager deployment | `{}` | +| `podDisruptionBudget.enabled` | Adds a PodDisruptionBudget for the cert-manager deployment | `false` | +| `podDisruptionBudget.minAvailable` | Configures the minimum available pods for voluntary disruptions. Cannot used if `maxUnavailable` is set. | `1` | +| `podDisruptionBudget.maxUnavailable` | Configures the maximum unavailable pods for voluntary disruptions. Cannot used if `minAvailable` is set. | | +| `podDnsPolicy` | Optional cert-manager pod [DNS policy](https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pods-dns-policy) | | +| `podDnsConfig` | Optional cert-manager pod [DNS configurations](https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pods-dns-config) | | +| `podLabels` | Labels to add to the cert-manager pod | `{}` | +| `serviceLabels` | Labels to add to the cert-manager controller service | `{}` | +| `serviceAnnotations` | Annotations to add to the cert-manager service | `{}` | +| `http_proxy` | Value of the `HTTP_PROXY` environment variable in the cert-manager pod | | +| `https_proxy` | Value of the `HTTPS_PROXY` environment variable in the cert-manager pod | | +| `no_proxy` | Value of the `NO_PROXY` environment variable in the cert-manager pod | | +| `dns01RecursiveNameservers` | Comma separated string with host and port of the recursive nameservers cert-manager should query | `` | +| `dns01RecursiveNameserversOnly` | Forces cert-manager to only use the recursive nameservers for verification. | `false` | +| `enableCertificateOwnerRef` | When this flag is enabled, secrets will be automatically removed when the certificate resource is deleted | `false` | +| `webhook.replicaCount` | Number of cert-manager webhook replicas | `1` | +| `webhook.timeoutSeconds` | Seconds the API server should wait the webhook to respond before treating the call as a failure. | `10` | +| `webhook.podAnnotations` | Annotations to add to the webhook pods | `{}` | +| `webhook.podLabels` | Labels to add to the cert-manager webhook pod | `{}` | +| `webhook.serviceLabels` | Labels to add to the cert-manager webhook service | `{}` | +| `webhook.deploymentAnnotations` | Annotations to add to the webhook deployment | `{}` | +| `webhook.podDisruptionBudget.enabled` | Adds a PodDisruptionBudget for the cert-manager deployment | `false` | +| `webhook.podDisruptionBudget.minAvailable` | Configures the minimum available pods for voluntary disruptions. Cannot used if `maxUnavailable` is set. | `1` | +| `webhook.podDisruptionBudget.maxUnavailable` | Configures the maximum unavailable pods for voluntary disruptions. Cannot used if `minAvailable` is set. | | +| `webhook.mutatingWebhookConfigurationAnnotations` | Annotations to add to the mutating webhook configuration | `{}` | +| `webhook.validatingWebhookConfigurationAnnotations` | Annotations to add to the validating webhook configuration | `{}` | +| `webhook.serviceAnnotations` | Annotations to add to the webhook service | `{}` | +| `webhook.config` | WebhookConfiguration YAML used to configure flags for the webhook. Generates a ConfigMap containing contents of the field. See `values.yaml` for example. | `{}` | +| `webhook.extraArgs` | Optional flags for cert-manager webhook component | `[]` | +| `webhook.serviceAccount.create` | If `true`, create a new service account for the webhook component | `true` | +| `webhook.serviceAccount.name` | Service account for the webhook component to be used. If not set and `webhook.serviceAccount.create` is `true`, a name is generated using the fullname template | | +| `webhook.serviceAccount.annotations` | Annotations to add to the service account for the webhook component | | +| `webhook.serviceAccount.automountServiceAccountToken` | Automount API credentials for the webhook Service Account | | +| `webhook.resources` | CPU/memory resource requests/limits for the webhook pods | `{}` | +| `webhook.nodeSelector` | Node labels for webhook pod assignment | `{}` | +| `webhook.networkPolicy.enabled` | Enable default network policies for webhooks egress and ingress traffic | `false` | +| `webhook.networkPolicy.ingress` | Sets ingress policy block. See NetworkPolicy documentation. See `values.yaml` for example. | `{}` | +| `webhook.networkPolicy.egress` | Sets ingress policy block. See NetworkPolicy documentation. See `values.yaml` for example. | `{}` | +| `webhook.affinity` | Node affinity for webhook pod assignment | `{}` | +| `webhook.tolerations` | Node tolerations for webhook pod assignment | `[]` | +| `webhook.topologySpreadConstraints` | Topology spread constraints for webhook pod assignment | `[]` | +| `webhook.image.repository` | Webhook image repository | `quay.io/jetstack/cert-manager-webhook` | +| `webhook.image.tag` | Webhook image tag | `v1.12.3` | +| `webhook.image.pullPolicy` | Webhook image pull policy | `IfNotPresent` | +| `webhook.securePort` | The port that the webhook should listen on for requests. | `10250` | +| `webhook.securityContext` | Security context for webhook pod assignment | refer to [Default Security Contexts](#default-security-contexts) | +| `webhook.containerSecurityContext` | Security context to be set on the webhook component container | refer to [Default Security Contexts](#default-security-contexts) | +| `webhook.hostNetwork` | If `true`, run the Webhook on the host network. | `false` | +| `webhook.serviceType` | The type of the `Service`. | `ClusterIP` | +| `webhook.loadBalancerIP` | The specific load balancer IP to use (when `serviceType` is `LoadBalancer`). | | +| `webhook.url.host` | The host to use to reach the webhook, instead of using internal cluster DNS for the service. | | +| `webhook.livenessProbe.failureThreshold` | The liveness probe failure threshold | `3` | +| `webhook.livenessProbe.initialDelaySeconds` | The liveness probe initial delay (in seconds) | `60` | +| `webhook.livenessProbe.periodSeconds` | The liveness probe period (in seconds) | `10` | +| `webhook.livenessProbe.successThreshold` | The liveness probe success threshold | `1` | +| `webhook.livenessProbe.timeoutSeconds` | The liveness probe timeout (in seconds) | `1` | +| `webhook.readinessProbe.failureThreshold` | The readiness probe failure threshold | `3` | +| `webhook.readinessProbe.initialDelaySeconds` | The readiness probe initial delay (in seconds) | `5` | +| `webhook.readinessProbe.periodSeconds` | The readiness probe period (in seconds) | `5` | +| `webhook.readinessProbe.successThreshold` | The readiness probe success threshold | `1` | +| `webhook.readinessProbe.timeoutSeconds` | The readiness probe timeout (in seconds) | `1` | +| `cainjector.enabled` | Toggles whether the cainjector component should be installed (required for the webhook component to work) | `true` | +| `cainjector.replicaCount` | Number of cert-manager cainjector replicas | `1` | +| `cainjector.podAnnotations` | Annotations to add to the cainjector pods | `{}` | +| `cainjector.podLabels` | Labels to add to the cert-manager cainjector pod | `{}` | +| `cainjector.deploymentAnnotations` | Annotations to add to the cainjector deployment | `{}` | +| `cainjector.podDisruptionBudget.enabled` | Adds a PodDisruptionBudget for the cert-manager deployment | `false` | +| `cainjector.podDisruptionBudget.minAvailable` | Configures the minimum available pods for voluntary disruptions. Cannot used if `maxUnavailable` is set. | `1` | +| `cainjector.podDisruptionBudget.maxUnavailable` | Configures the maximum unavailable pods for voluntary disruptions. Cannot used if `minAvailable` is set. | | +| `cainjector.extraArgs` | Optional flags for cert-manager cainjector component | `[]` | +| `cainjector.serviceAccount.create` | If `true`, create a new service account for the cainjector component | `true` | +| `cainjector.serviceAccount.name` | Service account for the cainjector component to be used. If not set and `cainjector.serviceAccount.create` is `true`, a name is generated using the fullname template | | +| `cainjector.serviceAccount.annotations` | Annotations to add to the service account for the cainjector component | | +| `cainjector.serviceAccount.automountServiceAccountToken` | Automount API credentials for the cainjector Service Account | `true` | +| `cainjector.resources` | CPU/memory resource requests/limits for the cainjector pods | `{}` | +| `cainjector.nodeSelector` | Node labels for cainjector pod assignment | `{}` | +| `cainjector.affinity` | Node affinity for cainjector pod assignment | `{}` | +| `cainjector.tolerations` | Node tolerations for cainjector pod assignment | `[]` | +| `cainjector.topologySpreadConstraints` | Topology spread constraints for cainjector pod assignment | `[]` | +| `cainjector.image.repository` | cainjector image repository | `quay.io/jetstack/cert-manager-cainjector` | +| `cainjector.image.tag` | cainjector image tag | `v1.12.3` | +| `cainjector.image.pullPolicy` | cainjector image pull policy | `IfNotPresent` | +| `cainjector.securityContext` | Security context for cainjector pod assignment | refer to [Default Security Contexts](#default-security-contexts) | +| `cainjector.containerSecurityContext` | Security context to be set on cainjector component container | refer to [Default Security Contexts](#default-security-contexts) | +| `acmesolver.image.repository` | acmesolver image repository | `quay.io/jetstack/cert-manager-acmesolver` | +| `acmesolver.image.tag` | acmesolver image tag | `v1.12.3` | +| `acmesolver.image.pullPolicy` | acmesolver image pull policy | `IfNotPresent` | +| `startupapicheck.enabled` | Toggles whether the startupapicheck Job should be installed | `true` | +| `startupapicheck.securityContext` | Security context for startupapicheck pod assignment | refer to [Default Security Contexts](#default-security-contexts) | +| `startupapicheck.containerSecurityContext` | Security context to be set on startupapicheck component container | refer to [Default Security Contexts](#default-security-contexts) | +| `startupapicheck.timeout` | Timeout for 'kubectl check api' command | `1m` | +| `startupapicheck.backoffLimit` | Job backoffLimit | `4` | +| `startupapicheck.jobAnnotations` | Optional additional annotations to add to the startupapicheck Job | `{}` | +| `startupapicheck.podAnnotations` | Optional additional annotations to add to the startupapicheck Pods | `{}` | +| `startupapicheck.extraArgs` | Optional additional arguments for startupapicheck | `[]` | +| `startupapicheck.resources` | CPU/memory resource requests/limits for the startupapicheck pod | `{}` | +| `startupapicheck.nodeSelector` | Node labels for startupapicheck pod assignment | `{}` | +| `startupapicheck.affinity` | Node affinity for startupapicheck pod assignment | `{}` | +| `startupapicheck.tolerations` | Node tolerations for startupapicheck pod assignment | `[]` | +| `startupapicheck.podLabels` | Optional additional labels to add to the startupapicheck Pods | `{}` | +| `startupapicheck.image.repository` | startupapicheck image repository | `quay.io/jetstack/cert-manager-ctl` | +| `startupapicheck.image.tag` | startupapicheck image tag | `v1.12.3` | +| `startupapicheck.image.pullPolicy` | startupapicheck image pull policy | `IfNotPresent` | +| `startupapicheck.serviceAccount.create` | If `true`, create a new service account for the startupapicheck component | `true` | +| `startupapicheck.serviceAccount.name` | Service account for the startupapicheck component to be used. If not set and `startupapicheck.serviceAccount.create` is `true`, a name is generated using the fullname template | | +| `startupapicheck.serviceAccount.annotations` | Annotations to add to the service account for the startupapicheck component | | +| `startupapicheck.serviceAccount.automountServiceAccountToken` | Automount API credentials for the startupapicheck Service Account | `true` | +| `maxConcurrentChallenges` | The maximum number of challenges that can be scheduled as 'processing' at once | `60` | + +### Default Security Contexts + +The default pod-level and container-level security contexts, below, adhere to the [restricted](https://kubernetes.io/docs/concepts/security/pod-security-standards/#restricted) Pod Security Standards policies. + +Default pod-level securityContext: +```yaml +runAsNonRoot: true +seccompProfile: + type: RuntimeDefault +``` + +Default containerSecurityContext: +```yaml +allowPrivilegeEscalation: false +capabilities: + drop: + - ALL +``` + +### Assigning Values + +Specify each parameter using the `--set key=value[,key=value]` argument to `helm install`. + +Alternatively, a YAML file that specifies the values for the above parameters can be provided while installing the chart. For example, + +```console +$ helm install my-release -f values.yaml . +``` +> **Tip**: You can use the default [values.yaml](https://github.com/cert-manager/cert-manager/blob/master/deploy/charts/cert-manager/values.yaml) + +## Contributing + +This chart is maintained at [github.com/cert-manager/cert-manager](https://github.com/cert-manager/cert-manager/tree/master/deploy/charts/cert-manager). diff --git a/packages/system/cert-manager/charts/cert-manager/templates/NOTES.txt b/packages/system/cert-manager/charts/cert-manager/templates/NOTES.txt new file mode 100644 index 00000000..10253546 --- /dev/null +++ b/packages/system/cert-manager/charts/cert-manager/templates/NOTES.txt @@ -0,0 +1,15 @@ +cert-manager {{ .Chart.AppVersion }} has been deployed successfully! + +In order to begin issuing certificates, you will need to set up a ClusterIssuer +or Issuer resource (for example, by creating a 'letsencrypt-staging' issuer). + +More information on the different types of issuers and how to configure them +can be found in our documentation: + +https://cert-manager.io/docs/configuration/ + +For information on how to configure cert-manager to automatically provision +Certificates for Ingress resources, take a look at the `ingress-shim` +documentation: + +https://cert-manager.io/docs/usage/ingress/ diff --git a/packages/system/cert-manager/charts/cert-manager/templates/_helpers.tpl b/packages/system/cert-manager/charts/cert-manager/templates/_helpers.tpl new file mode 100644 index 00000000..90db4af2 --- /dev/null +++ b/packages/system/cert-manager/charts/cert-manager/templates/_helpers.tpl @@ -0,0 +1,174 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "cert-manager.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | 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). +*/}} +{{- define "cert-manager.fullname" -}} +{{- if .Values.fullnameOverride -}} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- if contains $name .Release.Name -}} +{{- .Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Create the name of the service account to use +*/}} +{{- define "cert-manager.serviceAccountName" -}} +{{- if .Values.serviceAccount.create -}} + {{ default (include "cert-manager.fullname" .) .Values.serviceAccount.name }} +{{- else -}} + {{ default "default" .Values.serviceAccount.name }} +{{- end -}} +{{- end -}} + +{{/* +Webhook templates +*/}} + +{{/* +Expand the name of the chart. +Manually fix the 'app' and 'name' labels to 'webhook' to maintain +compatibility with the v0.9 deployment selector. +*/}} +{{- define "webhook.name" -}} +{{- printf "webhook" -}} +{{- 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 "webhook.fullname" -}} +{{- $trimmedName := printf "%s" (include "cert-manager.fullname" .) | trunc 55 | trimSuffix "-" -}} +{{- printf "%s-webhook" $trimmedName | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{- define "webhook.caRef" -}} +{{- template "cert-manager.namespace" }}/{{ template "webhook.fullname" . }}-ca +{{- end -}} + +{{/* +Create the name of the service account to use +*/}} +{{- define "webhook.serviceAccountName" -}} +{{- if .Values.webhook.serviceAccount.create -}} + {{ default (include "webhook.fullname" .) .Values.webhook.serviceAccount.name }} +{{- else -}} + {{ default "default" .Values.webhook.serviceAccount.name }} +{{- end -}} +{{- end -}} + +{{/* +cainjector templates +*/}} + +{{/* +Expand the name of the chart. +Manually fix the 'app' and 'name' labels to 'cainjector' to maintain +compatibility with the v0.9 deployment selector. +*/}} +{{- define "cainjector.name" -}} +{{- printf "cainjector" -}} +{{- 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 "cainjector.fullname" -}} +{{- $trimmedName := printf "%s" (include "cert-manager.fullname" .) | trunc 52 | trimSuffix "-" -}} +{{- printf "%s-cainjector" $trimmedName | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create the name of the service account to use +*/}} +{{- define "cainjector.serviceAccountName" -}} +{{- if .Values.cainjector.serviceAccount.create -}} + {{ default (include "cainjector.fullname" .) .Values.cainjector.serviceAccount.name }} +{{- else -}} + {{ default "default" .Values.cainjector.serviceAccount.name }} +{{- end -}} +{{- end -}} + +{{/* +startupapicheck templates +*/}} + +{{/* +Expand the name of the chart. +Manually fix the 'app' and 'name' labels to 'startupapicheck' to maintain +compatibility with the v0.9 deployment selector. +*/}} +{{- define "startupapicheck.name" -}} +{{- printf "startupapicheck" -}} +{{- 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 "startupapicheck.fullname" -}} +{{- $trimmedName := printf "%s" (include "cert-manager.fullname" .) | trunc 52 | trimSuffix "-" -}} +{{- printf "%s-startupapicheck" $trimmedName | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create the name of the service account to use +*/}} +{{- define "startupapicheck.serviceAccountName" -}} +{{- if .Values.startupapicheck.serviceAccount.create -}} + {{ default (include "startupapicheck.fullname" .) .Values.startupapicheck.serviceAccount.name }} +{{- else -}} + {{ default "default" .Values.startupapicheck.serviceAccount.name }} +{{- end -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "chartName" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Labels that should be added on each resource +*/}} +{{- define "labels" -}} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- if eq (default "helm" .Values.creator) "helm" }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +helm.sh/chart: {{ include "chartName" . }} +{{- end -}} +{{- if .Values.global.commonLabels}} +{{ toYaml .Values.global.commonLabels }} +{{- end }} +{{- end -}} + +{{/* +Namespace for all resources to be installed into +If not defined in values file then the helm release namespace is used +By default this is not set so the helm release namespace will be used + +This gets around an problem within helm discussed here +https://github.com/helm/helm/issues/5358 +*/}} +{{- define "cert-manager.namespace" -}} + {{ .Values.namespace | default .Release.Namespace }} +{{- end -}} diff --git a/packages/system/cert-manager/charts/cert-manager/templates/cainjector-deployment.yaml b/packages/system/cert-manager/charts/cert-manager/templates/cainjector-deployment.yaml new file mode 100644 index 00000000..12201737 --- /dev/null +++ b/packages/system/cert-manager/charts/cert-manager/templates/cainjector-deployment.yaml @@ -0,0 +1,117 @@ +{{- if .Values.cainjector.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "cainjector.fullname" . }} + namespace: {{ include "cert-manager.namespace" . }} + labels: + app: {{ include "cainjector.name" . }} + app.kubernetes.io/name: {{ include "cainjector.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "cainjector" + {{- include "labels" . | nindent 4 }} + {{- with .Values.cainjector.deploymentAnnotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + replicas: {{ .Values.cainjector.replicaCount }} + selector: + matchLabels: + app.kubernetes.io/name: {{ include "cainjector.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "cainjector" + {{- with .Values.cainjector.strategy }} + strategy: + {{- toYaml . | nindent 4 }} + {{- end }} + template: + metadata: + labels: + app: {{ include "cainjector.name" . }} + app.kubernetes.io/name: {{ include "cainjector.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "cainjector" + {{- include "labels" . | nindent 8 }} + {{- with .Values.cainjector.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.cainjector.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + serviceAccountName: {{ template "cainjector.serviceAccountName" . }} + {{- if hasKey .Values.cainjector "automountServiceAccountToken" }} + automountServiceAccountToken: {{ .Values.cainjector.automountServiceAccountToken }} + {{- end }} + {{- with .Values.global.priorityClassName }} + priorityClassName: {{ . | quote }} + {{- end }} + {{- with .Values.cainjector.securityContext }} + securityContext: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: {{ .Chart.Name }}-cainjector + {{- with .Values.cainjector.image }} + image: "{{- if .registry -}}{{ .registry }}/{{- end -}}{{ .repository }}{{- if (.digest) -}} @{{ .digest }}{{- else -}}:{{ default $.Chart.AppVersion .tag }} {{- end -}}" + {{- end }} + imagePullPolicy: {{ .Values.cainjector.image.pullPolicy }} + args: + {{- if .Values.global.logLevel }} + - --v={{ .Values.global.logLevel }} + {{- end }} + {{- with .Values.global.leaderElection }} + - --leader-election-namespace={{ .namespace }} + {{- if .leaseDuration }} + - --leader-election-lease-duration={{ .leaseDuration }} + {{- end }} + {{- if .renewDeadline }} + - --leader-election-renew-deadline={{ .renewDeadline }} + {{- end }} + {{- if .retryPeriod }} + - --leader-election-retry-period={{ .retryPeriod }} + {{- end }} + {{- end }} + {{- with .Values.cainjector.extraArgs }} + {{- toYaml . | nindent 10 }} + {{- end }} + env: + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + {{- with .Values.cainjector.containerSecurityContext }} + securityContext: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.cainjector.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.cainjector.volumeMounts }} + volumeMounts: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.cainjector.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.cainjector.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.cainjector.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.cainjector.topologySpreadConstraints }} + topologySpreadConstraints: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.cainjector.volumes }} + volumes: + {{- toYaml . | nindent 8 }} + {{- end }} +{{- end }} diff --git a/packages/system/cert-manager/charts/cert-manager/templates/cainjector-poddisruptionbudget.yaml b/packages/system/cert-manager/charts/cert-manager/templates/cainjector-poddisruptionbudget.yaml new file mode 100644 index 00000000..f080b753 --- /dev/null +++ b/packages/system/cert-manager/charts/cert-manager/templates/cainjector-poddisruptionbudget.yaml @@ -0,0 +1,26 @@ +{{- if .Values.cainjector.podDisruptionBudget.enabled }} +apiVersion: policy/v1 +kind: PodDisruptionBudget +metadata: + name: {{ include "cainjector.fullname" . }} + namespace: {{ include "cert-manager.namespace" . }} + labels: + app: {{ include "cainjector.name" . }} + app.kubernetes.io/name: {{ include "cainjector.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "cainjector" + {{- include "labels" . | nindent 4 }} +spec: + selector: + matchLabels: + app.kubernetes.io/name: {{ include "cainjector.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "cainjector" + + {{- with .Values.cainjector.podDisruptionBudget.minAvailable }} + minAvailable: {{ . }} + {{- end }} + {{- with .Values.cainjector.podDisruptionBudget.maxUnavailable }} + maxUnavailable: {{ . }} + {{- end }} +{{- end }} diff --git a/packages/system/cert-manager/charts/cert-manager/templates/cainjector-psp-clusterrole.yaml b/packages/system/cert-manager/charts/cert-manager/templates/cainjector-psp-clusterrole.yaml new file mode 100644 index 00000000..b75b9eb6 --- /dev/null +++ b/packages/system/cert-manager/charts/cert-manager/templates/cainjector-psp-clusterrole.yaml @@ -0,0 +1,20 @@ +{{- if .Values.cainjector.enabled }} +{{- if .Values.global.podSecurityPolicy.enabled }} +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ template "cainjector.fullname" . }}-psp + labels: + app: {{ include "cainjector.name" . }} + app.kubernetes.io/name: {{ include "cainjector.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "cainjector" + {{- include "labels" . | nindent 4 }} +rules: +- apiGroups: ['policy'] + resources: ['podsecuritypolicies'] + verbs: ['use'] + resourceNames: + - {{ template "cainjector.fullname" . }} +{{- end }} +{{- end }} diff --git a/packages/system/cert-manager/charts/cert-manager/templates/cainjector-psp-clusterrolebinding.yaml b/packages/system/cert-manager/charts/cert-manager/templates/cainjector-psp-clusterrolebinding.yaml new file mode 100644 index 00000000..e2bfa26b --- /dev/null +++ b/packages/system/cert-manager/charts/cert-manager/templates/cainjector-psp-clusterrolebinding.yaml @@ -0,0 +1,22 @@ +{{- if .Values.cainjector.enabled }} +{{- if .Values.global.podSecurityPolicy.enabled }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ template "cainjector.fullname" . }}-psp + labels: + app: {{ include "cainjector.name" . }} + app.kubernetes.io/name: {{ include "cainjector.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "cainjector" + {{- include "labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ template "cainjector.fullname" . }}-psp +subjects: + - kind: ServiceAccount + name: {{ template "cainjector.serviceAccountName" . }} + namespace: {{ include "cert-manager.namespace" . }} +{{- end }} +{{- end }} diff --git a/packages/system/cert-manager/charts/cert-manager/templates/cainjector-psp.yaml b/packages/system/cert-manager/charts/cert-manager/templates/cainjector-psp.yaml new file mode 100644 index 00000000..24f01da5 --- /dev/null +++ b/packages/system/cert-manager/charts/cert-manager/templates/cainjector-psp.yaml @@ -0,0 +1,51 @@ +{{- if .Values.cainjector.enabled }} +{{- if .Values.global.podSecurityPolicy.enabled }} +apiVersion: policy/v1beta1 +kind: PodSecurityPolicy +metadata: + name: {{ template "cainjector.fullname" . }} + labels: + app: {{ include "cainjector.name" . }} + app.kubernetes.io/name: {{ include "cainjector.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "cainjector" + {{- include "labels" . | nindent 4 }} + annotations: + seccomp.security.alpha.kubernetes.io/allowedProfileNames: 'docker/default' + seccomp.security.alpha.kubernetes.io/defaultProfileName: 'docker/default' + {{- if .Values.global.podSecurityPolicy.useAppArmor }} + apparmor.security.beta.kubernetes.io/allowedProfileNames: 'runtime/default' + apparmor.security.beta.kubernetes.io/defaultProfileName: 'runtime/default' + {{- end }} +spec: + privileged: false + allowPrivilegeEscalation: false + allowedCapabilities: [] # default set of capabilities are implicitly allowed + volumes: + - 'configMap' + - 'emptyDir' + - 'projected' + - 'secret' + - 'downwardAPI' + hostNetwork: false + hostIPC: false + hostPID: false + runAsUser: + rule: 'MustRunAs' + ranges: + - min: 1000 + max: 1000 + seLinux: + rule: 'RunAsAny' + supplementalGroups: + rule: 'MustRunAs' + ranges: + - min: 1000 + max: 1000 + fsGroup: + rule: 'MustRunAs' + ranges: + - min: 1000 + max: 1000 +{{- end }} +{{- end }} diff --git a/packages/system/cert-manager/charts/cert-manager/templates/cainjector-rbac.yaml b/packages/system/cert-manager/charts/cert-manager/templates/cainjector-rbac.yaml new file mode 100644 index 00000000..2aa59eee --- /dev/null +++ b/packages/system/cert-manager/charts/cert-manager/templates/cainjector-rbac.yaml @@ -0,0 +1,103 @@ +{{- if .Values.cainjector.enabled }} +{{- if .Values.global.rbac.create }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ template "cainjector.fullname" . }} + labels: + app: {{ include "cainjector.name" . }} + app.kubernetes.io/name: {{ include "cainjector.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "cainjector" + {{- include "labels" . | nindent 4 }} +rules: + - apiGroups: ["cert-manager.io"] + resources: ["certificates"] + verbs: ["get", "list", "watch"] + - apiGroups: [""] + resources: ["secrets"] + verbs: ["get", "list", "watch"] + - apiGroups: [""] + resources: ["events"] + verbs: ["get", "create", "update", "patch"] + - apiGroups: ["admissionregistration.k8s.io"] + resources: ["validatingwebhookconfigurations", "mutatingwebhookconfigurations"] + verbs: ["get", "list", "watch", "update", "patch"] + - apiGroups: ["apiregistration.k8s.io"] + resources: ["apiservices"] + verbs: ["get", "list", "watch", "update", "patch"] + - apiGroups: ["apiextensions.k8s.io"] + resources: ["customresourcedefinitions"] + verbs: ["get", "list", "watch", "update", "patch"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ template "cainjector.fullname" . }} + labels: + app: {{ include "cainjector.name" . }} + app.kubernetes.io/name: {{ include "cainjector.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "cainjector" + {{- include "labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ template "cainjector.fullname" . }} +subjects: + - name: {{ template "cainjector.serviceAccountName" . }} + namespace: {{ include "cert-manager.namespace" . }} + kind: ServiceAccount + +--- +# leader election rules +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ template "cainjector.fullname" . }}:leaderelection + namespace: {{ .Values.global.leaderElection.namespace }} + labels: + app: {{ include "cainjector.name" . }} + app.kubernetes.io/name: {{ include "cainjector.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "cainjector" + {{- include "labels" . | nindent 4 }} +rules: + # Used for leader election by the controller + # cert-manager-cainjector-leader-election is used by the CertificateBased injector controller + # see cmd/cainjector/start.go#L113 + # cert-manager-cainjector-leader-election-core is used by the SecretBased injector controller + # see cmd/cainjector/start.go#L137 + - apiGroups: ["coordination.k8s.io"] + resources: ["leases"] + resourceNames: ["cert-manager-cainjector-leader-election", "cert-manager-cainjector-leader-election-core"] + verbs: ["get", "update", "patch"] + - apiGroups: ["coordination.k8s.io"] + resources: ["leases"] + verbs: ["create"] + +--- + +# grant cert-manager permission to manage the leaderelection configmap in the +# leader election namespace +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ include "cainjector.fullname" . }}:leaderelection + namespace: {{ .Values.global.leaderElection.namespace }} + labels: + app: {{ include "cainjector.name" . }} + app.kubernetes.io/name: {{ include "cainjector.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "cainjector" + {{- include "labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ template "cainjector.fullname" . }}:leaderelection +subjects: + - kind: ServiceAccount + name: {{ template "cainjector.serviceAccountName" . }} + namespace: {{ include "cert-manager.namespace" . }} +{{- end }} +{{- end }} diff --git a/packages/system/cert-manager/charts/cert-manager/templates/cainjector-serviceaccount.yaml b/packages/system/cert-manager/charts/cert-manager/templates/cainjector-serviceaccount.yaml new file mode 100644 index 00000000..fedc731f --- /dev/null +++ b/packages/system/cert-manager/charts/cert-manager/templates/cainjector-serviceaccount.yaml @@ -0,0 +1,27 @@ +{{- if .Values.cainjector.enabled }} +{{- if .Values.cainjector.serviceAccount.create }} +apiVersion: v1 +kind: ServiceAccount +automountServiceAccountToken: {{ .Values.cainjector.serviceAccount.automountServiceAccountToken }} +metadata: + name: {{ template "cainjector.serviceAccountName" . }} + namespace: {{ include "cert-manager.namespace" . }} + {{- with .Values.cainjector.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} + labels: + app: {{ include "cainjector.name" . }} + app.kubernetes.io/name: {{ include "cainjector.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "cainjector" + {{- include "labels" . | nindent 4 }} + {{- with .Values.cainjector.serviceAccount.labels }} + {{ toYaml . | nindent 4 }} + {{- end }} +{{- with .Values.global.imagePullSecrets }} +imagePullSecrets: + {{- toYaml . | nindent 2 }} +{{- end }} +{{- end }} +{{- end }} diff --git a/packages/system/cert-manager/charts/cert-manager/templates/crds.yaml b/packages/system/cert-manager/charts/cert-manager/templates/crds.yaml new file mode 100644 index 00000000..82069874 --- /dev/null +++ b/packages/system/cert-manager/charts/cert-manager/templates/crds.yaml @@ -0,0 +1,4462 @@ +{{- if .Values.installCRDs }} +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: certificaterequests.cert-manager.io + labels: + app: '{{ template "cert-manager.name" . }}' + app.kubernetes.io/name: '{{ template "cert-manager.name" . }}' + app.kubernetes.io/instance: '{{ .Release.Name }}' + # Generated labels {{- include "labels" . | nindent 4 }} +spec: + group: cert-manager.io + names: + kind: CertificateRequest + listKind: CertificateRequestList + plural: certificaterequests + shortNames: + - cr + - crs + singular: certificaterequest + categories: + - cert-manager + scope: Namespaced + versions: + - name: v1 + subresources: + status: {} + additionalPrinterColumns: + - jsonPath: .status.conditions[?(@.type=="Approved")].status + name: Approved + type: string + - jsonPath: .status.conditions[?(@.type=="Denied")].status + name: Denied + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].status + name: Ready + type: string + - jsonPath: .spec.issuerRef.name + name: Issuer + type: string + - jsonPath: .spec.username + name: Requestor + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].message + name: Status + priority: 1 + type: string + - jsonPath: .metadata.creationTimestamp + description: CreationTimestamp is a timestamp representing the server time when this object was created. It is not guaranteed to be set in happens-before order across separate operations. Clients may not set this value. It is represented in RFC3339 form and is in UTC. + name: Age + type: date + schema: + openAPIV3Schema: + description: "A CertificateRequest is used to request a signed certificate from one of the configured issuers. \n All fields within the CertificateRequest's `spec` are immutable after creation. A CertificateRequest will either succeed or fail, as denoted by its `status.state` field. \n A CertificateRequest is a one-shot resource, meaning it represents a single point in time request for a certificate and cannot be re-used." + type: object + required: + - spec + 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: Desired state of the CertificateRequest resource. + type: object + required: + - issuerRef + - request + properties: + duration: + description: The requested 'duration' (i.e. lifetime) of the Certificate. This option may be ignored/overridden by some issuer types. + type: string + extra: + description: Extra contains extra attributes of the user that created the CertificateRequest. Populated by the cert-manager webhook on creation and immutable. + type: object + additionalProperties: + type: array + items: + type: string + groups: + description: Groups contains group membership of the user that created the CertificateRequest. Populated by the cert-manager webhook on creation and immutable. + type: array + items: + type: string + x-kubernetes-list-type: atomic + isCA: + description: IsCA will request to mark the certificate as valid for certificate signing when submitting to the issuer. This will automatically add the `cert sign` usage to the list of `usages`. + type: boolean + issuerRef: + description: IssuerRef is a reference to the issuer for this CertificateRequest. If the `kind` field is not set, or set to `Issuer`, an Issuer resource with the given name in the same namespace as the CertificateRequest will be used. If the `kind` field is set to `ClusterIssuer`, a ClusterIssuer with the provided name will be used. The `name` field in this stanza is required at all times. The group field refers to the API group of the issuer which defaults to `cert-manager.io` if empty. + type: object + required: + - name + properties: + group: + description: Group of the resource being referred to. + type: string + kind: + description: Kind of the resource being referred to. + type: string + name: + description: Name of the resource being referred to. + type: string + request: + description: The PEM-encoded x509 certificate signing request to be submitted to the CA for signing. + type: string + format: byte + uid: + description: UID contains the uid of the user that created the CertificateRequest. Populated by the cert-manager webhook on creation and immutable. + type: string + usages: + description: Usages is the set of x509 usages that are requested for the certificate. If usages are set they SHOULD be encoded inside the CSR spec Defaults to `digital signature` and `key encipherment` if not specified. + type: array + items: + description: "KeyUsage specifies valid usage contexts for keys. See: https://tools.ietf.org/html/rfc5280#section-4.2.1.3 https://tools.ietf.org/html/rfc5280#section-4.2.1.12 \n Valid KeyUsage values are as follows: \"signing\", \"digital signature\", \"content commitment\", \"key encipherment\", \"key agreement\", \"data encipherment\", \"cert sign\", \"crl sign\", \"encipher only\", \"decipher only\", \"any\", \"server auth\", \"client auth\", \"code signing\", \"email protection\", \"s/mime\", \"ipsec end system\", \"ipsec tunnel\", \"ipsec user\", \"timestamping\", \"ocsp signing\", \"microsoft sgc\", \"netscape sgc\"" + type: string + enum: + - signing + - digital signature + - content commitment + - key encipherment + - key agreement + - data encipherment + - cert sign + - crl sign + - encipher only + - decipher only + - any + - server auth + - client auth + - code signing + - email protection + - s/mime + - ipsec end system + - ipsec tunnel + - ipsec user + - timestamping + - ocsp signing + - microsoft sgc + - netscape sgc + username: + description: Username contains the name of the user that created the CertificateRequest. Populated by the cert-manager webhook on creation and immutable. + type: string + status: + description: Status of the CertificateRequest. This is set and managed automatically. + type: object + properties: + ca: + description: The PEM encoded x509 certificate of the signer, also known as the CA (Certificate Authority). This is set on a best-effort basis by different issuers. If not set, the CA is assumed to be unknown/not available. + type: string + format: byte + certificate: + description: The PEM encoded x509 certificate resulting from the certificate signing request. If not set, the CertificateRequest has either not been completed or has failed. More information on failure can be found by checking the `conditions` field. + type: string + format: byte + conditions: + description: List of status conditions to indicate the status of a CertificateRequest. Known condition types are `Ready` and `InvalidRequest`. + type: array + items: + description: CertificateRequestCondition contains condition information for a CertificateRequest. + type: object + required: + - status + - type + properties: + lastTransitionTime: + description: LastTransitionTime is the timestamp corresponding to the last status change of this condition. + type: string + format: date-time + message: + description: Message is a human readable description of the details of the last transition, complementing reason. + type: string + reason: + description: Reason is a brief machine readable explanation for the condition's last transition. + type: string + status: + description: Status of the condition, one of (`True`, `False`, `Unknown`). + type: string + enum: + - "True" + - "False" + - Unknown + type: + description: Type of the condition, known values are (`Ready`, `InvalidRequest`, `Approved`, `Denied`). + type: string + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + failureTime: + description: FailureTime stores the time that this CertificateRequest failed. This is used to influence garbage collection and back-off. + type: string + format: date-time + served: true + storage: true +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: certificates.cert-manager.io + labels: + app: '{{ template "cert-manager.name" . }}' + app.kubernetes.io/name: '{{ template "cert-manager.name" . }}' + app.kubernetes.io/instance: '{{ .Release.Name }}' + # Generated labels {{- include "labels" . | nindent 4 }} +spec: + group: cert-manager.io + names: + kind: Certificate + listKind: CertificateList + plural: certificates + shortNames: + - cert + - certs + singular: certificate + categories: + - cert-manager + scope: Namespaced + versions: + - name: v1 + subresources: + status: {} + additionalPrinterColumns: + - jsonPath: .status.conditions[?(@.type=="Ready")].status + name: Ready + type: string + - jsonPath: .spec.secretName + name: Secret + type: string + - jsonPath: .spec.issuerRef.name + name: Issuer + priority: 1 + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].message + name: Status + priority: 1 + type: string + - jsonPath: .metadata.creationTimestamp + description: CreationTimestamp is a timestamp representing the server time when this object was created. It is not guaranteed to be set in happens-before order across separate operations. Clients may not set this value. It is represented in RFC3339 form and is in UTC. + name: Age + type: date + schema: + openAPIV3Schema: + description: "A Certificate resource should be created to ensure an up to date and signed x509 certificate is stored in the Kubernetes Secret resource named in `spec.secretName`. \n The stored certificate will be renewed before it expires (as configured by `spec.renewBefore`)." + type: object + required: + - spec + 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: Desired state of the Certificate resource. + type: object + required: + - issuerRef + - secretName + properties: + additionalOutputFormats: + description: AdditionalOutputFormats defines extra output formats of the private key and signed certificate chain to be written to this Certificate's target Secret. This is an Alpha Feature and is only enabled with the `--feature-gates=AdditionalCertificateOutputFormats=true` option on both the controller and webhook components. + type: array + items: + description: CertificateAdditionalOutputFormat defines an additional output format of a Certificate resource. These contain supplementary data formats of the signed certificate chain and paired private key. + type: object + required: + - type + properties: + type: + description: Type is the name of the format type that should be written to the Certificate's target Secret. + type: string + enum: + - DER + - CombinedPEM + commonName: + description: 'CommonName is a common name to be used on the Certificate. The CommonName should have a length of 64 characters or fewer to avoid generating invalid CSRs. This value is ignored by TLS clients when any subject alt name is set. This is x509 behaviour: https://tools.ietf.org/html/rfc6125#section-6.4.4' + type: string + dnsNames: + description: DNSNames is a list of DNS subjectAltNames to be set on the Certificate. + type: array + items: + type: string + duration: + description: The requested 'duration' (i.e. lifetime) of the Certificate. This option may be ignored/overridden by some issuer types. If unset this defaults to 90 days. Certificate will be renewed either 2/3 through its duration or `renewBefore` period before its expiry, whichever is later. Minimum accepted duration is 1 hour. Value must be in units accepted by Go time.ParseDuration https://golang.org/pkg/time/#ParseDuration + type: string + emailAddresses: + description: EmailAddresses is a list of email subjectAltNames to be set on the Certificate. + type: array + items: + type: string + encodeUsagesInRequest: + description: EncodeUsagesInRequest controls whether key usages should be present in the CertificateRequest + type: boolean + ipAddresses: + description: IPAddresses is a list of IP address subjectAltNames to be set on the Certificate. + type: array + items: + type: string + isCA: + description: IsCA will mark this Certificate as valid for certificate signing. This will automatically add the `cert sign` usage to the list of `usages`. + type: boolean + issuerRef: + description: IssuerRef is a reference to the issuer for this certificate. If the `kind` field is not set, or set to `Issuer`, an Issuer resource with the given name in the same namespace as the Certificate will be used. If the `kind` field is set to `ClusterIssuer`, a ClusterIssuer with the provided name will be used. The `name` field in this stanza is required at all times. + type: object + required: + - name + properties: + group: + description: Group of the resource being referred to. + type: string + kind: + description: Kind of the resource being referred to. + type: string + name: + description: Name of the resource being referred to. + type: string + keystores: + description: Keystores configures additional keystore output formats stored in the `secretName` Secret resource. + type: object + properties: + jks: + description: JKS configures options for storing a JKS keystore in the `spec.secretName` Secret resource. + type: object + required: + - create + - passwordSecretRef + properties: + create: + description: Create enables JKS keystore creation for the Certificate. If true, a file named `keystore.jks` will be created in the target Secret resource, encrypted using the password stored in `passwordSecretRef`. The keystore file will be updated immediately. If the issuer provided a CA certificate, a file named `truststore.jks` will also be created in the target Secret resource, encrypted using the password stored in `passwordSecretRef` containing the issuing Certificate Authority + type: boolean + passwordSecretRef: + description: PasswordSecretRef is a reference to a key in a Secret resource containing the password used to encrypt the JKS keystore. + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + pkcs12: + description: PKCS12 configures options for storing a PKCS12 keystore in the `spec.secretName` Secret resource. + type: object + required: + - create + - passwordSecretRef + properties: + create: + description: Create enables PKCS12 keystore creation for the Certificate. If true, a file named `keystore.p12` will be created in the target Secret resource, encrypted using the password stored in `passwordSecretRef`. The keystore file will be updated immediately. If the issuer provided a CA certificate, a file named `truststore.p12` will also be created in the target Secret resource, encrypted using the password stored in `passwordSecretRef` containing the issuing Certificate Authority + type: boolean + passwordSecretRef: + description: PasswordSecretRef is a reference to a key in a Secret resource containing the password used to encrypt the PKCS12 keystore. + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + literalSubject: + description: LiteralSubject is an LDAP formatted string that represents the [X.509 Subject field](https://datatracker.ietf.org/doc/html/rfc5280#section-4.1.2.6). Use this *instead* of the Subject field if you need to ensure the correct ordering of the RDN sequence, such as when issuing certs for LDAP authentication. See https://github.com/cert-manager/cert-manager/issues/3203, https://github.com/cert-manager/cert-manager/issues/4424. This field is alpha level and is only supported by cert-manager installations where LiteralCertificateSubject feature gate is enabled on both cert-manager controller and webhook. + type: string + privateKey: + description: Options to control private keys used for the Certificate. + type: object + properties: + algorithm: + description: Algorithm is the private key algorithm of the corresponding private key for this certificate. If provided, allowed values are either `RSA`,`Ed25519` or `ECDSA` If `algorithm` is specified and `size` is not provided, key size of 256 will be used for `ECDSA` key algorithm and key size of 2048 will be used for `RSA` key algorithm. key size is ignored when using the `Ed25519` key algorithm. + type: string + enum: + - RSA + - ECDSA + - Ed25519 + encoding: + description: The private key cryptography standards (PKCS) encoding for this certificate's private key to be encoded in. If provided, allowed values are `PKCS1` and `PKCS8` standing for PKCS#1 and PKCS#8, respectively. Defaults to `PKCS1` if not specified. + type: string + enum: + - PKCS1 + - PKCS8 + rotationPolicy: + description: RotationPolicy controls how private keys should be regenerated when a re-issuance is being processed. If set to Never, a private key will only be generated if one does not already exist in the target `spec.secretName`. If one does exists but it does not have the correct algorithm or size, a warning will be raised to await user intervention. If set to Always, a private key matching the specified requirements will be generated whenever a re-issuance occurs. Default is 'Never' for backward compatibility. + type: string + enum: + - Never + - Always + size: + description: Size is the key bit size of the corresponding private key for this certificate. If `algorithm` is set to `RSA`, valid values are `2048`, `4096` or `8192`, and will default to `2048` if not specified. If `algorithm` is set to `ECDSA`, valid values are `256`, `384` or `521`, and will default to `256` if not specified. If `algorithm` is set to `Ed25519`, Size is ignored. No other values are allowed. + type: integer + renewBefore: + description: How long before the currently issued certificate's expiry cert-manager should renew the certificate. The default is 2/3 of the issued certificate's duration. Minimum accepted value is 5 minutes. Value must be in units accepted by Go time.ParseDuration https://golang.org/pkg/time/#ParseDuration + type: string + revisionHistoryLimit: + description: revisionHistoryLimit is the maximum number of CertificateRequest revisions that are maintained in the Certificate's history. Each revision represents a single `CertificateRequest` created by this Certificate, either when it was created, renewed, or Spec was changed. Revisions will be removed by oldest first if the number of revisions exceeds this number. If set, revisionHistoryLimit must be a value of `1` or greater. If unset (`nil`), revisions will not be garbage collected. Default value is `nil`. + type: integer + format: int32 + secretName: + description: SecretName is the name of the secret resource that will be automatically created and managed by this Certificate resource. It will be populated with a private key and certificate, signed by the denoted issuer. + type: string + secretTemplate: + description: SecretTemplate defines annotations and labels to be copied to the Certificate's Secret. Labels and annotations on the Secret will be changed as they appear on the SecretTemplate when added or removed. SecretTemplate annotations are added in conjunction with, and cannot overwrite, the base set of annotations cert-manager sets on the Certificate's Secret. + type: object + properties: + annotations: + description: Annotations is a key value map to be copied to the target Kubernetes Secret. + type: object + additionalProperties: + type: string + labels: + description: Labels is a key value map to be copied to the target Kubernetes Secret. + type: object + additionalProperties: + type: string + subject: + description: Full X509 name specification (https://golang.org/pkg/crypto/x509/pkix/#Name). + type: object + properties: + countries: + description: Countries to be used on the Certificate. + type: array + items: + type: string + localities: + description: Cities to be used on the Certificate. + type: array + items: + type: string + organizationalUnits: + description: Organizational Units to be used on the Certificate. + type: array + items: + type: string + organizations: + description: Organizations to be used on the Certificate. + type: array + items: + type: string + postalCodes: + description: Postal codes to be used on the Certificate. + type: array + items: + type: string + provinces: + description: State/Provinces to be used on the Certificate. + type: array + items: + type: string + serialNumber: + description: Serial number to be used on the Certificate. + type: string + streetAddresses: + description: Street addresses to be used on the Certificate. + type: array + items: + type: string + uris: + description: URIs is a list of URI subjectAltNames to be set on the Certificate. + type: array + items: + type: string + usages: + description: Usages is the set of x509 usages that are requested for the certificate. Defaults to `digital signature` and `key encipherment` if not specified. + type: array + items: + description: "KeyUsage specifies valid usage contexts for keys. See: https://tools.ietf.org/html/rfc5280#section-4.2.1.3 https://tools.ietf.org/html/rfc5280#section-4.2.1.12 \n Valid KeyUsage values are as follows: \"signing\", \"digital signature\", \"content commitment\", \"key encipherment\", \"key agreement\", \"data encipherment\", \"cert sign\", \"crl sign\", \"encipher only\", \"decipher only\", \"any\", \"server auth\", \"client auth\", \"code signing\", \"email protection\", \"s/mime\", \"ipsec end system\", \"ipsec tunnel\", \"ipsec user\", \"timestamping\", \"ocsp signing\", \"microsoft sgc\", \"netscape sgc\"" + type: string + enum: + - signing + - digital signature + - content commitment + - key encipherment + - key agreement + - data encipherment + - cert sign + - crl sign + - encipher only + - decipher only + - any + - server auth + - client auth + - code signing + - email protection + - s/mime + - ipsec end system + - ipsec tunnel + - ipsec user + - timestamping + - ocsp signing + - microsoft sgc + - netscape sgc + status: + description: Status of the Certificate. This is set and managed automatically. + type: object + properties: + conditions: + description: List of status conditions to indicate the status of certificates. Known condition types are `Ready` and `Issuing`. + type: array + items: + description: CertificateCondition contains condition information for an Certificate. + type: object + required: + - status + - type + properties: + lastTransitionTime: + description: LastTransitionTime is the timestamp corresponding to the last status change of this condition. + type: string + format: date-time + message: + description: Message is a human readable description of the details of the last transition, complementing reason. + type: string + observedGeneration: + description: If set, this represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.condition[x].observedGeneration is 9, the condition is out of date with respect to the current state of the Certificate. + type: integer + format: int64 + reason: + description: Reason is a brief machine readable explanation for the condition's last transition. + type: string + status: + description: Status of the condition, one of (`True`, `False`, `Unknown`). + type: string + enum: + - "True" + - "False" + - Unknown + type: + description: Type of the condition, known values are (`Ready`, `Issuing`). + type: string + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + failedIssuanceAttempts: + description: The number of continuous failed issuance attempts up till now. This field gets removed (if set) on a successful issuance and gets set to 1 if unset and an issuance has failed. If an issuance has failed, the delay till the next issuance will be calculated using formula time.Hour * 2 ^ (failedIssuanceAttempts - 1). + type: integer + lastFailureTime: + description: LastFailureTime is set only if the lastest issuance for this Certificate failed and contains the time of the failure. If an issuance has failed, the delay till the next issuance will be calculated using formula time.Hour * 2 ^ (failedIssuanceAttempts - 1). If the latest issuance has succeeded this field will be unset. + type: string + format: date-time + nextPrivateKeySecretName: + description: The name of the Secret resource containing the private key to be used for the next certificate iteration. The keymanager controller will automatically set this field if the `Issuing` condition is set to `True`. It will automatically unset this field when the Issuing condition is not set or False. + type: string + notAfter: + description: The expiration time of the certificate stored in the secret named by this resource in `spec.secretName`. + type: string + format: date-time + notBefore: + description: The time after which the certificate stored in the secret named by this resource in spec.secretName is valid. + type: string + format: date-time + renewalTime: + description: RenewalTime is the time at which the certificate will be next renewed. If not set, no upcoming renewal is scheduled. + type: string + format: date-time + revision: + description: "The current 'revision' of the certificate as issued. \n When a CertificateRequest resource is created, it will have the `cert-manager.io/certificate-revision` set to one greater than the current value of this field. \n Upon issuance, this field will be set to the value of the annotation on the CertificateRequest resource used to issue the certificate. \n Persisting the value on the CertificateRequest resource allows the certificates controller to know whether a request is part of an old issuance or if it is part of the ongoing revision's issuance by checking if the revision value in the annotation is greater than this field." + type: integer + served: true + storage: true +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: challenges.acme.cert-manager.io + labels: + app: '{{ template "cert-manager.name" . }}' + app.kubernetes.io/name: '{{ template "cert-manager.name" . }}' + app.kubernetes.io/instance: '{{ .Release.Name }}' + # Generated labels {{- include "labels" . | nindent 4 }} +spec: + group: acme.cert-manager.io + names: + kind: Challenge + listKind: ChallengeList + plural: challenges + singular: challenge + categories: + - cert-manager + - cert-manager-acme + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .status.state + name: State + type: string + - jsonPath: .spec.dnsName + name: Domain + type: string + - jsonPath: .status.reason + name: Reason + priority: 1 + type: string + - description: CreationTimestamp is a timestamp representing the server time when this object was created. It is not guaranteed to be set in happens-before order across separate operations. Clients may not set this value. It is represented in RFC3339 form and is in UTC. + jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1 + schema: + openAPIV3Schema: + description: Challenge is a type to represent a Challenge request with an ACME server + type: object + required: + - metadata + - spec + 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: + type: object + required: + - authorizationURL + - dnsName + - issuerRef + - key + - solver + - token + - type + - url + properties: + authorizationURL: + description: The URL to the ACME Authorization resource that this challenge is a part of. + type: string + dnsName: + description: dnsName is the identifier that this challenge is for, e.g. example.com. If the requested DNSName is a 'wildcard', this field MUST be set to the non-wildcard domain, e.g. for `*.example.com`, it must be `example.com`. + type: string + issuerRef: + description: References a properly configured ACME-type Issuer which should be used to create this Challenge. If the Issuer does not exist, processing will be retried. If the Issuer is not an 'ACME' Issuer, an error will be returned and the Challenge will be marked as failed. + type: object + required: + - name + properties: + group: + description: Group of the resource being referred to. + type: string + kind: + description: Kind of the resource being referred to. + type: string + name: + description: Name of the resource being referred to. + type: string + key: + description: 'The ACME challenge key for this challenge For HTTP01 challenges, this is the value that must be responded with to complete the HTTP01 challenge in the format: `.`. For DNS01 challenges, this is the base64 encoded SHA256 sum of the `.` text that must be set as the TXT record content.' + type: string + solver: + description: Contains the domain solving configuration that should be used to solve this challenge resource. + type: object + properties: + dns01: + description: Configures cert-manager to attempt to complete authorizations by performing the DNS01 challenge flow. + type: object + properties: + acmeDNS: + description: Use the 'ACME DNS' (https://github.com/joohoi/acme-dns) API to manage DNS01 challenge records. + type: object + required: + - accountSecretRef + - host + properties: + accountSecretRef: + description: A reference to a specific 'key' within a Secret resource. In some instances, `key` is a required field. + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + host: + type: string + akamai: + description: Use the Akamai DNS zone management API to manage DNS01 challenge records. + type: object + required: + - accessTokenSecretRef + - clientSecretSecretRef + - clientTokenSecretRef + - serviceConsumerDomain + properties: + accessTokenSecretRef: + description: A reference to a specific 'key' within a Secret resource. In some instances, `key` is a required field. + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + clientSecretSecretRef: + description: A reference to a specific 'key' within a Secret resource. In some instances, `key` is a required field. + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + clientTokenSecretRef: + description: A reference to a specific 'key' within a Secret resource. In some instances, `key` is a required field. + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + serviceConsumerDomain: + type: string + azureDNS: + description: Use the Microsoft Azure DNS API to manage DNS01 challenge records. + type: object + required: + - resourceGroupName + - subscriptionID + properties: + clientID: + description: if both this and ClientSecret are left unset MSI will be used + type: string + clientSecretSecretRef: + description: if both this and ClientID are left unset MSI will be used + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + environment: + description: name of the Azure environment (default AzurePublicCloud) + type: string + enum: + - AzurePublicCloud + - AzureChinaCloud + - AzureGermanCloud + - AzureUSGovernmentCloud + hostedZoneName: + description: name of the DNS zone that should be used + type: string + managedIdentity: + description: managed identity configuration, can not be used at the same time as clientID, clientSecretSecretRef or tenantID + type: object + properties: + clientID: + description: client ID of the managed identity, can not be used at the same time as resourceID + type: string + resourceID: + description: resource ID of the managed identity, can not be used at the same time as clientID + type: string + resourceGroupName: + description: resource group the DNS zone is located in + type: string + subscriptionID: + description: ID of the Azure subscription + type: string + tenantID: + description: when specifying ClientID and ClientSecret then this field is also needed + type: string + cloudDNS: + description: Use the Google Cloud DNS API to manage DNS01 challenge records. + type: object + required: + - project + properties: + hostedZoneName: + description: HostedZoneName is an optional field that tells cert-manager in which Cloud DNS zone the challenge record has to be created. If left empty cert-manager will automatically choose a zone. + type: string + project: + type: string + serviceAccountSecretRef: + description: A reference to a specific 'key' within a Secret resource. In some instances, `key` is a required field. + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + cloudflare: + description: Use the Cloudflare API to manage DNS01 challenge records. + type: object + properties: + apiKeySecretRef: + description: 'API key to use to authenticate with Cloudflare. Note: using an API token to authenticate is now the recommended method as it allows greater control of permissions.' + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + apiTokenSecretRef: + description: API token used to authenticate with Cloudflare. + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + email: + description: Email of the account, only required when using API key based authentication. + type: string + cnameStrategy: + description: CNAMEStrategy configures how the DNS01 provider should handle CNAME records when found in DNS zones. + type: string + enum: + - None + - Follow + digitalocean: + description: Use the DigitalOcean DNS API to manage DNS01 challenge records. + type: object + required: + - tokenSecretRef + properties: + tokenSecretRef: + description: A reference to a specific 'key' within a Secret resource. In some instances, `key` is a required field. + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + rfc2136: + description: Use RFC2136 ("Dynamic Updates in the Domain Name System") (https://datatracker.ietf.org/doc/rfc2136/) to manage DNS01 challenge records. + type: object + required: + - nameserver + properties: + nameserver: + description: The IP address or hostname of an authoritative DNS server supporting RFC2136 in the form host:port. If the host is an IPv6 address it must be enclosed in square brackets (e.g [2001:db8::1]) ; port is optional. This field is required. + type: string + tsigAlgorithm: + description: 'The TSIG Algorithm configured in the DNS supporting RFC2136. Used only when ``tsigSecretSecretRef`` and ``tsigKeyName`` are defined. Supported values are (case-insensitive): ``HMACMD5`` (default), ``HMACSHA1``, ``HMACSHA256`` or ``HMACSHA512``.' + type: string + tsigKeyName: + description: The TSIG Key name configured in the DNS. If ``tsigSecretSecretRef`` is defined, this field is required. + type: string + tsigSecretSecretRef: + description: The name of the secret containing the TSIG value. If ``tsigKeyName`` is defined, this field is required. + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + route53: + description: Use the AWS Route53 API to manage DNS01 challenge records. + type: object + required: + - region + properties: + accessKeyID: + description: 'The AccessKeyID is used for authentication. Cannot be set when SecretAccessKeyID is set. If neither the Access Key nor Key ID are set, we fall-back to using env vars, shared credentials file or AWS Instance metadata, see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials' + type: string + accessKeyIDSecretRef: + description: 'The SecretAccessKey is used for authentication. If set, pull the AWS access key ID from a key within a Kubernetes Secret. Cannot be set when AccessKeyID is set. If neither the Access Key nor Key ID are set, we fall-back to using env vars, shared credentials file or AWS Instance metadata, see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials' + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + hostedZoneID: + description: If set, the provider will manage only this zone in Route53 and will not do an lookup using the route53:ListHostedZonesByName api call. + type: string + region: + description: Always set the region when using AccessKeyID and SecretAccessKey + type: string + role: + description: Role is a Role ARN which the Route53 provider will assume using either the explicit credentials AccessKeyID/SecretAccessKey or the inferred credentials from environment variables, shared credentials file or AWS Instance metadata + type: string + secretAccessKeySecretRef: + description: 'The SecretAccessKey is used for authentication. If neither the Access Key nor Key ID are set, we fall-back to using env vars, shared credentials file or AWS Instance metadata, see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials' + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + webhook: + description: Configure an external webhook based DNS01 challenge solver to manage DNS01 challenge records. + type: object + required: + - groupName + - solverName + properties: + config: + description: Additional configuration that should be passed to the webhook apiserver when challenges are processed. This can contain arbitrary JSON data. Secret values should not be specified in this stanza. If secret values are needed (e.g. credentials for a DNS service), you should use a SecretKeySelector to reference a Secret resource. For details on the schema of this field, consult the webhook provider implementation's documentation. + x-kubernetes-preserve-unknown-fields: true + groupName: + description: The API group name that should be used when POSTing ChallengePayload resources to the webhook apiserver. This should be the same as the GroupName specified in the webhook provider implementation. + type: string + solverName: + description: The name of the solver to use, as defined in the webhook provider implementation. This will typically be the name of the provider, e.g. 'cloudflare'. + type: string + http01: + description: Configures cert-manager to attempt to complete authorizations by performing the HTTP01 challenge flow. It is not possible to obtain certificates for wildcard domain names (e.g. `*.example.com`) using the HTTP01 challenge mechanism. + type: object + properties: + gatewayHTTPRoute: + description: The Gateway API is a sig-network community API that models service networking in Kubernetes (https://gateway-api.sigs.k8s.io/). The Gateway solver will create HTTPRoutes with the specified labels in the same namespace as the challenge. This solver is experimental, and fields / behaviour may change in the future. + type: object + properties: + labels: + description: Custom labels that will be applied to HTTPRoutes created by cert-manager while solving HTTP-01 challenges. + type: object + additionalProperties: + type: string + parentRefs: + description: 'When solving an HTTP-01 challenge, cert-manager creates an HTTPRoute. cert-manager needs to know which parentRefs should be used when creating the HTTPRoute. Usually, the parentRef references a Gateway. See: https://gateway-api.sigs.k8s.io/api-types/httproute/#attaching-to-gateways' + type: array + items: + description: "ParentReference identifies an API object (usually a Gateway) that can be considered a parent of this resource (usually a route). The only kind of parent resource with \"Core\" support is Gateway. This API may be extended in the future to support additional kinds of parent resources, such as HTTPRoute. \n The API object must be valid in the cluster; the Group and Kind must be registered in the cluster for this reference to be valid." + type: object + required: + - name + properties: + group: + description: "Group is the group of the referent. When unspecified, \"gateway.networking.k8s.io\" is inferred. To set the core API group (such as for a \"Service\" kind referent), Group must be explicitly set to \"\" (empty string). \n Support: Core" + type: string + default: gateway.networking.k8s.io + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + kind: + description: "Kind is kind of the referent. \n Support: Core (Gateway) \n Support: Implementation-specific (Other Resources)" + type: string + default: Gateway + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + name: + description: "Name is the name of the referent. \n Support: Core" + type: string + maxLength: 253 + minLength: 1 + namespace: + description: "Namespace is the namespace of the referent. When unspecified, this refers to the local namespace of the Route. \n Note that there are specific rules for ParentRefs which cross namespace boundaries. Cross-namespace references are only valid if they are explicitly allowed by something in the namespace they are referring to. For example: Gateway has the AllowedRoutes field, and ReferenceGrant provides a generic way to enable any other kind of cross-namespace reference. \n Support: Core" + type: string + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + port: + description: "Port is the network port this Route targets. It can be interpreted differently based on the type of parent resource. \n When the parent resource is a Gateway, this targets all listeners listening on the specified port that also support this kind of Route(and select this Route). It's not recommended to set `Port` unless the networking behaviors specified in a Route must apply to a specific port as opposed to a listener(s) whose port(s) may be changed. When both Port and SectionName are specified, the name and port of the selected listener must match both specified values. \n Implementations MAY choose to support other parent resources. Implementations supporting other types of parent resources MUST clearly document how/if Port is interpreted. \n For the purpose of status, an attachment is considered successful as long as the parent resource accepts it partially. For example, Gateway listeners can restrict which Routes can attach to them by Route kind, namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from the referencing Route, the Route MUST be considered successfully attached. If no Gateway listeners accept attachment from this Route, the Route MUST be considered detached from the Gateway. \n Support: Extended \n " + type: integer + format: int32 + maximum: 65535 + minimum: 1 + sectionName: + description: "SectionName is the name of a section within the target resource. In the following resources, SectionName is interpreted as the following: \n * Gateway: Listener Name. When both Port (experimental) and SectionName are specified, the name and port of the selected listener must match both specified values. \n Implementations MAY choose to support attaching Routes to other resources. If that is the case, they MUST clearly document how SectionName is interpreted. \n When unspecified (empty string), this will reference the entire resource. For the purpose of status, an attachment is considered successful if at least one section in the parent resource accepts it. For example, Gateway listeners can restrict which Routes can attach to them by Route kind, namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from the referencing Route, the Route MUST be considered successfully attached. If no Gateway listeners accept attachment from this Route, the Route MUST be considered detached from the Gateway. \n Support: Core" + type: string + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + serviceType: + description: Optional service type for Kubernetes solver service. Supported values are NodePort or ClusterIP. If unset, defaults to NodePort. + type: string + ingress: + description: The ingress based HTTP01 challenge solver will solve challenges by creating or modifying Ingress resources in order to route requests for '/.well-known/acme-challenge/XYZ' to 'challenge solver' pods that are provisioned by cert-manager for each Challenge to be completed. + type: object + properties: + class: + description: This field configures the annotation `kubernetes.io/ingress.class` when creating Ingress resources to solve ACME challenges that use this challenge solver. Only one of `class`, `name` or `ingressClassName` may be specified. + type: string + ingressClassName: + description: This field configures the field `ingressClassName` on the created Ingress resources used to solve ACME challenges that use this challenge solver. This is the recommended way of configuring the ingress class. Only one of `class`, `name` or `ingressClassName` may be specified. + type: string + ingressTemplate: + description: Optional ingress template used to configure the ACME challenge solver ingress used for HTTP01 challenges. + type: object + properties: + metadata: + description: ObjectMeta overrides for the ingress used to solve HTTP01 challenges. Only the 'labels' and 'annotations' fields may be set. If labels or annotations overlap with in-built values, the values here will override the in-built values. + type: object + properties: + annotations: + description: Annotations that should be added to the created ACME HTTP01 solver ingress. + type: object + additionalProperties: + type: string + labels: + description: Labels that should be added to the created ACME HTTP01 solver ingress. + type: object + additionalProperties: + type: string + name: + description: The name of the ingress resource that should have ACME challenge solving routes inserted into it in order to solve HTTP01 challenges. This is typically used in conjunction with ingress controllers like ingress-gce, which maintains a 1:1 mapping between external IPs and ingress resources. Only one of `class`, `name` or `ingressClassName` may be specified. + type: string + podTemplate: + description: Optional pod template used to configure the ACME challenge solver pods used for HTTP01 challenges. + type: object + properties: + metadata: + description: ObjectMeta overrides for the pod used to solve HTTP01 challenges. Only the 'labels' and 'annotations' fields may be set. If labels or annotations overlap with in-built values, the values here will override the in-built values. + type: object + properties: + annotations: + description: Annotations that should be added to the create ACME HTTP01 solver pods. + type: object + additionalProperties: + type: string + labels: + description: Labels that should be added to the created ACME HTTP01 solver pods. + type: object + additionalProperties: + type: string + spec: + description: PodSpec defines overrides for the HTTP01 challenge solver pod. Check ACMEChallengeSolverHTTP01IngressPodSpec to find out currently supported fields. All other fields will be ignored. + type: object + properties: + affinity: + description: If specified, the pod's scheduling constraints + type: object + properties: + nodeAffinity: + description: Describes node affinity scheduling rules for the pod. + type: object + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods to nodes that satisfy the affinity expressions specified by this field, but it may choose a node that violates one or more of the expressions. The node that is most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling affinity expressions, etc.), compute a sum by iterating through the elements of this field and adding "weight" to the sum if the node matches the corresponding matchExpressions; the node(s) with the highest sum are the most preferred. + type: array + items: + description: An empty preferred scheduling term matches all objects with implicit weight 0 (i.e. it's a no-op). A null preferred scheduling term matches no objects (i.e. is also a no-op). + type: object + required: + - preference + - weight + properties: + preference: + description: A node selector term, associated with the corresponding weight. + type: object + properties: + matchExpressions: + description: A list of node selector requirements by node's labels. + type: array + items: + description: A node selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: The label key that the selector applies to. + type: string + operator: + description: Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: 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. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch. + type: array + items: + type: string + matchFields: + description: A list of node selector requirements by node's fields. + type: array + items: + description: A node selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: The label key that the selector applies to. + type: string + operator: + description: Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: 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. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch. + type: array + items: + type: string + x-kubernetes-map-type: atomic + weight: + description: Weight associated with matching the corresponding nodeSelectorTerm, in the range 1-100. + type: integer + format: int32 + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by this field are not met at scheduling time, the pod will not be scheduled onto the node. If the affinity requirements specified by this field cease to be met at some point during pod execution (e.g. due to an update), the system may or may not try to eventually evict the pod from its node. + type: object + required: + - nodeSelectorTerms + properties: + nodeSelectorTerms: + description: Required. A list of node selector terms. The terms are ORed. + type: array + items: + description: A null or empty node selector term matches no objects. The requirements of them are ANDed. The TopologySelectorTerm type implements a subset of the NodeSelectorTerm. + type: object + properties: + matchExpressions: + description: A list of node selector requirements by node's labels. + type: array + items: + description: A node selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: The label key that the selector applies to. + type: string + operator: + description: Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: 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. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch. + type: array + items: + type: string + matchFields: + description: A list of node selector requirements by node's fields. + type: array + items: + description: A node selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: The label key that the selector applies to. + type: string + operator: + description: Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: 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. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch. + type: array + items: + type: string + x-kubernetes-map-type: atomic + x-kubernetes-map-type: atomic + podAffinity: + description: Describes pod affinity scheduling rules (e.g. co-locate this pod in the same node, zone, etc. as some other pod(s)). + type: object + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods to nodes that satisfy the affinity expressions specified by this field, but it may choose a node that violates one or more of the expressions. The node that is most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling affinity expressions, etc.), compute a sum by iterating through the elements of this field and adding "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. + type: array + items: + description: The weights of all of the matched WeightedPodAffinityTerm fields are added per-node to find the most preferred node(s) + type: object + required: + - podAffinityTerm + - weight + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated with the corresponding weight. + type: object + required: + - topologyKey + properties: + labelSelector: + description: A label query over a set of resources, in this case pods. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + matchLabels: + 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 + additionalProperties: + type: string + x-kubernetes-map-type: atomic + namespaceSelector: + description: A label query over the set of namespaces that the term applies to. The term is applied to the union of the namespaces selected by this field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector ({}) matches all namespaces. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + matchLabels: + 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 + additionalProperties: + type: string + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static list of namespace names that the term applies to. The term is applied to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list and null namespaceSelector means "this pod's namespace". + type: array + items: + type: string + topologyKey: + description: This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. Empty topologyKey is not allowed. + type: string + weight: + description: weight associated with matching the corresponding podAffinityTerm, in the range 1-100. + type: integer + format: int32 + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by this field are not met at scheduling time, the pod will not be scheduled onto the node. If the affinity requirements specified by this field cease to be met at some point during pod execution (e.g. due to a pod label update), the system may or may not try to eventually evict the pod from its node. When there are multiple elements, the lists of nodes corresponding to each podAffinityTerm are intersected, i.e. all terms must be satisfied. + type: array + items: + description: Defines a set of pods (namely those matching the labelSelector relative to the given namespace(s)) that this pod should be co-located (affinity) or not co-located (anti-affinity) with, where co-located is defined as running on a node whose value of the label with key matches that of any node on which a pod of the set of pods is running + type: object + required: + - topologyKey + properties: + labelSelector: + description: A label query over a set of resources, in this case pods. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + matchLabels: + 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 + additionalProperties: + type: string + x-kubernetes-map-type: atomic + namespaceSelector: + description: A label query over the set of namespaces that the term applies to. The term is applied to the union of the namespaces selected by this field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector ({}) matches all namespaces. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + matchLabels: + 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 + additionalProperties: + type: string + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static list of namespace names that the term applies to. The term is applied to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list and null namespaceSelector means "this pod's namespace". + type: array + items: + type: string + topologyKey: + description: This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. Empty topologyKey is not allowed. + type: string + podAntiAffinity: + description: Describes pod anti-affinity scheduling rules (e.g. avoid putting this pod in the same node, zone, etc. as some other pod(s)). + type: object + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods to nodes that satisfy the anti-affinity expressions specified by this field, but it may choose a node that violates one or more of the expressions. The node that is most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), compute a sum by iterating through the elements of this field and adding "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. + type: array + items: + description: The weights of all of the matched WeightedPodAffinityTerm fields are added per-node to find the most preferred node(s) + type: object + required: + - podAffinityTerm + - weight + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated with the corresponding weight. + type: object + required: + - topologyKey + properties: + labelSelector: + description: A label query over a set of resources, in this case pods. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + matchLabels: + 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 + additionalProperties: + type: string + x-kubernetes-map-type: atomic + namespaceSelector: + description: A label query over the set of namespaces that the term applies to. The term is applied to the union of the namespaces selected by this field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector ({}) matches all namespaces. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + matchLabels: + 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 + additionalProperties: + type: string + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static list of namespace names that the term applies to. The term is applied to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list and null namespaceSelector means "this pod's namespace". + type: array + items: + type: string + topologyKey: + description: This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. Empty topologyKey is not allowed. + type: string + weight: + description: weight associated with matching the corresponding podAffinityTerm, in the range 1-100. + type: integer + format: int32 + requiredDuringSchedulingIgnoredDuringExecution: + description: If the anti-affinity requirements specified by this field are not met at scheduling time, the pod will not be scheduled onto the node. If the anti-affinity requirements specified by this field cease to be met at some point during pod execution (e.g. due to a pod label update), the system may or may not try to eventually evict the pod from its node. When there are multiple elements, the lists of nodes corresponding to each podAffinityTerm are intersected, i.e. all terms must be satisfied. + type: array + items: + description: Defines a set of pods (namely those matching the labelSelector relative to the given namespace(s)) that this pod should be co-located (affinity) or not co-located (anti-affinity) with, where co-located is defined as running on a node whose value of the label with key matches that of any node on which a pod of the set of pods is running + type: object + required: + - topologyKey + properties: + labelSelector: + description: A label query over a set of resources, in this case pods. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + matchLabels: + 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 + additionalProperties: + type: string + x-kubernetes-map-type: atomic + namespaceSelector: + description: A label query over the set of namespaces that the term applies to. The term is applied to the union of the namespaces selected by this field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector ({}) matches all namespaces. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + matchLabels: + 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 + additionalProperties: + type: string + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static list of namespace names that the term applies to. The term is applied to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list and null namespaceSelector means "this pod's namespace". + type: array + items: + type: string + topologyKey: + description: This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. Empty topologyKey is not allowed. + type: string + imagePullSecrets: + description: If specified, the pod's imagePullSecrets + type: array + items: + description: LocalObjectReference contains enough information to let you locate the referenced object inside the same namespace. + type: object + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + x-kubernetes-map-type: atomic + nodeSelector: + description: 'NodeSelector is a selector which must be true for the pod to fit on a node. Selector which must match a node''s labels for the pod to be scheduled on that node. More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/' + type: object + additionalProperties: + type: string + priorityClassName: + description: If specified, the pod's priorityClassName. + type: string + serviceAccountName: + description: If specified, the pod's service account + type: string + tolerations: + description: If specified, the pod's tolerations. + type: array + items: + description: The pod this Toleration is attached to tolerates any taint that matches the triple using the matching operator . + type: object + 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. + type: integer + format: int64 + 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 + serviceType: + description: Optional service type for Kubernetes solver service. Supported values are NodePort or ClusterIP. If unset, defaults to NodePort. + type: string + selector: + description: Selector selects a set of DNSNames on the Certificate resource that should be solved using this challenge solver. If not specified, the solver will be treated as the 'default' solver with the lowest priority, i.e. if any other solver has a more specific match, it will be used instead. + type: object + properties: + dnsNames: + description: List of DNSNames that this solver will be used to solve. If specified and a match is found, a dnsNames selector will take precedence over a dnsZones selector. If multiple solvers match with the same dnsNames value, the solver with the most matching labels in matchLabels will be selected. If neither has more matches, the solver defined earlier in the list will be selected. + type: array + items: + type: string + dnsZones: + description: List of DNSZones that this solver will be used to solve. The most specific DNS zone match specified here will take precedence over other DNS zone matches, so a solver specifying sys.example.com will be selected over one specifying example.com for the domain www.sys.example.com. If multiple solvers match with the same dnsZones value, the solver with the most matching labels in matchLabels will be selected. If neither has more matches, the solver defined earlier in the list will be selected. + type: array + items: + type: string + matchLabels: + description: A label selector that is used to refine the set of certificate's that this challenge solver will apply to. + type: object + additionalProperties: + type: string + token: + description: The ACME challenge token for this challenge. This is the raw value returned from the ACME server. + type: string + type: + description: The type of ACME challenge this resource represents. One of "HTTP-01" or "DNS-01". + type: string + enum: + - HTTP-01 + - DNS-01 + url: + description: The URL of the ACME Challenge resource for this challenge. This can be used to lookup details about the status of this challenge. + type: string + wildcard: + description: wildcard will be true if this challenge is for a wildcard identifier, for example '*.example.com'. + type: boolean + status: + type: object + properties: + presented: + description: presented will be set to true if the challenge values for this challenge are currently 'presented'. This *does not* imply the self check is passing. Only that the values have been 'submitted' for the appropriate challenge mechanism (i.e. the DNS01 TXT record has been presented, or the HTTP01 configuration has been configured). + type: boolean + processing: + description: Used to denote whether this challenge should be processed or not. This field will only be set to true by the 'scheduling' component. It will only be set to false by the 'challenges' controller, after the challenge has reached a final state or timed out. If this field is set to false, the challenge controller will not take any more action. + type: boolean + reason: + description: Contains human readable information on why the Challenge is in the current state. + type: string + state: + description: Contains the current 'state' of the challenge. If not set, the state of the challenge is unknown. + type: string + enum: + - valid + - ready + - pending + - processing + - invalid + - expired + - errored + served: true + storage: true + subresources: + status: {} +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: clusterissuers.cert-manager.io + labels: + app: '{{ template "cert-manager.name" . }}' + app.kubernetes.io/name: '{{ template "cert-manager.name" . }}' + app.kubernetes.io/instance: "{{ .Release.Name }}" + # Generated labels {{- include "labels" . | nindent 4 }} +spec: + group: cert-manager.io + names: + kind: ClusterIssuer + listKind: ClusterIssuerList + plural: clusterissuers + singular: clusterissuer + categories: + - cert-manager + scope: Cluster + versions: + - name: v1 + subresources: + status: {} + additionalPrinterColumns: + - jsonPath: .status.conditions[?(@.type=="Ready")].status + name: Ready + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].message + name: Status + priority: 1 + type: string + - jsonPath: .metadata.creationTimestamp + description: CreationTimestamp is a timestamp representing the server time when this object was created. It is not guaranteed to be set in happens-before order across separate operations. Clients may not set this value. It is represented in RFC3339 form and is in UTC. + name: Age + type: date + schema: + openAPIV3Schema: + description: A ClusterIssuer represents a certificate issuing authority which can be referenced as part of `issuerRef` fields. It is similar to an Issuer, however it is cluster-scoped and therefore can be referenced by resources that exist in *any* namespace, not just the same namespace as the referent. + type: object + required: + - spec + 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: Desired state of the ClusterIssuer resource. + type: object + properties: + acme: + description: ACME configures this issuer to communicate with a RFC8555 (ACME) server to obtain signed x509 certificates. + type: object + required: + - privateKeySecretRef + - server + properties: + caBundle: + description: Base64-encoded bundle of PEM CAs which can be used to validate the certificate chain presented by the ACME server. Mutually exclusive with SkipTLSVerify; prefer using CABundle to prevent various kinds of security vulnerabilities. If CABundle and SkipTLSVerify are unset, the system certificate bundle inside the container is used to validate the TLS connection. + type: string + format: byte + disableAccountKeyGeneration: + description: Enables or disables generating a new ACME account key. If true, the Issuer resource will *not* request a new account but will expect the account key to be supplied via an existing secret. If false, the cert-manager system will generate a new ACME account key for the Issuer. Defaults to false. + type: boolean + email: + description: Email is the email address to be associated with the ACME account. This field is optional, but it is strongly recommended to be set. It will be used to contact you in case of issues with your account or certificates, including expiry notification emails. This field may be updated after the account is initially registered. + type: string + enableDurationFeature: + description: Enables requesting a Not After date on certificates that matches the duration of the certificate. This is not supported by all ACME servers like Let's Encrypt. If set to true when the ACME server does not support it it will create an error on the Order. Defaults to false. + type: boolean + externalAccountBinding: + description: ExternalAccountBinding is a reference to a CA external account of the ACME server. If set, upon registration cert-manager will attempt to associate the given external account credentials with the registered ACME account. + type: object + required: + - keyID + - keySecretRef + properties: + keyAlgorithm: + description: 'Deprecated: keyAlgorithm field exists for historical compatibility reasons and should not be used. The algorithm is now hardcoded to HS256 in golang/x/crypto/acme.' + type: string + enum: + - HS256 + - HS384 + - HS512 + keyID: + description: keyID is the ID of the CA key that the External Account is bound to. + type: string + keySecretRef: + description: keySecretRef is a Secret Key Selector referencing a data item in a Kubernetes Secret which holds the symmetric MAC key of the External Account Binding. The `key` is the index string that is paired with the key data in the Secret and should not be confused with the key data itself, or indeed with the External Account Binding keyID above. The secret key stored in the Secret **must** be un-padded, base64 URL encoded data. + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + preferredChain: + description: 'PreferredChain is the chain to use if the ACME server outputs multiple. PreferredChain is no guarantee that this one gets delivered by the ACME endpoint. For example, for Let''s Encrypt''s DST crosssign you would use: "DST Root CA X3" or "ISRG Root X1" for the newer Let''s Encrypt root CA. This value picks the first certificate bundle in the ACME alternative chains that has a certificate with this value as its issuer''s CN' + type: string + maxLength: 64 + privateKeySecretRef: + description: PrivateKey is the name of a Kubernetes Secret resource that will be used to store the automatically generated ACME account private key. Optionally, a `key` may be specified to select a specific entry within the named Secret resource. If `key` is not specified, a default of `tls.key` will be used. + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + server: + description: 'Server is the URL used to access the ACME server''s ''directory'' endpoint. For example, for Let''s Encrypt''s staging endpoint, you would use: "https://acme-staging-v02.api.letsencrypt.org/directory". Only ACME v2 endpoints (i.e. RFC 8555) are supported.' + type: string + skipTLSVerify: + description: 'INSECURE: Enables or disables validation of the ACME server TLS certificate. If true, requests to the ACME server will not have the TLS certificate chain validated. Mutually exclusive with CABundle; prefer using CABundle to prevent various kinds of security vulnerabilities. Only enable this option in development environments. If CABundle and SkipTLSVerify are unset, the system certificate bundle inside the container is used to validate the TLS connection. Defaults to false.' + type: boolean + solvers: + description: 'Solvers is a list of challenge solvers that will be used to solve ACME challenges for the matching domains. Solver configurations must be provided in order to obtain certificates from an ACME server. For more information, see: https://cert-manager.io/docs/configuration/acme/' + type: array + items: + description: An ACMEChallengeSolver describes how to solve ACME challenges for the issuer it is part of. A selector may be provided to use different solving strategies for different DNS names. Only one of HTTP01 or DNS01 must be provided. + type: object + properties: + dns01: + description: Configures cert-manager to attempt to complete authorizations by performing the DNS01 challenge flow. + type: object + properties: + acmeDNS: + description: Use the 'ACME DNS' (https://github.com/joohoi/acme-dns) API to manage DNS01 challenge records. + type: object + required: + - accountSecretRef + - host + properties: + accountSecretRef: + description: A reference to a specific 'key' within a Secret resource. In some instances, `key` is a required field. + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + host: + type: string + akamai: + description: Use the Akamai DNS zone management API to manage DNS01 challenge records. + type: object + required: + - accessTokenSecretRef + - clientSecretSecretRef + - clientTokenSecretRef + - serviceConsumerDomain + properties: + accessTokenSecretRef: + description: A reference to a specific 'key' within a Secret resource. In some instances, `key` is a required field. + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + clientSecretSecretRef: + description: A reference to a specific 'key' within a Secret resource. In some instances, `key` is a required field. + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + clientTokenSecretRef: + description: A reference to a specific 'key' within a Secret resource. In some instances, `key` is a required field. + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + serviceConsumerDomain: + type: string + azureDNS: + description: Use the Microsoft Azure DNS API to manage DNS01 challenge records. + type: object + required: + - resourceGroupName + - subscriptionID + properties: + clientID: + description: if both this and ClientSecret are left unset MSI will be used + type: string + clientSecretSecretRef: + description: if both this and ClientID are left unset MSI will be used + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + environment: + description: name of the Azure environment (default AzurePublicCloud) + type: string + enum: + - AzurePublicCloud + - AzureChinaCloud + - AzureGermanCloud + - AzureUSGovernmentCloud + hostedZoneName: + description: name of the DNS zone that should be used + type: string + managedIdentity: + description: managed identity configuration, can not be used at the same time as clientID, clientSecretSecretRef or tenantID + type: object + properties: + clientID: + description: client ID of the managed identity, can not be used at the same time as resourceID + type: string + resourceID: + description: resource ID of the managed identity, can not be used at the same time as clientID + type: string + resourceGroupName: + description: resource group the DNS zone is located in + type: string + subscriptionID: + description: ID of the Azure subscription + type: string + tenantID: + description: when specifying ClientID and ClientSecret then this field is also needed + type: string + cloudDNS: + description: Use the Google Cloud DNS API to manage DNS01 challenge records. + type: object + required: + - project + properties: + hostedZoneName: + description: HostedZoneName is an optional field that tells cert-manager in which Cloud DNS zone the challenge record has to be created. If left empty cert-manager will automatically choose a zone. + type: string + project: + type: string + serviceAccountSecretRef: + description: A reference to a specific 'key' within a Secret resource. In some instances, `key` is a required field. + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + cloudflare: + description: Use the Cloudflare API to manage DNS01 challenge records. + type: object + properties: + apiKeySecretRef: + description: 'API key to use to authenticate with Cloudflare. Note: using an API token to authenticate is now the recommended method as it allows greater control of permissions.' + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + apiTokenSecretRef: + description: API token used to authenticate with Cloudflare. + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + email: + description: Email of the account, only required when using API key based authentication. + type: string + cnameStrategy: + description: CNAMEStrategy configures how the DNS01 provider should handle CNAME records when found in DNS zones. + type: string + enum: + - None + - Follow + digitalocean: + description: Use the DigitalOcean DNS API to manage DNS01 challenge records. + type: object + required: + - tokenSecretRef + properties: + tokenSecretRef: + description: A reference to a specific 'key' within a Secret resource. In some instances, `key` is a required field. + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + rfc2136: + description: Use RFC2136 ("Dynamic Updates in the Domain Name System") (https://datatracker.ietf.org/doc/rfc2136/) to manage DNS01 challenge records. + type: object + required: + - nameserver + properties: + nameserver: + description: The IP address or hostname of an authoritative DNS server supporting RFC2136 in the form host:port. If the host is an IPv6 address it must be enclosed in square brackets (e.g [2001:db8::1]) ; port is optional. This field is required. + type: string + tsigAlgorithm: + description: 'The TSIG Algorithm configured in the DNS supporting RFC2136. Used only when ``tsigSecretSecretRef`` and ``tsigKeyName`` are defined. Supported values are (case-insensitive): ``HMACMD5`` (default), ``HMACSHA1``, ``HMACSHA256`` or ``HMACSHA512``.' + type: string + tsigKeyName: + description: The TSIG Key name configured in the DNS. If ``tsigSecretSecretRef`` is defined, this field is required. + type: string + tsigSecretSecretRef: + description: The name of the secret containing the TSIG value. If ``tsigKeyName`` is defined, this field is required. + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + route53: + description: Use the AWS Route53 API to manage DNS01 challenge records. + type: object + required: + - region + properties: + accessKeyID: + description: 'The AccessKeyID is used for authentication. Cannot be set when SecretAccessKeyID is set. If neither the Access Key nor Key ID are set, we fall-back to using env vars, shared credentials file or AWS Instance metadata, see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials' + type: string + accessKeyIDSecretRef: + description: 'The SecretAccessKey is used for authentication. If set, pull the AWS access key ID from a key within a Kubernetes Secret. Cannot be set when AccessKeyID is set. If neither the Access Key nor Key ID are set, we fall-back to using env vars, shared credentials file or AWS Instance metadata, see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials' + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + hostedZoneID: + description: If set, the provider will manage only this zone in Route53 and will not do an lookup using the route53:ListHostedZonesByName api call. + type: string + region: + description: Always set the region when using AccessKeyID and SecretAccessKey + type: string + role: + description: Role is a Role ARN which the Route53 provider will assume using either the explicit credentials AccessKeyID/SecretAccessKey or the inferred credentials from environment variables, shared credentials file or AWS Instance metadata + type: string + secretAccessKeySecretRef: + description: 'The SecretAccessKey is used for authentication. If neither the Access Key nor Key ID are set, we fall-back to using env vars, shared credentials file or AWS Instance metadata, see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials' + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + webhook: + description: Configure an external webhook based DNS01 challenge solver to manage DNS01 challenge records. + type: object + required: + - groupName + - solverName + properties: + config: + description: Additional configuration that should be passed to the webhook apiserver when challenges are processed. This can contain arbitrary JSON data. Secret values should not be specified in this stanza. If secret values are needed (e.g. credentials for a DNS service), you should use a SecretKeySelector to reference a Secret resource. For details on the schema of this field, consult the webhook provider implementation's documentation. + x-kubernetes-preserve-unknown-fields: true + groupName: + description: The API group name that should be used when POSTing ChallengePayload resources to the webhook apiserver. This should be the same as the GroupName specified in the webhook provider implementation. + type: string + solverName: + description: The name of the solver to use, as defined in the webhook provider implementation. This will typically be the name of the provider, e.g. 'cloudflare'. + type: string + http01: + description: Configures cert-manager to attempt to complete authorizations by performing the HTTP01 challenge flow. It is not possible to obtain certificates for wildcard domain names (e.g. `*.example.com`) using the HTTP01 challenge mechanism. + type: object + properties: + gatewayHTTPRoute: + description: The Gateway API is a sig-network community API that models service networking in Kubernetes (https://gateway-api.sigs.k8s.io/). The Gateway solver will create HTTPRoutes with the specified labels in the same namespace as the challenge. This solver is experimental, and fields / behaviour may change in the future. + type: object + properties: + labels: + description: Custom labels that will be applied to HTTPRoutes created by cert-manager while solving HTTP-01 challenges. + type: object + additionalProperties: + type: string + parentRefs: + description: 'When solving an HTTP-01 challenge, cert-manager creates an HTTPRoute. cert-manager needs to know which parentRefs should be used when creating the HTTPRoute. Usually, the parentRef references a Gateway. See: https://gateway-api.sigs.k8s.io/api-types/httproute/#attaching-to-gateways' + type: array + items: + description: "ParentReference identifies an API object (usually a Gateway) that can be considered a parent of this resource (usually a route). The only kind of parent resource with \"Core\" support is Gateway. This API may be extended in the future to support additional kinds of parent resources, such as HTTPRoute. \n The API object must be valid in the cluster; the Group and Kind must be registered in the cluster for this reference to be valid." + type: object + required: + - name + properties: + group: + description: "Group is the group of the referent. When unspecified, \"gateway.networking.k8s.io\" is inferred. To set the core API group (such as for a \"Service\" kind referent), Group must be explicitly set to \"\" (empty string). \n Support: Core" + type: string + default: gateway.networking.k8s.io + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + kind: + description: "Kind is kind of the referent. \n Support: Core (Gateway) \n Support: Implementation-specific (Other Resources)" + type: string + default: Gateway + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + name: + description: "Name is the name of the referent. \n Support: Core" + type: string + maxLength: 253 + minLength: 1 + namespace: + description: "Namespace is the namespace of the referent. When unspecified, this refers to the local namespace of the Route. \n Note that there are specific rules for ParentRefs which cross namespace boundaries. Cross-namespace references are only valid if they are explicitly allowed by something in the namespace they are referring to. For example: Gateway has the AllowedRoutes field, and ReferenceGrant provides a generic way to enable any other kind of cross-namespace reference. \n Support: Core" + type: string + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + port: + description: "Port is the network port this Route targets. It can be interpreted differently based on the type of parent resource. \n When the parent resource is a Gateway, this targets all listeners listening on the specified port that also support this kind of Route(and select this Route). It's not recommended to set `Port` unless the networking behaviors specified in a Route must apply to a specific port as opposed to a listener(s) whose port(s) may be changed. When both Port and SectionName are specified, the name and port of the selected listener must match both specified values. \n Implementations MAY choose to support other parent resources. Implementations supporting other types of parent resources MUST clearly document how/if Port is interpreted. \n For the purpose of status, an attachment is considered successful as long as the parent resource accepts it partially. For example, Gateway listeners can restrict which Routes can attach to them by Route kind, namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from the referencing Route, the Route MUST be considered successfully attached. If no Gateway listeners accept attachment from this Route, the Route MUST be considered detached from the Gateway. \n Support: Extended \n " + type: integer + format: int32 + maximum: 65535 + minimum: 1 + sectionName: + description: "SectionName is the name of a section within the target resource. In the following resources, SectionName is interpreted as the following: \n * Gateway: Listener Name. When both Port (experimental) and SectionName are specified, the name and port of the selected listener must match both specified values. \n Implementations MAY choose to support attaching Routes to other resources. If that is the case, they MUST clearly document how SectionName is interpreted. \n When unspecified (empty string), this will reference the entire resource. For the purpose of status, an attachment is considered successful if at least one section in the parent resource accepts it. For example, Gateway listeners can restrict which Routes can attach to them by Route kind, namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from the referencing Route, the Route MUST be considered successfully attached. If no Gateway listeners accept attachment from this Route, the Route MUST be considered detached from the Gateway. \n Support: Core" + type: string + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + serviceType: + description: Optional service type for Kubernetes solver service. Supported values are NodePort or ClusterIP. If unset, defaults to NodePort. + type: string + ingress: + description: The ingress based HTTP01 challenge solver will solve challenges by creating or modifying Ingress resources in order to route requests for '/.well-known/acme-challenge/XYZ' to 'challenge solver' pods that are provisioned by cert-manager for each Challenge to be completed. + type: object + properties: + class: + description: This field configures the annotation `kubernetes.io/ingress.class` when creating Ingress resources to solve ACME challenges that use this challenge solver. Only one of `class`, `name` or `ingressClassName` may be specified. + type: string + ingressClassName: + description: This field configures the field `ingressClassName` on the created Ingress resources used to solve ACME challenges that use this challenge solver. This is the recommended way of configuring the ingress class. Only one of `class`, `name` or `ingressClassName` may be specified. + type: string + ingressTemplate: + description: Optional ingress template used to configure the ACME challenge solver ingress used for HTTP01 challenges. + type: object + properties: + metadata: + description: ObjectMeta overrides for the ingress used to solve HTTP01 challenges. Only the 'labels' and 'annotations' fields may be set. If labels or annotations overlap with in-built values, the values here will override the in-built values. + type: object + properties: + annotations: + description: Annotations that should be added to the created ACME HTTP01 solver ingress. + type: object + additionalProperties: + type: string + labels: + description: Labels that should be added to the created ACME HTTP01 solver ingress. + type: object + additionalProperties: + type: string + name: + description: The name of the ingress resource that should have ACME challenge solving routes inserted into it in order to solve HTTP01 challenges. This is typically used in conjunction with ingress controllers like ingress-gce, which maintains a 1:1 mapping between external IPs and ingress resources. Only one of `class`, `name` or `ingressClassName` may be specified. + type: string + podTemplate: + description: Optional pod template used to configure the ACME challenge solver pods used for HTTP01 challenges. + type: object + properties: + metadata: + description: ObjectMeta overrides for the pod used to solve HTTP01 challenges. Only the 'labels' and 'annotations' fields may be set. If labels or annotations overlap with in-built values, the values here will override the in-built values. + type: object + properties: + annotations: + description: Annotations that should be added to the create ACME HTTP01 solver pods. + type: object + additionalProperties: + type: string + labels: + description: Labels that should be added to the created ACME HTTP01 solver pods. + type: object + additionalProperties: + type: string + spec: + description: PodSpec defines overrides for the HTTP01 challenge solver pod. Check ACMEChallengeSolverHTTP01IngressPodSpec to find out currently supported fields. All other fields will be ignored. + type: object + properties: + affinity: + description: If specified, the pod's scheduling constraints + type: object + properties: + nodeAffinity: + description: Describes node affinity scheduling rules for the pod. + type: object + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods to nodes that satisfy the affinity expressions specified by this field, but it may choose a node that violates one or more of the expressions. The node that is most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling affinity expressions, etc.), compute a sum by iterating through the elements of this field and adding "weight" to the sum if the node matches the corresponding matchExpressions; the node(s) with the highest sum are the most preferred. + type: array + items: + description: An empty preferred scheduling term matches all objects with implicit weight 0 (i.e. it's a no-op). A null preferred scheduling term matches no objects (i.e. is also a no-op). + type: object + required: + - preference + - weight + properties: + preference: + description: A node selector term, associated with the corresponding weight. + type: object + properties: + matchExpressions: + description: A list of node selector requirements by node's labels. + type: array + items: + description: A node selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: The label key that the selector applies to. + type: string + operator: + description: Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: 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. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch. + type: array + items: + type: string + matchFields: + description: A list of node selector requirements by node's fields. + type: array + items: + description: A node selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: The label key that the selector applies to. + type: string + operator: + description: Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: 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. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch. + type: array + items: + type: string + x-kubernetes-map-type: atomic + weight: + description: Weight associated with matching the corresponding nodeSelectorTerm, in the range 1-100. + type: integer + format: int32 + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by this field are not met at scheduling time, the pod will not be scheduled onto the node. If the affinity requirements specified by this field cease to be met at some point during pod execution (e.g. due to an update), the system may or may not try to eventually evict the pod from its node. + type: object + required: + - nodeSelectorTerms + properties: + nodeSelectorTerms: + description: Required. A list of node selector terms. The terms are ORed. + type: array + items: + description: A null or empty node selector term matches no objects. The requirements of them are ANDed. The TopologySelectorTerm type implements a subset of the NodeSelectorTerm. + type: object + properties: + matchExpressions: + description: A list of node selector requirements by node's labels. + type: array + items: + description: A node selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: The label key that the selector applies to. + type: string + operator: + description: Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: 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. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch. + type: array + items: + type: string + matchFields: + description: A list of node selector requirements by node's fields. + type: array + items: + description: A node selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: The label key that the selector applies to. + type: string + operator: + description: Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: 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. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch. + type: array + items: + type: string + x-kubernetes-map-type: atomic + x-kubernetes-map-type: atomic + podAffinity: + description: Describes pod affinity scheduling rules (e.g. co-locate this pod in the same node, zone, etc. as some other pod(s)). + type: object + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods to nodes that satisfy the affinity expressions specified by this field, but it may choose a node that violates one or more of the expressions. The node that is most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling affinity expressions, etc.), compute a sum by iterating through the elements of this field and adding "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. + type: array + items: + description: The weights of all of the matched WeightedPodAffinityTerm fields are added per-node to find the most preferred node(s) + type: object + required: + - podAffinityTerm + - weight + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated with the corresponding weight. + type: object + required: + - topologyKey + properties: + labelSelector: + description: A label query over a set of resources, in this case pods. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + matchLabels: + 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 + additionalProperties: + type: string + x-kubernetes-map-type: atomic + namespaceSelector: + description: A label query over the set of namespaces that the term applies to. The term is applied to the union of the namespaces selected by this field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector ({}) matches all namespaces. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + matchLabels: + 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 + additionalProperties: + type: string + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static list of namespace names that the term applies to. The term is applied to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list and null namespaceSelector means "this pod's namespace". + type: array + items: + type: string + topologyKey: + description: This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. Empty topologyKey is not allowed. + type: string + weight: + description: weight associated with matching the corresponding podAffinityTerm, in the range 1-100. + type: integer + format: int32 + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by this field are not met at scheduling time, the pod will not be scheduled onto the node. If the affinity requirements specified by this field cease to be met at some point during pod execution (e.g. due to a pod label update), the system may or may not try to eventually evict the pod from its node. When there are multiple elements, the lists of nodes corresponding to each podAffinityTerm are intersected, i.e. all terms must be satisfied. + type: array + items: + description: Defines a set of pods (namely those matching the labelSelector relative to the given namespace(s)) that this pod should be co-located (affinity) or not co-located (anti-affinity) with, where co-located is defined as running on a node whose value of the label with key matches that of any node on which a pod of the set of pods is running + type: object + required: + - topologyKey + properties: + labelSelector: + description: A label query over a set of resources, in this case pods. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + matchLabels: + 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 + additionalProperties: + type: string + x-kubernetes-map-type: atomic + namespaceSelector: + description: A label query over the set of namespaces that the term applies to. The term is applied to the union of the namespaces selected by this field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector ({}) matches all namespaces. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + matchLabels: + 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 + additionalProperties: + type: string + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static list of namespace names that the term applies to. The term is applied to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list and null namespaceSelector means "this pod's namespace". + type: array + items: + type: string + topologyKey: + description: This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. Empty topologyKey is not allowed. + type: string + podAntiAffinity: + description: Describes pod anti-affinity scheduling rules (e.g. avoid putting this pod in the same node, zone, etc. as some other pod(s)). + type: object + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods to nodes that satisfy the anti-affinity expressions specified by this field, but it may choose a node that violates one or more of the expressions. The node that is most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), compute a sum by iterating through the elements of this field and adding "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. + type: array + items: + description: The weights of all of the matched WeightedPodAffinityTerm fields are added per-node to find the most preferred node(s) + type: object + required: + - podAffinityTerm + - weight + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated with the corresponding weight. + type: object + required: + - topologyKey + properties: + labelSelector: + description: A label query over a set of resources, in this case pods. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + matchLabels: + 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 + additionalProperties: + type: string + x-kubernetes-map-type: atomic + namespaceSelector: + description: A label query over the set of namespaces that the term applies to. The term is applied to the union of the namespaces selected by this field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector ({}) matches all namespaces. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + matchLabels: + 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 + additionalProperties: + type: string + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static list of namespace names that the term applies to. The term is applied to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list and null namespaceSelector means "this pod's namespace". + type: array + items: + type: string + topologyKey: + description: This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. Empty topologyKey is not allowed. + type: string + weight: + description: weight associated with matching the corresponding podAffinityTerm, in the range 1-100. + type: integer + format: int32 + requiredDuringSchedulingIgnoredDuringExecution: + description: If the anti-affinity requirements specified by this field are not met at scheduling time, the pod will not be scheduled onto the node. If the anti-affinity requirements specified by this field cease to be met at some point during pod execution (e.g. due to a pod label update), the system may or may not try to eventually evict the pod from its node. When there are multiple elements, the lists of nodes corresponding to each podAffinityTerm are intersected, i.e. all terms must be satisfied. + type: array + items: + description: Defines a set of pods (namely those matching the labelSelector relative to the given namespace(s)) that this pod should be co-located (affinity) or not co-located (anti-affinity) with, where co-located is defined as running on a node whose value of the label with key matches that of any node on which a pod of the set of pods is running + type: object + required: + - topologyKey + properties: + labelSelector: + description: A label query over a set of resources, in this case pods. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + matchLabels: + 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 + additionalProperties: + type: string + x-kubernetes-map-type: atomic + namespaceSelector: + description: A label query over the set of namespaces that the term applies to. The term is applied to the union of the namespaces selected by this field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector ({}) matches all namespaces. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + matchLabels: + 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 + additionalProperties: + type: string + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static list of namespace names that the term applies to. The term is applied to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list and null namespaceSelector means "this pod's namespace". + type: array + items: + type: string + topologyKey: + description: This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. Empty topologyKey is not allowed. + type: string + imagePullSecrets: + description: If specified, the pod's imagePullSecrets + type: array + items: + description: LocalObjectReference contains enough information to let you locate the referenced object inside the same namespace. + type: object + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + x-kubernetes-map-type: atomic + nodeSelector: + description: 'NodeSelector is a selector which must be true for the pod to fit on a node. Selector which must match a node''s labels for the pod to be scheduled on that node. More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/' + type: object + additionalProperties: + type: string + priorityClassName: + description: If specified, the pod's priorityClassName. + type: string + serviceAccountName: + description: If specified, the pod's service account + type: string + tolerations: + description: If specified, the pod's tolerations. + type: array + items: + description: The pod this Toleration is attached to tolerates any taint that matches the triple using the matching operator . + type: object + 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. + type: integer + format: int64 + 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 + serviceType: + description: Optional service type for Kubernetes solver service. Supported values are NodePort or ClusterIP. If unset, defaults to NodePort. + type: string + selector: + description: Selector selects a set of DNSNames on the Certificate resource that should be solved using this challenge solver. If not specified, the solver will be treated as the 'default' solver with the lowest priority, i.e. if any other solver has a more specific match, it will be used instead. + type: object + properties: + dnsNames: + description: List of DNSNames that this solver will be used to solve. If specified and a match is found, a dnsNames selector will take precedence over a dnsZones selector. If multiple solvers match with the same dnsNames value, the solver with the most matching labels in matchLabels will be selected. If neither has more matches, the solver defined earlier in the list will be selected. + type: array + items: + type: string + dnsZones: + description: List of DNSZones that this solver will be used to solve. The most specific DNS zone match specified here will take precedence over other DNS zone matches, so a solver specifying sys.example.com will be selected over one specifying example.com for the domain www.sys.example.com. If multiple solvers match with the same dnsZones value, the solver with the most matching labels in matchLabels will be selected. If neither has more matches, the solver defined earlier in the list will be selected. + type: array + items: + type: string + matchLabels: + description: A label selector that is used to refine the set of certificate's that this challenge solver will apply to. + type: object + additionalProperties: + type: string + ca: + description: CA configures this issuer to sign certificates using a signing CA keypair stored in a Secret resource. This is used to build internal PKIs that are managed by cert-manager. + type: object + required: + - secretName + properties: + crlDistributionPoints: + description: The CRL distribution points is an X.509 v3 certificate extension which identifies the location of the CRL from which the revocation of this certificate can be checked. If not set, certificates will be issued without distribution points set. + type: array + items: + type: string + ocspServers: + description: The OCSP server list is an X.509 v3 extension that defines a list of URLs of OCSP responders. The OCSP responders can be queried for the revocation status of an issued certificate. If not set, the certificate will be issued with no OCSP servers set. For example, an OCSP server URL could be "http://ocsp.int-x3.letsencrypt.org". + type: array + items: + type: string + secretName: + description: SecretName is the name of the secret used to sign Certificates issued by this Issuer. + type: string + selfSigned: + description: SelfSigned configures this issuer to 'self sign' certificates using the private key used to create the CertificateRequest object. + type: object + properties: + crlDistributionPoints: + description: The CRL distribution points is an X.509 v3 certificate extension which identifies the location of the CRL from which the revocation of this certificate can be checked. If not set certificate will be issued without CDP. Values are strings. + type: array + items: + type: string + vault: + description: Vault configures this issuer to sign certificates using a HashiCorp Vault PKI backend. + type: object + required: + - auth + - path + - server + properties: + auth: + description: Auth configures how cert-manager authenticates with the Vault server. + type: object + properties: + appRole: + description: AppRole authenticates with Vault using the App Role auth mechanism, with the role and secret stored in a Kubernetes Secret resource. + type: object + required: + - path + - roleId + - secretRef + properties: + path: + description: 'Path where the App Role authentication backend is mounted in Vault, e.g: "approle"' + type: string + roleId: + description: RoleID configured in the App Role authentication backend when setting up the authentication backend in Vault. + type: string + secretRef: + description: Reference to a key in a Secret that contains the App Role secret used to authenticate with Vault. The `key` field must be specified and denotes which entry within the Secret resource is used as the app role secret. + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + kubernetes: + description: Kubernetes authenticates with Vault by passing the ServiceAccount token stored in the named Secret resource to the Vault server. + type: object + required: + - role + properties: + mountPath: + description: The Vault mountPath here is the mount path to use when authenticating with Vault. For example, setting a value to `/v1/auth/foo`, will use the path `/v1/auth/foo/login` to authenticate with Vault. If unspecified, the default value "/v1/auth/kubernetes" will be used. + type: string + role: + description: A required field containing the Vault Role to assume. A Role binds a Kubernetes ServiceAccount with a set of Vault policies. + type: string + secretRef: + description: The required Secret field containing a Kubernetes ServiceAccount JWT used for authenticating with Vault. Use of 'ambient credentials' is not supported. + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + serviceAccountRef: + description: A reference to a service account that will be used to request a bound token (also known as "projected token"). Compared to using "secretRef", using this field means that you don't rely on statically bound tokens. To use this field, you must configure an RBAC rule to let cert-manager request a token. + type: object + required: + - name + properties: + name: + description: Name of the ServiceAccount used to request a token. + type: string + tokenSecretRef: + description: TokenSecretRef authenticates with Vault by presenting a token. + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + caBundle: + description: Base64-encoded bundle of PEM CAs which will be used to validate the certificate chain presented by Vault. Only used if using HTTPS to connect to Vault and ignored for HTTP connections. Mutually exclusive with CABundleSecretRef. If neither CABundle nor CABundleSecretRef are defined, the certificate bundle in the cert-manager controller container is used to validate the TLS connection. + type: string + format: byte + caBundleSecretRef: + description: Reference to a Secret containing a bundle of PEM-encoded CAs to use when verifying the certificate chain presented by Vault when using HTTPS. Mutually exclusive with CABundle. If neither CABundle nor CABundleSecretRef are defined, the certificate bundle in the cert-manager controller container is used to validate the TLS connection. If no key for the Secret is specified, cert-manager will default to 'ca.crt'. + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + namespace: + description: 'Name of the vault namespace. Namespaces is a set of features within Vault Enterprise that allows Vault environments to support Secure Multi-tenancy. e.g: "ns1" More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces' + type: string + path: + description: 'Path is the mount path of the Vault PKI backend''s `sign` endpoint, e.g: "my_pki_mount/sign/my-role-name".' + type: string + server: + description: 'Server is the connection address for the Vault server, e.g: "https://vault.example.com:8200".' + type: string + venafi: + description: Venafi configures this issuer to sign certificates using a Venafi TPP or Venafi Cloud policy zone. + type: object + required: + - zone + properties: + cloud: + description: Cloud specifies the Venafi cloud configuration settings. Only one of TPP or Cloud may be specified. + type: object + required: + - apiTokenSecretRef + properties: + apiTokenSecretRef: + description: APITokenSecretRef is a secret key selector for the Venafi Cloud API token. + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + url: + description: URL is the base URL for Venafi Cloud. Defaults to "https://api.venafi.cloud/v1". + type: string + tpp: + description: TPP specifies Trust Protection Platform configuration settings. Only one of TPP or Cloud may be specified. + type: object + required: + - credentialsRef + - url + properties: + caBundle: + description: Base64-encoded bundle of PEM CAs which will be used to validate the certificate chain presented by the TPP server. Only used if using HTTPS; ignored for HTTP. If undefined, the certificate bundle in the cert-manager controller container is used to validate the chain. + type: string + format: byte + credentialsRef: + description: CredentialsRef is a reference to a Secret containing the username and password for the TPP server. The secret must contain two keys, 'username' and 'password'. + type: object + required: + - name + properties: + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + url: + description: 'URL is the base URL for the vedsdk endpoint of the Venafi TPP instance, for example: "https://tpp.example.com/vedsdk".' + type: string + zone: + description: Zone is the Venafi Policy Zone to use for this issuer. All requests made to the Venafi platform will be restricted by the named zone policy. This field is required. + type: string + status: + description: Status of the ClusterIssuer. This is set and managed automatically. + type: object + properties: + acme: + description: ACME specific status options. This field should only be set if the Issuer is configured to use an ACME server to issue certificates. + type: object + properties: + lastPrivateKeyHash: + description: LastPrivateKeyHash is a hash of the private key associated with the latest registered ACME account, in order to track changes made to registered account associated with the Issuer + type: string + lastRegisteredEmail: + description: LastRegisteredEmail is the email associated with the latest registered ACME account, in order to track changes made to registered account associated with the Issuer + type: string + uri: + description: URI is the unique account identifier, which can also be used to retrieve account details from the CA + type: string + conditions: + description: List of status conditions to indicate the status of a CertificateRequest. Known condition types are `Ready`. + type: array + items: + description: IssuerCondition contains condition information for an Issuer. + type: object + required: + - status + - type + properties: + lastTransitionTime: + description: LastTransitionTime is the timestamp corresponding to the last status change of this condition. + type: string + format: date-time + message: + description: Message is a human readable description of the details of the last transition, complementing reason. + type: string + observedGeneration: + description: If set, this represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.condition[x].observedGeneration is 9, the condition is out of date with respect to the current state of the Issuer. + type: integer + format: int64 + reason: + description: Reason is a brief machine readable explanation for the condition's last transition. + type: string + status: + description: Status of the condition, one of (`True`, `False`, `Unknown`). + type: string + enum: + - "True" + - "False" + - Unknown + type: + description: Type of the condition, known values are (`Ready`). + type: string + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + served: true + storage: true +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: issuers.cert-manager.io + labels: + app: '{{ template "cert-manager.name" . }}' + app.kubernetes.io/name: '{{ template "cert-manager.name" . }}' + app.kubernetes.io/instance: "{{ .Release.Name }}" + # Generated labels {{- include "labels" . | nindent 4 }} +spec: + group: cert-manager.io + names: + kind: Issuer + listKind: IssuerList + plural: issuers + singular: issuer + categories: + - cert-manager + scope: Namespaced + versions: + - name: v1 + subresources: + status: {} + additionalPrinterColumns: + - jsonPath: .status.conditions[?(@.type=="Ready")].status + name: Ready + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].message + name: Status + priority: 1 + type: string + - jsonPath: .metadata.creationTimestamp + description: CreationTimestamp is a timestamp representing the server time when this object was created. It is not guaranteed to be set in happens-before order across separate operations. Clients may not set this value. It is represented in RFC3339 form and is in UTC. + name: Age + type: date + schema: + openAPIV3Schema: + description: An Issuer represents a certificate issuing authority which can be referenced as part of `issuerRef` fields. It is scoped to a single namespace and can therefore only be referenced by resources within the same namespace. + type: object + required: + - spec + 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: Desired state of the Issuer resource. + type: object + properties: + acme: + description: ACME configures this issuer to communicate with a RFC8555 (ACME) server to obtain signed x509 certificates. + type: object + required: + - privateKeySecretRef + - server + properties: + caBundle: + description: Base64-encoded bundle of PEM CAs which can be used to validate the certificate chain presented by the ACME server. Mutually exclusive with SkipTLSVerify; prefer using CABundle to prevent various kinds of security vulnerabilities. If CABundle and SkipTLSVerify are unset, the system certificate bundle inside the container is used to validate the TLS connection. + type: string + format: byte + disableAccountKeyGeneration: + description: Enables or disables generating a new ACME account key. If true, the Issuer resource will *not* request a new account but will expect the account key to be supplied via an existing secret. If false, the cert-manager system will generate a new ACME account key for the Issuer. Defaults to false. + type: boolean + email: + description: Email is the email address to be associated with the ACME account. This field is optional, but it is strongly recommended to be set. It will be used to contact you in case of issues with your account or certificates, including expiry notification emails. This field may be updated after the account is initially registered. + type: string + enableDurationFeature: + description: Enables requesting a Not After date on certificates that matches the duration of the certificate. This is not supported by all ACME servers like Let's Encrypt. If set to true when the ACME server does not support it it will create an error on the Order. Defaults to false. + type: boolean + externalAccountBinding: + description: ExternalAccountBinding is a reference to a CA external account of the ACME server. If set, upon registration cert-manager will attempt to associate the given external account credentials with the registered ACME account. + type: object + required: + - keyID + - keySecretRef + properties: + keyAlgorithm: + description: 'Deprecated: keyAlgorithm field exists for historical compatibility reasons and should not be used. The algorithm is now hardcoded to HS256 in golang/x/crypto/acme.' + type: string + enum: + - HS256 + - HS384 + - HS512 + keyID: + description: keyID is the ID of the CA key that the External Account is bound to. + type: string + keySecretRef: + description: keySecretRef is a Secret Key Selector referencing a data item in a Kubernetes Secret which holds the symmetric MAC key of the External Account Binding. The `key` is the index string that is paired with the key data in the Secret and should not be confused with the key data itself, or indeed with the External Account Binding keyID above. The secret key stored in the Secret **must** be un-padded, base64 URL encoded data. + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + preferredChain: + description: 'PreferredChain is the chain to use if the ACME server outputs multiple. PreferredChain is no guarantee that this one gets delivered by the ACME endpoint. For example, for Let''s Encrypt''s DST crosssign you would use: "DST Root CA X3" or "ISRG Root X1" for the newer Let''s Encrypt root CA. This value picks the first certificate bundle in the ACME alternative chains that has a certificate with this value as its issuer''s CN' + type: string + maxLength: 64 + privateKeySecretRef: + description: PrivateKey is the name of a Kubernetes Secret resource that will be used to store the automatically generated ACME account private key. Optionally, a `key` may be specified to select a specific entry within the named Secret resource. If `key` is not specified, a default of `tls.key` will be used. + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + server: + description: 'Server is the URL used to access the ACME server''s ''directory'' endpoint. For example, for Let''s Encrypt''s staging endpoint, you would use: "https://acme-staging-v02.api.letsencrypt.org/directory". Only ACME v2 endpoints (i.e. RFC 8555) are supported.' + type: string + skipTLSVerify: + description: 'INSECURE: Enables or disables validation of the ACME server TLS certificate. If true, requests to the ACME server will not have the TLS certificate chain validated. Mutually exclusive with CABundle; prefer using CABundle to prevent various kinds of security vulnerabilities. Only enable this option in development environments. If CABundle and SkipTLSVerify are unset, the system certificate bundle inside the container is used to validate the TLS connection. Defaults to false.' + type: boolean + solvers: + description: 'Solvers is a list of challenge solvers that will be used to solve ACME challenges for the matching domains. Solver configurations must be provided in order to obtain certificates from an ACME server. For more information, see: https://cert-manager.io/docs/configuration/acme/' + type: array + items: + description: An ACMEChallengeSolver describes how to solve ACME challenges for the issuer it is part of. A selector may be provided to use different solving strategies for different DNS names. Only one of HTTP01 or DNS01 must be provided. + type: object + properties: + dns01: + description: Configures cert-manager to attempt to complete authorizations by performing the DNS01 challenge flow. + type: object + properties: + acmeDNS: + description: Use the 'ACME DNS' (https://github.com/joohoi/acme-dns) API to manage DNS01 challenge records. + type: object + required: + - accountSecretRef + - host + properties: + accountSecretRef: + description: A reference to a specific 'key' within a Secret resource. In some instances, `key` is a required field. + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + host: + type: string + akamai: + description: Use the Akamai DNS zone management API to manage DNS01 challenge records. + type: object + required: + - accessTokenSecretRef + - clientSecretSecretRef + - clientTokenSecretRef + - serviceConsumerDomain + properties: + accessTokenSecretRef: + description: A reference to a specific 'key' within a Secret resource. In some instances, `key` is a required field. + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + clientSecretSecretRef: + description: A reference to a specific 'key' within a Secret resource. In some instances, `key` is a required field. + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + clientTokenSecretRef: + description: A reference to a specific 'key' within a Secret resource. In some instances, `key` is a required field. + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + serviceConsumerDomain: + type: string + azureDNS: + description: Use the Microsoft Azure DNS API to manage DNS01 challenge records. + type: object + required: + - resourceGroupName + - subscriptionID + properties: + clientID: + description: if both this and ClientSecret are left unset MSI will be used + type: string + clientSecretSecretRef: + description: if both this and ClientID are left unset MSI will be used + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + environment: + description: name of the Azure environment (default AzurePublicCloud) + type: string + enum: + - AzurePublicCloud + - AzureChinaCloud + - AzureGermanCloud + - AzureUSGovernmentCloud + hostedZoneName: + description: name of the DNS zone that should be used + type: string + managedIdentity: + description: managed identity configuration, can not be used at the same time as clientID, clientSecretSecretRef or tenantID + type: object + properties: + clientID: + description: client ID of the managed identity, can not be used at the same time as resourceID + type: string + resourceID: + description: resource ID of the managed identity, can not be used at the same time as clientID + type: string + resourceGroupName: + description: resource group the DNS zone is located in + type: string + subscriptionID: + description: ID of the Azure subscription + type: string + tenantID: + description: when specifying ClientID and ClientSecret then this field is also needed + type: string + cloudDNS: + description: Use the Google Cloud DNS API to manage DNS01 challenge records. + type: object + required: + - project + properties: + hostedZoneName: + description: HostedZoneName is an optional field that tells cert-manager in which Cloud DNS zone the challenge record has to be created. If left empty cert-manager will automatically choose a zone. + type: string + project: + type: string + serviceAccountSecretRef: + description: A reference to a specific 'key' within a Secret resource. In some instances, `key` is a required field. + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + cloudflare: + description: Use the Cloudflare API to manage DNS01 challenge records. + type: object + properties: + apiKeySecretRef: + description: 'API key to use to authenticate with Cloudflare. Note: using an API token to authenticate is now the recommended method as it allows greater control of permissions.' + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + apiTokenSecretRef: + description: API token used to authenticate with Cloudflare. + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + email: + description: Email of the account, only required when using API key based authentication. + type: string + cnameStrategy: + description: CNAMEStrategy configures how the DNS01 provider should handle CNAME records when found in DNS zones. + type: string + enum: + - None + - Follow + digitalocean: + description: Use the DigitalOcean DNS API to manage DNS01 challenge records. + type: object + required: + - tokenSecretRef + properties: + tokenSecretRef: + description: A reference to a specific 'key' within a Secret resource. In some instances, `key` is a required field. + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + rfc2136: + description: Use RFC2136 ("Dynamic Updates in the Domain Name System") (https://datatracker.ietf.org/doc/rfc2136/) to manage DNS01 challenge records. + type: object + required: + - nameserver + properties: + nameserver: + description: The IP address or hostname of an authoritative DNS server supporting RFC2136 in the form host:port. If the host is an IPv6 address it must be enclosed in square brackets (e.g [2001:db8::1]) ; port is optional. This field is required. + type: string + tsigAlgorithm: + description: 'The TSIG Algorithm configured in the DNS supporting RFC2136. Used only when ``tsigSecretSecretRef`` and ``tsigKeyName`` are defined. Supported values are (case-insensitive): ``HMACMD5`` (default), ``HMACSHA1``, ``HMACSHA256`` or ``HMACSHA512``.' + type: string + tsigKeyName: + description: The TSIG Key name configured in the DNS. If ``tsigSecretSecretRef`` is defined, this field is required. + type: string + tsigSecretSecretRef: + description: The name of the secret containing the TSIG value. If ``tsigKeyName`` is defined, this field is required. + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + route53: + description: Use the AWS Route53 API to manage DNS01 challenge records. + type: object + required: + - region + properties: + accessKeyID: + description: 'The AccessKeyID is used for authentication. Cannot be set when SecretAccessKeyID is set. If neither the Access Key nor Key ID are set, we fall-back to using env vars, shared credentials file or AWS Instance metadata, see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials' + type: string + accessKeyIDSecretRef: + description: 'The SecretAccessKey is used for authentication. If set, pull the AWS access key ID from a key within a Kubernetes Secret. Cannot be set when AccessKeyID is set. If neither the Access Key nor Key ID are set, we fall-back to using env vars, shared credentials file or AWS Instance metadata, see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials' + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + hostedZoneID: + description: If set, the provider will manage only this zone in Route53 and will not do an lookup using the route53:ListHostedZonesByName api call. + type: string + region: + description: Always set the region when using AccessKeyID and SecretAccessKey + type: string + role: + description: Role is a Role ARN which the Route53 provider will assume using either the explicit credentials AccessKeyID/SecretAccessKey or the inferred credentials from environment variables, shared credentials file or AWS Instance metadata + type: string + secretAccessKeySecretRef: + description: 'The SecretAccessKey is used for authentication. If neither the Access Key nor Key ID are set, we fall-back to using env vars, shared credentials file or AWS Instance metadata, see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials' + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + webhook: + description: Configure an external webhook based DNS01 challenge solver to manage DNS01 challenge records. + type: object + required: + - groupName + - solverName + properties: + config: + description: Additional configuration that should be passed to the webhook apiserver when challenges are processed. This can contain arbitrary JSON data. Secret values should not be specified in this stanza. If secret values are needed (e.g. credentials for a DNS service), you should use a SecretKeySelector to reference a Secret resource. For details on the schema of this field, consult the webhook provider implementation's documentation. + x-kubernetes-preserve-unknown-fields: true + groupName: + description: The API group name that should be used when POSTing ChallengePayload resources to the webhook apiserver. This should be the same as the GroupName specified in the webhook provider implementation. + type: string + solverName: + description: The name of the solver to use, as defined in the webhook provider implementation. This will typically be the name of the provider, e.g. 'cloudflare'. + type: string + http01: + description: Configures cert-manager to attempt to complete authorizations by performing the HTTP01 challenge flow. It is not possible to obtain certificates for wildcard domain names (e.g. `*.example.com`) using the HTTP01 challenge mechanism. + type: object + properties: + gatewayHTTPRoute: + description: The Gateway API is a sig-network community API that models service networking in Kubernetes (https://gateway-api.sigs.k8s.io/). The Gateway solver will create HTTPRoutes with the specified labels in the same namespace as the challenge. This solver is experimental, and fields / behaviour may change in the future. + type: object + properties: + labels: + description: Custom labels that will be applied to HTTPRoutes created by cert-manager while solving HTTP-01 challenges. + type: object + additionalProperties: + type: string + parentRefs: + description: 'When solving an HTTP-01 challenge, cert-manager creates an HTTPRoute. cert-manager needs to know which parentRefs should be used when creating the HTTPRoute. Usually, the parentRef references a Gateway. See: https://gateway-api.sigs.k8s.io/api-types/httproute/#attaching-to-gateways' + type: array + items: + description: "ParentReference identifies an API object (usually a Gateway) that can be considered a parent of this resource (usually a route). The only kind of parent resource with \"Core\" support is Gateway. This API may be extended in the future to support additional kinds of parent resources, such as HTTPRoute. \n The API object must be valid in the cluster; the Group and Kind must be registered in the cluster for this reference to be valid." + type: object + required: + - name + properties: + group: + description: "Group is the group of the referent. When unspecified, \"gateway.networking.k8s.io\" is inferred. To set the core API group (such as for a \"Service\" kind referent), Group must be explicitly set to \"\" (empty string). \n Support: Core" + type: string + default: gateway.networking.k8s.io + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + kind: + description: "Kind is kind of the referent. \n Support: Core (Gateway) \n Support: Implementation-specific (Other Resources)" + type: string + default: Gateway + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + name: + description: "Name is the name of the referent. \n Support: Core" + type: string + maxLength: 253 + minLength: 1 + namespace: + description: "Namespace is the namespace of the referent. When unspecified, this refers to the local namespace of the Route. \n Note that there are specific rules for ParentRefs which cross namespace boundaries. Cross-namespace references are only valid if they are explicitly allowed by something in the namespace they are referring to. For example: Gateway has the AllowedRoutes field, and ReferenceGrant provides a generic way to enable any other kind of cross-namespace reference. \n Support: Core" + type: string + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + port: + description: "Port is the network port this Route targets. It can be interpreted differently based on the type of parent resource. \n When the parent resource is a Gateway, this targets all listeners listening on the specified port that also support this kind of Route(and select this Route). It's not recommended to set `Port` unless the networking behaviors specified in a Route must apply to a specific port as opposed to a listener(s) whose port(s) may be changed. When both Port and SectionName are specified, the name and port of the selected listener must match both specified values. \n Implementations MAY choose to support other parent resources. Implementations supporting other types of parent resources MUST clearly document how/if Port is interpreted. \n For the purpose of status, an attachment is considered successful as long as the parent resource accepts it partially. For example, Gateway listeners can restrict which Routes can attach to them by Route kind, namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from the referencing Route, the Route MUST be considered successfully attached. If no Gateway listeners accept attachment from this Route, the Route MUST be considered detached from the Gateway. \n Support: Extended \n " + type: integer + format: int32 + maximum: 65535 + minimum: 1 + sectionName: + description: "SectionName is the name of a section within the target resource. In the following resources, SectionName is interpreted as the following: \n * Gateway: Listener Name. When both Port (experimental) and SectionName are specified, the name and port of the selected listener must match both specified values. \n Implementations MAY choose to support attaching Routes to other resources. If that is the case, they MUST clearly document how SectionName is interpreted. \n When unspecified (empty string), this will reference the entire resource. For the purpose of status, an attachment is considered successful if at least one section in the parent resource accepts it. For example, Gateway listeners can restrict which Routes can attach to them by Route kind, namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from the referencing Route, the Route MUST be considered successfully attached. If no Gateway listeners accept attachment from this Route, the Route MUST be considered detached from the Gateway. \n Support: Core" + type: string + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + serviceType: + description: Optional service type for Kubernetes solver service. Supported values are NodePort or ClusterIP. If unset, defaults to NodePort. + type: string + ingress: + description: The ingress based HTTP01 challenge solver will solve challenges by creating or modifying Ingress resources in order to route requests for '/.well-known/acme-challenge/XYZ' to 'challenge solver' pods that are provisioned by cert-manager for each Challenge to be completed. + type: object + properties: + class: + description: This field configures the annotation `kubernetes.io/ingress.class` when creating Ingress resources to solve ACME challenges that use this challenge solver. Only one of `class`, `name` or `ingressClassName` may be specified. + type: string + ingressClassName: + description: This field configures the field `ingressClassName` on the created Ingress resources used to solve ACME challenges that use this challenge solver. This is the recommended way of configuring the ingress class. Only one of `class`, `name` or `ingressClassName` may be specified. + type: string + ingressTemplate: + description: Optional ingress template used to configure the ACME challenge solver ingress used for HTTP01 challenges. + type: object + properties: + metadata: + description: ObjectMeta overrides for the ingress used to solve HTTP01 challenges. Only the 'labels' and 'annotations' fields may be set. If labels or annotations overlap with in-built values, the values here will override the in-built values. + type: object + properties: + annotations: + description: Annotations that should be added to the created ACME HTTP01 solver ingress. + type: object + additionalProperties: + type: string + labels: + description: Labels that should be added to the created ACME HTTP01 solver ingress. + type: object + additionalProperties: + type: string + name: + description: The name of the ingress resource that should have ACME challenge solving routes inserted into it in order to solve HTTP01 challenges. This is typically used in conjunction with ingress controllers like ingress-gce, which maintains a 1:1 mapping between external IPs and ingress resources. Only one of `class`, `name` or `ingressClassName` may be specified. + type: string + podTemplate: + description: Optional pod template used to configure the ACME challenge solver pods used for HTTP01 challenges. + type: object + properties: + metadata: + description: ObjectMeta overrides for the pod used to solve HTTP01 challenges. Only the 'labels' and 'annotations' fields may be set. If labels or annotations overlap with in-built values, the values here will override the in-built values. + type: object + properties: + annotations: + description: Annotations that should be added to the create ACME HTTP01 solver pods. + type: object + additionalProperties: + type: string + labels: + description: Labels that should be added to the created ACME HTTP01 solver pods. + type: object + additionalProperties: + type: string + spec: + description: PodSpec defines overrides for the HTTP01 challenge solver pod. Check ACMEChallengeSolverHTTP01IngressPodSpec to find out currently supported fields. All other fields will be ignored. + type: object + properties: + affinity: + description: If specified, the pod's scheduling constraints + type: object + properties: + nodeAffinity: + description: Describes node affinity scheduling rules for the pod. + type: object + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods to nodes that satisfy the affinity expressions specified by this field, but it may choose a node that violates one or more of the expressions. The node that is most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling affinity expressions, etc.), compute a sum by iterating through the elements of this field and adding "weight" to the sum if the node matches the corresponding matchExpressions; the node(s) with the highest sum are the most preferred. + type: array + items: + description: An empty preferred scheduling term matches all objects with implicit weight 0 (i.e. it's a no-op). A null preferred scheduling term matches no objects (i.e. is also a no-op). + type: object + required: + - preference + - weight + properties: + preference: + description: A node selector term, associated with the corresponding weight. + type: object + properties: + matchExpressions: + description: A list of node selector requirements by node's labels. + type: array + items: + description: A node selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: The label key that the selector applies to. + type: string + operator: + description: Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: 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. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch. + type: array + items: + type: string + matchFields: + description: A list of node selector requirements by node's fields. + type: array + items: + description: A node selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: The label key that the selector applies to. + type: string + operator: + description: Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: 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. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch. + type: array + items: + type: string + x-kubernetes-map-type: atomic + weight: + description: Weight associated with matching the corresponding nodeSelectorTerm, in the range 1-100. + type: integer + format: int32 + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by this field are not met at scheduling time, the pod will not be scheduled onto the node. If the affinity requirements specified by this field cease to be met at some point during pod execution (e.g. due to an update), the system may or may not try to eventually evict the pod from its node. + type: object + required: + - nodeSelectorTerms + properties: + nodeSelectorTerms: + description: Required. A list of node selector terms. The terms are ORed. + type: array + items: + description: A null or empty node selector term matches no objects. The requirements of them are ANDed. The TopologySelectorTerm type implements a subset of the NodeSelectorTerm. + type: object + properties: + matchExpressions: + description: A list of node selector requirements by node's labels. + type: array + items: + description: A node selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: The label key that the selector applies to. + type: string + operator: + description: Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: 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. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch. + type: array + items: + type: string + matchFields: + description: A list of node selector requirements by node's fields. + type: array + items: + description: A node selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: The label key that the selector applies to. + type: string + operator: + description: Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: 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. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch. + type: array + items: + type: string + x-kubernetes-map-type: atomic + x-kubernetes-map-type: atomic + podAffinity: + description: Describes pod affinity scheduling rules (e.g. co-locate this pod in the same node, zone, etc. as some other pod(s)). + type: object + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods to nodes that satisfy the affinity expressions specified by this field, but it may choose a node that violates one or more of the expressions. The node that is most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling affinity expressions, etc.), compute a sum by iterating through the elements of this field and adding "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. + type: array + items: + description: The weights of all of the matched WeightedPodAffinityTerm fields are added per-node to find the most preferred node(s) + type: object + required: + - podAffinityTerm + - weight + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated with the corresponding weight. + type: object + required: + - topologyKey + properties: + labelSelector: + description: A label query over a set of resources, in this case pods. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + matchLabels: + 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 + additionalProperties: + type: string + x-kubernetes-map-type: atomic + namespaceSelector: + description: A label query over the set of namespaces that the term applies to. The term is applied to the union of the namespaces selected by this field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector ({}) matches all namespaces. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + matchLabels: + 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 + additionalProperties: + type: string + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static list of namespace names that the term applies to. The term is applied to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list and null namespaceSelector means "this pod's namespace". + type: array + items: + type: string + topologyKey: + description: This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. Empty topologyKey is not allowed. + type: string + weight: + description: weight associated with matching the corresponding podAffinityTerm, in the range 1-100. + type: integer + format: int32 + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by this field are not met at scheduling time, the pod will not be scheduled onto the node. If the affinity requirements specified by this field cease to be met at some point during pod execution (e.g. due to a pod label update), the system may or may not try to eventually evict the pod from its node. When there are multiple elements, the lists of nodes corresponding to each podAffinityTerm are intersected, i.e. all terms must be satisfied. + type: array + items: + description: Defines a set of pods (namely those matching the labelSelector relative to the given namespace(s)) that this pod should be co-located (affinity) or not co-located (anti-affinity) with, where co-located is defined as running on a node whose value of the label with key matches that of any node on which a pod of the set of pods is running + type: object + required: + - topologyKey + properties: + labelSelector: + description: A label query over a set of resources, in this case pods. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + matchLabels: + 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 + additionalProperties: + type: string + x-kubernetes-map-type: atomic + namespaceSelector: + description: A label query over the set of namespaces that the term applies to. The term is applied to the union of the namespaces selected by this field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector ({}) matches all namespaces. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + matchLabels: + 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 + additionalProperties: + type: string + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static list of namespace names that the term applies to. The term is applied to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list and null namespaceSelector means "this pod's namespace". + type: array + items: + type: string + topologyKey: + description: This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. Empty topologyKey is not allowed. + type: string + podAntiAffinity: + description: Describes pod anti-affinity scheduling rules (e.g. avoid putting this pod in the same node, zone, etc. as some other pod(s)). + type: object + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods to nodes that satisfy the anti-affinity expressions specified by this field, but it may choose a node that violates one or more of the expressions. The node that is most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), compute a sum by iterating through the elements of this field and adding "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. + type: array + items: + description: The weights of all of the matched WeightedPodAffinityTerm fields are added per-node to find the most preferred node(s) + type: object + required: + - podAffinityTerm + - weight + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated with the corresponding weight. + type: object + required: + - topologyKey + properties: + labelSelector: + description: A label query over a set of resources, in this case pods. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + matchLabels: + 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 + additionalProperties: + type: string + x-kubernetes-map-type: atomic + namespaceSelector: + description: A label query over the set of namespaces that the term applies to. The term is applied to the union of the namespaces selected by this field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector ({}) matches all namespaces. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + matchLabels: + 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 + additionalProperties: + type: string + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static list of namespace names that the term applies to. The term is applied to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list and null namespaceSelector means "this pod's namespace". + type: array + items: + type: string + topologyKey: + description: This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. Empty topologyKey is not allowed. + type: string + weight: + description: weight associated with matching the corresponding podAffinityTerm, in the range 1-100. + type: integer + format: int32 + requiredDuringSchedulingIgnoredDuringExecution: + description: If the anti-affinity requirements specified by this field are not met at scheduling time, the pod will not be scheduled onto the node. If the anti-affinity requirements specified by this field cease to be met at some point during pod execution (e.g. due to a pod label update), the system may or may not try to eventually evict the pod from its node. When there are multiple elements, the lists of nodes corresponding to each podAffinityTerm are intersected, i.e. all terms must be satisfied. + type: array + items: + description: Defines a set of pods (namely those matching the labelSelector relative to the given namespace(s)) that this pod should be co-located (affinity) or not co-located (anti-affinity) with, where co-located is defined as running on a node whose value of the label with key matches that of any node on which a pod of the set of pods is running + type: object + required: + - topologyKey + properties: + labelSelector: + description: A label query over a set of resources, in this case pods. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + matchLabels: + 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 + additionalProperties: + type: string + x-kubernetes-map-type: atomic + namespaceSelector: + description: A label query over the set of namespaces that the term applies to. The term is applied to the union of the namespaces selected by this field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector ({}) matches all namespaces. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + matchLabels: + 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 + additionalProperties: + type: string + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static list of namespace names that the term applies to. The term is applied to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list and null namespaceSelector means "this pod's namespace". + type: array + items: + type: string + topologyKey: + description: This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. Empty topologyKey is not allowed. + type: string + imagePullSecrets: + description: If specified, the pod's imagePullSecrets + type: array + items: + description: LocalObjectReference contains enough information to let you locate the referenced object inside the same namespace. + type: object + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + x-kubernetes-map-type: atomic + nodeSelector: + description: 'NodeSelector is a selector which must be true for the pod to fit on a node. Selector which must match a node''s labels for the pod to be scheduled on that node. More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/' + type: object + additionalProperties: + type: string + priorityClassName: + description: If specified, the pod's priorityClassName. + type: string + serviceAccountName: + description: If specified, the pod's service account + type: string + tolerations: + description: If specified, the pod's tolerations. + type: array + items: + description: The pod this Toleration is attached to tolerates any taint that matches the triple using the matching operator . + type: object + 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. + type: integer + format: int64 + 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 + serviceType: + description: Optional service type for Kubernetes solver service. Supported values are NodePort or ClusterIP. If unset, defaults to NodePort. + type: string + selector: + description: Selector selects a set of DNSNames on the Certificate resource that should be solved using this challenge solver. If not specified, the solver will be treated as the 'default' solver with the lowest priority, i.e. if any other solver has a more specific match, it will be used instead. + type: object + properties: + dnsNames: + description: List of DNSNames that this solver will be used to solve. If specified and a match is found, a dnsNames selector will take precedence over a dnsZones selector. If multiple solvers match with the same dnsNames value, the solver with the most matching labels in matchLabels will be selected. If neither has more matches, the solver defined earlier in the list will be selected. + type: array + items: + type: string + dnsZones: + description: List of DNSZones that this solver will be used to solve. The most specific DNS zone match specified here will take precedence over other DNS zone matches, so a solver specifying sys.example.com will be selected over one specifying example.com for the domain www.sys.example.com. If multiple solvers match with the same dnsZones value, the solver with the most matching labels in matchLabels will be selected. If neither has more matches, the solver defined earlier in the list will be selected. + type: array + items: + type: string + matchLabels: + description: A label selector that is used to refine the set of certificate's that this challenge solver will apply to. + type: object + additionalProperties: + type: string + ca: + description: CA configures this issuer to sign certificates using a signing CA keypair stored in a Secret resource. This is used to build internal PKIs that are managed by cert-manager. + type: object + required: + - secretName + properties: + crlDistributionPoints: + description: The CRL distribution points is an X.509 v3 certificate extension which identifies the location of the CRL from which the revocation of this certificate can be checked. If not set, certificates will be issued without distribution points set. + type: array + items: + type: string + ocspServers: + description: The OCSP server list is an X.509 v3 extension that defines a list of URLs of OCSP responders. The OCSP responders can be queried for the revocation status of an issued certificate. If not set, the certificate will be issued with no OCSP servers set. For example, an OCSP server URL could be "http://ocsp.int-x3.letsencrypt.org". + type: array + items: + type: string + secretName: + description: SecretName is the name of the secret used to sign Certificates issued by this Issuer. + type: string + selfSigned: + description: SelfSigned configures this issuer to 'self sign' certificates using the private key used to create the CertificateRequest object. + type: object + properties: + crlDistributionPoints: + description: The CRL distribution points is an X.509 v3 certificate extension which identifies the location of the CRL from which the revocation of this certificate can be checked. If not set certificate will be issued without CDP. Values are strings. + type: array + items: + type: string + vault: + description: Vault configures this issuer to sign certificates using a HashiCorp Vault PKI backend. + type: object + required: + - auth + - path + - server + properties: + auth: + description: Auth configures how cert-manager authenticates with the Vault server. + type: object + properties: + appRole: + description: AppRole authenticates with Vault using the App Role auth mechanism, with the role and secret stored in a Kubernetes Secret resource. + type: object + required: + - path + - roleId + - secretRef + properties: + path: + description: 'Path where the App Role authentication backend is mounted in Vault, e.g: "approle"' + type: string + roleId: + description: RoleID configured in the App Role authentication backend when setting up the authentication backend in Vault. + type: string + secretRef: + description: Reference to a key in a Secret that contains the App Role secret used to authenticate with Vault. The `key` field must be specified and denotes which entry within the Secret resource is used as the app role secret. + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + kubernetes: + description: Kubernetes authenticates with Vault by passing the ServiceAccount token stored in the named Secret resource to the Vault server. + type: object + required: + - role + properties: + mountPath: + description: The Vault mountPath here is the mount path to use when authenticating with Vault. For example, setting a value to `/v1/auth/foo`, will use the path `/v1/auth/foo/login` to authenticate with Vault. If unspecified, the default value "/v1/auth/kubernetes" will be used. + type: string + role: + description: A required field containing the Vault Role to assume. A Role binds a Kubernetes ServiceAccount with a set of Vault policies. + type: string + secretRef: + description: The required Secret field containing a Kubernetes ServiceAccount JWT used for authenticating with Vault. Use of 'ambient credentials' is not supported. + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + serviceAccountRef: + description: A reference to a service account that will be used to request a bound token (also known as "projected token"). Compared to using "secretRef", using this field means that you don't rely on statically bound tokens. To use this field, you must configure an RBAC rule to let cert-manager request a token. + type: object + required: + - name + properties: + name: + description: Name of the ServiceAccount used to request a token. + type: string + tokenSecretRef: + description: TokenSecretRef authenticates with Vault by presenting a token. + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + caBundle: + description: Base64-encoded bundle of PEM CAs which will be used to validate the certificate chain presented by Vault. Only used if using HTTPS to connect to Vault and ignored for HTTP connections. Mutually exclusive with CABundleSecretRef. If neither CABundle nor CABundleSecretRef are defined, the certificate bundle in the cert-manager controller container is used to validate the TLS connection. + type: string + format: byte + caBundleSecretRef: + description: Reference to a Secret containing a bundle of PEM-encoded CAs to use when verifying the certificate chain presented by Vault when using HTTPS. Mutually exclusive with CABundle. If neither CABundle nor CABundleSecretRef are defined, the certificate bundle in the cert-manager controller container is used to validate the TLS connection. If no key for the Secret is specified, cert-manager will default to 'ca.crt'. + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + namespace: + description: 'Name of the vault namespace. Namespaces is a set of features within Vault Enterprise that allows Vault environments to support Secure Multi-tenancy. e.g: "ns1" More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces' + type: string + path: + description: 'Path is the mount path of the Vault PKI backend''s `sign` endpoint, e.g: "my_pki_mount/sign/my-role-name".' + type: string + server: + description: 'Server is the connection address for the Vault server, e.g: "https://vault.example.com:8200".' + type: string + venafi: + description: Venafi configures this issuer to sign certificates using a Venafi TPP or Venafi Cloud policy zone. + type: object + required: + - zone + properties: + cloud: + description: Cloud specifies the Venafi cloud configuration settings. Only one of TPP or Cloud may be specified. + type: object + required: + - apiTokenSecretRef + properties: + apiTokenSecretRef: + description: APITokenSecretRef is a secret key selector for the Venafi Cloud API token. + type: object + required: + - name + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + url: + description: URL is the base URL for Venafi Cloud. Defaults to "https://api.venafi.cloud/v1". + type: string + tpp: + description: TPP specifies Trust Protection Platform configuration settings. Only one of TPP or Cloud may be specified. + type: object + required: + - credentialsRef + - url + properties: + caBundle: + description: Base64-encoded bundle of PEM CAs which will be used to validate the certificate chain presented by the TPP server. Only used if using HTTPS; ignored for HTTP. If undefined, the certificate bundle in the cert-manager controller container is used to validate the chain. + type: string + format: byte + credentialsRef: + description: CredentialsRef is a reference to a Secret containing the username and password for the TPP server. The secret must contain two keys, 'username' and 'password'. + type: object + required: + - name + properties: + name: + description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + url: + description: 'URL is the base URL for the vedsdk endpoint of the Venafi TPP instance, for example: "https://tpp.example.com/vedsdk".' + type: string + zone: + description: Zone is the Venafi Policy Zone to use for this issuer. All requests made to the Venafi platform will be restricted by the named zone policy. This field is required. + type: string + status: + description: Status of the Issuer. This is set and managed automatically. + type: object + properties: + acme: + description: ACME specific status options. This field should only be set if the Issuer is configured to use an ACME server to issue certificates. + type: object + properties: + lastPrivateKeyHash: + description: LastPrivateKeyHash is a hash of the private key associated with the latest registered ACME account, in order to track changes made to registered account associated with the Issuer + type: string + lastRegisteredEmail: + description: LastRegisteredEmail is the email associated with the latest registered ACME account, in order to track changes made to registered account associated with the Issuer + type: string + uri: + description: URI is the unique account identifier, which can also be used to retrieve account details from the CA + type: string + conditions: + description: List of status conditions to indicate the status of a CertificateRequest. Known condition types are `Ready`. + type: array + items: + description: IssuerCondition contains condition information for an Issuer. + type: object + required: + - status + - type + properties: + lastTransitionTime: + description: LastTransitionTime is the timestamp corresponding to the last status change of this condition. + type: string + format: date-time + message: + description: Message is a human readable description of the details of the last transition, complementing reason. + type: string + observedGeneration: + description: If set, this represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.condition[x].observedGeneration is 9, the condition is out of date with respect to the current state of the Issuer. + type: integer + format: int64 + reason: + description: Reason is a brief machine readable explanation for the condition's last transition. + type: string + status: + description: Status of the condition, one of (`True`, `False`, `Unknown`). + type: string + enum: + - "True" + - "False" + - Unknown + type: + description: Type of the condition, known values are (`Ready`). + type: string + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + served: true + storage: true +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: orders.acme.cert-manager.io + labels: + app: '{{ template "cert-manager.name" . }}' + app.kubernetes.io/name: '{{ template "cert-manager.name" . }}' + app.kubernetes.io/instance: '{{ .Release.Name }}' + # Generated labels {{- include "labels" . | nindent 4 }} +spec: + group: acme.cert-manager.io + names: + kind: Order + listKind: OrderList + plural: orders + singular: order + categories: + - cert-manager + - cert-manager-acme + scope: Namespaced + versions: + - name: v1 + subresources: + status: {} + additionalPrinterColumns: + - jsonPath: .status.state + name: State + type: string + - jsonPath: .spec.issuerRef.name + name: Issuer + priority: 1 + type: string + - jsonPath: .status.reason + name: Reason + priority: 1 + type: string + - jsonPath: .metadata.creationTimestamp + description: CreationTimestamp is a timestamp representing the server time when this object was created. It is not guaranteed to be set in happens-before order across separate operations. Clients may not set this value. It is represented in RFC3339 form and is in UTC. + name: Age + type: date + schema: + openAPIV3Schema: + description: Order is a type to represent an Order with an ACME server + type: object + required: + - metadata + - spec + 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: + type: object + required: + - issuerRef + - request + properties: + commonName: + description: CommonName is the common name as specified on the DER encoded CSR. If specified, this value must also be present in `dnsNames` or `ipAddresses`. This field must match the corresponding field on the DER encoded CSR. + type: string + dnsNames: + description: DNSNames is a list of DNS names that should be included as part of the Order validation process. This field must match the corresponding field on the DER encoded CSR. + type: array + items: + type: string + duration: + description: Duration is the duration for the not after date for the requested certificate. this is set on order creation as pe the ACME spec. + type: string + ipAddresses: + description: IPAddresses is a list of IP addresses that should be included as part of the Order validation process. This field must match the corresponding field on the DER encoded CSR. + type: array + items: + type: string + issuerRef: + description: IssuerRef references a properly configured ACME-type Issuer which should be used to create this Order. If the Issuer does not exist, processing will be retried. If the Issuer is not an 'ACME' Issuer, an error will be returned and the Order will be marked as failed. + type: object + required: + - name + properties: + group: + description: Group of the resource being referred to. + type: string + kind: + description: Kind of the resource being referred to. + type: string + name: + description: Name of the resource being referred to. + type: string + request: + description: Certificate signing request bytes in DER encoding. This will be used when finalizing the order. This field must be set on the order. + type: string + format: byte + status: + type: object + properties: + authorizations: + description: Authorizations contains data returned from the ACME server on what authorizations must be completed in order to validate the DNS names specified on the Order. + type: array + items: + description: ACMEAuthorization contains data returned from the ACME server on an authorization that must be completed in order validate a DNS name on an ACME Order resource. + type: object + required: + - url + properties: + challenges: + description: Challenges specifies the challenge types offered by the ACME server. One of these challenge types will be selected when validating the DNS name and an appropriate Challenge resource will be created to perform the ACME challenge process. + type: array + items: + description: Challenge specifies a challenge offered by the ACME server for an Order. An appropriate Challenge resource can be created to perform the ACME challenge process. + type: object + required: + - token + - type + - url + properties: + token: + description: Token is the token that must be presented for this challenge. This is used to compute the 'key' that must also be presented. + type: string + type: + description: Type is the type of challenge being offered, e.g. 'http-01', 'dns-01', 'tls-sni-01', etc. This is the raw value retrieved from the ACME server. Only 'http-01' and 'dns-01' are supported by cert-manager, other values will be ignored. + type: string + url: + description: URL is the URL of this challenge. It can be used to retrieve additional metadata about the Challenge from the ACME server. + type: string + identifier: + description: Identifier is the DNS name to be validated as part of this authorization + type: string + initialState: + description: InitialState is the initial state of the ACME authorization when first fetched from the ACME server. If an Authorization is already 'valid', the Order controller will not create a Challenge resource for the authorization. This will occur when working with an ACME server that enables 'authz reuse' (such as Let's Encrypt's production endpoint). If not set and 'identifier' is set, the state is assumed to be pending and a Challenge will be created. + type: string + enum: + - valid + - ready + - pending + - processing + - invalid + - expired + - errored + url: + description: URL is the URL of the Authorization that must be completed + type: string + wildcard: + description: Wildcard will be true if this authorization is for a wildcard DNS name. If this is true, the identifier will be the *non-wildcard* version of the DNS name. For example, if '*.example.com' is the DNS name being validated, this field will be 'true' and the 'identifier' field will be 'example.com'. + type: boolean + certificate: + description: Certificate is a copy of the PEM encoded certificate for this Order. This field will be populated after the order has been successfully finalized with the ACME server, and the order has transitioned to the 'valid' state. + type: string + format: byte + failureTime: + description: FailureTime stores the time that this order failed. This is used to influence garbage collection and back-off. + type: string + format: date-time + finalizeURL: + description: FinalizeURL of the Order. This is used to obtain certificates for this order once it has been completed. + type: string + reason: + description: Reason optionally provides more information about a why the order is in the current state. + type: string + state: + description: State contains the current state of this Order resource. States 'success' and 'expired' are 'final' + type: string + enum: + - valid + - ready + - pending + - processing + - invalid + - expired + - errored + url: + description: URL of the Order. This will initially be empty when the resource is first created. The Order controller will populate this field when the Order is first processed. This field will be immutable after it is initially set. + type: string + served: true + storage: true +{{- end }} diff --git a/packages/system/cert-manager/charts/cert-manager/templates/deployment.yaml b/packages/system/cert-manager/charts/cert-manager/templates/deployment.yaml new file mode 100644 index 00000000..aea5736c --- /dev/null +++ b/packages/system/cert-manager/charts/cert-manager/templates/deployment.yaml @@ -0,0 +1,204 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ template "cert-manager.fullname" . }} + namespace: {{ include "cert-manager.namespace" . }} + labels: + app: {{ template "cert-manager.name" . }} + app.kubernetes.io/name: {{ template "cert-manager.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "controller" + {{- include "labels" . | nindent 4 }} + {{- with .Values.deploymentAnnotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + replicas: {{ .Values.replicaCount }} + selector: + matchLabels: + app.kubernetes.io/name: {{ template "cert-manager.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "controller" + {{- with .Values.strategy }} + strategy: + {{- toYaml . | nindent 4 }} + {{- end }} + template: + metadata: + labels: + app: {{ template "cert-manager.name" . }} + app.kubernetes.io/name: {{ template "cert-manager.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "controller" + {{- include "labels" . | nindent 8 }} + {{- with .Values.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if and .Values.prometheus.enabled (not .Values.prometheus.servicemonitor.enabled) }} + {{- if not .Values.podAnnotations }} + annotations: + {{- end }} + prometheus.io/path: "/metrics" + prometheus.io/scrape: 'true' + prometheus.io/port: '9402' + {{- end }} + spec: + serviceAccountName: {{ template "cert-manager.serviceAccountName" . }} + {{- if hasKey .Values "automountServiceAccountToken" }} + automountServiceAccountToken: {{ .Values.automountServiceAccountToken }} + {{- end }} + {{- with .Values.global.priorityClassName }} + priorityClassName: {{ . | quote }} + {{- end }} + {{- with .Values.securityContext }} + securityContext: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.volumes }} + volumes: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: {{ .Chart.Name }}-controller + {{- with .Values.image }} + image: "{{- if .registry -}}{{ .registry }}/{{- end -}}{{ .repository }}{{- if (.digest) -}} @{{ .digest }}{{- else -}}:{{ default $.Chart.AppVersion .tag }} {{- end -}}" + {{- end }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + args: + {{- if .Values.global.logLevel }} + - --v={{ .Values.global.logLevel }} + {{- end }} + {{- if .Values.clusterResourceNamespace }} + - --cluster-resource-namespace={{ .Values.clusterResourceNamespace }} + {{- else }} + - --cluster-resource-namespace=$(POD_NAMESPACE) + {{- end }} + {{- with .Values.global.leaderElection }} + - --leader-election-namespace={{ .namespace }} + {{- if .leaseDuration }} + - --leader-election-lease-duration={{ .leaseDuration }} + {{- end }} + {{- if .renewDeadline }} + - --leader-election-renew-deadline={{ .renewDeadline }} + {{- end }} + {{- if .retryPeriod }} + - --leader-election-retry-period={{ .retryPeriod }} + {{- end }} + {{- end }} + {{- with .Values.acmesolver.image }} + - --acme-http01-solver-image={{- if .registry -}}{{ .registry }}/{{- end -}}{{ .repository }}{{- if (.digest) -}} @{{ .digest }}{{- else -}}:{{ default $.Chart.AppVersion .tag }} {{- end -}} + {{- end }} + {{- with .Values.extraArgs }} + {{- toYaml . | nindent 10 }} + {{- end }} + {{- with .Values.ingressShim }} + {{- if .defaultIssuerName }} + - --default-issuer-name={{ .defaultIssuerName }} + {{- end }} + {{- if .defaultIssuerKind }} + - --default-issuer-kind={{ .defaultIssuerKind }} + {{- end }} + {{- if .defaultIssuerGroup }} + - --default-issuer-group={{ .defaultIssuerGroup }} + {{- end }} + {{- end }} + {{- if .Values.featureGates }} + - --feature-gates={{ .Values.featureGates }} + {{- end }} + {{- if .Values.maxConcurrentChallenges }} + - --max-concurrent-challenges={{ .Values.maxConcurrentChallenges }} + {{- end }} + {{- if .Values.enableCertificateOwnerRef }} + - --enable-certificate-owner-ref=true + {{- end }} + {{- if .Values.dns01RecursiveNameserversOnly }} + - --dns01-recursive-nameservers-only=true + {{- end }} + {{- with .Values.dns01RecursiveNameservers }} + - --dns01-recursive-nameservers={{ . }} + {{- end }} + ports: + - containerPort: 9402 + name: http-metrics + protocol: TCP + - containerPort: 9403 + name: http-healthz + protocol: TCP + {{- with .Values.containerSecurityContext }} + securityContext: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.volumeMounts }} + volumeMounts: + {{- toYaml . | nindent 12 }} + {{- end }} + env: + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + {{- with .Values.extraEnv }} + {{- toYaml . | nindent 10 }} + {{- end }} + {{- with .Values.http_proxy }} + - name: HTTP_PROXY + value: {{ . }} + {{- end }} + {{- with .Values.https_proxy }} + - name: HTTPS_PROXY + value: {{ . }} + {{- end }} + {{- with .Values.no_proxy }} + - name: NO_PROXY + value: {{ . }} + {{- end }} + {{- with .Values.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + + {{- with .Values.livenessProbe }} + {{- if .enabled }} + # LivenessProbe settings are based on those used for the Kubernetes + # controller-manager. See: + # https://github.com/kubernetes/kubernetes/blob/806b30170c61a38fedd54cc9ede4cd6275a1ad3b/cmd/kubeadm/app/util/staticpod/utils.go#L241-L245 + livenessProbe: + httpGet: + port: http-healthz + path: /livez + scheme: HTTP + initialDelaySeconds: {{ .initialDelaySeconds }} + periodSeconds: {{ .periodSeconds }} + timeoutSeconds: {{ .timeoutSeconds }} + successThreshold: {{ .successThreshold }} + failureThreshold: {{ .failureThreshold }} + {{- end }} + {{- end }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.topologySpreadConstraints }} + topologySpreadConstraints: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.podDnsPolicy }} + dnsPolicy: {{ . }} + {{- end }} + {{- with .Values.podDnsConfig }} + dnsConfig: + {{- toYaml . | nindent 8 }} + {{- end }} diff --git a/packages/system/cert-manager/charts/cert-manager/templates/networkpolicy-egress.yaml b/packages/system/cert-manager/charts/cert-manager/templates/networkpolicy-egress.yaml new file mode 100644 index 00000000..09712009 --- /dev/null +++ b/packages/system/cert-manager/charts/cert-manager/templates/networkpolicy-egress.yaml @@ -0,0 +1,23 @@ +{{- if .Values.webhook.networkPolicy.enabled }} +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: {{ template "webhook.fullname" . }}-allow-egress + namespace: {{ include "cert-manager.namespace" . }} +spec: + egress: + {{- with .Values.webhook.networkPolicy.egress }} + {{- toYaml . | nindent 2 }} + {{- end }} + podSelector: + matchLabels: + app: {{ include "webhook.name" . }} + app.kubernetes.io/name: {{ include "webhook.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "webhook" + {{- with .Values.webhook.podLabels }} + {{- toYaml . | nindent 6 }} + {{- end }} + policyTypes: + - Egress +{{- end }} diff --git a/packages/system/cert-manager/charts/cert-manager/templates/networkpolicy-webhooks.yaml b/packages/system/cert-manager/charts/cert-manager/templates/networkpolicy-webhooks.yaml new file mode 100644 index 00000000..349877a8 --- /dev/null +++ b/packages/system/cert-manager/charts/cert-manager/templates/networkpolicy-webhooks.yaml @@ -0,0 +1,25 @@ +{{- if .Values.webhook.networkPolicy.enabled }} + +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: {{ template "webhook.fullname" . }}-allow-ingress + namespace: {{ include "cert-manager.namespace" . }} +spec: + ingress: + {{- with .Values.webhook.networkPolicy.ingress }} + {{- toYaml . | nindent 2 }} + {{- end }} + podSelector: + matchLabels: + app: {{ include "webhook.name" . }} + app.kubernetes.io/name: {{ include "webhook.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "webhook" + {{- with .Values.webhook.podLabels }} + {{- toYaml . | nindent 6 }} + {{- end }} + policyTypes: + - Ingress + +{{- end }} diff --git a/packages/system/cert-manager/charts/cert-manager/templates/poddisruptionbudget.yaml b/packages/system/cert-manager/charts/cert-manager/templates/poddisruptionbudget.yaml new file mode 100644 index 00000000..dab75ce6 --- /dev/null +++ b/packages/system/cert-manager/charts/cert-manager/templates/poddisruptionbudget.yaml @@ -0,0 +1,26 @@ +{{- if .Values.podDisruptionBudget.enabled }} +apiVersion: policy/v1 +kind: PodDisruptionBudget +metadata: + name: {{ include "cert-manager.fullname" . }} + namespace: {{ include "cert-manager.namespace" . }} + labels: + app: {{ include "cert-manager.name" . }} + app.kubernetes.io/name: {{ include "cert-manager.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "controller" + {{- include "labels" . | nindent 4 }} +spec: + selector: + matchLabels: + app.kubernetes.io/name: {{ include "cert-manager.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "controller" + + {{- with .Values.podDisruptionBudget.minAvailable }} + minAvailable: {{ . }} + {{- end }} + {{- with .Values.podDisruptionBudget.maxUnavailable }} + maxUnavailable: {{ . }} + {{- end }} +{{- end }} diff --git a/packages/system/cert-manager/charts/cert-manager/templates/psp-clusterrole.yaml b/packages/system/cert-manager/charts/cert-manager/templates/psp-clusterrole.yaml new file mode 100644 index 00000000..1d40a023 --- /dev/null +++ b/packages/system/cert-manager/charts/cert-manager/templates/psp-clusterrole.yaml @@ -0,0 +1,18 @@ +{{- if .Values.global.podSecurityPolicy.enabled }} +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ template "cert-manager.fullname" . }}-psp + labels: + app: {{ include "cert-manager.name" . }} + app.kubernetes.io/name: {{ include "cert-manager.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "controller" + {{- include "labels" . | nindent 4 }} +rules: +- apiGroups: ['policy'] + resources: ['podsecuritypolicies'] + verbs: ['use'] + resourceNames: + - {{ template "cert-manager.fullname" . }} +{{- end }} diff --git a/packages/system/cert-manager/charts/cert-manager/templates/psp-clusterrolebinding.yaml b/packages/system/cert-manager/charts/cert-manager/templates/psp-clusterrolebinding.yaml new file mode 100644 index 00000000..4f09b6bf --- /dev/null +++ b/packages/system/cert-manager/charts/cert-manager/templates/psp-clusterrolebinding.yaml @@ -0,0 +1,20 @@ +{{- if .Values.global.podSecurityPolicy.enabled }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ template "cert-manager.fullname" . }}-psp + labels: + app: {{ include "cert-manager.name" . }} + app.kubernetes.io/name: {{ include "cert-manager.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "controller" + {{- include "labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ template "cert-manager.fullname" . }}-psp +subjects: + - kind: ServiceAccount + name: {{ template "cert-manager.serviceAccountName" . }} + namespace: {{ include "cert-manager.namespace" . }} +{{- end }} diff --git a/packages/system/cert-manager/charts/cert-manager/templates/psp.yaml b/packages/system/cert-manager/charts/cert-manager/templates/psp.yaml new file mode 100644 index 00000000..9e99f5c7 --- /dev/null +++ b/packages/system/cert-manager/charts/cert-manager/templates/psp.yaml @@ -0,0 +1,49 @@ +{{- if .Values.global.podSecurityPolicy.enabled }} +apiVersion: policy/v1beta1 +kind: PodSecurityPolicy +metadata: + name: {{ template "cert-manager.fullname" . }} + labels: + app: {{ include "cert-manager.name" . }} + app.kubernetes.io/name: {{ include "cert-manager.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "controller" + {{- include "labels" . | nindent 4 }} + annotations: + seccomp.security.alpha.kubernetes.io/allowedProfileNames: 'docker/default' + seccomp.security.alpha.kubernetes.io/defaultProfileName: 'docker/default' + {{- if .Values.global.podSecurityPolicy.useAppArmor }} + apparmor.security.beta.kubernetes.io/allowedProfileNames: 'runtime/default' + apparmor.security.beta.kubernetes.io/defaultProfileName: 'runtime/default' + {{- end }} +spec: + privileged: false + allowPrivilegeEscalation: false + allowedCapabilities: [] # default set of capabilities are implicitly allowed + volumes: + - 'configMap' + - 'emptyDir' + - 'projected' + - 'secret' + - 'downwardAPI' + hostNetwork: false + hostIPC: false + hostPID: false + runAsUser: + rule: 'MustRunAs' + ranges: + - min: 1000 + max: 1000 + seLinux: + rule: 'RunAsAny' + supplementalGroups: + rule: 'MustRunAs' + ranges: + - min: 1000 + max: 1000 + fsGroup: + rule: 'MustRunAs' + ranges: + - min: 1000 + max: 1000 +{{- end }} diff --git a/packages/system/cert-manager/charts/cert-manager/templates/rbac.yaml b/packages/system/cert-manager/charts/cert-manager/templates/rbac.yaml new file mode 100644 index 00000000..830e3728 --- /dev/null +++ b/packages/system/cert-manager/charts/cert-manager/templates/rbac.yaml @@ -0,0 +1,544 @@ +{{- if .Values.global.rbac.create }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ template "cert-manager.fullname" . }}:leaderelection + namespace: {{ .Values.global.leaderElection.namespace }} + labels: + app: {{ include "cert-manager.name" . }} + app.kubernetes.io/name: {{ include "cert-manager.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "controller" + {{- include "labels" . | nindent 4 }} +rules: + - apiGroups: ["coordination.k8s.io"] + resources: ["leases"] + resourceNames: ["cert-manager-controller"] + verbs: ["get", "update", "patch"] + - apiGroups: ["coordination.k8s.io"] + resources: ["leases"] + verbs: ["create"] + +--- + +# grant cert-manager permission to manage the leaderelection configmap in the +# leader election namespace +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ include "cert-manager.fullname" . }}:leaderelection + namespace: {{ .Values.global.leaderElection.namespace }} + labels: + app: {{ include "cert-manager.name" . }} + app.kubernetes.io/name: {{ include "cert-manager.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "controller" + {{- include "labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ template "cert-manager.fullname" . }}:leaderelection +subjects: + - apiGroup: "" + kind: ServiceAccount + name: {{ template "cert-manager.serviceAccountName" . }} + namespace: {{ include "cert-manager.namespace" . }} + +--- + +# Issuer controller role +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ template "cert-manager.fullname" . }}-controller-issuers + labels: + app: {{ include "cert-manager.name" . }} + app.kubernetes.io/name: {{ include "cert-manager.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "controller" + {{- include "labels" . | nindent 4 }} +rules: + - apiGroups: ["cert-manager.io"] + resources: ["issuers", "issuers/status"] + verbs: ["update", "patch"] + - apiGroups: ["cert-manager.io"] + resources: ["issuers"] + verbs: ["get", "list", "watch"] + - apiGroups: [""] + resources: ["secrets"] + verbs: ["get", "list", "watch", "create", "update", "delete"] + - apiGroups: [""] + resources: ["events"] + verbs: ["create", "patch"] +--- + +# ClusterIssuer controller role +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ template "cert-manager.fullname" . }}-controller-clusterissuers + labels: + app: {{ include "cert-manager.name" . }} + app.kubernetes.io/name: {{ include "cert-manager.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "controller" + {{- include "labels" . | nindent 4 }} +rules: + - apiGroups: ["cert-manager.io"] + resources: ["clusterissuers", "clusterissuers/status"] + verbs: ["update", "patch"] + - apiGroups: ["cert-manager.io"] + resources: ["clusterissuers"] + verbs: ["get", "list", "watch"] + - apiGroups: [""] + resources: ["secrets"] + verbs: ["get", "list", "watch", "create", "update", "delete"] + - apiGroups: [""] + resources: ["events"] + verbs: ["create", "patch"] + +--- + +# Certificates controller role +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ template "cert-manager.fullname" . }}-controller-certificates + labels: + app: {{ include "cert-manager.name" . }} + app.kubernetes.io/name: {{ include "cert-manager.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "controller" + {{- include "labels" . | nindent 4 }} +rules: + - apiGroups: ["cert-manager.io"] + resources: ["certificates", "certificates/status", "certificaterequests", "certificaterequests/status"] + verbs: ["update", "patch"] + - apiGroups: ["cert-manager.io"] + resources: ["certificates", "certificaterequests", "clusterissuers", "issuers"] + verbs: ["get", "list", "watch"] + # We require these rules to support users with the OwnerReferencesPermissionEnforcement + # admission controller enabled: + # https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#ownerreferencespermissionenforcement + - apiGroups: ["cert-manager.io"] + resources: ["certificates/finalizers", "certificaterequests/finalizers"] + verbs: ["update"] + - apiGroups: ["acme.cert-manager.io"] + resources: ["orders"] + verbs: ["create", "delete", "get", "list", "watch"] + - apiGroups: [""] + resources: ["secrets"] + verbs: ["get", "list", "watch", "create", "update", "delete", "patch"] + - apiGroups: [""] + resources: ["events"] + verbs: ["create", "patch"] + +--- + +# Orders controller role +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ template "cert-manager.fullname" . }}-controller-orders + labels: + app: {{ include "cert-manager.name" . }} + app.kubernetes.io/name: {{ include "cert-manager.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "controller" + {{- include "labels" . | nindent 4 }} +rules: + - apiGroups: ["acme.cert-manager.io"] + resources: ["orders", "orders/status"] + verbs: ["update", "patch"] + - apiGroups: ["acme.cert-manager.io"] + resources: ["orders", "challenges"] + verbs: ["get", "list", "watch"] + - apiGroups: ["cert-manager.io"] + resources: ["clusterissuers", "issuers"] + verbs: ["get", "list", "watch"] + - apiGroups: ["acme.cert-manager.io"] + resources: ["challenges"] + verbs: ["create", "delete"] + # We require these rules to support users with the OwnerReferencesPermissionEnforcement + # admission controller enabled: + # https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#ownerreferencespermissionenforcement + - apiGroups: ["acme.cert-manager.io"] + resources: ["orders/finalizers"] + verbs: ["update"] + - apiGroups: [""] + resources: ["secrets"] + verbs: ["get", "list", "watch"] + - apiGroups: [""] + resources: ["events"] + verbs: ["create", "patch"] + +--- + +# Challenges controller role +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ template "cert-manager.fullname" . }}-controller-challenges + labels: + app: {{ include "cert-manager.name" . }} + app.kubernetes.io/name: {{ include "cert-manager.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "controller" + {{- include "labels" . | nindent 4 }} +rules: + # Use to update challenge resource status + - apiGroups: ["acme.cert-manager.io"] + resources: ["challenges", "challenges/status"] + verbs: ["update", "patch"] + # Used to watch challenge resources + - apiGroups: ["acme.cert-manager.io"] + resources: ["challenges"] + verbs: ["get", "list", "watch"] + # Used to watch challenges, issuer and clusterissuer resources + - apiGroups: ["cert-manager.io"] + resources: ["issuers", "clusterissuers"] + verbs: ["get", "list", "watch"] + # Need to be able to retrieve ACME account private key to complete challenges + - apiGroups: [""] + resources: ["secrets"] + verbs: ["get", "list", "watch"] + # Used to create events + - apiGroups: [""] + resources: ["events"] + verbs: ["create", "patch"] + # HTTP01 rules + - apiGroups: [""] + resources: ["pods", "services"] + verbs: ["get", "list", "watch", "create", "delete"] + - apiGroups: ["networking.k8s.io"] + resources: ["ingresses"] + verbs: ["get", "list", "watch", "create", "delete", "update"] + - apiGroups: [ "gateway.networking.k8s.io" ] + resources: [ "httproutes" ] + verbs: ["get", "list", "watch", "create", "delete", "update"] + # We require the ability to specify a custom hostname when we are creating + # new ingress resources. + # See: https://github.com/openshift/origin/blob/21f191775636f9acadb44fa42beeb4f75b255532/pkg/route/apiserver/admission/ingress_admission.go#L84-L148 + - apiGroups: ["route.openshift.io"] + resources: ["routes/custom-host"] + verbs: ["create"] + # We require these rules to support users with the OwnerReferencesPermissionEnforcement + # admission controller enabled: + # https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#ownerreferencespermissionenforcement + - apiGroups: ["acme.cert-manager.io"] + resources: ["challenges/finalizers"] + verbs: ["update"] + # DNS01 rules (duplicated above) + - apiGroups: [""] + resources: ["secrets"] + verbs: ["get", "list", "watch"] + +--- + +# ingress-shim controller role +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ template "cert-manager.fullname" . }}-controller-ingress-shim + labels: + app: {{ include "cert-manager.name" . }} + app.kubernetes.io/name: {{ include "cert-manager.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "controller" + {{- include "labels" . | nindent 4 }} +rules: + - apiGroups: ["cert-manager.io"] + resources: ["certificates", "certificaterequests"] + verbs: ["create", "update", "delete"] + - apiGroups: ["cert-manager.io"] + resources: ["certificates", "certificaterequests", "issuers", "clusterissuers"] + verbs: ["get", "list", "watch"] + - apiGroups: ["networking.k8s.io"] + resources: ["ingresses"] + verbs: ["get", "list", "watch"] + # We require these rules to support users with the OwnerReferencesPermissionEnforcement + # admission controller enabled: + # https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#ownerreferencespermissionenforcement + - apiGroups: ["networking.k8s.io"] + resources: ["ingresses/finalizers"] + verbs: ["update"] + - apiGroups: ["gateway.networking.k8s.io"] + resources: ["gateways", "httproutes"] + verbs: ["get", "list", "watch"] + - apiGroups: ["gateway.networking.k8s.io"] + resources: ["gateways/finalizers", "httproutes/finalizers"] + verbs: ["update"] + - apiGroups: [""] + resources: ["events"] + verbs: ["create", "patch"] + +--- + +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ template "cert-manager.fullname" . }}-controller-issuers + labels: + app: {{ include "cert-manager.name" . }} + app.kubernetes.io/name: {{ include "cert-manager.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "controller" + {{- include "labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ template "cert-manager.fullname" . }}-controller-issuers +subjects: + - name: {{ template "cert-manager.serviceAccountName" . }} + namespace: {{ include "cert-manager.namespace" . }} + kind: ServiceAccount + +--- + +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ template "cert-manager.fullname" . }}-controller-clusterissuers + labels: + app: {{ include "cert-manager.name" . }} + app.kubernetes.io/name: {{ include "cert-manager.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "controller" + {{- include "labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ template "cert-manager.fullname" . }}-controller-clusterissuers +subjects: + - name: {{ template "cert-manager.serviceAccountName" . }} + namespace: {{ include "cert-manager.namespace" . }} + kind: ServiceAccount + +--- + +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ template "cert-manager.fullname" . }}-controller-certificates + labels: + app: {{ include "cert-manager.name" . }} + app.kubernetes.io/name: {{ include "cert-manager.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "controller" + {{- include "labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ template "cert-manager.fullname" . }}-controller-certificates +subjects: + - name: {{ template "cert-manager.serviceAccountName" . }} + namespace: {{ include "cert-manager.namespace" . }} + kind: ServiceAccount + +--- + +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ template "cert-manager.fullname" . }}-controller-orders + labels: + app: {{ include "cert-manager.name" . }} + app.kubernetes.io/name: {{ include "cert-manager.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "controller" + {{- include "labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ template "cert-manager.fullname" . }}-controller-orders +subjects: + - name: {{ template "cert-manager.serviceAccountName" . }} + namespace: {{ include "cert-manager.namespace" . }} + kind: ServiceAccount + +--- + +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ template "cert-manager.fullname" . }}-controller-challenges + labels: + app: {{ include "cert-manager.name" . }} + app.kubernetes.io/name: {{ include "cert-manager.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "controller" + {{- include "labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ template "cert-manager.fullname" . }}-controller-challenges +subjects: + - name: {{ template "cert-manager.serviceAccountName" . }} + namespace: {{ include "cert-manager.namespace" . }} + kind: ServiceAccount + +--- + +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ template "cert-manager.fullname" . }}-controller-ingress-shim + labels: + app: {{ include "cert-manager.name" . }} + app.kubernetes.io/name: {{ include "cert-manager.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "controller" + {{- include "labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ template "cert-manager.fullname" . }}-controller-ingress-shim +subjects: + - name: {{ template "cert-manager.serviceAccountName" . }} + namespace: {{ include "cert-manager.namespace" . }} + kind: ServiceAccount + +--- + +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ template "cert-manager.fullname" . }}-view + labels: + app: {{ include "cert-manager.name" . }} + app.kubernetes.io/name: {{ include "cert-manager.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "controller" + {{- include "labels" . | nindent 4 }} + {{- if .Values.global.rbac.aggregateClusterRoles }} + rbac.authorization.k8s.io/aggregate-to-view: "true" + rbac.authorization.k8s.io/aggregate-to-edit: "true" + rbac.authorization.k8s.io/aggregate-to-admin: "true" + {{- end }} +rules: + - apiGroups: ["cert-manager.io"] + resources: ["certificates", "certificaterequests", "issuers"] + verbs: ["get", "list", "watch"] + - apiGroups: ["acme.cert-manager.io"] + resources: ["challenges", "orders"] + verbs: ["get", "list", "watch"] + + +--- + +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ template "cert-manager.fullname" . }}-edit + labels: + app: {{ include "cert-manager.name" . }} + app.kubernetes.io/name: {{ include "cert-manager.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "controller" + {{- include "labels" . | nindent 4 }} + {{- if .Values.global.rbac.aggregateClusterRoles }} + rbac.authorization.k8s.io/aggregate-to-edit: "true" + rbac.authorization.k8s.io/aggregate-to-admin: "true" + {{- end }} +rules: + - apiGroups: ["cert-manager.io"] + resources: ["certificates", "certificaterequests", "issuers"] + verbs: ["create", "delete", "deletecollection", "patch", "update"] + - apiGroups: ["cert-manager.io"] + resources: ["certificates/status"] + verbs: ["update"] + - apiGroups: ["acme.cert-manager.io"] + resources: ["challenges", "orders"] + verbs: ["create", "delete", "deletecollection", "patch", "update"] + +--- + +# Permission to approve CertificateRequests referencing cert-manager.io Issuers and ClusterIssuers +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ template "cert-manager.fullname" . }}-controller-approve:cert-manager-io + labels: + app: {{ include "cert-manager.name" . }} + app.kubernetes.io/name: {{ include "cert-manager.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "cert-manager" + {{- include "labels" . | nindent 4 }} +rules: + - apiGroups: ["cert-manager.io"] + resources: ["signers"] + verbs: ["approve"] + resourceNames: ["issuers.cert-manager.io/*", "clusterissuers.cert-manager.io/*"] + +--- + +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ template "cert-manager.fullname" . }}-controller-approve:cert-manager-io + labels: + app: {{ include "cert-manager.name" . }} + app.kubernetes.io/name: {{ include "cert-manager.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "cert-manager" + {{- include "labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ template "cert-manager.fullname" . }}-controller-approve:cert-manager-io +subjects: + - name: {{ template "cert-manager.serviceAccountName" . }} + namespace: {{ include "cert-manager.namespace" . }} + kind: ServiceAccount + +--- + +# Permission to: +# - Update and sign CertificatSigningeRequests referencing cert-manager.io Issuers and ClusterIssuers +# - Perform SubjectAccessReviews to test whether users are able to reference Namespaced Issuers +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ template "cert-manager.fullname" . }}-controller-certificatesigningrequests + labels: + app: {{ include "cert-manager.name" . }} + app.kubernetes.io/name: {{ include "cert-manager.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "cert-manager" + {{- include "labels" . | nindent 4 }} +rules: + - apiGroups: ["certificates.k8s.io"] + resources: ["certificatesigningrequests"] + verbs: ["get", "list", "watch", "update"] + - apiGroups: ["certificates.k8s.io"] + resources: ["certificatesigningrequests/status"] + verbs: ["update", "patch"] + - apiGroups: ["certificates.k8s.io"] + resources: ["signers"] + resourceNames: ["issuers.cert-manager.io/*", "clusterissuers.cert-manager.io/*"] + verbs: ["sign"] + - apiGroups: ["authorization.k8s.io"] + resources: ["subjectaccessreviews"] + verbs: ["create"] + +--- + +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ template "cert-manager.fullname" . }}-controller-certificatesigningrequests + labels: + app: {{ include "cert-manager.name" . }} + app.kubernetes.io/name: {{ include "cert-manager.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "cert-manager" + {{- include "labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ template "cert-manager.fullname" . }}-controller-certificatesigningrequests +subjects: + - name: {{ template "cert-manager.serviceAccountName" . }} + namespace: {{ include "cert-manager.namespace" . }} + kind: ServiceAccount +{{- end }} diff --git a/packages/system/cert-manager/charts/cert-manager/templates/service.yaml b/packages/system/cert-manager/charts/cert-manager/templates/service.yaml new file mode 100644 index 00000000..ec34d587 --- /dev/null +++ b/packages/system/cert-manager/charts/cert-manager/templates/service.yaml @@ -0,0 +1,31 @@ +{{- if .Values.prometheus.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ template "cert-manager.fullname" . }} + namespace: {{ include "cert-manager.namespace" . }} +{{- with .Values.serviceAnnotations }} + annotations: +{{ toYaml . | indent 4 }} +{{- end }} + labels: + app: {{ include "cert-manager.name" . }} + app.kubernetes.io/name: {{ include "cert-manager.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "controller" + {{- include "labels" . | nindent 4 }} + {{- with .Values.serviceLabels }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + type: ClusterIP + ports: + - protocol: TCP + port: 9402 + name: tcp-prometheus-servicemonitor + targetPort: {{ .Values.prometheus.servicemonitor.targetPort }} + selector: + app.kubernetes.io/name: {{ include "cert-manager.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "controller" +{{- end }} diff --git a/packages/system/cert-manager/charts/cert-manager/templates/serviceaccount.yaml b/packages/system/cert-manager/charts/cert-manager/templates/serviceaccount.yaml new file mode 100644 index 00000000..6026842f --- /dev/null +++ b/packages/system/cert-manager/charts/cert-manager/templates/serviceaccount.yaml @@ -0,0 +1,25 @@ +{{- if .Values.serviceAccount.create }} +apiVersion: v1 +kind: ServiceAccount +{{- with .Values.global.imagePullSecrets }} +imagePullSecrets: + {{- toYaml . | nindent 2 }} +{{- end }} +automountServiceAccountToken: {{ .Values.serviceAccount.automountServiceAccountToken }} +metadata: + name: {{ template "cert-manager.serviceAccountName" . }} + namespace: {{ include "cert-manager.namespace" . }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} + labels: + app: {{ include "cert-manager.name" . }} + app.kubernetes.io/name: {{ include "cert-manager.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "controller" + {{- include "labels" . | nindent 4 }} + {{- with .Values.serviceAccount.labels }} + {{ toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/packages/system/cert-manager/charts/cert-manager/templates/servicemonitor.yaml b/packages/system/cert-manager/charts/cert-manager/templates/servicemonitor.yaml new file mode 100644 index 00000000..9d9e8999 --- /dev/null +++ b/packages/system/cert-manager/charts/cert-manager/templates/servicemonitor.yaml @@ -0,0 +1,45 @@ +{{- if and .Values.prometheus.enabled .Values.prometheus.servicemonitor.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ template "cert-manager.fullname" . }} +{{- if .Values.prometheus.servicemonitor.namespace }} + namespace: {{ .Values.prometheus.servicemonitor.namespace }} +{{- else }} + namespace: {{ include "cert-manager.namespace" . }} +{{- end }} + labels: + app: {{ include "cert-manager.name" . }} + app.kubernetes.io/name: {{ include "cert-manager.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "controller" + {{- include "labels" . | nindent 4 }} + prometheus: {{ .Values.prometheus.servicemonitor.prometheusInstance }} + {{- with .Values.prometheus.servicemonitor.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +{{- if .Values.prometheus.servicemonitor.annotations }} + annotations: + {{- with .Values.prometheus.servicemonitor.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} +spec: + jobLabel: {{ template "cert-manager.fullname" . }} + selector: + matchLabels: + app.kubernetes.io/name: {{ template "cert-manager.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "controller" +{{- if .Values.prometheus.servicemonitor.namespace }} + namespaceSelector: + matchNames: + - {{ include "cert-manager.namespace" . }} +{{- end }} + endpoints: + - targetPort: {{ .Values.prometheus.servicemonitor.targetPort }} + path: {{ .Values.prometheus.servicemonitor.path }} + interval: {{ .Values.prometheus.servicemonitor.interval }} + scrapeTimeout: {{ .Values.prometheus.servicemonitor.scrapeTimeout }} + honorLabels: {{ .Values.prometheus.servicemonitor.honorLabels }} +{{- end }} diff --git a/packages/system/cert-manager/charts/cert-manager/templates/startupapicheck-job.yaml b/packages/system/cert-manager/charts/cert-manager/templates/startupapicheck-job.yaml new file mode 100644 index 00000000..a9b965e1 --- /dev/null +++ b/packages/system/cert-manager/charts/cert-manager/templates/startupapicheck-job.yaml @@ -0,0 +1,88 @@ +{{- if .Values.startupapicheck.enabled }} +apiVersion: batch/v1 +kind: Job +metadata: + name: {{ include "startupapicheck.fullname" . }} + namespace: {{ include "cert-manager.namespace" . }} + labels: + app: {{ include "startupapicheck.name" . }} + app.kubernetes.io/name: {{ include "startupapicheck.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "startupapicheck" + {{- include "labels" . | nindent 4 }} + {{- with .Values.startupapicheck.jobAnnotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + backoffLimit: {{ .Values.startupapicheck.backoffLimit }} + template: + metadata: + labels: + app: {{ include "startupapicheck.name" . }} + app.kubernetes.io/name: {{ include "startupapicheck.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "startupapicheck" + {{- include "labels" . | nindent 8 }} + {{- with .Values.startupapicheck.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.startupapicheck.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + restartPolicy: OnFailure + serviceAccountName: {{ template "startupapicheck.serviceAccountName" . }} + {{- if hasKey .Values.startupapicheck "automountServiceAccountToken" }} + automountServiceAccountToken: {{ .Values.startupapicheck.automountServiceAccountToken }} + {{- end }} + {{- with .Values.global.priorityClassName }} + priorityClassName: {{ . | quote }} + {{- end }} + {{- with .Values.startupapicheck.securityContext }} + securityContext: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: {{ .Chart.Name }}-startupapicheck + {{- with .Values.startupapicheck.image }} + image: "{{- if .registry -}}{{ .registry }}/{{- end -}}{{ .repository }}{{- if (.digest) -}} @{{ .digest }}{{- else -}}:{{ default $.Chart.AppVersion .tag }} {{- end -}}" + {{- end }} + imagePullPolicy: {{ .Values.startupapicheck.image.pullPolicy }} + args: + - check + - api + - --wait={{ .Values.startupapicheck.timeout }} + {{- with .Values.startupapicheck.extraArgs }} + {{- toYaml . | nindent 10 }} + {{- end }} + {{- with .Values.startupapicheck.containerSecurityContext }} + securityContext: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.startupapicheck.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.startupapicheck.volumeMounts }} + volumeMounts: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.startupapicheck.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.startupapicheck.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.startupapicheck.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.startupapicheck.volumes }} + volumes: + {{- toYaml . | nindent 8 }} + {{- end }} +{{- end }} diff --git a/packages/system/cert-manager/charts/cert-manager/templates/startupapicheck-psp-clusterrole.yaml b/packages/system/cert-manager/charts/cert-manager/templates/startupapicheck-psp-clusterrole.yaml new file mode 100644 index 00000000..dacd4be2 --- /dev/null +++ b/packages/system/cert-manager/charts/cert-manager/templates/startupapicheck-psp-clusterrole.yaml @@ -0,0 +1,24 @@ +{{- if .Values.startupapicheck.enabled }} +{{- if .Values.global.podSecurityPolicy.enabled }} +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ template "startupapicheck.fullname" . }}-psp + labels: + app: {{ include "startupapicheck.name" . }} + app.kubernetes.io/name: {{ include "startupapicheck.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "startupapicheck" + {{- include "labels" . | nindent 4 }} + {{- with .Values.startupapicheck.rbac.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +rules: +- apiGroups: ['policy'] + resources: ['podsecuritypolicies'] + verbs: ['use'] + resourceNames: + - {{ template "startupapicheck.fullname" . }} +{{- end }} +{{- end }} diff --git a/packages/system/cert-manager/charts/cert-manager/templates/startupapicheck-psp-clusterrolebinding.yaml b/packages/system/cert-manager/charts/cert-manager/templates/startupapicheck-psp-clusterrolebinding.yaml new file mode 100644 index 00000000..54d5a42d --- /dev/null +++ b/packages/system/cert-manager/charts/cert-manager/templates/startupapicheck-psp-clusterrolebinding.yaml @@ -0,0 +1,26 @@ +{{- if .Values.startupapicheck.enabled }} +{{- if .Values.global.podSecurityPolicy.enabled }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ template "startupapicheck.fullname" . }}-psp + labels: + app: {{ include "startupapicheck.name" . }} + app.kubernetes.io/name: {{ include "startupapicheck.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "startupapicheck" + {{- include "labels" . | nindent 4 }} + {{- with .Values.startupapicheck.rbac.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ template "startupapicheck.fullname" . }}-psp +subjects: + - kind: ServiceAccount + name: {{ template "startupapicheck.serviceAccountName" . }} + namespace: {{ include "cert-manager.namespace" . }} +{{- end }} +{{- end }} diff --git a/packages/system/cert-manager/charts/cert-manager/templates/startupapicheck-psp.yaml b/packages/system/cert-manager/charts/cert-manager/templates/startupapicheck-psp.yaml new file mode 100644 index 00000000..f09d60d6 --- /dev/null +++ b/packages/system/cert-manager/charts/cert-manager/templates/startupapicheck-psp.yaml @@ -0,0 +1,51 @@ +{{- if .Values.startupapicheck.enabled }} +{{- if .Values.global.podSecurityPolicy.enabled }} +apiVersion: policy/v1beta1 +kind: PodSecurityPolicy +metadata: + name: {{ template "startupapicheck.fullname" . }} + labels: + app: {{ include "startupapicheck.name" . }} + app.kubernetes.io/name: {{ include "startupapicheck.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "startupapicheck" + {{- include "labels" . | nindent 4 }} + annotations: + seccomp.security.alpha.kubernetes.io/allowedProfileNames: 'docker/default' + seccomp.security.alpha.kubernetes.io/defaultProfileName: 'docker/default' + {{- if .Values.global.podSecurityPolicy.useAppArmor }} + apparmor.security.beta.kubernetes.io/allowedProfileNames: 'runtime/default' + apparmor.security.beta.kubernetes.io/defaultProfileName: 'runtime/default' + {{- end }} + {{- with .Values.startupapicheck.rbac.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + privileged: false + allowPrivilegeEscalation: false + allowedCapabilities: [] # default set of capabilities are implicitly allowed + volumes: + - 'projected' + - 'secret' + hostNetwork: false + hostIPC: false + hostPID: false + runAsUser: + rule: 'MustRunAs' + ranges: + - min: 1000 + max: 1000 + seLinux: + rule: 'RunAsAny' + supplementalGroups: + rule: 'MustRunAs' + ranges: + - min: 1000 + max: 1000 + fsGroup: + rule: 'MustRunAs' + ranges: + - min: 1000 + max: 1000 +{{- end }} +{{- end }} diff --git a/packages/system/cert-manager/charts/cert-manager/templates/startupapicheck-rbac.yaml b/packages/system/cert-manager/charts/cert-manager/templates/startupapicheck-rbac.yaml new file mode 100644 index 00000000..606e7256 --- /dev/null +++ b/packages/system/cert-manager/charts/cert-manager/templates/startupapicheck-rbac.yaml @@ -0,0 +1,48 @@ +{{- if .Values.startupapicheck.enabled }} +{{- if .Values.global.rbac.create }} +# create certificate role +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ template "startupapicheck.fullname" . }}:create-cert + namespace: {{ include "cert-manager.namespace" . }} + labels: + app: {{ include "startupapicheck.name" . }} + app.kubernetes.io/name: {{ include "startupapicheck.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "startupapicheck" + {{- include "labels" . | nindent 4 }} + {{- with .Values.startupapicheck.rbac.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +rules: + - apiGroups: ["cert-manager.io"] + resources: ["certificates"] + verbs: ["create"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ include "startupapicheck.fullname" . }}:create-cert + namespace: {{ include "cert-manager.namespace" . }} + labels: + app: {{ include "startupapicheck.name" . }} + app.kubernetes.io/name: {{ include "startupapicheck.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "startupapicheck" + {{- include "labels" . | nindent 4 }} + {{- with .Values.startupapicheck.rbac.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ template "startupapicheck.fullname" . }}:create-cert +subjects: + - kind: ServiceAccount + name: {{ template "startupapicheck.serviceAccountName" . }} + namespace: {{ include "cert-manager.namespace" . }} +{{- end }} +{{- end }} diff --git a/packages/system/cert-manager/charts/cert-manager/templates/startupapicheck-serviceaccount.yaml b/packages/system/cert-manager/charts/cert-manager/templates/startupapicheck-serviceaccount.yaml new file mode 100644 index 00000000..8c417604 --- /dev/null +++ b/packages/system/cert-manager/charts/cert-manager/templates/startupapicheck-serviceaccount.yaml @@ -0,0 +1,27 @@ +{{- if .Values.startupapicheck.enabled }} +{{- if .Values.startupapicheck.serviceAccount.create }} +apiVersion: v1 +kind: ServiceAccount +automountServiceAccountToken: {{ .Values.startupapicheck.serviceAccount.automountServiceAccountToken }} +metadata: + name: {{ template "startupapicheck.serviceAccountName" . }} + namespace: {{ include "cert-manager.namespace" . }} + {{- with .Values.startupapicheck.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} + labels: + app: {{ include "startupapicheck.name" . }} + app.kubernetes.io/name: {{ include "startupapicheck.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "startupapicheck" + {{- include "labels" . | nindent 4 }} + {{- with .Values.startupapicheck.serviceAccount.labels }} + {{ toYaml . | nindent 4 }} + {{- end }} +{{- with .Values.global.imagePullSecrets }} +imagePullSecrets: + {{- toYaml . | nindent 2 }} +{{- end }} +{{- end }} +{{- end }} diff --git a/packages/system/cert-manager/charts/cert-manager/templates/webhook-config.yaml b/packages/system/cert-manager/charts/cert-manager/templates/webhook-config.yaml new file mode 100644 index 00000000..f3f72f02 --- /dev/null +++ b/packages/system/cert-manager/charts/cert-manager/templates/webhook-config.yaml @@ -0,0 +1,25 @@ +{{- if .Values.webhook.config -}} + {{- if not .Values.webhook.config.apiVersion -}} + {{- fail "webhook.config.apiVersion must be set" -}} + {{- end -}} + + {{- if not .Values.webhook.config.kind -}} + {{- fail "webhook.config.kind must be set" -}} + {{- end -}} +{{- end -}} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "webhook.fullname" . }} + namespace: {{ include "cert-manager.namespace" . }} + labels: + app: {{ include "webhook.name" . }} + app.kubernetes.io/name: {{ include "webhook.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "webhook" + {{- include "labels" . | nindent 4 }} +data: + {{- if .Values.webhook.config }} + config.yaml: | + {{ .Values.webhook.config | toYaml | nindent 4 }} + {{- end }} diff --git a/packages/system/cert-manager/charts/cert-manager/templates/webhook-deployment.yaml b/packages/system/cert-manager/charts/cert-manager/templates/webhook-deployment.yaml new file mode 100644 index 00000000..043c4b15 --- /dev/null +++ b/packages/system/cert-manager/charts/cert-manager/templates/webhook-deployment.yaml @@ -0,0 +1,185 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "webhook.fullname" . }} + namespace: {{ include "cert-manager.namespace" . }} + labels: + app: {{ include "webhook.name" . }} + app.kubernetes.io/name: {{ include "webhook.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "webhook" + {{- include "labels" . | nindent 4 }} + {{- with .Values.webhook.deploymentAnnotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + replicas: {{ .Values.webhook.replicaCount }} + selector: + matchLabels: + app.kubernetes.io/name: {{ include "webhook.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "webhook" + {{- with .Values.webhook.strategy }} + strategy: + {{- toYaml . | nindent 4 }} + {{- end }} + template: + metadata: + labels: + app: {{ include "webhook.name" . }} + app.kubernetes.io/name: {{ include "webhook.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "webhook" + {{- include "labels" . | nindent 8 }} + {{- with .Values.webhook.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.webhook.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + serviceAccountName: {{ template "webhook.serviceAccountName" . }} + {{- if hasKey .Values.webhook "automountServiceAccountToken" }} + automountServiceAccountToken: {{ .Values.webhook.automountServiceAccountToken }} + {{- end }} + {{- with .Values.global.priorityClassName }} + priorityClassName: {{ . | quote }} + {{- end }} + {{- with .Values.webhook.securityContext }} + securityContext: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if .Values.webhook.hostNetwork }} + hostNetwork: true + {{- end }} + containers: + - name: {{ .Chart.Name }}-webhook + {{- with .Values.webhook.image }} + image: "{{- if .registry -}}{{ .registry }}/{{- end -}}{{ .repository }}{{- if (.digest) -}} @{{ .digest }}{{- else -}}:{{ default $.Chart.AppVersion .tag }} {{- end -}}" + {{- end }} + imagePullPolicy: {{ .Values.webhook.image.pullPolicy }} + args: + {{- if .Values.global.logLevel }} + - --v={{ .Values.global.logLevel }} + {{- end }} + {{- if .Values.webhook.config }} + - --config=/var/cert-manager/config/config.yaml + {{- end }} + {{- $config := default .Values.webhook.config "" }} + {{ if not $config.securePort -}} + - --secure-port={{ .Values.webhook.securePort }} + {{- end }} + {{- if .Values.featureGates }} + - --feature-gates={{ .Values.featureGates }} + {{- end }} + {{- $tlsConfig := default $config.tlsConfig "" }} + {{ if or (not $config.tlsConfig) (and (not $tlsConfig.dynamic) (not $tlsConfig.filesystem) ) -}} + - --dynamic-serving-ca-secret-namespace=$(POD_NAMESPACE) + - --dynamic-serving-ca-secret-name={{ template "webhook.fullname" . }}-ca + - --dynamic-serving-dns-names={{ template "webhook.fullname" . }} + - --dynamic-serving-dns-names={{ template "webhook.fullname" . }}.$(POD_NAMESPACE) + - --dynamic-serving-dns-names={{ template "webhook.fullname" . }}.$(POD_NAMESPACE).svc + {{ if .Values.webhook.url.host }} + - --dynamic-serving-dns-names={{ .Values.webhook.url.host }} + {{- end }} + {{- end }} + {{- with .Values.webhook.extraArgs }} + {{- toYaml . | nindent 10 }} + {{- end }} + ports: + - name: https + protocol: TCP + {{- if $config.securePort }} + containerPort: {{ $config.securePort }} + {{- else if .Values.webhook.securePort }} + containerPort: {{ .Values.webhook.securePort }} + {{- else }} + containerPort: 6443 + {{- end }} + - name: healthcheck + protocol: TCP + {{- if $config.healthzPort }} + containerPort: {{ $config.healthzPort }} + {{- else }} + containerPort: 6080 + {{- end }} + livenessProbe: + httpGet: + path: /livez + {{- if $config.healthzPort }} + port: {{ $config.healthzPort }} + {{- else }} + port: 6080 + {{- end }} + scheme: HTTP + initialDelaySeconds: {{ .Values.webhook.livenessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.webhook.livenessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.webhook.livenessProbe.timeoutSeconds }} + successThreshold: {{ .Values.webhook.livenessProbe.successThreshold }} + failureThreshold: {{ .Values.webhook.livenessProbe.failureThreshold }} + readinessProbe: + httpGet: + path: /healthz + {{- if $config.healthzPort }} + port: {{ $config.healthzPort }} + {{- else }} + port: 6080 + {{- end }} + scheme: HTTP + initialDelaySeconds: {{ .Values.webhook.readinessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.webhook.readinessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.webhook.readinessProbe.timeoutSeconds }} + successThreshold: {{ .Values.webhook.readinessProbe.successThreshold }} + failureThreshold: {{ .Values.webhook.readinessProbe.failureThreshold }} + {{- with .Values.webhook.containerSecurityContext }} + securityContext: + {{- toYaml . | nindent 12 }} + {{- end }} + env: + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + {{- with .Values.webhook.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- if or .Values.webhook.config .Values.webhook.volumeMounts }} + volumeMounts: + {{- if .Values.webhook.config }} + - name: config + mountPath: /var/cert-manager/config + {{- end }} + {{- if .Values.webhook.volumeMounts }} + {{- toYaml .Values.webhook.volumeMounts | nindent 12 }} + {{- end }} + {{- end }} + {{- with .Values.webhook.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.webhook.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.webhook.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.webhook.topologySpreadConstraints }} + topologySpreadConstraints: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if or .Values.webhook.config .Values.webhook.volumes }} + volumes: + {{- if .Values.webhook.config }} + - name: config + configMap: + name: {{ include "webhook.fullname" . }} + {{- end }} + {{- if .Values.webhook.volumes }} + {{- toYaml .Values.webhook.volumes | nindent 8 }} + {{- end }} + {{- end }} diff --git a/packages/system/cert-manager/charts/cert-manager/templates/webhook-mutating-webhook.yaml b/packages/system/cert-manager/charts/cert-manager/templates/webhook-mutating-webhook.yaml new file mode 100644 index 00000000..f3db011e --- /dev/null +++ b/packages/system/cert-manager/charts/cert-manager/templates/webhook-mutating-webhook.yaml @@ -0,0 +1,46 @@ +apiVersion: admissionregistration.k8s.io/v1 +kind: MutatingWebhookConfiguration +metadata: + name: {{ include "webhook.fullname" . }} + labels: + app: {{ include "webhook.name" . }} + app.kubernetes.io/name: {{ include "webhook.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "webhook" + {{- include "labels" . | nindent 4 }} + annotations: + cert-manager.io/inject-ca-from-secret: {{ printf "%s/%s-ca" (include "cert-manager.namespace" .) (include "webhook.fullname" .) | quote }} + {{- with .Values.webhook.mutatingWebhookConfigurationAnnotations }} + {{- toYaml . | nindent 4 }} + {{- end }} +webhooks: + - name: webhook.cert-manager.io + rules: + - apiGroups: + - "cert-manager.io" + - "acme.cert-manager.io" + apiVersions: + - "v1" + operations: + - CREATE + - UPDATE + resources: + - "*/*" + admissionReviewVersions: ["v1"] + # This webhook only accepts v1 cert-manager resources. + # Equivalent matchPolicy ensures that non-v1 resource requests are sent to + # this webhook (after the resources have been converted to v1). + matchPolicy: Equivalent + timeoutSeconds: {{ .Values.webhook.timeoutSeconds }} + failurePolicy: Fail + # Only include 'sideEffects' field in Kubernetes 1.12+ + sideEffects: None + clientConfig: + {{- if .Values.webhook.url.host }} + url: https://{{ .Values.webhook.url.host }}/mutate + {{- else }} + service: + name: {{ template "webhook.fullname" . }} + namespace: {{ include "cert-manager.namespace" . }} + path: /mutate + {{- end }} diff --git a/packages/system/cert-manager/charts/cert-manager/templates/webhook-poddisruptionbudget.yaml b/packages/system/cert-manager/charts/cert-manager/templates/webhook-poddisruptionbudget.yaml new file mode 100644 index 00000000..c8a357cb --- /dev/null +++ b/packages/system/cert-manager/charts/cert-manager/templates/webhook-poddisruptionbudget.yaml @@ -0,0 +1,26 @@ +{{- if .Values.webhook.podDisruptionBudget.enabled }} +apiVersion: policy/v1 +kind: PodDisruptionBudget +metadata: + name: {{ include "webhook.fullname" . }} + namespace: {{ include "cert-manager.namespace" . }} + labels: + app: {{ include "webhook.name" . }} + app.kubernetes.io/name: {{ include "webhook.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "webhook" + {{- include "labels" . | nindent 4 }} +spec: + selector: + matchLabels: + app.kubernetes.io/name: {{ include "webhook.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "webhook" + + {{- with .Values.webhook.podDisruptionBudget.minAvailable }} + minAvailable: {{ . }} + {{- end }} + {{- with .Values.webhook.podDisruptionBudget.maxUnavailable }} + maxUnavailable: {{ . }} + {{- end }} +{{- end }} diff --git a/packages/system/cert-manager/charts/cert-manager/templates/webhook-psp-clusterrole.yaml b/packages/system/cert-manager/charts/cert-manager/templates/webhook-psp-clusterrole.yaml new file mode 100644 index 00000000..f6fa4c55 --- /dev/null +++ b/packages/system/cert-manager/charts/cert-manager/templates/webhook-psp-clusterrole.yaml @@ -0,0 +1,18 @@ +{{- if .Values.global.podSecurityPolicy.enabled }} +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ template "webhook.fullname" . }}-psp + labels: + app: {{ include "webhook.name" . }} + app.kubernetes.io/name: {{ include "webhook.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "webhook" + {{- include "labels" . | nindent 4 }} +rules: +- apiGroups: ['policy'] + resources: ['podsecuritypolicies'] + verbs: ['use'] + resourceNames: + - {{ template "webhook.fullname" . }} +{{- end }} diff --git a/packages/system/cert-manager/charts/cert-manager/templates/webhook-psp-clusterrolebinding.yaml b/packages/system/cert-manager/charts/cert-manager/templates/webhook-psp-clusterrolebinding.yaml new file mode 100644 index 00000000..858df8ff --- /dev/null +++ b/packages/system/cert-manager/charts/cert-manager/templates/webhook-psp-clusterrolebinding.yaml @@ -0,0 +1,20 @@ +{{- if .Values.global.podSecurityPolicy.enabled }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ template "webhook.fullname" . }}-psp + labels: + app: {{ include "webhook.name" . }} + app.kubernetes.io/name: {{ include "webhook.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "webhook" + {{- include "labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ template "webhook.fullname" . }}-psp +subjects: + - kind: ServiceAccount + name: {{ template "webhook.serviceAccountName" . }} + namespace: {{ include "cert-manager.namespace" . }} +{{- end }} diff --git a/packages/system/cert-manager/charts/cert-manager/templates/webhook-psp.yaml b/packages/system/cert-manager/charts/cert-manager/templates/webhook-psp.yaml new file mode 100644 index 00000000..4d5d959d --- /dev/null +++ b/packages/system/cert-manager/charts/cert-manager/templates/webhook-psp.yaml @@ -0,0 +1,54 @@ +{{- if .Values.global.podSecurityPolicy.enabled }} +apiVersion: policy/v1beta1 +kind: PodSecurityPolicy +metadata: + name: {{ template "webhook.fullname" . }} + labels: + app: {{ include "webhook.name" . }} + app.kubernetes.io/name: {{ include "webhook.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "webhook" + {{- include "labels" . | nindent 4 }} + annotations: + seccomp.security.alpha.kubernetes.io/allowedProfileNames: 'docker/default' + seccomp.security.alpha.kubernetes.io/defaultProfileName: 'docker/default' + {{- if .Values.global.podSecurityPolicy.useAppArmor }} + apparmor.security.beta.kubernetes.io/allowedProfileNames: 'runtime/default' + apparmor.security.beta.kubernetes.io/defaultProfileName: 'runtime/default' + {{- end }} +spec: + privileged: false + allowPrivilegeEscalation: false + allowedCapabilities: [] # default set of capabilities are implicitly allowed + volumes: + - 'configMap' + - 'emptyDir' + - 'projected' + - 'secret' + - 'downwardAPI' + hostNetwork: {{ .Values.webhook.hostNetwork }} + {{- if .Values.webhook.hostNetwork }} + hostPorts: + - max: {{ .Values.webhook.securePort }} + min: {{ .Values.webhook.securePort }} + {{- end }} + hostIPC: false + hostPID: false + runAsUser: + rule: 'MustRunAs' + ranges: + - min: 1000 + max: 1000 + seLinux: + rule: 'RunAsAny' + supplementalGroups: + rule: 'MustRunAs' + ranges: + - min: 1000 + max: 1000 + fsGroup: + rule: 'MustRunAs' + ranges: + - min: 1000 + max: 1000 +{{- end }} diff --git a/packages/system/cert-manager/charts/cert-manager/templates/webhook-rbac.yaml b/packages/system/cert-manager/charts/cert-manager/templates/webhook-rbac.yaml new file mode 100644 index 00000000..b075ffd4 --- /dev/null +++ b/packages/system/cert-manager/charts/cert-manager/templates/webhook-rbac.yaml @@ -0,0 +1,83 @@ +{{- if .Values.global.rbac.create }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ template "webhook.fullname" . }}:dynamic-serving + namespace: {{ include "cert-manager.namespace" . }} + labels: + app: {{ include "webhook.name" . }} + app.kubernetes.io/name: {{ include "webhook.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "webhook" + {{- include "labels" . | nindent 4 }} +rules: +- apiGroups: [""] + resources: ["secrets"] + resourceNames: + - '{{ template "webhook.fullname" . }}-ca' + verbs: ["get", "list", "watch", "update"] +# It's not possible to grant CREATE permission on a single resourceName. +- apiGroups: [""] + resources: ["secrets"] + verbs: ["create"] +--- + +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ template "webhook.fullname" . }}:dynamic-serving + namespace: {{ include "cert-manager.namespace" . }} + labels: + app: {{ include "webhook.name" . }} + app.kubernetes.io/name: {{ include "webhook.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "webhook" + {{- include "labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ template "webhook.fullname" . }}:dynamic-serving +subjects: +- apiGroup: "" + kind: ServiceAccount + name: {{ template "webhook.serviceAccountName" . }} + namespace: {{ include "cert-manager.namespace" . }} + +--- + +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ template "webhook.fullname" . }}:subjectaccessreviews + labels: + app: {{ include "webhook.name" . }} + app.kubernetes.io/name: {{ include "webhook.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "webhook" + {{- include "labels" . | nindent 4 }} +rules: +- apiGroups: ["authorization.k8s.io"] + resources: ["subjectaccessreviews"] + verbs: ["create"] +--- + +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ template "webhook.fullname" . }}:subjectaccessreviews + labels: + app: {{ include "webhook.name" . }} + app.kubernetes.io/name: {{ include "webhook.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "webhook" + {{- include "labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ template "webhook.fullname" . }}:subjectaccessreviews +subjects: +- apiGroup: "" + kind: ServiceAccount + name: {{ template "webhook.serviceAccountName" . }} + namespace: {{ include "cert-manager.namespace" . }} +{{- end }} diff --git a/packages/system/cert-manager/charts/cert-manager/templates/webhook-service.yaml b/packages/system/cert-manager/charts/cert-manager/templates/webhook-service.yaml new file mode 100644 index 00000000..5f939504 --- /dev/null +++ b/packages/system/cert-manager/charts/cert-manager/templates/webhook-service.yaml @@ -0,0 +1,32 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ template "webhook.fullname" . }} + namespace: {{ include "cert-manager.namespace" . }} +{{- with .Values.webhook.serviceAnnotations }} + annotations: +{{ toYaml . | indent 4 }} +{{- end }} + labels: + app: {{ include "webhook.name" . }} + app.kubernetes.io/name: {{ include "webhook.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "webhook" + {{- include "labels" . | nindent 4 }} + {{- with .Values.webhook.serviceLabels }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + type: {{ .Values.webhook.serviceType }} + {{- with .Values.webhook.loadBalancerIP }} + loadBalancerIP: {{ . }} + {{- end }} + ports: + - name: https + port: 443 + protocol: TCP + targetPort: "https" + selector: + app.kubernetes.io/name: {{ include "webhook.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "webhook" diff --git a/packages/system/cert-manager/charts/cert-manager/templates/webhook-serviceaccount.yaml b/packages/system/cert-manager/charts/cert-manager/templates/webhook-serviceaccount.yaml new file mode 100644 index 00000000..dff5c067 --- /dev/null +++ b/packages/system/cert-manager/charts/cert-manager/templates/webhook-serviceaccount.yaml @@ -0,0 +1,25 @@ +{{- if .Values.webhook.serviceAccount.create }} +apiVersion: v1 +kind: ServiceAccount +automountServiceAccountToken: {{ .Values.webhook.serviceAccount.automountServiceAccountToken }} +metadata: + name: {{ template "webhook.serviceAccountName" . }} + namespace: {{ include "cert-manager.namespace" . }} + {{- with .Values.webhook.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} + labels: + app: {{ include "webhook.name" . }} + app.kubernetes.io/name: {{ include "webhook.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "webhook" + {{- include "labels" . | nindent 4 }} + {{- with .Values.webhook.serviceAccount.labels }} + {{ toYaml . | nindent 4 }} + {{- end }} +{{- with .Values.global.imagePullSecrets }} +imagePullSecrets: + {{- toYaml . | nindent 2 }} +{{- end }} +{{- end }} diff --git a/packages/system/cert-manager/charts/cert-manager/templates/webhook-validating-webhook.yaml b/packages/system/cert-manager/charts/cert-manager/templates/webhook-validating-webhook.yaml new file mode 100644 index 00000000..a5d168e2 --- /dev/null +++ b/packages/system/cert-manager/charts/cert-manager/templates/webhook-validating-webhook.yaml @@ -0,0 +1,55 @@ +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingWebhookConfiguration +metadata: + name: {{ include "webhook.fullname" . }} + labels: + app: {{ include "webhook.name" . }} + app.kubernetes.io/name: {{ include "webhook.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "webhook" + {{- include "labels" . | nindent 4 }} + annotations: + cert-manager.io/inject-ca-from-secret: {{ printf "%s/%s-ca" (include "cert-manager.namespace" .) (include "webhook.fullname" .) | quote}} + {{- with .Values.webhook.validatingWebhookConfigurationAnnotations }} + {{- toYaml . | nindent 4 }} + {{- end }} +webhooks: + - name: webhook.cert-manager.io + namespaceSelector: + matchExpressions: + - key: "cert-manager.io/disable-validation" + operator: "NotIn" + values: + - "true" + - key: "name" + operator: "NotIn" + values: + - {{ include "cert-manager.namespace" . }} + rules: + - apiGroups: + - "cert-manager.io" + - "acme.cert-manager.io" + apiVersions: + - "v1" + operations: + - CREATE + - UPDATE + resources: + - "*/*" + admissionReviewVersions: ["v1"] + # This webhook only accepts v1 cert-manager resources. + # Equivalent matchPolicy ensures that non-v1 resource requests are sent to + # this webhook (after the resources have been converted to v1). + matchPolicy: Equivalent + timeoutSeconds: {{ .Values.webhook.timeoutSeconds }} + failurePolicy: Fail + sideEffects: None + clientConfig: + {{- if .Values.webhook.url.host }} + url: https://{{ .Values.webhook.url.host }}/validate + {{- else }} + service: + name: {{ template "webhook.fullname" . }} + namespace: {{ include "cert-manager.namespace" . }} + path: /validate + {{- end }} diff --git a/packages/system/cert-manager/charts/cert-manager/values.yaml b/packages/system/cert-manager/charts/cert-manager/values.yaml new file mode 100644 index 00000000..66df39a4 --- /dev/null +++ b/packages/system/cert-manager/charts/cert-manager/values.yaml @@ -0,0 +1,692 @@ +# Default values for cert-manager. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. +global: + # Reference to one or more secrets to be used when pulling images + # ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ + imagePullSecrets: [] + # - name: "image-pull-secret" + + # Labels to apply to all resources + # Please note that this does not add labels to the resources created dynamically by the controllers. + # For these resources, you have to add the labels in the template in the cert-manager custom resource: + # eg. podTemplate/ ingressTemplate in ACMEChallengeSolverHTTP01Ingress + # ref: https://cert-manager.io/docs/reference/api-docs/#acme.cert-manager.io/v1.ACMEChallengeSolverHTTP01Ingress + # eg. secretTemplate in CertificateSpec + # ref: https://cert-manager.io/docs/reference/api-docs/#cert-manager.io/v1.CertificateSpec + commonLabels: {} + # team_name: dev + + # Optional priority class to be used for the cert-manager pods + priorityClassName: "" + rbac: + create: true + # Aggregate ClusterRoles to Kubernetes default user-facing roles. Ref: https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles + aggregateClusterRoles: true + + podSecurityPolicy: + enabled: false + useAppArmor: true + + # Set the verbosity of cert-manager. Range of 0 - 6 with 6 being the most verbose. + logLevel: 2 + + leaderElection: + # Override the namespace used for the leader election lease + namespace: "kube-system" + + # The duration that non-leader candidates will wait after observing a + # leadership renewal until attempting to acquire leadership of a led but + # unrenewed leader slot. This is effectively the maximum duration that a + # leader can be stopped before it is replaced by another candidate. + # leaseDuration: 60s + + # The interval between attempts by the acting master to renew a leadership + # slot before it stops leading. This must be less than or equal to the + # lease duration. + # renewDeadline: 40s + + # The duration the clients should wait between attempting acquisition and + # renewal of a leadership. + # retryPeriod: 15s + +installCRDs: false + +replicaCount: 1 + +strategy: {} + # type: RollingUpdate + # rollingUpdate: + # maxSurge: 0 + # maxUnavailable: 1 + +podDisruptionBudget: + enabled: false + + minAvailable: 1 + # maxUnavailable: 1 + + # minAvailable and maxUnavailable can either be set to an integer (e.g. 1) + # or a percentage value (e.g. 25%) + +# Comma separated list of feature gates that should be enabled on the controller +# Note: do not use this field to pass feature gate values into webhook +# component as this behaviour relies on a bug that will be fixed in cert-manager 1.13 +# https://github.com/cert-manager/cert-manager/pull/6093 +# Use webhook.extraArgs to pass --feature-gates flag directly instead. +featureGates: "" + +# The maximum number of challenges that can be scheduled as 'processing' at once +maxConcurrentChallenges: 60 + +image: + repository: quay.io/jetstack/cert-manager-controller + # You can manage a registry with + # registry: quay.io + # repository: jetstack/cert-manager-controller + + # Override the image tag to deploy by setting this variable. + # If no value is set, the chart's appVersion will be used. + # tag: canary + + # Setting a digest will override any tag + # digest: sha256:0e072dddd1f7f8fc8909a2ca6f65e76c5f0d2fcfb8be47935ae3457e8bbceb20 + pullPolicy: IfNotPresent + +# Override the namespace used to store DNS provider credentials etc. for ClusterIssuer +# resources. By default, the same namespace as cert-manager is deployed within is +# used. This namespace will not be automatically created by the Helm chart. +clusterResourceNamespace: "" + +# This namespace allows you to define where the services will be installed into +# if not set then they will use the namespace of the release +# This is helpful when installing cert manager as a chart dependency (sub chart) +namespace: "" + +serviceAccount: + # Specifies whether a service account should be created + create: true + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + # name: "" + # Optional additional annotations to add to the controller's ServiceAccount + # annotations: {} + # Automount API credentials for a Service Account. + # Optional additional labels to add to the controller's ServiceAccount + # labels: {} + automountServiceAccountToken: true + +# Automounting API credentials for a particular pod +# automountServiceAccountToken: true + +# When this flag is enabled, secrets will be automatically removed when the certificate resource is deleted +enableCertificateOwnerRef: false + +# Setting Nameservers for DNS01 Self Check +# See: https://cert-manager.io/docs/configuration/acme/dns01/#setting-nameservers-for-dns01-self-check + +# Comma separated string with host and port of the recursive nameservers cert-manager should query +dns01RecursiveNameservers: "" + +# Forces cert-manager to only use the recursive nameservers for verification. +# Enabling this option could cause the DNS01 self check to take longer due to caching performed by the recursive nameservers +dns01RecursiveNameserversOnly: false + +# Additional command line flags to pass to cert-manager controller binary. +# To see all available flags run docker run quay.io/jetstack/cert-manager-controller: --help +extraArgs: [] + # Use this flag to enable or disable arbitrary controllers, for example, disable the CertificiateRequests approver + # - --controllers=*,-certificaterequests-approver + +extraEnv: [] +# - name: SOME_VAR +# value: 'some value' + +resources: {} + # requests: + # cpu: 10m + # memory: 32Mi + +# Pod Security Context +# ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ +securityContext: + runAsNonRoot: true + seccompProfile: + type: RuntimeDefault + +# Container Security Context to be set on the controller component container +# ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ +containerSecurityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + + +volumes: [] + +volumeMounts: [] + +# Optional additional annotations to add to the controller Deployment +# deploymentAnnotations: {} + +# Optional additional annotations to add to the controller Pods +# podAnnotations: {} + +podLabels: {} + +# Optional annotations to add to the controller Service +# serviceAnnotations: {} + +# Optional additional labels to add to the controller Service +# serviceLabels: {} + +# Optional DNS settings, useful if you have a public and private DNS zone for +# the same domain on Route 53. What follows is an example of ensuring +# cert-manager can access an ingress or DNS TXT records at all times. +# NOTE: This requires Kubernetes 1.10 or `CustomPodDNS` feature gate enabled for +# the cluster to work. +# podDnsPolicy: "None" +# podDnsConfig: +# nameservers: +# - "1.1.1.1" +# - "8.8.8.8" + +nodeSelector: + kubernetes.io/os: linux + +ingressShim: {} + # defaultIssuerName: "" + # defaultIssuerKind: "" + # defaultIssuerGroup: "" + +prometheus: + enabled: true + servicemonitor: + enabled: false + prometheusInstance: default + targetPort: 9402 + path: /metrics + interval: 60s + scrapeTimeout: 30s + labels: {} + annotations: {} + honorLabels: false + +# Use these variables to configure the HTTP_PROXY environment variables +# http_proxy: "http://proxy:8080" +# https_proxy: "https://proxy:8080" +# no_proxy: 127.0.0.1,localhost + +# A Kubernetes Affinty, if required; see https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#affinity-v1-core +# for example: +# affinity: +# nodeAffinity: +# requiredDuringSchedulingIgnoredDuringExecution: +# nodeSelectorTerms: +# - matchExpressions: +# - key: foo.bar.com/role +# operator: In +# values: +# - master +affinity: {} + +# A list of Kubernetes Tolerations, if required; see https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#toleration-v1-core +# for example: +# tolerations: +# - key: foo.bar.com/role +# operator: Equal +# value: master +# effect: NoSchedule +tolerations: [] + +# A list of Kubernetes TopologySpreadConstraints, if required; see https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#topologyspreadconstraint-v1-core +# for example: +# topologySpreadConstraints: +# - maxSkew: 2 +# topologyKey: topology.kubernetes.io/zone +# whenUnsatisfiable: ScheduleAnyway +# labelSelector: +# matchLabels: +# app.kubernetes.io/instance: cert-manager +# app.kubernetes.io/component: controller +topologySpreadConstraints: [] + +# LivenessProbe settings for the controller container of the controller Pod. +# +# Disabled by default, because the controller has a leader election mechanism +# which should cause it to exit if it is unable to renew its leader election +# record. +# LivenessProbe durations and thresholds are based on those used for the Kubernetes +# controller-manager. See: +# https://github.com/kubernetes/kubernetes/blob/806b30170c61a38fedd54cc9ede4cd6275a1ad3b/cmd/kubeadm/app/util/staticpod/utils.go#L241-L245 +livenessProbe: + enabled: false + initialDelaySeconds: 10 + periodSeconds: 10 + timeoutSeconds: 15 + successThreshold: 1 + failureThreshold: 8 + +webhook: + replicaCount: 1 + timeoutSeconds: 10 + + # Used to configure options for the webhook pod. + # This allows setting options that'd usually be provided via flags. + # An APIVersion and Kind must be specified in your values.yaml file. + # Flags will override options that are set here. + config: + # apiVersion: webhook.config.cert-manager.io/v1alpha1 + # kind: WebhookConfiguration + + # The port that the webhook should listen on for requests. + # In GKE private clusters, by default kubernetes apiservers are allowed to + # talk to the cluster nodes only on 443 and 10250. so configuring + # securePort: 10250, will work out of the box without needing to add firewall + # rules or requiring NET_BIND_SERVICE capabilities to bind port numbers <1000. + # This should be uncommented and set as a default by the chart once we graduate + # the apiVersion of WebhookConfiguration past v1alpha1. + # securePort: 10250 + + strategy: {} + # type: RollingUpdate + # rollingUpdate: + # maxSurge: 0 + # maxUnavailable: 1 + + # Pod Security Context to be set on the webhook component Pod + # ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ + securityContext: + runAsNonRoot: true + seccompProfile: + type: RuntimeDefault + + podDisruptionBudget: + enabled: false + + minAvailable: 1 + # maxUnavailable: 1 + + # minAvailable and maxUnavailable can either be set to an integer (e.g. 1) + # or a percentage value (e.g. 25%) + + # Container Security Context to be set on the webhook component container + # ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ + containerSecurityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + + # Optional additional annotations to add to the webhook Deployment + # deploymentAnnotations: {} + + # Optional additional annotations to add to the webhook Pods + # podAnnotations: {} + + # Optional additional annotations to add to the webhook Service + # serviceAnnotations: {} + + # Optional additional annotations to add to the webhook MutatingWebhookConfiguration + # mutatingWebhookConfigurationAnnotations: {} + + # Optional additional annotations to add to the webhook ValidatingWebhookConfiguration + # validatingWebhookConfigurationAnnotations: {} + + # Additional command line flags to pass to cert-manager webhook binary. + # To see all available flags run docker run quay.io/jetstack/cert-manager-webhook: --help + extraArgs: [] + # Path to a file containing a WebhookConfiguration object used to configure the webhook + # - --config= + + resources: {} + # requests: + # cpu: 10m + # memory: 32Mi + + ## Liveness and readiness probe values + ## Ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes + ## + livenessProbe: + failureThreshold: 3 + initialDelaySeconds: 60 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 + readinessProbe: + failureThreshold: 3 + initialDelaySeconds: 5 + periodSeconds: 5 + successThreshold: 1 + timeoutSeconds: 1 + + nodeSelector: + kubernetes.io/os: linux + + affinity: {} + + tolerations: [] + + topologySpreadConstraints: [] + + # Optional additional labels to add to the Webhook Pods + podLabels: {} + + # Optional additional labels to add to the Webhook Service + serviceLabels: {} + + image: + repository: quay.io/jetstack/cert-manager-webhook + # You can manage a registry with + # registry: quay.io + # repository: jetstack/cert-manager-webhook + + # Override the image tag to deploy by setting this variable. + # If no value is set, the chart's appVersion will be used. + # tag: canary + + # Setting a digest will override any tag + # digest: sha256:0e072dddd1f7f8fc8909a2ca6f65e76c5f0d2fcfb8be47935ae3457e8bbceb20 + + pullPolicy: IfNotPresent + + serviceAccount: + # Specifies whether a service account should be created + create: true + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + # name: "" + # Optional additional annotations to add to the controller's ServiceAccount + # annotations: {} + # Optional additional labels to add to the webhook's ServiceAccount + # labels: {} + # Automount API credentials for a Service Account. + automountServiceAccountToken: true + + # Automounting API credentials for a particular pod + # automountServiceAccountToken: true + + # The port that the webhook should listen on for requests. + # In GKE private clusters, by default kubernetes apiservers are allowed to + # talk to the cluster nodes only on 443 and 10250. so configuring + # securePort: 10250, will work out of the box without needing to add firewall + # rules or requiring NET_BIND_SERVICE capabilities to bind port numbers <1000 + securePort: 10250 + + # Specifies if the webhook should be started in hostNetwork mode. + # + # Required for use in some managed kubernetes clusters (such as AWS EKS) with custom + # CNI (such as calico), because control-plane managed by AWS cannot communicate + # with pods' IP CIDR and admission webhooks are not working + # + # Since the default port for the webhook conflicts with kubelet on the host + # network, `webhook.securePort` should be changed to an available port if + # running in hostNetwork mode. + hostNetwork: false + + # Specifies how the service should be handled. Useful if you want to expose the + # webhook to outside of the cluster. In some cases, the control plane cannot + # reach internal services. + serviceType: ClusterIP + # loadBalancerIP: + + # Overrides the mutating webhook and validating webhook so they reach the webhook + # service using the `url` field instead of a service. + url: {} + # host: + + # Enables default network policies for webhooks. + networkPolicy: + enabled: false + ingress: + - from: + - ipBlock: + cidr: 0.0.0.0/0 + egress: + - ports: + - port: 80 + protocol: TCP + - port: 443 + protocol: TCP + - port: 53 + protocol: TCP + - port: 53 + protocol: UDP + # On OpenShift and OKD, the Kubernetes API server listens on + # port 6443. + - port: 6443 + protocol: TCP + to: + - ipBlock: + cidr: 0.0.0.0/0 + + volumes: [] + volumeMounts: [] + +cainjector: + enabled: true + replicaCount: 1 + + strategy: {} + # type: RollingUpdate + # rollingUpdate: + # maxSurge: 0 + # maxUnavailable: 1 + + # Pod Security Context to be set on the cainjector component Pod + # ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ + securityContext: + runAsNonRoot: true + seccompProfile: + type: RuntimeDefault + + podDisruptionBudget: + enabled: false + + minAvailable: 1 + # maxUnavailable: 1 + + # minAvailable and maxUnavailable can either be set to an integer (e.g. 1) + # or a percentage value (e.g. 25%) + + # Container Security Context to be set on the cainjector component container + # ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ + containerSecurityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + + + # Optional additional annotations to add to the cainjector Deployment + # deploymentAnnotations: {} + + # Optional additional annotations to add to the cainjector Pods + # podAnnotations: {} + + # Additional command line flags to pass to cert-manager cainjector binary. + # To see all available flags run docker run quay.io/jetstack/cert-manager-cainjector: --help + extraArgs: [] + # Enable profiling for cainjector + # - --enable-profiling=true + + resources: {} + # requests: + # cpu: 10m + # memory: 32Mi + + nodeSelector: + kubernetes.io/os: linux + + affinity: {} + + tolerations: [] + + topologySpreadConstraints: [] + + # Optional additional labels to add to the CA Injector Pods + podLabels: {} + + image: + repository: quay.io/jetstack/cert-manager-cainjector + # You can manage a registry with + # registry: quay.io + # repository: jetstack/cert-manager-cainjector + + # Override the image tag to deploy by setting this variable. + # If no value is set, the chart's appVersion will be used. + # tag: canary + + # Setting a digest will override any tag + # digest: sha256:0e072dddd1f7f8fc8909a2ca6f65e76c5f0d2fcfb8be47935ae3457e8bbceb20 + + pullPolicy: IfNotPresent + + serviceAccount: + # Specifies whether a service account should be created + create: true + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + # name: "" + # Optional additional annotations to add to the controller's ServiceAccount + # annotations: {} + # Automount API credentials for a Service Account. + # Optional additional labels to add to the cainjector's ServiceAccount + # labels: {} + automountServiceAccountToken: true + + # Automounting API credentials for a particular pod + # automountServiceAccountToken: true + + volumes: [] + volumeMounts: [] + +acmesolver: + image: + repository: quay.io/jetstack/cert-manager-acmesolver + # You can manage a registry with + # registry: quay.io + # repository: jetstack/cert-manager-acmesolver + + # Override the image tag to deploy by setting this variable. + # If no value is set, the chart's appVersion will be used. + # tag: canary + + # Setting a digest will override any tag + # digest: sha256:0e072dddd1f7f8fc8909a2ca6f65e76c5f0d2fcfb8be47935ae3457e8bbceb20 + +# This startupapicheck is a Helm post-install hook that waits for the webhook +# endpoints to become available. +# The check is implemented using a Kubernetes Job- if you are injecting mesh +# sidecar proxies into cert-manager pods, you probably want to ensure that they +# are not injected into this Job's pod. Otherwise the installation may time out +# due to the Job never being completed because the sidecar proxy does not exit. +# See https://github.com/cert-manager/cert-manager/pull/4414 for context. +startupapicheck: + enabled: true + + # Pod Security Context to be set on the startupapicheck component Pod + # ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ + securityContext: + runAsNonRoot: true + seccompProfile: + type: RuntimeDefault + + # Container Security Context to be set on the controller component container + # ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ + containerSecurityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + + # Timeout for 'kubectl check api' command + timeout: 1m + + # Job backoffLimit + backoffLimit: 4 + + # Optional additional annotations to add to the startupapicheck Job + jobAnnotations: + helm.sh/hook: post-install + helm.sh/hook-weight: "1" + helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded + + # Optional additional annotations to add to the startupapicheck Pods + # podAnnotations: {} + + # Additional command line flags to pass to startupapicheck binary. + # To see all available flags run docker run quay.io/jetstack/cert-manager-ctl: --help + extraArgs: [] + + resources: {} + # requests: + # cpu: 10m + # memory: 32Mi + + nodeSelector: + kubernetes.io/os: linux + + affinity: {} + + tolerations: [] + + # Optional additional labels to add to the startupapicheck Pods + podLabels: {} + + image: + repository: quay.io/jetstack/cert-manager-ctl + # You can manage a registry with + # registry: quay.io + # repository: jetstack/cert-manager-ctl + + # Override the image tag to deploy by setting this variable. + # If no value is set, the chart's appVersion will be used. + # tag: canary + + # Setting a digest will override any tag + # digest: sha256:0e072dddd1f7f8fc8909a2ca6f65e76c5f0d2fcfb8be47935ae3457e8bbceb20 + + pullPolicy: IfNotPresent + + rbac: + # annotations for the startup API Check job RBAC and PSP resources + annotations: + helm.sh/hook: post-install + helm.sh/hook-weight: "-5" + helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded + + # Automounting API credentials for a particular pod + # automountServiceAccountToken: true + + serviceAccount: + # Specifies whether a service account should be created + create: true + + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + # name: "" + + # Optional additional annotations to add to the Job's ServiceAccount + annotations: + helm.sh/hook: post-install + helm.sh/hook-weight: "-5" + helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded + + # Automount API credentials for a Service Account. + automountServiceAccountToken: true + + # Optional additional labels to add to the startupapicheck's ServiceAccount + # labels: {} + + volumes: [] + volumeMounts: [] diff --git a/packages/system/cert-manager/values.yaml b/packages/system/cert-manager/values.yaml new file mode 100644 index 00000000..0b21fc93 --- /dev/null +++ b/packages/system/cert-manager/values.yaml @@ -0,0 +1,2 @@ +cert-manager: + installCRDs: true diff --git a/packages/system/cilium/Chart.yaml b/packages/system/cilium/Chart.yaml new file mode 100644 index 00000000..7d6bef13 --- /dev/null +++ b/packages/system/cilium/Chart.yaml @@ -0,0 +1,2 @@ +name: cozy-cilium +version: 1.0.0 diff --git a/packages/system/cilium/Makefile b/packages/system/cilium/Makefile new file mode 100644 index 00000000..db14cf98 --- /dev/null +++ b/packages/system/cilium/Makefile @@ -0,0 +1,19 @@ +NAMESPACE=cozy-cilium +NAME=cilium + +show: + helm template --dry-run=server -n $(NAMESPACE) $(NAME) . + +apply: + helm upgrade -i -n $(NAMESPACE) $(NAME) . + +diff: + helm diff upgrade --allow-unreleased --normalize-manifests -n $(NAMESPACE) $(NAME) . + +update: + rm -rf charts + helm repo add cilium https://helm.cilium.io/ + helm repo update cilium + helm pull cilium/cilium --untar --untardir charts + sed -i -e '/Used in iptables/d' -e '/SYS_MODULE/d' charts/cilium/values.yaml + patch -p3 < patches/fix-cgroups.patch diff --git a/packages/system/cilium/charts/cilium/.helmignore b/packages/system/cilium/charts/cilium/.helmignore new file mode 100644 index 00000000..f9dcfa99 --- /dev/null +++ b/packages/system/cilium/charts/cilium/.helmignore @@ -0,0 +1,24 @@ +# 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/ +.github/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/packages/system/cilium/charts/cilium/Chart.yaml b/packages/system/cilium/charts/cilium/Chart.yaml new file mode 100644 index 00000000..1b4e38a8 --- /dev/null +++ b/packages/system/cilium/charts/cilium/Chart.yaml @@ -0,0 +1,141 @@ +annotations: + artifacthub.io/crds: | + - kind: CiliumNetworkPolicy + version: v2 + name: ciliumnetworkpolicies.cilium.io + displayName: Cilium Network Policy + description: | + Cilium Network Policies provide additional functionality beyond what + is provided by standard Kubernetes NetworkPolicy such as the ability + to allow traffic based on FQDNs, or to filter at Layer 7. + - kind: CiliumClusterwideNetworkPolicy + version: v2 + name: ciliumclusterwidenetworkpolicies.cilium.io + displayName: Cilium Clusterwide Network Policy + description: | + Cilium Clusterwide Network Policies support configuring network traffic + policiies across the entire cluster, including applying node firewalls. + - kind: CiliumExternalWorkload + version: v2 + name: ciliumexternalworkloads.cilium.io + displayName: Cilium External Workload + description: | + Cilium External Workload supports configuring the ability for external + non-Kubernetes workloads to join the cluster. + - kind: CiliumLocalRedirectPolicy + version: v2 + name: ciliumlocalredirectpolicies.cilium.io + displayName: Cilium Local Redirect Policy + description: | + Cilium Local Redirect Policy allows local redirects to be configured + within a node to support use cases like Node-Local DNS or KIAM. + - kind: CiliumNode + version: v2 + name: ciliumnodes.cilium.io + displayName: Cilium Node + description: | + Cilium Node represents a node managed by Cilium. It contains a + specification to control various node specific configuration aspects + and a status section to represent the status of the node. + - kind: CiliumIdentity + version: v2 + name: ciliumidentities.cilium.io + displayName: Cilium Identity + description: | + Cilium Identity allows introspection into security identities that + Cilium allocates which identify sets of labels that are assigned to + individual endpoints in the cluster. + - kind: CiliumEndpoint + version: v2 + name: ciliumendpoints.cilium.io + displayName: Cilium Endpoint + description: | + Cilium Endpoint represents the status of individual pods or nodes in + the cluster which are managed by Cilium, including enforcement status, + IP addressing and whether the networking is succesfully operational. + - kind: CiliumEndpointSlice + version: v2alpha1 + name: ciliumendpointslices.cilium.io + displayName: Cilium Endpoint Slice + description: | + Cilium Endpoint Slice represents the status of groups of pods or nodes + in the cluster which are managed by Cilium, including enforcement status, + IP addressing and whether the networking is succesfully operational. + - kind: CiliumEgressGatewayPolicy + version: v2 + name: ciliumegressgatewaypolicies.cilium.io + displayName: Cilium Egress Gateway Policy + description: | + Cilium Egress Gateway Policy provides control over the way that traffic + leaves the cluster and which source addresses to use for that traffic. + - kind: CiliumClusterwideEnvoyConfig + version: v2 + name: ciliumclusterwideenvoyconfigs.cilium.io + displayName: Cilium Clusterwide Envoy Config + description: | + Cilium Clusterwide Envoy Config specifies Envoy resources and K8s service mappings + to be provisioned into Cilium host proxy instances in cluster context. + - kind: CiliumEnvoyConfig + version: v2 + name: ciliumenvoyconfigs.cilium.io + displayName: Cilium Envoy Config + description: | + Cilium Envoy Config specifies Envoy resources and K8s service mappings + to be provisioned into Cilium host proxy instances in namespace context. + - kind: CiliumBGPPeeringPolicy + version: v2alpha1 + name: ciliumbgppeeringpolicies.cilium.io + displayName: Cilium BGP Peering Policy + description: | + Cilium BGP Peering Policy instructs Cilium to create specific BGP peering + configurations. + - kind: CiliumLoadBalancerIPPool + version: v2alpha1 + name: ciliumloadbalancerippools.cilium.io + displayName: Cilium Load Balancer IP Pool + description: | + Defining a Cilium Load Balancer IP Pool instructs Cilium to assign IPs to LoadBalancer Services. + - kind: CiliumNodeConfig + version: v2alpha1 + name: ciliumnodeconfigs.cilium.io + displayName: Cilium Node Configuration + description: | + CiliumNodeConfig is a list of configuration key-value pairs. It is applied to + nodes indicated by a label selector. + - kind: CiliumCIDRGroup + version: v2alpha1 + name: ciliumcidrgroups.cilium.io + displayName: Cilium CIDR Group + description: | + CiliumCIDRGroup is a list of CIDRs that can be referenced as a single entity from CiliumNetworkPolicies. + - kind: CiliumL2AnnouncementPolicy + version: v2alpha1 + name: ciliuml2announcementpolicies.cilium.io + displayName: Cilium L2 Announcement Policy + description: | + CiliumL2AnnouncementPolicy is a policy which determines which service IPs will be announced to + the local area network, by which nodes, and via which interfaces. + - kind: CiliumPodIPPool + version: v2alpha1 + name: ciliumpodippools.cilium.io + displayName: Cilium Pod IP Pool + description: | + CiliumPodIPPool defines an IP pool that can be used for pooled IPAM (i.e. the multi-pool IPAM mode). +apiVersion: v2 +appVersion: 1.14.5 +description: eBPF-based Networking, Security, and Observability +home: https://cilium.io/ +icon: https://cdn.jsdelivr.net/gh/cilium/cilium@v1.14/Documentation/images/logo-solo.svg +keywords: +- BPF +- eBPF +- Kubernetes +- Networking +- Security +- Observability +- Troubleshooting +kubeVersion: '>= 1.16.0-0' +name: cilium +sources: +- https://github.com/cilium/cilium +version: 1.14.5 diff --git a/packages/system/cilium/charts/cilium/LICENSE b/packages/system/cilium/charts/cilium/LICENSE new file mode 100644 index 00000000..a2e486a8 --- /dev/null +++ b/packages/system/cilium/charts/cilium/LICENSE @@ -0,0 +1,202 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} Authors of Cilium + + 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/packages/system/cilium/charts/cilium/README.md b/packages/system/cilium/charts/cilium/README.md new file mode 100644 index 00000000..aaa41fee --- /dev/null +++ b/packages/system/cilium/charts/cilium/README.md @@ -0,0 +1,748 @@ +# cilium + +![Version: 1.14.5](https://img.shields.io/badge/Version-1.14.5-informational?style=flat-square) ![AppVersion: 1.14.5](https://img.shields.io/badge/AppVersion-1.14.5-informational?style=flat-square) + +Cilium is open source software for providing and transparently securing +network connectivity and loadbalancing between application workloads such as +application containers or processes. Cilium operates at Layer 3/4 to provide +traditional networking and security services as well as Layer 7 to protect and +secure use of modern application protocols such as HTTP, gRPC and Kafka. + +A new Linux kernel technology called eBPF is at the foundation of Cilium. +It supports dynamic insertion of eBPF bytecode into the Linux kernel at various +integration points such as: network IO, application sockets, and tracepoints +to implement security, networking and visibility logic. eBPF is highly +efficient and flexible. + +![Cilium feature overview](https://raw.githubusercontent.com/cilium/cilium/main/Documentation/images/cilium_overview.png) + +## Prerequisites + +* Kubernetes: `>= 1.16.0-0` +* Helm: `>= 3.0` + +## Getting Started + +Try Cilium on any Kubernetes distribution in under 15 minutes: + +| Minikube | Self-Managed K8s | Amazon EKS | Google GKE | Microsoft AKS | +|:-:|:-:|:-:|:-:|:-:| +| [![Minikube](https://raw.githubusercontent.com/cilium/charts/master/images/minikube.svg)](https://docs.cilium.io/en/stable/gettingstarted/k8s-install-default/) | [![Self-Managed Kubernetes](https://raw.githubusercontent.com/cilium/charts/master/images/k8s.png)](https://docs.cilium.io/en/stable/gettingstarted/k8s-install-default/) | [![Amazon EKS](https://raw.githubusercontent.com/cilium/charts/master/images/aws.svg)](https://docs.cilium.io/en/stable/gettingstarted/k8s-install-default/) | [![Google GKE](https://raw.githubusercontent.com/cilium/charts/master/images/google-cloud.svg)](https://docs.cilium.io/en/stable/gettingstarted/k8s-install-default/) | [![Microsoft AKS](https://raw.githubusercontent.com/cilium/charts/master/images/azure.svg)](https://docs.cilium.io/en/stable/gettingstarted/k8s-install-default/) | + +Or, for a quick install with the default configuration: + +``` +$ helm repo add cilium https://helm.cilium.io/ +$ helm install cilium cilium/cilium --namespace=kube-system +``` + +After Cilium is installed, you can explore the features that Cilium has to +offer from the [Getting Started Guides page](https://docs.cilium.io/en/stable/gettingstarted/). + +## Source Code + +* + +## Getting Help + +The best way to get help if you get stuck is to ask a question on the +[Cilium Slack channel](https://cilium.herokuapp.com/). With Cilium +contributors across the globe, there is almost always someone available to help. + +## Values + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| MTU | int | `0` | Configure the underlying network MTU to overwrite auto-detected MTU. | +| affinity | object | `{"podAntiAffinity":{"requiredDuringSchedulingIgnoredDuringExecution":[{"labelSelector":{"matchLabels":{"k8s-app":"cilium"}},"topologyKey":"kubernetes.io/hostname"}]}}` | Affinity for cilium-agent. | +| agent | bool | `true` | Install the cilium agent resources. | +| agentNotReadyTaintKey | string | `"node.cilium.io/agent-not-ready"` | Configure the key of the taint indicating that Cilium is not ready on the node. When set to a value starting with `ignore-taint.cluster-autoscaler.kubernetes.io/`, the Cluster Autoscaler will ignore the taint on its decisions, allowing the cluster to scale up. | +| aksbyocni.enabled | bool | `false` | Enable AKS BYOCNI integration. Note that this is incompatible with AKS clusters not created in BYOCNI mode: use Azure integration (`azure.enabled`) instead. | +| alibabacloud.enabled | bool | `false` | Enable AlibabaCloud ENI integration | +| annotateK8sNode | bool | `false` | Annotate k8s node upon initialization with Cilium's metadata. | +| authentication.enabled | bool | `true` | Enable authentication processing and garbage collection. Note that if disabled, policy enforcement will still block requests that require authentication. But the resulting authentication requests for these requests will not be processed, therefore the requests not be allowed. | +| authentication.gcInterval | string | `"5m0s"` | Interval for garbage collection of auth map entries. | +| authentication.mutual.port | int | `4250` | Port on the agent where mutual authentication handshakes between agents will be performed | +| authentication.mutual.spire.adminSocketPath | string | `"/run/spire/sockets/admin.sock"` | SPIRE socket path where the SPIRE delegated api agent is listening | +| authentication.mutual.spire.agentSocketPath | string | `"/run/spire/sockets/agent/agent.sock"` | SPIRE socket path where the SPIRE workload agent is listening. Applies to both the Cilium Agent and Operator | +| authentication.mutual.spire.connectionTimeout | string | `"30s"` | SPIRE connection timeout | +| authentication.mutual.spire.enabled | bool | `false` | Enable SPIRE integration (beta) | +| authentication.mutual.spire.install.agent.affinity | object | `{}` | SPIRE agent affinity configuration | +| authentication.mutual.spire.install.agent.annotations | object | `{}` | SPIRE agent annotations | +| authentication.mutual.spire.install.agent.image | string | `"ghcr.io/spiffe/spire-agent:1.6.3@sha256:8eef9857bf223181ecef10d9bbcd2f7838f3689e9bd2445bede35066a732e823"` | SPIRE agent image | +| authentication.mutual.spire.install.agent.labels | object | `{}` | SPIRE agent labels | +| authentication.mutual.spire.install.agent.nodeSelector | object | `{}` | SPIRE agent nodeSelector configuration ref: ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#nodeselector | +| authentication.mutual.spire.install.agent.podSecurityContext | object | `{}` | Security context to be added to spire agent pods. SecurityContext holds pod-level security attributes and common container settings. ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod | +| authentication.mutual.spire.install.agent.securityContext | object | `{}` | Security context to be added to spire agent containers. SecurityContext holds pod-level security attributes and common container settings. ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container | +| authentication.mutual.spire.install.agent.serviceAccount | object | `{"create":true,"name":"spire-agent"}` | SPIRE agent service account | +| authentication.mutual.spire.install.agent.skipKubeletVerification | bool | `true` | SPIRE Workload Attestor kubelet verification. | +| authentication.mutual.spire.install.agent.tolerations | list | `[]` | SPIRE agent tolerations configuration ref: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/ | +| authentication.mutual.spire.install.enabled | bool | `true` | Enable SPIRE installation. This will only take effect only if authentication.mutual.spire.enabled is true | +| authentication.mutual.spire.install.namespace | string | `"cilium-spire"` | SPIRE namespace to install into | +| authentication.mutual.spire.install.server.affinity | object | `{}` | SPIRE server affinity configuration | +| authentication.mutual.spire.install.server.annotations | object | `{}` | SPIRE server annotations | +| authentication.mutual.spire.install.server.ca.keyType | string | `"rsa-4096"` | SPIRE CA key type AWS requires the use of RSA. EC cryptography is not supported | +| authentication.mutual.spire.install.server.ca.subject | object | `{"commonName":"Cilium SPIRE CA","country":"US","organization":"SPIRE"}` | SPIRE CA Subject | +| authentication.mutual.spire.install.server.dataStorage.accessMode | string | `"ReadWriteOnce"` | Access mode of the SPIRE server data storage | +| authentication.mutual.spire.install.server.dataStorage.enabled | bool | `true` | Enable SPIRE server data storage | +| authentication.mutual.spire.install.server.dataStorage.size | string | `"1Gi"` | Size of the SPIRE server data storage | +| authentication.mutual.spire.install.server.dataStorage.storageClass | string | `nil` | StorageClass of the SPIRE server data storage | +| authentication.mutual.spire.install.server.image | string | `"ghcr.io/spiffe/spire-server:1.6.3@sha256:f4bc49fb0bd1d817a6c46204cc7ce943c73fb0a5496a78e0e4dc20c9a816ad7f"` | SPIRE server image | +| authentication.mutual.spire.install.server.initContainers | list | `[]` | SPIRE server init containers | +| authentication.mutual.spire.install.server.labels | object | `{}` | SPIRE server labels | +| authentication.mutual.spire.install.server.nodeSelector | object | `{}` | SPIRE server nodeSelector configuration ref: ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#nodeselector | +| authentication.mutual.spire.install.server.service.annotations | object | `{}` | Annotations to be added to the SPIRE server service | +| authentication.mutual.spire.install.server.service.labels | object | `{}` | Labels to be added to the SPIRE server service | +| authentication.mutual.spire.install.server.service.type | string | `"ClusterIP"` | Service type for the SPIRE server service | +| authentication.mutual.spire.install.server.serviceAccount | object | `{"create":true,"name":"spire-server"}` | SPIRE server service account | +| authentication.mutual.spire.install.server.tolerations | list | `[]` | SPIRE server tolerations configuration ref: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/ | +| authentication.mutual.spire.serverAddress | string | `nil` | SPIRE server address used by Cilium Operator If k8s Service DNS along with port number is used (e.g. ..svc(.*): format), Cilium Operator will resolve its address by looking up the clusterIP from Service resource. Example values: 10.0.0.1:8081, spire-server.cilium-spire.svc:8081 | +| authentication.mutual.spire.trustDomain | string | `"spiffe.cilium"` | SPIFFE trust domain to use for fetching certificates | +| authentication.queueSize | int | `1024` | Buffer size of the channel Cilium uses to receive authentication events from the signal map. | +| authentication.rotatedIdentitiesQueueSize | int | `1024` | Buffer size of the channel Cilium uses to receive certificate expiration events from auth handlers. | +| autoDirectNodeRoutes | bool | `false` | Enable installation of PodCIDR routes between worker nodes if worker nodes share a common L2 network segment. | +| azure.enabled | bool | `false` | Enable Azure integration. Note that this is incompatible with AKS clusters created in BYOCNI mode: use AKS BYOCNI integration (`aksbyocni.enabled`) instead. | +| bandwidthManager | object | `{"bbr":false,"enabled":false}` | Enable bandwidth manager to optimize TCP and UDP workloads and allow for rate-limiting traffic from individual Pods with EDT (Earliest Departure Time) through the "kubernetes.io/egress-bandwidth" Pod annotation. | +| bandwidthManager.bbr | bool | `false` | Activate BBR TCP congestion control for Pods | +| bandwidthManager.enabled | bool | `false` | Enable bandwidth manager infrastructure (also prerequirement for BBR) | +| bgp | object | `{"announce":{"loadbalancerIP":false,"podCIDR":false},"enabled":false}` | Configure BGP | +| bgp.announce.loadbalancerIP | bool | `false` | Enable allocation and announcement of service LoadBalancer IPs | +| bgp.announce.podCIDR | bool | `false` | Enable announcement of node pod CIDR | +| bgp.enabled | bool | `false` | Enable BGP support inside Cilium; embeds a new ConfigMap for BGP inside cilium-agent and cilium-operator | +| bgpControlPlane | object | `{"enabled":false}` | This feature set enables virtual BGP routers to be created via CiliumBGPPeeringPolicy CRDs. | +| bgpControlPlane.enabled | bool | `false` | Enables the BGP control plane. | +| bpf.authMapMax | int | `524288` | Configure the maximum number of entries in auth map. | +| bpf.autoMount.enabled | bool | `true` | Enable automatic mount of BPF filesystem When `autoMount` is enabled, the BPF filesystem is mounted at `bpf.root` path on the underlying host and inside the cilium agent pod. If users disable `autoMount`, it's expected that users have mounted bpffs filesystem at the specified `bpf.root` volume, and then the volume will be mounted inside the cilium agent pod at the same path. | +| bpf.ctAnyMax | int | `262144` | Configure the maximum number of entries for the non-TCP connection tracking table. | +| bpf.ctTcpMax | int | `524288` | Configure the maximum number of entries in the TCP connection tracking table. | +| bpf.hostLegacyRouting | bool | `false` | Configure whether direct routing mode should route traffic via host stack (true) or directly and more efficiently out of BPF (false) if the kernel supports it. The latter has the implication that it will also bypass netfilter in the host namespace. | +| bpf.lbExternalClusterIP | bool | `false` | Allow cluster external access to ClusterIP services. | +| bpf.lbMapMax | int | `65536` | Configure the maximum number of service entries in the load balancer maps. | +| bpf.mapDynamicSizeRatio | float64 | `0.0025` | Configure auto-sizing for all BPF maps based on available memory. ref: https://docs.cilium.io/en/stable/network/ebpf/maps/ | +| bpf.masquerade | bool | `false` | Enable native IP masquerade support in eBPF | +| bpf.monitorAggregation | string | `"medium"` | Configure the level of aggregation for monitor notifications. Valid options are none, low, medium, maximum. | +| bpf.monitorFlags | string | `"all"` | Configure which TCP flags trigger notifications when seen for the first time in a connection. | +| bpf.monitorInterval | string | `"5s"` | Configure the typical time between monitor notifications for active connections. | +| bpf.natMax | int | `524288` | Configure the maximum number of entries for the NAT table. | +| bpf.neighMax | int | `524288` | Configure the maximum number of entries for the neighbor table. | +| bpf.policyMapMax | int | `16384` | Configure the maximum number of entries in endpoint policy map (per endpoint). | +| bpf.preallocateMaps | bool | `false` | Enables pre-allocation of eBPF map values. This increases memory usage but can reduce latency. | +| bpf.root | string | `"/sys/fs/bpf"` | Configure the mount point for the BPF filesystem | +| bpf.tproxy | bool | `false` | Configure the eBPF-based TPROXY to reduce reliance on iptables rules for implementing Layer 7 policy. | +| bpf.vlanBypass | list | `[]` | Configure explicitly allowed VLAN id's for bpf logic bypass. [0] will allow all VLAN id's without any filtering. | +| bpfClockProbe | bool | `false` | Enable BPF clock source probing for more efficient tick retrieval. | +| certgen | object | `{"annotations":{"cronJob":{},"job":{}},"extraVolumeMounts":[],"extraVolumes":[],"image":{"digest":"sha256:89a0847753686444daabde9474b48340993bd19c7bea66a46e45b2974b82041f","override":null,"pullPolicy":"IfNotPresent","repository":"quay.io/cilium/certgen","tag":"v0.1.9","useDigest":true},"podLabels":{},"tolerations":[],"ttlSecondsAfterFinished":1800}` | Configure certificate generation for Hubble integration. If hubble.tls.auto.method=cronJob, these values are used for the Kubernetes CronJob which will be scheduled regularly to (re)generate any certificates not provided manually. | +| certgen.annotations | object | `{"cronJob":{},"job":{}}` | Annotations to be added to the hubble-certgen initial Job and CronJob | +| certgen.extraVolumeMounts | list | `[]` | Additional certgen volumeMounts. | +| certgen.extraVolumes | list | `[]` | Additional certgen volumes. | +| certgen.podLabels | object | `{}` | Labels to be added to hubble-certgen pods | +| certgen.tolerations | list | `[]` | Node tolerations for pod assignment on nodes with taints ref: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/ | +| certgen.ttlSecondsAfterFinished | int | `1800` | Seconds after which the completed job pod will be deleted | +| cgroup | object | `{"autoMount":{"enabled":true,"resources":{}},"hostRoot":"/run/cilium/cgroupv2"}` | Configure cgroup related configuration | +| cgroup.autoMount.enabled | bool | `true` | Enable auto mount of cgroup2 filesystem. When `autoMount` is enabled, cgroup2 filesystem is mounted at `cgroup.hostRoot` path on the underlying host and inside the cilium agent pod. If users disable `autoMount`, it's expected that users have mounted cgroup2 filesystem at the specified `cgroup.hostRoot` volume, and then the volume will be mounted inside the cilium agent pod at the same path. | +| cgroup.autoMount.resources | object | `{}` | Init Container Cgroup Automount resource limits & requests | +| cgroup.hostRoot | string | `"/run/cilium/cgroupv2"` | Configure cgroup root where cgroup2 filesystem is mounted on the host (see also: `cgroup.autoMount`) | +| cleanBpfState | bool | `false` | Clean all eBPF datapath state from the initContainer of the cilium-agent DaemonSet. WARNING: Use with care! | +| cleanState | bool | `false` | Clean all local Cilium state from the initContainer of the cilium-agent DaemonSet. Implies cleanBpfState: true. WARNING: Use with care! | +| cluster.id | int | `0` | Unique ID of the cluster. Must be unique across all connected clusters and in the range of 1 to 255. Only required for Cluster Mesh, may be 0 if Cluster Mesh is not used. | +| cluster.name | string | `"default"` | Name of the cluster. Only required for Cluster Mesh and mutual authentication with SPIRE. | +| clustermesh.apiserver.affinity | object | `{"podAntiAffinity":{"requiredDuringSchedulingIgnoredDuringExecution":[{"labelSelector":{"matchLabels":{"k8s-app":"clustermesh-apiserver"}},"topologyKey":"kubernetes.io/hostname"}]}}` | Affinity for clustermesh.apiserver | +| clustermesh.apiserver.etcd.image | object | `{"digest":"sha256:795d8660c48c439a7c3764c2330ed9222ab5db5bb524d8d0607cac76f7ba82a3","override":null,"pullPolicy":"IfNotPresent","repository":"quay.io/coreos/etcd","tag":"v3.5.4","useDigest":true}` | Clustermesh API server etcd image. | +| clustermesh.apiserver.etcd.init.resources | object | `{}` | Specifies the resources for etcd init container in the apiserver | +| clustermesh.apiserver.etcd.resources | object | `{}` | Specifies the resources for etcd container in the apiserver | +| clustermesh.apiserver.etcd.securityContext | object | `{}` | Security context to be added to clustermesh-apiserver etcd containers | +| clustermesh.apiserver.extraArgs | list | `[]` | Additional clustermesh-apiserver arguments. | +| clustermesh.apiserver.extraEnv | list | `[]` | Additional clustermesh-apiserver environment variables. | +| clustermesh.apiserver.extraVolumeMounts | list | `[]` | Additional clustermesh-apiserver volumeMounts. | +| clustermesh.apiserver.extraVolumes | list | `[]` | Additional clustermesh-apiserver volumes. | +| clustermesh.apiserver.image | object | `{"digest":"sha256:7eaa35cf5452c43b1f7d0cde0d707823ae7e49965bcb54c053e31ea4e04c3d96","override":null,"pullPolicy":"IfNotPresent","repository":"quay.io/cilium/clustermesh-apiserver","tag":"v1.14.5","useDigest":true}` | Clustermesh API server image. | +| clustermesh.apiserver.kvstoremesh.enabled | bool | `false` | Enable KVStoreMesh. KVStoreMesh caches the information retrieved from the remote clusters in the local etcd instance. | +| clustermesh.apiserver.kvstoremesh.extraArgs | list | `[]` | Additional KVStoreMesh arguments. | +| clustermesh.apiserver.kvstoremesh.extraEnv | list | `[]` | Additional KVStoreMesh environment variables. | +| clustermesh.apiserver.kvstoremesh.extraVolumeMounts | list | `[]` | Additional KVStoreMesh volumeMounts. | +| clustermesh.apiserver.kvstoremesh.image | object | `{"digest":"sha256:d7137edd0efa2b1407b20088af3980a9993bb616d85bf9b55ea2891d1b99023a","override":null,"pullPolicy":"IfNotPresent","repository":"quay.io/cilium/kvstoremesh","tag":"v1.14.5","useDigest":true}` | KVStoreMesh image. | +| clustermesh.apiserver.kvstoremesh.resources | object | `{}` | Resource requests and limits for the KVStoreMesh container | +| clustermesh.apiserver.kvstoremesh.securityContext | object | `{"allowPrivilegeEscalation":false,"capabilities":{"drop":["ALL"]}}` | KVStoreMesh Security context | +| clustermesh.apiserver.metrics.enabled | bool | `true` | Enables exporting apiserver metrics in OpenMetrics format. | +| clustermesh.apiserver.metrics.etcd.enabled | bool | `false` | Enables exporting etcd metrics in OpenMetrics format. | +| clustermesh.apiserver.metrics.etcd.mode | string | `"basic"` | Set level of detail for etcd metrics; specify 'extensive' to include server side gRPC histogram metrics. | +| clustermesh.apiserver.metrics.etcd.port | int | `9963` | Configure the port the etcd metric server listens on. | +| clustermesh.apiserver.metrics.kvstoremesh.enabled | bool | `true` | Enables exporting KVStoreMesh metrics in OpenMetrics format. | +| clustermesh.apiserver.metrics.kvstoremesh.port | int | `9964` | Configure the port the KVStoreMesh metric server listens on. | +| clustermesh.apiserver.metrics.port | int | `9962` | Configure the port the apiserver metric server listens on. | +| clustermesh.apiserver.metrics.serviceMonitor.annotations | object | `{}` | Annotations to add to ServiceMonitor clustermesh-apiserver | +| clustermesh.apiserver.metrics.serviceMonitor.enabled | bool | `false` | Enable service monitor. This requires the prometheus CRDs to be available (see https://github.com/prometheus-operator/prometheus-operator/blob/main/example/prometheus-operator-crd/monitoring.coreos.com_servicemonitors.yaml) | +| clustermesh.apiserver.metrics.serviceMonitor.etcd.interval | string | `"10s"` | Interval for scrape metrics (etcd metrics) | +| clustermesh.apiserver.metrics.serviceMonitor.etcd.metricRelabelings | string | `nil` | Metrics relabeling configs for the ServiceMonitor clustermesh-apiserver (etcd metrics) | +| clustermesh.apiserver.metrics.serviceMonitor.etcd.relabelings | string | `nil` | Relabeling configs for the ServiceMonitor clustermesh-apiserver (etcd metrics) | +| clustermesh.apiserver.metrics.serviceMonitor.interval | string | `"10s"` | Interval for scrape metrics (apiserver metrics) | +| clustermesh.apiserver.metrics.serviceMonitor.kvstoremesh.interval | string | `"10s"` | Interval for scrape metrics (KVStoreMesh metrics) | +| clustermesh.apiserver.metrics.serviceMonitor.kvstoremesh.metricRelabelings | string | `nil` | Metrics relabeling configs for the ServiceMonitor clustermesh-apiserver (KVStoreMesh metrics) | +| clustermesh.apiserver.metrics.serviceMonitor.kvstoremesh.relabelings | string | `nil` | Relabeling configs for the ServiceMonitor clustermesh-apiserver (KVStoreMesh metrics) | +| clustermesh.apiserver.metrics.serviceMonitor.labels | object | `{}` | Labels to add to ServiceMonitor clustermesh-apiserver | +| clustermesh.apiserver.metrics.serviceMonitor.metricRelabelings | string | `nil` | Metrics relabeling configs for the ServiceMonitor clustermesh-apiserver (apiserver metrics) | +| clustermesh.apiserver.metrics.serviceMonitor.relabelings | string | `nil` | Relabeling configs for the ServiceMonitor clustermesh-apiserver (apiserver metrics) | +| clustermesh.apiserver.nodeSelector | object | `{"kubernetes.io/os":"linux"}` | Node labels for pod assignment ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#nodeselector | +| clustermesh.apiserver.podAnnotations | object | `{}` | Annotations to be added to clustermesh-apiserver pods | +| clustermesh.apiserver.podDisruptionBudget.enabled | bool | `false` | enable PodDisruptionBudget ref: https://kubernetes.io/docs/concepts/workloads/pods/disruptions/ | +| clustermesh.apiserver.podDisruptionBudget.maxUnavailable | int | `1` | Maximum number/percentage of pods that may be made unavailable | +| clustermesh.apiserver.podDisruptionBudget.minAvailable | string | `nil` | Minimum number/percentage of pods that should remain scheduled. When it's set, maxUnavailable must be disabled by `maxUnavailable: null` | +| clustermesh.apiserver.podLabels | object | `{}` | Labels to be added to clustermesh-apiserver pods | +| clustermesh.apiserver.podSecurityContext | object | `{}` | Security context to be added to clustermesh-apiserver pods | +| clustermesh.apiserver.priorityClassName | string | `""` | The priority class to use for clustermesh-apiserver | +| clustermesh.apiserver.replicas | int | `1` | Number of replicas run for the clustermesh-apiserver deployment. | +| clustermesh.apiserver.resources | object | `{}` | Resource requests and limits for the clustermesh-apiserver | +| clustermesh.apiserver.securityContext | object | `{}` | Security context to be added to clustermesh-apiserver containers | +| clustermesh.apiserver.service.annotations | object | `{}` | Annotations for the clustermesh-apiserver For GKE LoadBalancer, use annotation cloud.google.com/load-balancer-type: "Internal" For EKS LoadBalancer, use annotation service.beta.kubernetes.io/aws-load-balancer-internal: 0.0.0.0/0 | +| clustermesh.apiserver.service.externalTrafficPolicy | string | `nil` | The externalTrafficPolicy of service used for apiserver access. | +| clustermesh.apiserver.service.internalTrafficPolicy | string | `nil` | The internalTrafficPolicy of service used for apiserver access. | +| clustermesh.apiserver.service.nodePort | int | `32379` | Optional port to use as the node port for apiserver access. WARNING: make sure to configure a different NodePort in each cluster if kube-proxy replacement is enabled, as Cilium is currently affected by a known bug (#24692) when NodePorts are handled by the KPR implementation. If a service with the same NodePort exists both in the local and the remote cluster, all traffic originating from inside the cluster and targeting the corresponding NodePort will be redirected to a local backend, regardless of whether the destination node belongs to the local or the remote cluster. | +| clustermesh.apiserver.service.type | string | `"NodePort"` | The type of service used for apiserver access. | +| clustermesh.apiserver.tls.admin | object | `{"cert":"","key":""}` | base64 encoded PEM values for the clustermesh-apiserver admin certificate and private key. Used if 'auto' is not enabled. | +| clustermesh.apiserver.tls.authMode | string | `"legacy"` | Configure the clustermesh authentication mode. Supported values: - legacy: All clusters access remote clustermesh instances with the same username (i.e., remote). The "remote" certificate must be generated with CN=remote if provided manually. - migration: Intermediate mode required to upgrade from legacy to cluster (and vice versa) with no disruption. Specifically, it enables the creation of the per-cluster usernames, while still using the common one for authentication. The "remote" certificate must be generated with CN=remote if provided manually (same as legacy). - cluster: Each cluster accesses remote etcd instances with a username depending on the local cluster name (i.e., remote-). The "remote" certificate must be generated with CN=remote- if provided manually. Cluster mode is meaningful only when the same CA is shared across all clusters part of the mesh. | +| clustermesh.apiserver.tls.auto | object | `{"certManagerIssuerRef":{},"certValidityDuration":1095,"enabled":true,"method":"helm"}` | Configure automatic TLS certificates generation. A Kubernetes CronJob is used the generate any certificates not provided by the user at installation time. | +| clustermesh.apiserver.tls.auto.certManagerIssuerRef | object | `{}` | certmanager issuer used when clustermesh.apiserver.tls.auto.method=certmanager. | +| clustermesh.apiserver.tls.auto.certValidityDuration | int | `1095` | Generated certificates validity duration in days. | +| clustermesh.apiserver.tls.auto.enabled | bool | `true` | When set to true, automatically generate a CA and certificates to enable mTLS between clustermesh-apiserver and external workload instances. If set to false, the certs to be provided by setting appropriate values below. | +| clustermesh.apiserver.tls.ca | object | `{"cert":"","key":""}` | Deprecated in favor of tls.ca. To be removed in 1.15. base64 encoded PEM values for the ExternalWorkload CA certificate and private key. | +| clustermesh.apiserver.tls.ca.cert | string | `""` | Deprecated in favor of tls.ca.cert. To be removed in 1.15. Optional CA cert. If it is provided, it will be used by the 'cronJob' method to generate all other certificates. Otherwise, an ephemeral CA is generated. | +| clustermesh.apiserver.tls.ca.key | string | `""` | Deprecated in favor of tls.ca.key. To be removed in 1.15. Optional CA private key. If it is provided, it will be used by the 'cronJob' method to generate all other certificates. Otherwise, an ephemeral CA is generated. | +| clustermesh.apiserver.tls.client | object | `{"cert":"","key":""}` | base64 encoded PEM values for the clustermesh-apiserver client certificate and private key. Used if 'auto' is not enabled. | +| clustermesh.apiserver.tls.remote | object | `{"cert":"","key":""}` | base64 encoded PEM values for the clustermesh-apiserver remote cluster certificate and private key. Used if 'auto' is not enabled. | +| clustermesh.apiserver.tls.server | object | `{"cert":"","extraDnsNames":[],"extraIpAddresses":[],"key":""}` | base64 encoded PEM values for the clustermesh-apiserver server certificate and private key. Used if 'auto' is not enabled. | +| clustermesh.apiserver.tls.server.extraDnsNames | list | `[]` | Extra DNS names added to certificate when it's auto generated | +| clustermesh.apiserver.tls.server.extraIpAddresses | list | `[]` | Extra IP addresses added to certificate when it's auto generated | +| clustermesh.apiserver.tolerations | list | `[]` | Node tolerations for pod assignment on nodes with taints ref: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/ | +| clustermesh.apiserver.topologySpreadConstraints | list | `[]` | Pod topology spread constraints for clustermesh-apiserver | +| clustermesh.apiserver.updateStrategy | object | `{"rollingUpdate":{"maxUnavailable":1},"type":"RollingUpdate"}` | clustermesh-apiserver update strategy | +| clustermesh.config | object | `{"clusters":[],"domain":"mesh.cilium.io","enabled":false}` | Clustermesh explicit configuration. | +| clustermesh.config.clusters | list | `[]` | List of clusters to be peered in the mesh. | +| clustermesh.config.domain | string | `"mesh.cilium.io"` | Default dns domain for the Clustermesh API servers This is used in the case cluster addresses are not provided and IPs are used. | +| clustermesh.config.enabled | bool | `false` | Enable the Clustermesh explicit configuration. | +| clustermesh.useAPIServer | bool | `false` | Deploy clustermesh-apiserver for clustermesh | +| cni.binPath | string | `"/opt/cni/bin"` | Configure the path to the CNI binary directory on the host. | +| cni.chainingMode | string | `nil` | Configure chaining on top of other CNI plugins. Possible values: - none - aws-cni - flannel - generic-veth - portmap | +| cni.chainingTarget | string | `nil` | A CNI network name in to which the Cilium plugin should be added as a chained plugin. This will cause the agent to watch for a CNI network with this network name. When it is found, this will be used as the basis for Cilium's CNI configuration file. If this is set, it assumes a chaining mode of generic-veth. As a special case, a chaining mode of aws-cni implies a chainingTarget of aws-cni. | +| cni.confFileMountPath | string | `"/tmp/cni-configuration"` | Configure the path to where to mount the ConfigMap inside the agent pod. | +| cni.confPath | string | `"/etc/cni/net.d"` | Configure the path to the CNI configuration directory on the host. | +| cni.configMapKey | string | `"cni-config"` | Configure the key in the CNI ConfigMap to read the contents of the CNI configuration from. | +| cni.customConf | bool | `false` | Skip writing of the CNI configuration. This can be used if writing of the CNI configuration is performed by external automation. | +| cni.exclusive | bool | `true` | Make Cilium take ownership over the `/etc/cni/net.d` directory on the node, renaming all non-Cilium CNI configurations to `*.cilium_bak`. This ensures no Pods can be scheduled using other CNI plugins during Cilium agent downtime. | +| cni.hostConfDirMountPath | string | `"/host/etc/cni/net.d"` | Configure the path to where the CNI configuration directory is mounted inside the agent pod. | +| cni.install | bool | `true` | Install the CNI configuration and binary files into the filesystem. | +| cni.logFile | string | `"/var/run/cilium/cilium-cni.log"` | Configure the log file for CNI logging with retention policy of 7 days. Disable CNI file logging by setting this field to empty explicitly. | +| cni.uninstall | bool | `false` | Remove the CNI configuration and binary files on agent shutdown. Enable this if you're removing Cilium from the cluster. Disable this to prevent the CNI configuration file from being removed during agent upgrade, which can cause nodes to go unmanageable. | +| conntrackGCInterval | string | `"0s"` | Configure how frequently garbage collection should occur for the datapath connection tracking table. | +| conntrackGCMaxInterval | string | `""` | Configure the maximum frequency for the garbage collection of the connection tracking table. Only affects the automatic computation for the frequency and has no effect when 'conntrackGCInterval' is set. This can be set to more frequently clean up unused identities created from ToFQDN policies. | +| containerRuntime | object | `{"integration":"none"}` | Configure container runtime specific integration. Deprecated in favor of bpf.autoMount.enabled. To be removed in 1.15. | +| containerRuntime.integration | string | `"none"` | Enables specific integrations for container runtimes. Supported values: - crio - none | +| crdWaitTimeout | string | `"5m"` | Configure timeout in which Cilium will exit if CRDs are not available | +| customCalls | object | `{"enabled":false}` | Tail call hooks for custom eBPF programs. | +| customCalls.enabled | bool | `false` | Enable tail call hooks for custom eBPF programs. | +| daemon.allowedConfigOverrides | string | `nil` | allowedConfigOverrides is a list of config-map keys that can be overridden. That is to say, if this value is set, config sources (excepting the first one) can only override keys in this list. This takes precedence over blockedConfigOverrides. By default, all keys may be overridden. To disable overrides, set this to "none" or change the configSources variable. | +| daemon.blockedConfigOverrides | string | `nil` | blockedConfigOverrides is a list of config-map keys that may not be overridden. In other words, if any of these keys appear in a configuration source excepting the first one, they will be ignored This is ignored if allowedConfigOverrides is set. By default, all keys may be overridden. | +| daemon.configSources | string | `nil` | Configure a custom list of possible configuration override sources The default is "config-map:cilium-config,cilium-node-config". For supported values, see the help text for the build-config subcommand. Note that this value should be a comma-separated string. | +| daemon.runPath | string | `"/var/run/cilium"` | Configure where Cilium runtime state should be stored. | +| dashboards | object | `{"annotations":{},"enabled":false,"label":"grafana_dashboard","labelValue":"1","namespace":null}` | Grafana dashboards for cilium-agent grafana can import dashboards based on the label and value ref: https://github.com/grafana/helm-charts/tree/main/charts/grafana#sidecar-for-dashboards | +| debug.enabled | bool | `false` | Enable debug logging | +| debug.verbose | string | `nil` | Configure verbosity levels for debug logging This option is used to enable debug messages for operations related to such sub-system such as (e.g. kvstore, envoy, datapath or policy), and flow is for enabling debug messages emitted per request, message and connection. Applicable values: - flow - kvstore - envoy - datapath - policy | +| disableEndpointCRD | bool | `false` | Disable the usage of CiliumEndpoint CRD. | +| dnsPolicy | string | `""` | DNS policy for Cilium agent pods. Ref: https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-s-dns-policy | +| dnsProxy.dnsRejectResponseCode | string | `"refused"` | DNS response code for rejecting DNS requests, available options are '[nameError refused]'. | +| dnsProxy.enableDnsCompression | bool | `true` | Allow the DNS proxy to compress responses to endpoints that are larger than 512 Bytes or the EDNS0 option, if present. | +| dnsProxy.endpointMaxIpPerHostname | int | `50` | Maximum number of IPs to maintain per FQDN name for each endpoint. | +| dnsProxy.idleConnectionGracePeriod | string | `"0s"` | Time during which idle but previously active connections with expired DNS lookups are still considered alive. | +| dnsProxy.maxDeferredConnectionDeletes | int | `10000` | Maximum number of IPs to retain for expired DNS lookups with still-active connections. | +| dnsProxy.minTtl | int | `0` | The minimum time, in seconds, to use DNS data for toFQDNs policies. If the upstream DNS server returns a DNS record with a shorter TTL, Cilium overwrites the TTL with this value. Setting this value to zero means that Cilium will honor the TTLs returned by the upstream DNS server. | +| dnsProxy.preCache | string | `""` | DNS cache data at this path is preloaded on agent startup. | +| dnsProxy.proxyPort | int | `0` | Global port on which the in-agent DNS proxy should listen. Default 0 is a OS-assigned port. | +| dnsProxy.proxyResponseMaxDelay | string | `"100ms"` | The maximum time the DNS proxy holds an allowed DNS response before sending it along. Responses are sent as soon as the datapath is updated with the new IP information. | +| egressGateway | object | `{"enabled":false,"installRoutes":false,"reconciliationTriggerInterval":"1s"}` | Enables egress gateway to redirect and SNAT the traffic that leaves the cluster. | +| egressGateway.installRoutes | bool | `false` | Install egress gateway IP rules and routes in order to properly steer egress gateway traffic to the correct ENI interface | +| egressGateway.reconciliationTriggerInterval | string | `"1s"` | Time between triggers of egress gateway state reconciliations | +| enableCiliumEndpointSlice | bool | `false` | Enable CiliumEndpointSlice feature. | +| enableCnpStatusUpdates | bool | `false` | Whether to enable CNP status updates. | +| enableCriticalPriorityClass | bool | `true` | Explicitly enable or disable priority class. .Capabilities.KubeVersion is unsettable in `helm template` calls, it depends on k8s libraries version that Helm was compiled against. This option allows to explicitly disable setting the priority class, which is useful for rendering charts for gke clusters in advance. | +| enableIPv4BIGTCP | bool | `false` | Enables IPv4 BIG TCP support which increases maximum IPv4 GSO/GRO limits for nodes and pods | +| enableIPv4Masquerade | bool | `true` | Enables masquerading of IPv4 traffic leaving the node from endpoints. | +| enableIPv6BIGTCP | bool | `false` | Enables IPv6 BIG TCP support which increases maximum IPv6 GSO/GRO limits for nodes and pods | +| enableIPv6Masquerade | bool | `true` | Enables masquerading of IPv6 traffic leaving the node from endpoints. | +| enableK8sEventHandover | bool | `false` | Configures the use of the KVStore to optimize Kubernetes event handling by mirroring it into the KVstore for reduced overhead in large clusters. | +| enableK8sTerminatingEndpoint | bool | `true` | Configure whether to enable auto detect of terminating state for endpoints in order to support graceful termination. | +| enableRuntimeDeviceDetection | bool | `false` | Enables experimental support for the detection of new and removed datapath devices. When devices change the eBPF datapath is reloaded and services updated. If "devices" is set then only those devices, or devices matching a wildcard will be considered. | +| enableXTSocketFallback | bool | `true` | Enables the fallback compatibility solution for when the xt_socket kernel module is missing and it is needed for the datapath L7 redirection to work properly. See documentation for details on when this can be disabled: https://docs.cilium.io/en/stable/operations/system_requirements/#linux-kernel. | +| encryption.enabled | bool | `false` | Enable transparent network encryption. | +| encryption.interface | string | `""` | Deprecated in favor of encryption.ipsec.interface. To be removed in 1.15. The interface to use for encrypted traffic. This option is only effective when encryption.type is set to ipsec. | +| encryption.ipsec.interface | string | `""` | The interface to use for encrypted traffic. | +| encryption.ipsec.keyFile | string | `""` | Name of the key file inside the Kubernetes secret configured via secretName. | +| encryption.ipsec.keyRotationDuration | string | `"5m"` | Maximum duration of the IPsec key rotation. The previous key will be removed after that delay. | +| encryption.ipsec.keyWatcher | bool | `true` | Enable the key watcher. If disabled, a restart of the agent will be necessary on key rotations. | +| encryption.ipsec.mountPath | string | `""` | Path to mount the secret inside the Cilium pod. | +| encryption.ipsec.secretName | string | `""` | Name of the Kubernetes secret containing the encryption keys. | +| encryption.keyFile | string | `"keys"` | Deprecated in favor of encryption.ipsec.keyFile. To be removed in 1.15. Name of the key file inside the Kubernetes secret configured via secretName. This option is only effective when encryption.type is set to ipsec. | +| encryption.mountPath | string | `"/etc/ipsec"` | Deprecated in favor of encryption.ipsec.mountPath. To be removed in 1.15. Path to mount the secret inside the Cilium pod. This option is only effective when encryption.type is set to ipsec. | +| encryption.nodeEncryption | bool | `false` | Enable encryption for pure node to node traffic. This option is only effective when encryption.type is set to "wireguard". | +| encryption.secretName | string | `"cilium-ipsec-keys"` | Deprecated in favor of encryption.ipsec.secretName. To be removed in 1.15. Name of the Kubernetes secret containing the encryption keys. This option is only effective when encryption.type is set to ipsec. | +| encryption.type | string | `"ipsec"` | Encryption method. Can be either ipsec or wireguard. | +| encryption.wireguard.userspaceFallback | bool | `false` | Enables the fallback to the user-space implementation. | +| endpointHealthChecking.enabled | bool | `true` | Enable connectivity health checking between virtual endpoints. | +| endpointRoutes.enabled | bool | `false` | Enable use of per endpoint routes instead of routing via the cilium_host interface. | +| endpointStatus | object | `{"enabled":false,"status":""}` | Enable endpoint status. Status can be: policy, health, controllers, log and / or state. For 2 or more options use a space. | +| eni.awsEnablePrefixDelegation | bool | `false` | Enable ENI prefix delegation | +| eni.awsReleaseExcessIPs | bool | `false` | Release IPs not used from the ENI | +| eni.ec2APIEndpoint | string | `""` | EC2 API endpoint to use | +| eni.enabled | bool | `false` | Enable Elastic Network Interface (ENI) integration. | +| eni.eniTags | object | `{}` | Tags to apply to the newly created ENIs | +| eni.gcInterval | string | `"5m"` | Interval for garbage collection of unattached ENIs. Set to "0s" to disable. | +| eni.gcTags | object | `{"io.cilium/cilium-managed":"true,"io.cilium/cluster-name":""}` | Additional tags attached to ENIs created by Cilium. Dangling ENIs with this tag will be garbage collected | +| eni.iamRole | string | `""` | If using IAM role for Service Accounts will not try to inject identity values from cilium-aws kubernetes secret. Adds annotation to service account if managed by Helm. See https://github.com/aws/amazon-eks-pod-identity-webhook | +| eni.instanceTagsFilter | list | `[]` | Filter via AWS EC2 Instance tags (k=v) which will dictate which AWS EC2 Instances are going to be used to create new ENIs | +| eni.subnetIDsFilter | list | `[]` | Filter via subnet IDs which will dictate which subnets are going to be used to create new ENIs Important note: This requires that each instance has an ENI with a matching subnet attached when Cilium is deployed. If you only want to control subnets for ENIs attached by Cilium, use the CNI configuration file settings (cni.customConf) instead. | +| eni.subnetTagsFilter | list | `[]` | Filter via tags (k=v) which will dictate which subnets are going to be used to create new ENIs Important note: This requires that each instance has an ENI with a matching subnet attached when Cilium is deployed. If you only want to control subnets for ENIs attached by Cilium, use the CNI configuration file settings (cni.customConf) instead. | +| eni.updateEC2AdapterLimitViaAPI | bool | `true` | Update ENI Adapter limits from the EC2 API | +| envoy.affinity | object | `{"podAntiAffinity":{"requiredDuringSchedulingIgnoredDuringExecution":[{"labelSelector":{"matchLabels":{"k8s-app":"cilium-envoy"}},"topologyKey":"kubernetes.io/hostname"}]}}` | Affinity for cilium-envoy. | +| envoy.connectTimeoutSeconds | int | `2` | Time in seconds after which a TCP connection attempt times out | +| envoy.dnsPolicy | string | `nil` | DNS policy for Cilium envoy pods. Ref: https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-s-dns-policy | +| envoy.enabled | bool | `false` | Enable Envoy Proxy in standalone DaemonSet. | +| envoy.extraArgs | list | `[]` | Additional envoy container arguments. | +| envoy.extraContainers | list | `[]` | Additional containers added to the cilium Envoy DaemonSet. | +| envoy.extraEnv | list | `[]` | Additional envoy container environment variables. | +| envoy.extraHostPathMounts | list | `[]` | Additional envoy hostPath mounts. | +| envoy.extraVolumeMounts | list | `[]` | Additional envoy volumeMounts. | +| envoy.extraVolumes | list | `[]` | Additional envoy volumes. | +| envoy.healthPort | int | `9878` | TCP port for the health API. | +| envoy.idleTimeoutDurationSeconds | int | `60` | Set Envoy upstream HTTP idle connection timeout seconds. Does not apply to connections with pending requests. Default 60s | +| envoy.image | object | `{"digest":"sha256:992998398dadfff7117bfa9fdb7c9474fefab7f0237263f7c8114e106c67baca","override":null,"pullPolicy":"IfNotPresent","repository":"quay.io/cilium/cilium-envoy","tag":"v1.26.6-ad82c7c56e88989992fd25d8d67747de865c823b","useDigest":true}` | Envoy container image. | +| envoy.livenessProbe.failureThreshold | int | `10` | failure threshold of liveness probe | +| envoy.livenessProbe.periodSeconds | int | `30` | interval between checks of the liveness probe | +| envoy.log.format | string | `"[%Y-%m-%d %T.%e][%t][%l][%n] [%g:%#] %v"` | The format string to use for laying out the log message metadata of Envoy. | +| envoy.log.path | string | `""` | Path to a separate Envoy log file, if any. Defaults to /dev/stdout. | +| envoy.maxConnectionDurationSeconds | int | `0` | Set Envoy HTTP option max_connection_duration seconds. Default 0 (disable) | +| envoy.maxRequestsPerConnection | int | `0` | ProxyMaxRequestsPerConnection specifies the max_requests_per_connection setting for Envoy | +| envoy.nodeSelector | object | `{"kubernetes.io/os":"linux"}` | Node selector for cilium-envoy. | +| envoy.podAnnotations | object | `{}` | Annotations to be added to envoy pods | +| envoy.podLabels | object | `{}` | Labels to be added to envoy pods | +| envoy.podSecurityContext | object | `{}` | Security Context for cilium-envoy pods. | +| envoy.priorityClassName | string | `nil` | The priority class to use for cilium-envoy. | +| envoy.prometheus.enabled | bool | `true` | Enable prometheus metrics for cilium-envoy | +| envoy.prometheus.port | string | `"9964"` | Serve prometheus metrics for cilium-envoy on the configured port | +| envoy.prometheus.serviceMonitor.annotations | object | `{}` | Annotations to add to ServiceMonitor cilium-envoy | +| envoy.prometheus.serviceMonitor.enabled | bool | `false` | Enable service monitors. This requires the prometheus CRDs to be available (see https://github.com/prometheus-operator/prometheus-operator/blob/main/example/prometheus-operator-crd/monitoring.coreos.com_servicemonitors.yaml) | +| envoy.prometheus.serviceMonitor.interval | string | `"10s"` | Interval for scrape metrics. | +| envoy.prometheus.serviceMonitor.labels | object | `{}` | Labels to add to ServiceMonitor cilium-envoy | +| envoy.prometheus.serviceMonitor.metricRelabelings | string | `nil` | Metrics relabeling configs for the ServiceMonitor cilium-envoy | +| envoy.prometheus.serviceMonitor.relabelings | list | `[{"replacement":"${1}","sourceLabels":["__meta_kubernetes_pod_node_name"],"targetLabel":"node"}]` | Relabeling configs for the ServiceMonitor cilium-envoy | +| envoy.readinessProbe.failureThreshold | int | `3` | failure threshold of readiness probe | +| envoy.readinessProbe.periodSeconds | int | `30` | interval between checks of the readiness probe | +| envoy.resources | object | `{}` | Envoy resource limits & requests ref: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ | +| envoy.rollOutPods | bool | `false` | Roll out cilium envoy pods automatically when configmap is updated. | +| envoy.securityContext.capabilities.envoy | list | `["NET_ADMIN","SYS_ADMIN"]` | Capabilities for the `cilium-envoy` container | +| envoy.securityContext.privileged | bool | `false` | Run the pod with elevated privileges | +| envoy.securityContext.seLinuxOptions | object | `{"level":"s0","type":"spc_t"}` | SELinux options for the `cilium-envoy` container | +| envoy.startupProbe.failureThreshold | int | `105` | failure threshold of startup probe. 105 x 2s translates to the old behaviour of the readiness probe (120s delay + 30 x 3s) | +| envoy.startupProbe.periodSeconds | int | `2` | interval between checks of the startup probe | +| envoy.terminationGracePeriodSeconds | int | `1` | Configure termination grace period for cilium-envoy DaemonSet. | +| envoy.tolerations | list | `[{"operator":"Exists"}]` | Node tolerations for envoy scheduling to nodes with taints ref: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/ | +| envoy.updateStrategy | object | `{"rollingUpdate":{"maxUnavailable":2},"type":"RollingUpdate"}` | cilium-envoy update strategy ref: https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/#updating-a-daemonset | +| envoyConfig.enabled | bool | `false` | Enable CiliumEnvoyConfig CRD CiliumEnvoyConfig CRD can also be implicitly enabled by other options. | +| envoyConfig.secretsNamespace | object | `{"create":true,"name":"cilium-secrets"}` | SecretsNamespace is the namespace in which envoy SDS will retrieve secrets from. | +| envoyConfig.secretsNamespace.create | bool | `true` | Create secrets namespace for CiliumEnvoyConfig CRDs. | +| envoyConfig.secretsNamespace.name | string | `"cilium-secrets"` | The name of the secret namespace to which Cilium agents are given read access. | +| etcd.clusterDomain | string | `"cluster.local"` | Cluster domain for cilium-etcd-operator. | +| etcd.enabled | bool | `false` | Enable etcd mode for the agent. | +| etcd.endpoints | list | `["https://CHANGE-ME:2379"]` | List of etcd endpoints (not needed when using managed=true). | +| etcd.extraArgs | list | `[]` | Additional cilium-etcd-operator container arguments. | +| etcd.extraVolumeMounts | list | `[]` | Additional cilium-etcd-operator volumeMounts. | +| etcd.extraVolumes | list | `[]` | Additional cilium-etcd-operator volumes. | +| etcd.image | object | `{"digest":"sha256:04b8327f7f992693c2cb483b999041ed8f92efc8e14f2a5f3ab95574a65ea2dc","override":null,"pullPolicy":"IfNotPresent","repository":"quay.io/cilium/cilium-etcd-operator","tag":"v2.0.7","useDigest":true}` | cilium-etcd-operator image. | +| etcd.k8sService | bool | `false` | If etcd is behind a k8s service set this option to true so that Cilium does the service translation automatically without requiring a DNS to be running. | +| etcd.nodeSelector | object | `{"kubernetes.io/os":"linux"}` | Node labels for cilium-etcd-operator pod assignment ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#nodeselector | +| etcd.podAnnotations | object | `{}` | Annotations to be added to cilium-etcd-operator pods | +| etcd.podDisruptionBudget.enabled | bool | `false` | enable PodDisruptionBudget ref: https://kubernetes.io/docs/concepts/workloads/pods/disruptions/ | +| etcd.podDisruptionBudget.maxUnavailable | int | `1` | Maximum number/percentage of pods that may be made unavailable | +| etcd.podDisruptionBudget.minAvailable | string | `nil` | Minimum number/percentage of pods that should remain scheduled. When it's set, maxUnavailable must be disabled by `maxUnavailable: null` | +| etcd.podLabels | object | `{}` | Labels to be added to cilium-etcd-operator pods | +| etcd.podSecurityContext | object | `{}` | Security context to be added to cilium-etcd-operator pods | +| etcd.priorityClassName | string | `""` | The priority class to use for cilium-etcd-operator | +| etcd.resources | object | `{}` | cilium-etcd-operator resource limits & requests ref: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ | +| etcd.securityContext | object | `{}` | Security context to be added to cilium-etcd-operator pods | +| etcd.ssl | bool | `false` | Enable use of TLS/SSL for connectivity to etcd. (auto-enabled if managed=true) | +| etcd.tolerations | list | `[{"operator":"Exists"}]` | Node tolerations for cilium-etcd-operator scheduling to nodes with taints ref: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/ | +| etcd.topologySpreadConstraints | list | `[]` | Pod topology spread constraints for cilium-etcd-operator | +| etcd.updateStrategy | object | `{"rollingUpdate":{"maxSurge":1,"maxUnavailable":1},"type":"RollingUpdate"}` | cilium-etcd-operator update strategy | +| externalIPs.enabled | bool | `false` | Enable ExternalIPs service support. | +| externalWorkloads | object | `{"enabled":false}` | Configure external workloads support | +| externalWorkloads.enabled | bool | `false` | Enable support for external workloads, such as VMs (false by default). | +| extraArgs | list | `[]` | Additional agent container arguments. | +| extraConfig | object | `{}` | extraConfig allows you to specify additional configuration parameters to be included in the cilium-config configmap. | +| extraContainers | list | `[]` | Additional containers added to the cilium DaemonSet. | +| extraEnv | list | `[]` | Additional agent container environment variables. | +| extraHostPathMounts | list | `[]` | Additional agent hostPath mounts. | +| extraVolumeMounts | list | `[]` | Additional agent volumeMounts. | +| extraVolumes | list | `[]` | Additional agent volumes. | +| gatewayAPI.enabled | bool | `false` | Enable support for Gateway API in cilium This will automatically set enable-envoy-config as well. | +| gatewayAPI.secretsNamespace | object | `{"create":true,"name":"cilium-secrets","sync":true}` | SecretsNamespace is the namespace in which envoy SDS will retrieve TLS secrets from. | +| gatewayAPI.secretsNamespace.create | bool | `true` | Create secrets namespace for Gateway API. | +| gatewayAPI.secretsNamespace.name | string | `"cilium-secrets"` | Name of Gateway API secret namespace. | +| gatewayAPI.secretsNamespace.sync | bool | `true` | Enable secret sync, which will make sure all TLS secrets used by Ingress are synced to secretsNamespace.name. If disabled, TLS secrets must be maintained externally. | +| gke.enabled | bool | `false` | Enable Google Kubernetes Engine integration | +| healthChecking | bool | `true` | Enable connectivity health checking. | +| healthPort | int | `9879` | TCP port for the agent health API. This is not the port for cilium-health. | +| highScaleIPcache | object | `{"enabled":false}` | EnableHighScaleIPcache enables the special ipcache mode for high scale clusters. The ipcache content will be reduced to the strict minimum and traffic will be encapsulated to carry security identities. | +| highScaleIPcache.enabled | bool | `false` | Enable the high scale mode for the ipcache. | +| hostFirewall | object | `{"enabled":false}` | Configure the host firewall. | +| hostFirewall.enabled | bool | `false` | Enables the enforcement of host policies in the eBPF datapath. | +| hostPort.enabled | bool | `false` | Enable hostPort service support. | +| hubble.enabled | bool | `true` | Enable Hubble (true by default). | +| hubble.listenAddress | string | `":4244"` | An additional address for Hubble to listen to. Set this field ":4244" if you are enabling Hubble Relay, as it assumes that Hubble is listening on port 4244. | +| hubble.metrics | object | `{"dashboards":{"annotations":{},"enabled":false,"label":"grafana_dashboard","labelValue":"1","namespace":null},"enableOpenMetrics":false,"enabled":null,"port":9965,"serviceAnnotations":{},"serviceMonitor":{"annotations":{},"enabled":false,"interval":"10s","labels":{},"metricRelabelings":null,"relabelings":[{"replacement":"${1}","sourceLabels":["__meta_kubernetes_pod_node_name"],"targetLabel":"node"}]}}` | Hubble metrics configuration. See https://docs.cilium.io/en/stable/observability/metrics/#hubble-metrics for more comprehensive documentation about Hubble metrics. | +| hubble.metrics.dashboards | object | `{"annotations":{},"enabled":false,"label":"grafana_dashboard","labelValue":"1","namespace":null}` | Grafana dashboards for hubble grafana can import dashboards based on the label and value ref: https://github.com/grafana/helm-charts/tree/main/charts/grafana#sidecar-for-dashboards | +| hubble.metrics.enableOpenMetrics | bool | `false` | Enables exporting hubble metrics in OpenMetrics format. | +| hubble.metrics.enabled | string | `nil` | Configures the list of metrics to collect. If empty or null, metrics are disabled. Example: enabled: - dns:query;ignoreAAAA - drop - tcp - flow - icmp - http You can specify the list of metrics from the helm CLI: --set metrics.enabled="{dns:query;ignoreAAAA,drop,tcp,flow,icmp,http}" | +| hubble.metrics.port | int | `9965` | Configure the port the hubble metric server listens on. | +| hubble.metrics.serviceAnnotations | object | `{}` | Annotations to be added to hubble-metrics service. | +| hubble.metrics.serviceMonitor.annotations | object | `{}` | Annotations to add to ServiceMonitor hubble | +| hubble.metrics.serviceMonitor.enabled | bool | `false` | Create ServiceMonitor resources for Prometheus Operator. This requires the prometheus CRDs to be available. ref: https://github.com/prometheus-operator/prometheus-operator/blob/main/example/prometheus-operator-crd/monitoring.coreos.com_servicemonitors.yaml) | +| hubble.metrics.serviceMonitor.interval | string | `"10s"` | Interval for scrape metrics. | +| hubble.metrics.serviceMonitor.labels | object | `{}` | Labels to add to ServiceMonitor hubble | +| hubble.metrics.serviceMonitor.metricRelabelings | string | `nil` | Metrics relabeling configs for the ServiceMonitor hubble | +| hubble.metrics.serviceMonitor.relabelings | list | `[{"replacement":"${1}","sourceLabels":["__meta_kubernetes_pod_node_name"],"targetLabel":"node"}]` | Relabeling configs for the ServiceMonitor hubble | +| hubble.peerService.clusterDomain | string | `"cluster.local"` | The cluster domain to use to query the Hubble Peer service. It should be the local cluster. | +| hubble.peerService.targetPort | int | `4244` | Target Port for the Peer service, must match the hubble.listenAddress' port. | +| hubble.preferIpv6 | bool | `false` | Whether Hubble should prefer to announce IPv6 or IPv4 addresses if both are available. | +| hubble.relay.affinity | object | `{"podAffinity":{"requiredDuringSchedulingIgnoredDuringExecution":[{"labelSelector":{"matchLabels":{"k8s-app":"cilium"}},"topologyKey":"kubernetes.io/hostname"}]}}` | Affinity for hubble-replay | +| hubble.relay.dialTimeout | string | `nil` | Dial timeout to connect to the local hubble instance to receive peer information (e.g. "30s"). | +| hubble.relay.enabled | bool | `false` | Enable Hubble Relay (requires hubble.enabled=true) | +| hubble.relay.extraEnv | list | `[]` | Additional hubble-relay environment variables. | +| hubble.relay.extraVolumeMounts | list | `[]` | Additional hubble-relay volumeMounts. | +| hubble.relay.extraVolumes | list | `[]` | Additional hubble-relay volumes. | +| hubble.relay.gops.enabled | bool | `true` | Enable gops for hubble-relay | +| hubble.relay.gops.port | int | `9893` | Configure gops listen port for hubble-relay | +| hubble.relay.image | object | `{"digest":"sha256:dbef89f924a927043d02b40c18e417c1ea0e8f58b44523b80fef7e3652db24d4","override":null,"pullPolicy":"IfNotPresent","repository":"quay.io/cilium/hubble-relay","tag":"v1.14.5","useDigest":true}` | Hubble-relay container image. | +| hubble.relay.listenHost | string | `""` | Host to listen to. Specify an empty string to bind to all the interfaces. | +| hubble.relay.listenPort | string | `"4245"` | Port to listen to. | +| hubble.relay.nodeSelector | object | `{"kubernetes.io/os":"linux"}` | Node labels for pod assignment ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#nodeselector | +| hubble.relay.podAnnotations | object | `{}` | Annotations to be added to hubble-relay pods | +| hubble.relay.podDisruptionBudget.enabled | bool | `false` | enable PodDisruptionBudget ref: https://kubernetes.io/docs/concepts/workloads/pods/disruptions/ | +| hubble.relay.podDisruptionBudget.maxUnavailable | int | `1` | Maximum number/percentage of pods that may be made unavailable | +| hubble.relay.podDisruptionBudget.minAvailable | string | `nil` | Minimum number/percentage of pods that should remain scheduled. When it's set, maxUnavailable must be disabled by `maxUnavailable: null` | +| hubble.relay.podLabels | object | `{}` | Labels to be added to hubble-relay pods | +| hubble.relay.podSecurityContext | object | `{"fsGroup":65532}` | hubble-relay pod security context | +| hubble.relay.pprof.address | string | `"localhost"` | Configure pprof listen address for hubble-relay | +| hubble.relay.pprof.enabled | bool | `false` | Enable pprof for hubble-relay | +| hubble.relay.pprof.port | int | `6062` | Configure pprof listen port for hubble-relay | +| hubble.relay.priorityClassName | string | `""` | The priority class to use for hubble-relay | +| hubble.relay.prometheus | object | `{"enabled":false,"port":9966,"serviceMonitor":{"annotations":{},"enabled":false,"interval":"10s","labels":{},"metricRelabelings":null,"relabelings":null}}` | Enable prometheus metrics for hubble-relay on the configured port at /metrics | +| hubble.relay.prometheus.serviceMonitor.annotations | object | `{}` | Annotations to add to ServiceMonitor hubble-relay | +| hubble.relay.prometheus.serviceMonitor.enabled | bool | `false` | Enable service monitors. This requires the prometheus CRDs to be available (see https://github.com/prometheus-operator/prometheus-operator/blob/main/example/prometheus-operator-crd/monitoring.coreos.com_servicemonitors.yaml) | +| hubble.relay.prometheus.serviceMonitor.interval | string | `"10s"` | Interval for scrape metrics. | +| hubble.relay.prometheus.serviceMonitor.labels | object | `{}` | Labels to add to ServiceMonitor hubble-relay | +| hubble.relay.prometheus.serviceMonitor.metricRelabelings | string | `nil` | Metrics relabeling configs for the ServiceMonitor hubble-relay | +| hubble.relay.prometheus.serviceMonitor.relabelings | string | `nil` | Relabeling configs for the ServiceMonitor hubble-relay | +| hubble.relay.replicas | int | `1` | Number of replicas run for the hubble-relay deployment. | +| hubble.relay.resources | object | `{}` | Specifies the resources for the hubble-relay pods | +| hubble.relay.retryTimeout | string | `nil` | Backoff duration to retry connecting to the local hubble instance in case of failure (e.g. "30s"). | +| hubble.relay.rollOutPods | bool | `false` | Roll out Hubble Relay pods automatically when configmap is updated. | +| hubble.relay.securityContext | object | `{"capabilities":{"drop":["ALL"]},"runAsGroup":65532,"runAsNonRoot":true,"runAsUser":65532}` | hubble-relay container security context | +| hubble.relay.service | object | `{"nodePort":31234,"type":"ClusterIP"}` | hubble-relay service configuration. | +| hubble.relay.service.nodePort | int | `31234` | - The port to use when the service type is set to NodePort. | +| hubble.relay.service.type | string | `"ClusterIP"` | - The type of service used for Hubble Relay access, either ClusterIP or NodePort. | +| hubble.relay.sortBufferDrainTimeout | string | `nil` | When the per-request flows sort buffer is not full, a flow is drained every time this timeout is reached (only affects requests in follow-mode) (e.g. "1s"). | +| hubble.relay.sortBufferLenMax | string | `nil` | Max number of flows that can be buffered for sorting before being sent to the client (per request) (e.g. 100). | +| hubble.relay.terminationGracePeriodSeconds | int | `1` | Configure termination grace period for hubble relay Deployment. | +| hubble.relay.tls | object | `{"client":{"cert":"","key":""},"server":{"cert":"","enabled":false,"extraDnsNames":[],"extraIpAddresses":[],"key":"","mtls":false}}` | TLS configuration for Hubble Relay | +| hubble.relay.tls.client | object | `{"cert":"","key":""}` | base64 encoded PEM values for the hubble-relay client certificate and private key This keypair is presented to Hubble server instances for mTLS authentication and is required when hubble.tls.enabled is true. These values need to be set manually if hubble.tls.auto.enabled is false. | +| hubble.relay.tls.server | object | `{"cert":"","enabled":false,"extraDnsNames":[],"extraIpAddresses":[],"key":"","mtls":false}` | base64 encoded PEM values for the hubble-relay server certificate and private key | +| hubble.relay.tls.server.extraDnsNames | list | `[]` | extra DNS names added to certificate when its auto gen | +| hubble.relay.tls.server.extraIpAddresses | list | `[]` | extra IP addresses added to certificate when its auto gen | +| hubble.relay.tolerations | list | `[]` | Node tolerations for pod assignment on nodes with taints ref: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/ | +| hubble.relay.topologySpreadConstraints | list | `[]` | Pod topology spread constraints for hubble-relay | +| hubble.relay.updateStrategy | object | `{"rollingUpdate":{"maxUnavailable":1},"type":"RollingUpdate"}` | hubble-relay update strategy | +| hubble.skipUnknownCGroupIDs | bool | `true` | Skip Hubble events with unknown cgroup ids | +| hubble.socketPath | string | `"/var/run/cilium/hubble.sock"` | Unix domain socket path to listen to when Hubble is enabled. | +| hubble.tls | object | `{"auto":{"certManagerIssuerRef":{},"certValidityDuration":1095,"enabled":true,"method":"helm","schedule":"0 0 1 */4 *"},"enabled":true,"server":{"cert":"","extraDnsNames":[],"extraIpAddresses":[],"key":""}}` | TLS configuration for Hubble | +| hubble.tls.auto | object | `{"certManagerIssuerRef":{},"certValidityDuration":1095,"enabled":true,"method":"helm","schedule":"0 0 1 */4 *"}` | Configure automatic TLS certificates generation. | +| hubble.tls.auto.certManagerIssuerRef | object | `{}` | certmanager issuer used when hubble.tls.auto.method=certmanager. | +| hubble.tls.auto.certValidityDuration | int | `1095` | Generated certificates validity duration in days. | +| hubble.tls.auto.enabled | bool | `true` | Auto-generate certificates. When set to true, automatically generate a CA and certificates to enable mTLS between Hubble server and Hubble Relay instances. If set to false, the certs for Hubble server need to be provided by setting appropriate values below. | +| hubble.tls.auto.method | string | `"helm"` | Set the method to auto-generate certificates. Supported values: - helm: This method uses Helm to generate all certificates. - cronJob: This method uses a Kubernetes CronJob the generate any certificates not provided by the user at installation time. - certmanager: This method use cert-manager to generate & rotate certificates. | +| hubble.tls.auto.schedule | string | `"0 0 1 */4 *"` | Schedule for certificates regeneration (regardless of their expiration date). Only used if method is "cronJob". If nil, then no recurring job will be created. Instead, only the one-shot job is deployed to generate the certificates at installation time. Defaults to midnight of the first day of every fourth month. For syntax, see https://kubernetes.io/docs/concepts/workloads/controllers/cron-jobs/#schedule-syntax | +| hubble.tls.enabled | bool | `true` | Enable mutual TLS for listenAddress. Setting this value to false is highly discouraged as the Hubble API provides access to potentially sensitive network flow metadata and is exposed on the host network. | +| hubble.tls.server | object | `{"cert":"","extraDnsNames":[],"extraIpAddresses":[],"key":""}` | base64 encoded PEM values for the Hubble server certificate and private key | +| hubble.tls.server.extraDnsNames | list | `[]` | Extra DNS names added to certificate when it's auto generated | +| hubble.tls.server.extraIpAddresses | list | `[]` | Extra IP addresses added to certificate when it's auto generated | +| hubble.ui.affinity | object | `{}` | Affinity for hubble-ui | +| hubble.ui.backend.extraEnv | list | `[]` | Additional hubble-ui backend environment variables. | +| hubble.ui.backend.extraVolumeMounts | list | `[]` | Additional hubble-ui backend volumeMounts. | +| hubble.ui.backend.extraVolumes | list | `[]` | Additional hubble-ui backend volumes. | +| hubble.ui.backend.image | object | `{"digest":"sha256:1f86f3400827a0451e6332262467f894eeb7caf0eb8779bd951e2caa9d027cbe","override":null,"pullPolicy":"IfNotPresent","repository":"quay.io/cilium/hubble-ui-backend","tag":"v0.12.1","useDigest":true}` | Hubble-ui backend image. | +| hubble.ui.backend.resources | object | `{}` | Resource requests and limits for the 'backend' container of the 'hubble-ui' deployment. | +| hubble.ui.backend.securityContext | object | `{}` | Hubble-ui backend security context. | +| hubble.ui.baseUrl | string | `"/"` | Defines base url prefix for all hubble-ui http requests. It needs to be changed in case if ingress for hubble-ui is configured under some sub-path. Trailing `/` is required for custom path, ex. `/service-map/` | +| hubble.ui.enabled | bool | `false` | Whether to enable the Hubble UI. | +| hubble.ui.frontend.extraEnv | list | `[]` | Additional hubble-ui frontend environment variables. | +| hubble.ui.frontend.extraVolumeMounts | list | `[]` | Additional hubble-ui frontend volumeMounts. | +| hubble.ui.frontend.extraVolumes | list | `[]` | Additional hubble-ui frontend volumes. | +| hubble.ui.frontend.image | object | `{"digest":"sha256:9e5f81ee747866480ea1ac4630eb6975ff9227f9782b7c93919c081c33f38267","override":null,"pullPolicy":"IfNotPresent","repository":"quay.io/cilium/hubble-ui","tag":"v0.12.1","useDigest":true}` | Hubble-ui frontend image. | +| hubble.ui.frontend.resources | object | `{}` | Resource requests and limits for the 'frontend' container of the 'hubble-ui' deployment. | +| hubble.ui.frontend.securityContext | object | `{}` | Hubble-ui frontend security context. | +| hubble.ui.frontend.server.ipv6 | object | `{"enabled":true}` | Controls server listener for ipv6 | +| hubble.ui.ingress | object | `{"annotations":{},"className":"","enabled":false,"hosts":["chart-example.local"],"labels":{},"tls":[]}` | hubble-ui ingress configuration. | +| hubble.ui.nodeSelector | object | `{"kubernetes.io/os":"linux"}` | Node labels for pod assignment ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#nodeselector | +| hubble.ui.podAnnotations | object | `{}` | Annotations to be added to hubble-ui pods | +| hubble.ui.podDisruptionBudget.enabled | bool | `false` | enable PodDisruptionBudget ref: https://kubernetes.io/docs/concepts/workloads/pods/disruptions/ | +| hubble.ui.podDisruptionBudget.maxUnavailable | int | `1` | Maximum number/percentage of pods that may be made unavailable | +| hubble.ui.podDisruptionBudget.minAvailable | string | `nil` | Minimum number/percentage of pods that should remain scheduled. When it's set, maxUnavailable must be disabled by `maxUnavailable: null` | +| hubble.ui.podLabels | object | `{}` | Labels to be added to hubble-ui pods | +| hubble.ui.priorityClassName | string | `""` | The priority class to use for hubble-ui | +| hubble.ui.replicas | int | `1` | The number of replicas of Hubble UI to deploy. | +| hubble.ui.rollOutPods | bool | `false` | Roll out Hubble-ui pods automatically when configmap is updated. | +| hubble.ui.securityContext | object | `{"fsGroup":1001,"runAsGroup":1001,"runAsUser":1001}` | Security context to be added to Hubble UI pods | +| hubble.ui.service | object | `{"annotations":{},"nodePort":31235,"type":"ClusterIP"}` | hubble-ui service configuration. | +| hubble.ui.service.annotations | object | `{}` | Annotations to be added for the Hubble UI service | +| hubble.ui.service.nodePort | int | `31235` | - The port to use when the service type is set to NodePort. | +| hubble.ui.service.type | string | `"ClusterIP"` | - The type of service used for Hubble UI access, either ClusterIP or NodePort. | +| hubble.ui.standalone.enabled | bool | `false` | When true, it will allow installing the Hubble UI only, without checking dependencies. It is useful if a cluster already has cilium and Hubble relay installed and you just want Hubble UI to be deployed. When installed via helm, installing UI should be done via `helm upgrade` and when installed via the cilium cli, then `cilium hubble enable --ui` | +| hubble.ui.standalone.tls.certsVolume | object | `{}` | When deploying Hubble UI in standalone, with tls enabled for Hubble relay, it is required to provide a volume for mounting the client certificates. | +| hubble.ui.tls.client | object | `{"cert":"","key":""}` | base64 encoded PEM values used to connect to hubble-relay This keypair is presented to Hubble Relay instances for mTLS authentication and is required when hubble.relay.tls.server.enabled is true. These values need to be set manually if hubble.tls.auto.enabled is false. | +| hubble.ui.tolerations | list | `[]` | Node tolerations for pod assignment on nodes with taints ref: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/ | +| hubble.ui.topologySpreadConstraints | list | `[]` | Pod topology spread constraints for hubble-ui | +| hubble.ui.updateStrategy | object | `{"rollingUpdate":{"maxUnavailable":1},"type":"RollingUpdate"}` | hubble-ui update strategy. | +| identityAllocationMode | string | `"crd"` | Method to use for identity allocation (`crd` or `kvstore`). | +| identityChangeGracePeriod | string | `"5s"` | Time to wait before using new identity on endpoint identity change. | +| image | object | `{"digest":"sha256:d3b287029755b6a47dee01420e2ea469469f1b174a2089c10af7e5e9289ef05b","override":null,"pullPolicy":"IfNotPresent","repository":"quay.io/cilium/cilium","tag":"v1.14.5","useDigest":true}` | Agent container image. | +| imagePullSecrets | string | `nil` | Configure image pull secrets for pulling container images | +| ingressController.default | bool | `false` | Set cilium ingress controller to be the default ingress controller This will let cilium ingress controller route entries without ingress class set | +| ingressController.defaultSecretName | string | `nil` | Default secret name for ingresses without .spec.tls[].secretName set. | +| ingressController.defaultSecretNamespace | string | `nil` | Default secret namespace for ingresses without .spec.tls[].secretName set. | +| ingressController.enabled | bool | `false` | Enable cilium ingress controller This will automatically set enable-envoy-config as well. | +| ingressController.enforceHttps | bool | `true` | Enforce https for host having matching TLS host in Ingress. Incoming traffic to http listener will return 308 http error code with respective location in header. | +| ingressController.ingressLBAnnotationPrefixes | list | `["service.beta.kubernetes.io","service.kubernetes.io","cloud.google.com"]` | IngressLBAnnotations are the annotation prefixes, which are used to filter annotations to propagate from Ingress to the Load Balancer service | +| ingressController.loadbalancerMode | string | `"dedicated"` | Default ingress load balancer mode Supported values: shared, dedicated For granular control, use the following annotations on the ingress resource ingress.cilium.io/loadbalancer-mode: shared|dedicated, | +| ingressController.secretsNamespace | object | `{"create":true,"name":"cilium-secrets","sync":true}` | SecretsNamespace is the namespace in which envoy SDS will retrieve TLS secrets from. | +| ingressController.secretsNamespace.create | bool | `true` | Create secrets namespace for Ingress. | +| ingressController.secretsNamespace.name | string | `"cilium-secrets"` | Name of Ingress secret namespace. | +| ingressController.secretsNamespace.sync | bool | `true` | Enable secret sync, which will make sure all TLS secrets used by Ingress are synced to secretsNamespace.name. If disabled, TLS secrets must be maintained externally. | +| ingressController.service | object | `{"allocateLoadBalancerNodePorts":null,"annotations":{},"insecureNodePort":null,"labels":{},"loadBalancerClass":null,"loadBalancerIP":null,"name":"cilium-ingress","secureNodePort":null,"type":"LoadBalancer"}` | Load-balancer service in shared mode. This is a single load-balancer service for all Ingress resources. | +| ingressController.service.allocateLoadBalancerNodePorts | string | `nil` | Configure if node port allocation is required for LB service ref: https://kubernetes.io/docs/concepts/services-networking/service/#load-balancer-nodeport-allocation | +| ingressController.service.annotations | object | `{}` | Annotations to be added for the shared LB service | +| ingressController.service.insecureNodePort | string | `nil` | Configure a specific nodePort for insecure HTTP traffic on the shared LB service | +| ingressController.service.labels | object | `{}` | Labels to be added for the shared LB service | +| ingressController.service.loadBalancerClass | string | `nil` | Configure a specific loadBalancerClass on the shared LB service (requires Kubernetes 1.24+) | +| ingressController.service.loadBalancerIP | string | `nil` | Configure a specific loadBalancerIP on the shared LB service | +| ingressController.service.name | string | `"cilium-ingress"` | Service name | +| ingressController.service.secureNodePort | string | `nil` | Configure a specific nodePort for secure HTTPS traffic on the shared LB service | +| ingressController.service.type | string | `"LoadBalancer"` | Service type for the shared LB service | +| initResources | object | `{}` | resources & limits for the agent init containers | +| installNoConntrackIptablesRules | bool | `false` | Install Iptables rules to skip netfilter connection tracking on all pod traffic. This option is only effective when Cilium is running in direct routing and full KPR mode. Moreover, this option cannot be enabled when Cilium is running in a managed Kubernetes environment or in a chained CNI setup. | +| ipMasqAgent | object | `{"enabled":false}` | Configure the eBPF-based ip-masq-agent | +| ipam.ciliumNodeUpdateRate | string | `"15s"` | Maximum rate at which the CiliumNode custom resource is updated. | +| ipam.mode | string | `"cluster-pool"` | Configure IP Address Management mode. ref: https://docs.cilium.io/en/stable/network/concepts/ipam/ | +| ipam.operator.autoCreateCiliumPodIPPools | object | `{}` | IP pools to auto-create in multi-pool IPAM mode. | +| ipam.operator.clusterPoolIPv4MaskSize | int | `24` | IPv4 CIDR mask size to delegate to individual nodes for IPAM. | +| ipam.operator.clusterPoolIPv4PodCIDRList | list | `["10.0.0.0/8"]` | IPv4 CIDR list range to delegate to individual nodes for IPAM. | +| ipam.operator.clusterPoolIPv6MaskSize | int | `120` | IPv6 CIDR mask size to delegate to individual nodes for IPAM. | +| ipam.operator.clusterPoolIPv6PodCIDRList | list | `["fd00::/104"]` | IPv6 CIDR list range to delegate to individual nodes for IPAM. | +| ipam.operator.externalAPILimitBurstSize | string | `20` | The maximum burst size when rate limiting access to external APIs. Also known as the token bucket capacity. | +| ipam.operator.externalAPILimitQPS | string | `4.0` | The maximum queries per second when rate limiting access to external APIs. Also known as the bucket refill rate, which is used to refill the bucket up to the burst size capacity. | +| ipv4.enabled | bool | `true` | Enable IPv4 support. | +| ipv4NativeRoutingCIDR | string | `""` | Allows to explicitly specify the IPv4 CIDR for native routing. When specified, Cilium assumes networking for this CIDR is preconfigured and hands traffic destined for that range to the Linux network stack without applying any SNAT. Generally speaking, specifying a native routing CIDR implies that Cilium can depend on the underlying networking stack to route packets to their destination. To offer a concrete example, if Cilium is configured to use direct routing and the Kubernetes CIDR is included in the native routing CIDR, the user must configure the routes to reach pods, either manually or by setting the auto-direct-node-routes flag. | +| ipv6.enabled | bool | `false` | Enable IPv6 support. | +| ipv6NativeRoutingCIDR | string | `""` | Allows to explicitly specify the IPv6 CIDR for native routing. When specified, Cilium assumes networking for this CIDR is preconfigured and hands traffic destined for that range to the Linux network stack without applying any SNAT. Generally speaking, specifying a native routing CIDR implies that Cilium can depend on the underlying networking stack to route packets to their destination. To offer a concrete example, if Cilium is configured to use direct routing and the Kubernetes CIDR is included in the native routing CIDR, the user must configure the routes to reach pods, either manually or by setting the auto-direct-node-routes flag. | +| k8s | object | `{}` | Configure Kubernetes specific configuration | +| k8sClientRateLimit | object | `{"burst":10,"qps":5}` | Configure the client side rate limit for the agent and operator If the amount of requests to the Kubernetes API server exceeds the configured rate limit, the agent and operator will start to throttle requests by delaying them until there is budget or the request times out. | +| k8sClientRateLimit.burst | int | `10` | The burst request rate in requests per second. The rate limiter will allow short bursts with a higher rate. | +| k8sClientRateLimit.qps | int | `5` | The sustained request rate in requests per second. | +| k8sNetworkPolicy.enabled | bool | `true` | Enable support for K8s NetworkPolicy | +| k8sServiceHost | string | `""` | Kubernetes service host | +| k8sServicePort | string | `""` | Kubernetes service port | +| keepDeprecatedLabels | bool | `false` | Keep the deprecated selector labels when deploying Cilium DaemonSet. | +| keepDeprecatedProbes | bool | `false` | Keep the deprecated probes when deploying Cilium DaemonSet | +| kubeConfigPath | string | `"~/.kube/config"` | Kubernetes config path | +| kubeProxyReplacementHealthzBindAddr | string | `""` | healthz server bind address for the kube-proxy replacement. To enable set the value to '0.0.0.0:10256' for all ipv4 addresses and this '[::]:10256' for all ipv6 addresses. By default it is disabled. | +| l2NeighDiscovery.enabled | bool | `true` | Enable L2 neighbor discovery in the agent | +| l2NeighDiscovery.refreshPeriod | string | `"30s"` | Override the agent's default neighbor resolution refresh period. | +| l2announcements | object | `{"enabled":false}` | Configure L2 announcements | +| l2announcements.enabled | bool | `false` | Enable L2 announcements | +| l2podAnnouncements | object | `{"enabled":false,"interface":"eth0"}` | Configure L2 pod announcements | +| l2podAnnouncements.enabled | bool | `false` | Enable L2 pod announcements | +| l2podAnnouncements.interface | string | `"eth0"` | Interface used for sending Gratuitous ARP pod announcements | +| l7Proxy | bool | `true` | Enable Layer 7 network policy. | +| livenessProbe.failureThreshold | int | `10` | failure threshold of liveness probe | +| livenessProbe.periodSeconds | int | `30` | interval between checks of the liveness probe | +| loadBalancer | object | `{"l7":{"algorithm":"round_robin","backend":"disabled","ports":[]}}` | Configure service load balancing | +| loadBalancer.l7 | object | `{"algorithm":"round_robin","backend":"disabled","ports":[]}` | L7 LoadBalancer | +| loadBalancer.l7.algorithm | string | `"round_robin"` | Default LB algorithm The default LB algorithm to be used for services, which can be overridden by the service annotation (e.g. service.cilium.io/lb-l7-algorithm) Applicable values: round_robin, least_request, random | +| loadBalancer.l7.backend | string | `"disabled"` | Enable L7 service load balancing via envoy proxy. The request to a k8s service, which has specific annotation e.g. service.cilium.io/lb-l7, will be forwarded to the local backend proxy to be load balanced to the service endpoints. Please refer to docs for supported annotations for more configuration. Applicable values: - envoy: Enable L7 load balancing via envoy proxy. This will automatically set enable-envoy-config as well. - disabled: Disable L7 load balancing by way of service annotation. | +| loadBalancer.l7.ports | list | `[]` | List of ports from service to be automatically redirected to above backend. Any service exposing one of these ports will be automatically redirected. Fine-grained control can be achieved by using the service annotation. | +| localRedirectPolicy | bool | `false` | Enable Local Redirect Policy. | +| logSystemLoad | bool | `false` | Enables periodic logging of system load | +| maglev | object | `{}` | Configure maglev consistent hashing | +| monitor | object | `{"enabled":false}` | cilium-monitor sidecar. | +| monitor.enabled | bool | `false` | Enable the cilium-monitor sidecar. | +| name | string | `"cilium"` | Agent container name. | +| nat46x64Gateway | object | `{"enabled":false}` | Configure standalone NAT46/NAT64 gateway | +| nat46x64Gateway.enabled | bool | `false` | Enable RFC8215-prefixed translation | +| nodePort | object | `{"autoProtectPortRange":true,"bindProtection":true,"enableHealthCheck":true,"enabled":false}` | Configure N-S k8s service loadbalancing | +| nodePort.autoProtectPortRange | bool | `true` | Append NodePort range to ip_local_reserved_ports if clash with ephemeral ports is detected. | +| nodePort.bindProtection | bool | `true` | Set to true to prevent applications binding to service ports. | +| nodePort.enableHealthCheck | bool | `true` | Enable healthcheck nodePort server for NodePort services | +| nodePort.enabled | bool | `false` | Enable the Cilium NodePort service implementation. | +| nodeSelector | object | `{"kubernetes.io/os":"linux"}` | Node selector for cilium-agent. | +| nodeinit.affinity | object | `{}` | Affinity for cilium-nodeinit | +| nodeinit.bootstrapFile | string | `"/tmp/cilium-bootstrap.d/cilium-bootstrap-time"` | bootstrapFile is the location of the file where the bootstrap timestamp is written by the node-init DaemonSet | +| nodeinit.enabled | bool | `false` | Enable the node initialization DaemonSet | +| nodeinit.extraEnv | list | `[]` | Additional nodeinit environment variables. | +| nodeinit.extraVolumeMounts | list | `[]` | Additional nodeinit volumeMounts. | +| nodeinit.extraVolumes | list | `[]` | Additional nodeinit volumes. | +| nodeinit.image | object | `{"override":null,"pullPolicy":"IfNotPresent","repository":"quay.io/cilium/startup-script","tag":"62093c5c233ea914bfa26a10ba41f8780d9b737f"}` | node-init image. | +| nodeinit.nodeSelector | object | `{"kubernetes.io/os":"linux"}` | Node labels for nodeinit pod assignment ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#nodeselector | +| nodeinit.podAnnotations | object | `{}` | Annotations to be added to node-init pods. | +| nodeinit.podLabels | object | `{}` | Labels to be added to node-init pods. | +| nodeinit.prestop | object | `{"postScript":"","preScript":""}` | prestop offers way to customize prestop nodeinit script (pre and post position) | +| nodeinit.priorityClassName | string | `""` | The priority class to use for the nodeinit pod. | +| nodeinit.resources | object | `{"requests":{"cpu":"100m","memory":"100Mi"}}` | nodeinit resource limits & requests ref: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ | +| nodeinit.securityContext | object | `{"capabilities":{"add":["SYS_MODULE","NET_ADMIN","SYS_ADMIN","SYS_CHROOT","SYS_PTRACE"]},"privileged":false,"seLinuxOptions":{"level":"s0","type":"spc_t"}}` | Security context to be added to nodeinit pods. | +| nodeinit.startup | object | `{"postScript":"","preScript":""}` | startup offers way to customize startup nodeinit script (pre and post position) | +| nodeinit.tolerations | list | `[{"operator":"Exists"}]` | Node tolerations for nodeinit scheduling to nodes with taints ref: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/ | +| nodeinit.updateStrategy | object | `{"type":"RollingUpdate"}` | node-init update strategy | +| operator.affinity | object | `{"podAntiAffinity":{"requiredDuringSchedulingIgnoredDuringExecution":[{"labelSelector":{"matchLabels":{"io.cilium/app":"operator"}},"topologyKey":"kubernetes.io/hostname"}]}}` | Affinity for cilium-operator | +| operator.dashboards | object | `{"annotations":{},"enabled":false,"label":"grafana_dashboard","labelValue":"1","namespace":null}` | Grafana dashboards for cilium-operator grafana can import dashboards based on the label and value ref: https://github.com/grafana/helm-charts/tree/main/charts/grafana#sidecar-for-dashboards | +| operator.dnsPolicy | string | `""` | DNS policy for Cilium operator pods. Ref: https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-s-dns-policy | +| operator.enabled | bool | `true` | Enable the cilium-operator component (required). | +| operator.endpointGCInterval | string | `"5m0s"` | Interval for endpoint garbage collection. | +| operator.extraArgs | list | `[]` | Additional cilium-operator container arguments. | +| operator.extraEnv | list | `[]` | Additional cilium-operator environment variables. | +| operator.extraHostPathMounts | list | `[]` | Additional cilium-operator hostPath mounts. | +| operator.extraVolumeMounts | list | `[]` | Additional cilium-operator volumeMounts. | +| operator.extraVolumes | list | `[]` | Additional cilium-operator volumes. | +| operator.identityGCInterval | string | `"15m0s"` | Interval for identity garbage collection. | +| operator.identityHeartbeatTimeout | string | `"30m0s"` | Timeout for identity heartbeats. | +| operator.image | object | `{"alibabacloudDigest":"sha256:e0152c498ba73c56a82eee2a706c8f400e9a6999c665af31a935bdf08e659bc3","awsDigest":"sha256:785ccf1267d0ed3ba9e4bd8166577cb4f9e4ce996af26b27c9d5c554a0d5b09a","azureDigest":"sha256:9203f5583aa34e716d7a6588ebd144e43ce3b77873f578fc12b2679e33591353","genericDigest":"sha256:303f9076bdc73b3fc32aaedee64a14f6f44c8bb08ee9e3956d443021103ebe7a","override":null,"pullPolicy":"IfNotPresent","repository":"quay.io/cilium/operator","suffix":"","tag":"v1.14.5","useDigest":true}` | cilium-operator image. | +| operator.nodeGCInterval | string | `"5m0s"` | Interval for cilium node garbage collection. | +| operator.nodeSelector | object | `{"kubernetes.io/os":"linux"}` | Node labels for cilium-operator pod assignment ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#nodeselector | +| operator.podAnnotations | object | `{}` | Annotations to be added to cilium-operator pods | +| operator.podDisruptionBudget.enabled | bool | `false` | enable PodDisruptionBudget ref: https://kubernetes.io/docs/concepts/workloads/pods/disruptions/ | +| operator.podDisruptionBudget.maxUnavailable | int | `1` | Maximum number/percentage of pods that may be made unavailable | +| operator.podDisruptionBudget.minAvailable | string | `nil` | Minimum number/percentage of pods that should remain scheduled. When it's set, maxUnavailable must be disabled by `maxUnavailable: null` | +| operator.podLabels | object | `{}` | Labels to be added to cilium-operator pods | +| operator.podSecurityContext | object | `{}` | Security context to be added to cilium-operator pods | +| operator.pprof.address | string | `"localhost"` | Configure pprof listen address for cilium-operator | +| operator.pprof.enabled | bool | `false` | Enable pprof for cilium-operator | +| operator.pprof.port | int | `6061` | Configure pprof listen port for cilium-operator | +| operator.priorityClassName | string | `""` | The priority class to use for cilium-operator | +| operator.prometheus | object | `{"enabled":false,"port":9963,"serviceMonitor":{"annotations":{},"enabled":false,"interval":"10s","labels":{},"metricRelabelings":null,"relabelings":null}}` | Enable prometheus metrics for cilium-operator on the configured port at /metrics | +| operator.prometheus.serviceMonitor.annotations | object | `{}` | Annotations to add to ServiceMonitor cilium-operator | +| operator.prometheus.serviceMonitor.enabled | bool | `false` | Enable service monitors. This requires the prometheus CRDs to be available (see https://github.com/prometheus-operator/prometheus-operator/blob/main/example/prometheus-operator-crd/monitoring.coreos.com_servicemonitors.yaml) | +| operator.prometheus.serviceMonitor.interval | string | `"10s"` | Interval for scrape metrics. | +| operator.prometheus.serviceMonitor.labels | object | `{}` | Labels to add to ServiceMonitor cilium-operator | +| operator.prometheus.serviceMonitor.metricRelabelings | string | `nil` | Metrics relabeling configs for the ServiceMonitor cilium-operator | +| operator.prometheus.serviceMonitor.relabelings | string | `nil` | Relabeling configs for the ServiceMonitor cilium-operator | +| operator.removeNodeTaints | bool | `true` | Remove Cilium node taint from Kubernetes nodes that have a healthy Cilium pod running. | +| operator.replicas | int | `2` | Number of replicas to run for the cilium-operator deployment | +| operator.resources | object | `{}` | cilium-operator resource limits & requests ref: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ | +| operator.rollOutPods | bool | `false` | Roll out cilium-operator pods automatically when configmap is updated. | +| operator.securityContext | object | `{}` | Security context to be added to cilium-operator pods | +| operator.setNodeNetworkStatus | bool | `true` | Set Node condition NetworkUnavailable to 'false' with the reason 'CiliumIsUp' for nodes that have a healthy Cilium pod. | +| operator.setNodeTaints | string | same as removeNodeTaints | Taint nodes where Cilium is scheduled but not running. This prevents pods from being scheduled to nodes where Cilium is not the default CNI provider. | +| operator.skipCNPStatusStartupClean | bool | `false` | Skip CNP node status clean up at operator startup. | +| operator.skipCRDCreation | bool | `false` | Skip CRDs creation for cilium-operator | +| operator.tolerations | list | `[{"operator":"Exists"}]` | Node tolerations for cilium-operator scheduling to nodes with taints ref: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/ | +| operator.topologySpreadConstraints | list | `[]` | Pod topology spread constraints for cilium-operator | +| operator.unmanagedPodWatcher.intervalSeconds | int | `15` | Interval, in seconds, to check if there are any pods that are not managed by Cilium. | +| operator.unmanagedPodWatcher.restart | bool | `true` | Restart any pod that are not managed by Cilium. | +| operator.updateStrategy | object | `{"rollingUpdate":{"maxSurge":"25%","maxUnavailable":"50%"},"type":"RollingUpdate"}` | cilium-operator update strategy | +| pmtuDiscovery.enabled | bool | `false` | Enable path MTU discovery to send ICMP fragmentation-needed replies to the client. | +| podAnnotations | object | `{}` | Annotations to be added to agent pods | +| podLabels | object | `{}` | Labels to be added to agent pods | +| podSecurityContext | object | `{}` | Security Context for cilium-agent pods. | +| policyEnforcementMode | string | `"default"` | The agent can be put into one of the three policy enforcement modes: default, always and never. ref: https://docs.cilium.io/en/stable/security/policy/intro/#policy-enforcement-modes | +| pprof.address | string | `"localhost"` | Configure pprof listen address for cilium-agent | +| pprof.enabled | bool | `false` | Enable pprof for cilium-agent | +| pprof.port | int | `6060` | Configure pprof listen port for cilium-agent | +| preflight.affinity | object | `{"podAffinity":{"requiredDuringSchedulingIgnoredDuringExecution":[{"labelSelector":{"matchLabels":{"k8s-app":"cilium"}},"topologyKey":"kubernetes.io/hostname"}]}}` | Affinity for cilium-preflight | +| preflight.enabled | bool | `false` | Enable Cilium pre-flight resources (required for upgrade) | +| preflight.extraEnv | list | `[]` | Additional preflight environment variables. | +| preflight.extraVolumeMounts | list | `[]` | Additional preflight volumeMounts. | +| preflight.extraVolumes | list | `[]` | Additional preflight volumes. | +| preflight.image | object | `{"digest":"sha256:d3b287029755b6a47dee01420e2ea469469f1b174a2089c10af7e5e9289ef05b","override":null,"pullPolicy":"IfNotPresent","repository":"quay.io/cilium/cilium","tag":"v1.14.5","useDigest":true}` | Cilium pre-flight image. | +| preflight.nodeSelector | object | `{"kubernetes.io/os":"linux"}` | Node labels for preflight pod assignment ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#nodeselector | +| preflight.podAnnotations | object | `{}` | Annotations to be added to preflight pods | +| preflight.podDisruptionBudget.enabled | bool | `false` | enable PodDisruptionBudget ref: https://kubernetes.io/docs/concepts/workloads/pods/disruptions/ | +| preflight.podDisruptionBudget.maxUnavailable | int | `1` | Maximum number/percentage of pods that may be made unavailable | +| preflight.podDisruptionBudget.minAvailable | string | `nil` | Minimum number/percentage of pods that should remain scheduled. When it's set, maxUnavailable must be disabled by `maxUnavailable: null` | +| preflight.podLabels | object | `{}` | Labels to be added to the preflight pod. | +| preflight.podSecurityContext | object | `{}` | Security context to be added to preflight pods. | +| preflight.priorityClassName | string | `""` | The priority class to use for the preflight pod. | +| preflight.resources | object | `{}` | preflight resource limits & requests ref: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ | +| preflight.securityContext | object | `{}` | Security context to be added to preflight pods | +| preflight.terminationGracePeriodSeconds | int | `1` | Configure termination grace period for preflight Deployment and DaemonSet. | +| preflight.tofqdnsPreCache | string | `""` | Path to write the `--tofqdns-pre-cache` file to. | +| preflight.tolerations | list | `[{"effect":"NoSchedule","key":"node.kubernetes.io/not-ready"},{"effect":"NoSchedule","key":"node-role.kubernetes.io/master"},{"effect":"NoSchedule","key":"node-role.kubernetes.io/control-plane"},{"effect":"NoSchedule","key":"node.cloudprovider.kubernetes.io/uninitialized","value":"true"},{"key":"CriticalAddonsOnly","operator":"Exists"}]` | Node tolerations for preflight scheduling to nodes with taints ref: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/ | +| preflight.updateStrategy | object | `{"type":"RollingUpdate"}` | preflight update strategy | +| preflight.validateCNPs | bool | `true` | By default we should always validate the installed CNPs before upgrading Cilium. This will make sure the user will have the policies deployed in the cluster with the right schema. | +| priorityClassName | string | `""` | The priority class to use for cilium-agent. | +| prometheus | object | `{"enabled":false,"metrics":null,"port":9962,"serviceMonitor":{"annotations":{},"enabled":false,"interval":"10s","labels":{},"metricRelabelings":null,"relabelings":[{"replacement":"${1}","sourceLabels":["__meta_kubernetes_pod_node_name"],"targetLabel":"node"}],"trustCRDsExist":false}}` | Configure prometheus metrics on the configured port at /metrics | +| prometheus.metrics | string | `nil` | Metrics that should be enabled or disabled from the default metric list. The list is expected to be separated by a space. (+metric_foo to enable metric_foo , -metric_bar to disable metric_bar). ref: https://docs.cilium.io/en/stable/observability/metrics/ | +| prometheus.serviceMonitor.annotations | object | `{}` | Annotations to add to ServiceMonitor cilium-agent | +| prometheus.serviceMonitor.enabled | bool | `false` | Enable service monitors. This requires the prometheus CRDs to be available (see https://github.com/prometheus-operator/prometheus-operator/blob/main/example/prometheus-operator-crd/monitoring.coreos.com_servicemonitors.yaml) | +| prometheus.serviceMonitor.interval | string | `"10s"` | Interval for scrape metrics. | +| prometheus.serviceMonitor.labels | object | `{}` | Labels to add to ServiceMonitor cilium-agent | +| prometheus.serviceMonitor.metricRelabelings | string | `nil` | Metrics relabeling configs for the ServiceMonitor cilium-agent | +| prometheus.serviceMonitor.relabelings | list | `[{"replacement":"${1}","sourceLabels":["__meta_kubernetes_pod_node_name"],"targetLabel":"node"}]` | Relabeling configs for the ServiceMonitor cilium-agent | +| prometheus.serviceMonitor.trustCRDsExist | bool | `false` | Set to `true` and helm will not check for monitoring.coreos.com/v1 CRDs before deploying | +| proxy | object | `{"prometheus":{"enabled":true,"port":null},"sidecarImageRegex":"cilium/istio_proxy"}` | Configure Istio proxy options. | +| proxy.prometheus.enabled | bool | `true` | Deprecated in favor of envoy.prometheus.enabled | +| proxy.prometheus.port | string | `nil` | Deprecated in favor of envoy.prometheus.port | +| proxy.sidecarImageRegex | string | `"cilium/istio_proxy"` | Regular expression matching compatible Istio sidecar istio-proxy container image names | +| rbac.create | bool | `true` | Enable creation of Resource-Based Access Control configuration. | +| readinessProbe.failureThreshold | int | `3` | failure threshold of readiness probe | +| readinessProbe.periodSeconds | int | `30` | interval between checks of the readiness probe | +| remoteNodeIdentity | bool | `true` | Enable use of the remote node identity. ref: https://docs.cilium.io/en/v1.7/install/upgrade/#configmap-remote-node-identity | +| resourceQuotas | object | `{"cilium":{"hard":{"pods":"10k"}},"enabled":false,"operator":{"hard":{"pods":"15"}}}` | Enable resource quotas for priority classes used in the cluster. | +| resources | object | `{}` | Agent resource limits & requests ref: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ | +| rollOutCiliumPods | bool | `false` | Roll out cilium agent pods automatically when configmap is updated. | +| routingMode | string | `"tunnel"` | Enable native-routing mode or tunneling mode. Possible values: - "" - native - tunnel | +| sctp | object | `{"enabled":false}` | SCTP Configuration Values | +| sctp.enabled | bool | `false` | Enable SCTP support. NOTE: Currently, SCTP support does not support rewriting ports or multihoming. | +| securityContext.capabilities.applySysctlOverwrites | list | `["SYS_ADMIN","SYS_CHROOT","SYS_PTRACE"]` | capabilities for the `apply-sysctl-overwrites` init container | +| securityContext.capabilities.ciliumAgent | list | `["CHOWN","KILL","NET_ADMIN","NET_RAW","IPC_LOCK","SYS_MODULE","SYS_ADMIN","SYS_RESOURCE","DAC_OVERRIDE","FOWNER","SETGID","SETUID"]` | Capabilities for the `cilium-agent` container | +| securityContext.capabilities.cleanCiliumState | list | `["NET_ADMIN","SYS_MODULE","SYS_ADMIN","SYS_RESOURCE"]` | Capabilities for the `clean-cilium-state` init container | +| securityContext.capabilities.mountCgroup | list | `["SYS_ADMIN","SYS_CHROOT","SYS_PTRACE"]` | Capabilities for the `mount-cgroup` init container | +| securityContext.privileged | bool | `false` | Run the pod with elevated privileges | +| securityContext.seLinuxOptions | object | `{"level":"s0","type":"spc_t"}` | SELinux options for the `cilium-agent` and init containers | +| serviceAccounts | object | Component's fully qualified name. | Define serviceAccount names for components. | +| serviceAccounts.clustermeshcertgen | object | `{"annotations":{},"automount":true,"create":true,"name":"clustermesh-apiserver-generate-certs"}` | Clustermeshcertgen is used if clustermesh.apiserver.tls.auto.method=cronJob | +| serviceAccounts.hubblecertgen | object | `{"annotations":{},"automount":true,"create":true,"name":"hubble-generate-certs"}` | Hubblecertgen is used if hubble.tls.auto.method=cronJob | +| serviceAccounts.nodeinit.enabled | bool | `false` | Enabled is temporary until https://github.com/cilium/cilium-cli/issues/1396 is implemented. Cilium CLI doesn't create the SAs for node-init, thus the workaround. Helm is not affected by this issue. Name and automount can be configured, if enabled is set to true. Otherwise, they are ignored. Enabled can be removed once the issue is fixed. Cilium-nodeinit DS must also be fixed. | +| sleepAfterInit | bool | `false` | Do not run Cilium agent when running with clean mode. Useful to completely uninstall Cilium as it will stop Cilium from starting and create artifacts in the node. | +| socketLB | object | `{"enabled":false}` | Configure socket LB | +| socketLB.enabled | bool | `false` | Enable socket LB | +| startupProbe.failureThreshold | int | `105` | failure threshold of startup probe. 105 x 2s translates to the old behaviour of the readiness probe (120s delay + 30 x 3s) | +| startupProbe.periodSeconds | int | `2` | interval between checks of the startup probe | +| svcSourceRangeCheck | bool | `true` | Enable check of service source ranges (currently, only for LoadBalancer). | +| synchronizeK8sNodes | bool | `true` | Synchronize Kubernetes nodes to kvstore and perform CNP GC. | +| terminationGracePeriodSeconds | int | `1` | Configure termination grace period for cilium-agent DaemonSet. | +| tls | object | `{"ca":{"cert":"","certValidityDuration":1095,"key":""},"caBundle":{"enabled":false,"key":"ca.crt","name":"cilium-root-ca.crt","useSecret":false},"secretsBackend":"local"}` | Configure TLS configuration in the agent. | +| tls.ca | object | `{"cert":"","certValidityDuration":1095,"key":""}` | Base64 encoded PEM values for the CA certificate and private key. This can be used as common CA to generate certificates used by hubble and clustermesh components. It is neither required nor used when cert-manager is used to generate the certificates. | +| tls.ca.cert | string | `""` | Optional CA cert. If it is provided, it will be used by cilium to generate all other certificates. Otherwise, an ephemeral CA is generated. | +| tls.ca.certValidityDuration | int | `1095` | Generated certificates validity duration in days. This will be used for auto generated CA. | +| tls.ca.key | string | `""` | Optional CA private key. If it is provided, it will be used by cilium to generate all other certificates. Otherwise, an ephemeral CA is generated. | +| tls.caBundle | object | `{"enabled":false,"key":"ca.crt","name":"cilium-root-ca.crt","useSecret":false}` | Configure the CA trust bundle used for the validation of the certificates leveraged by hubble and clustermesh. When enabled, it overrides the content of the 'ca.crt' field of the respective certificates, allowing for CA rotation with no down-time. | +| tls.caBundle.enabled | bool | `false` | Enable the use of the CA trust bundle. | +| tls.caBundle.key | string | `"ca.crt"` | Entry of the ConfigMap containing the CA trust bundle. | +| tls.caBundle.name | string | `"cilium-root-ca.crt"` | Name of the ConfigMap containing the CA trust bundle. | +| tls.caBundle.useSecret | bool | `false` | Use a Secret instead of a ConfigMap. | +| tls.secretsBackend | string | `"local"` | This configures how the Cilium agent loads the secrets used TLS-aware CiliumNetworkPolicies (namely the secrets referenced by terminatingTLS and originatingTLS). Possible values: - local - k8s | +| tolerations | list | `[{"operator":"Exists"}]` | Node tolerations for agent scheduling to nodes with taints ref: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/ | +| tunnel | string | `"vxlan"` | Configure the encapsulation configuration for communication between nodes. Deprecated in favor of tunnelProtocol and routingMode. To be removed in 1.15. Possible values: - disabled - vxlan - geneve | +| tunnelPort | int | Port 8472 for VXLAN, Port 6081 for Geneve | Configure VXLAN and Geneve tunnel port. | +| tunnelProtocol | string | `"vxlan"` | Tunneling protocol to use in tunneling mode and for ad-hoc tunnels. Possible values: - "" - vxlan - geneve | +| updateStrategy | object | `{"rollingUpdate":{"maxUnavailable":2},"type":"RollingUpdate"}` | Cilium agent update strategy | +| vtep.cidr | string | `""` | A space separated list of VTEP device CIDRs, for example "1.1.1.0/24 1.1.2.0/24" | +| vtep.enabled | bool | `false` | Enables VXLAN Tunnel Endpoint (VTEP) Integration (beta) to allow Cilium-managed pods to talk to third party VTEP devices over Cilium tunnel. | +| vtep.endpoint | string | `""` | A space separated list of VTEP device endpoint IPs, for example "1.1.1.1 1.1.2.1" | +| vtep.mac | string | `""` | A space separated list of VTEP device MAC addresses (VTEP MAC), for example "x:x:x:x:x:x y:y:y:y:y:y:y" | +| vtep.mask | string | `""` | VTEP CIDRs Mask that applies to all VTEP CIDRs, for example "255.255.255.0" | +| waitForKubeProxy | bool | `false` | Wait for KUBE-PROXY-CANARY iptables rule to appear in "wait-for-kube-proxy" init container before launching cilium-agent. More context can be found in the commit message of below PR https://github.com/cilium/cilium/pull/20123 | +| wellKnownIdentities.enabled | bool | `false` | Enable the use of well-known identities. | diff --git a/packages/system/cilium/charts/cilium/README.md.gotmpl b/packages/system/cilium/charts/cilium/README.md.gotmpl new file mode 100644 index 00000000..db2d81b7 --- /dev/null +++ b/packages/system/cilium/charts/cilium/README.md.gotmpl @@ -0,0 +1,54 @@ +{{ template "chart.header" . }} + +{{ template "chart.deprecationWarning" . }} + +{{ template "chart.versionBadge" . }}{{ template "chart.typeBadge" . }}{{ template "chart.appVersionBadge" . }} + +Cilium is open source software for providing and transparently securing +network connectivity and loadbalancing between application workloads such as +application containers or processes. Cilium operates at Layer 3/4 to provide +traditional networking and security services as well as Layer 7 to protect and +secure use of modern application protocols such as HTTP, gRPC and Kafka. + +A new Linux kernel technology called eBPF is at the foundation of Cilium. +It supports dynamic insertion of eBPF bytecode into the Linux kernel at various +integration points such as: network IO, application sockets, and tracepoints +to implement security, networking and visibility logic. eBPF is highly +efficient and flexible. + +![Cilium feature overview](https://raw.githubusercontent.com/cilium/cilium/main/Documentation/images/cilium_overview.png) + +## Prerequisites + +* Kubernetes: `{{ template "chart.kubeVersion" . }}` +* Helm: `>= 3.0` + +## Getting Started + +Try Cilium on any Kubernetes distribution in under 15 minutes: + +| Minikube | Self-Managed K8s | Amazon EKS | Google GKE | Microsoft AKS | +|:-:|:-:|:-:|:-:|:-:| +| [![Minikube](https://raw.githubusercontent.com/cilium/charts/master/images/minikube.svg)](https://docs.cilium.io/en/stable/gettingstarted/k8s-install-default/) | [![Self-Managed Kubernetes](https://raw.githubusercontent.com/cilium/charts/master/images/k8s.png)](https://docs.cilium.io/en/stable/gettingstarted/k8s-install-default/) | [![Amazon EKS](https://raw.githubusercontent.com/cilium/charts/master/images/aws.svg)](https://docs.cilium.io/en/stable/gettingstarted/k8s-install-default/) | [![Google GKE](https://raw.githubusercontent.com/cilium/charts/master/images/google-cloud.svg)](https://docs.cilium.io/en/stable/gettingstarted/k8s-install-default/) | [![Microsoft AKS](https://raw.githubusercontent.com/cilium/charts/master/images/azure.svg)](https://docs.cilium.io/en/stable/gettingstarted/k8s-install-default/) | + +Or, for a quick install with the default configuration: + +``` +$ helm repo add cilium https://helm.cilium.io/ +$ helm install cilium cilium/cilium --namespace=kube-system +``` + +After Cilium is installed, you can explore the features that Cilium has to +offer from the [Getting Started Guides page](https://docs.cilium.io/en/stable/gettingstarted/). + +{{ template "chart.maintainersSection" . }} + +{{ template "chart.sourcesSection" . }} + +## Getting Help + +The best way to get help if you get stuck is to ask a question on the +[Cilium Slack channel](https://cilium.herokuapp.com/). With Cilium +contributors across the globe, there is almost always someone available to help. + +{{ template "chart.valuesSection" . }} diff --git a/packages/system/cilium/charts/cilium/files/agent/poststart-eni.bash b/packages/system/cilium/charts/cilium/files/agent/poststart-eni.bash new file mode 100644 index 00000000..66fccf45 --- /dev/null +++ b/packages/system/cilium/charts/cilium/files/agent/poststart-eni.bash @@ -0,0 +1,19 @@ +set -o errexit +set -o pipefail +set -o nounset + +# When running in AWS ENI mode, it's likely that 'aws-node' has +# had a chance to install SNAT iptables rules. These can result +# in dropped traffic, so we should attempt to remove them. +# We do it using a 'postStart' hook since this may need to run +# for nodes which might have already been init'ed but may still +# have dangling rules. This is safe because there are no +# dependencies on anything that is part of the startup script +# itself, and can be safely run multiple times per node (e.g. in +# case of a restart). +if [[ "$(iptables-save | grep -c 'AWS-SNAT-CHAIN|AWS-CONNMARK-CHAIN')" != "0" ]]; +then + echo 'Deleting iptables rules created by the AWS CNI VPC plugin' + iptables-save | grep -v 'AWS-SNAT-CHAIN|AWS-CONNMARK-CHAIN' | iptables-restore +fi +echo 'Done!' diff --git a/packages/system/cilium/charts/cilium/files/cilium-agent/dashboards/cilium-dashboard.json b/packages/system/cilium/charts/cilium/files/cilium-agent/dashboards/cilium-dashboard.json new file mode 100644 index 00000000..997608ee --- /dev/null +++ b/packages/system/cilium/charts/cilium/files/cilium-agent/dashboards/cilium-dashboard.json @@ -0,0 +1,8245 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": "-- Grafana --", + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "description": "Dashboard for Cilium (https://cilium.io/) metrics", + "editable": true, + "gnetId": null, + "graphTooltip": 1, + "iteration": 1606309591568, + "links": [], + "panels": [ + { + "aliasColors": { + "error": "#890f02", + "warning": "#c15c17" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 12, + "x": 0, + "y": 0 + }, + "hiddenSeries": false, + "id": 76, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "error", + "yaxis": 2 + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(cilium_errors_warnings_total{k8s_app=\"cilium\", pod=~\"$pod\"}[1m])) by (pod, level) * 60", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{level}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Errors & Warnings", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "opm", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "opm", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "avg": "#cffaff" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 12, + "x": 12, + "y": 0 + }, + "hiddenSeries": false, + "id": 96, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "max", + "fillBelowTo": "min", + "lines": false + }, + { + "alias": "min", + "lines": false + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "min(irate(cilium_process_cpu_seconds_total{k8s_app=\"cilium\", pod=~\"$pod\"}[1m])) by (pod) * 100", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "min", + "refId": "A" + }, + { + "expr": "avg(irate(cilium_process_cpu_seconds_total{k8s_app=\"cilium\", pod=~\"$pod\"}[1m])) by (pod) * 100", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "avg", + "refId": "B" + }, + { + "expr": "max(irate(cilium_process_cpu_seconds_total{k8s_app=\"cilium\", pod=~\"$pod\"}[1m])) by (pod) * 100", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "max", + "refId": "C" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "CPU Usage per node", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "percent", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "collapsed": false, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 5 + }, + "id": 161, + "panels": [], + "title": "Generic", + "type": "row" + }, + { + "aliasColors": { + "AVG_virtual_memory_bytes": "#508642", + "Average Virtual Memory": "#f9d9f9", + "MAX_virtual_memory_bytes": "#e5ac0e", + "Max Virtual Memory": "#584477" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 8, + "x": 0, + "y": 6 + }, + "hiddenSeries": false, + "id": 26, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Max Virtual Memory", + "fillBelowTo": "Min Virtual Memory", + "lines": false + }, + { + "alias": "Min Virtual Memory", + "lines": false + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "min(cilium_process_virtual_memory_bytes{k8s_app=\"cilium\", pod=~\"$pod\"})", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Min Virtual Memory", + "refId": "A" + }, + { + "expr": "avg(cilium_process_virtual_memory_bytes{k8s_app=\"cilium\", pod=~\"$pod\"})", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Average Virtual Memory", + "refId": "B" + }, + { + "expr": "max(cilium_process_virtual_memory_bytes{k8s_app=\"cilium\", pod=~\"$pod\"})", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Max Virtual Memory", + "refId": "C" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Virtual Memory Bytes", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "MAX_resident_memory_bytes_max": "#e5ac0e" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 8, + "x": 8, + "y": 6 + }, + "hiddenSeries": false, + "id": 24, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "avg(cilium_process_resident_memory_bytes{k8s_app=\"cilium\", pod=~\"$pod\"})", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "AVG_resident_memory_bytes", + "refId": "C" + }, + { + "expr": "max(cilium_process_resident_memory_bytes{k8s_app=\"cilium\", pod=~\"$pod\"})", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "MAX_resident_memory_bytes_max", + "refId": "D" + }, + { + "expr": "min(cilium_process_resident_memory_bytes{k8s_app=\"cilium\", pod=~\"$pod\"})", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "MIN_resident_memory_bytes_min", + "refId": "E" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Resident memory status", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "all nodes": "#e5a8e2" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 8, + "x": 16, + "y": 6 + }, + "hiddenSeries": false, + "id": 98, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "all nodes", + "yaxis": 2 + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(cilium_process_open_fds{k8s_app=\"cilium\", pod=~\"$pod\"})", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "all nodes", + "refId": "A" + }, + { + "expr": "min(cilium_process_open_fds{k8s_app=\"cilium\", pod=~\"$pod\"})", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "min/node", + "refId": "B" + }, + { + "expr": "avg(cilium_process_open_fds{k8s_app=\"cilium\", pod=~\"$pod\"})", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "avg/node", + "refId": "C" + }, + { + "expr": "max(cilium_process_open_fds{k8s_app=\"cilium\", pod=~\"$pod\"})", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "max/node", + "refId": "D" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Open file descriptors", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "MAX_resident_memory_bytes_max": "#e5ac0e" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "description": "BPF memory usage in the entire system including components not managed by Cilium.", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 12, + "x": 0, + "y": 11 + }, + "hiddenSeries": false, + "id": 178, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "avg(cilium_bpf_maps_virtual_memory_max_bytes{k8s_app=\"cilium\", pod=~\"$pod\"} + cilium_bpf_progs_virtual_memory_max_bytes{k8s_app=\"cilium\", pod=~\"$pod\"})", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "AVG_bpf_memory_bytes_avg", + "refId": "C" + }, + { + "expr": "max(cilium_bpf_maps_virtual_memory_max_bytes{k8s_app=\"cilium\", pod=~\"$pod\"} + cilium_bpf_progs_virtual_memory_max_bytes{k8s_app=\"cilium\", pod=~\"$pod\"})", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "MAX_bpf_memory_bytes_max", + "refId": "D" + }, + { + "expr": "min(cilium_bpf_maps_virtual_memory_max_bytes{k8s_app=\"cilium\", pod=~\"$pod\"} + cilium_bpf_progs_virtual_memory_max_bytes{k8s_app=\"cilium\", pod=~\"$pod\"})", + "format": "time_series", + "hide": false, + "instant": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "MIN_bpf_memory_bytes_min", + "refId": "E" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "System-wide BPF memory usage", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:136", + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "$$hashKey": "object:137", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "description": "Fill percentage of BPF maps, tagged by map name", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 12, + "x": 12, + "y": 11 + }, + "hiddenSeries": false, + "id": 194, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "cilium_bpf_map_pressure{k8s_app=\"cilium\", pod=~\"$pod\"}", + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "BPF map pressure", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:230", + "format": "percentunit", + "label": null, + "logBase": 1, + "max": "1.0", + "min": null, + "show": true + }, + { + "$$hashKey": "object:231", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "collapsed": false, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 17 + }, + "id": 155, + "panels": [], + "title": "API", + "type": "row" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 12, + "x": 0, + "y": 18 + }, + "hiddenSeries": false, + "id": 152, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "avg(rate(cilium_agent_api_process_time_seconds_sum{k8s_app=\"cilium\", pod=~\"$pod\"}[1m])/rate(cilium_agent_api_process_time_seconds_count{k8s_app=\"cilium\", pod=~\"$pod\"}[1m])) by (pod, method, path)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{method}} {{path}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "API call latency (average node)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 12, + "x": 12, + "y": 18 + }, + "hiddenSeries": false, + "id": 153, + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": true, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "max(rate(cilium_agent_api_process_time_seconds_sum{k8s_app=\"cilium\", pod=~\"$pod\"}[1m])/rate(cilium_agent_api_process_time_seconds_count{k8s_app=\"cilium\", pod=~\"$pod\"}[1m])) by (pod, method, path)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{method}} {{path}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "API call latency (max node)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 12, + "x": 0, + "y": 24 + }, + "hiddenSeries": false, + "id": 156, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "avg(rate(cilium_agent_api_process_time_seconds_count{k8s_app=\"cilium\", pod=~\"$pod\"}[1m])) by (pod, method, path)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{method}} {{path}} ", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "# API calls (average node)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 12, + "x": 12, + "y": 24 + }, + "hiddenSeries": false, + "id": 157, + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": true, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "max(rate(cilium_agent_api_process_time_seconds_count{k8s_app=\"cilium\", pod=~\"$pod\"}[1m])) by (pod, method, path)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{method}} {{path}} ", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "# API calls (max node)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 12, + "x": 0, + "y": 30 + }, + "hiddenSeries": false, + "id": 159, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "avg(rate(cilium_agent_api_process_time_seconds_count{k8s_app=\"cilium\", pod=~\"$pod\"}[1m])) by (pod, method, path, return_code)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{return_code}} ({{method}} {{path}} )", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "API return codes (average node)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 12, + "x": 12, + "y": 30 + }, + "hiddenSeries": false, + "id": 158, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(cilium_agent_api_process_time_seconds_count{k8s_app=\"cilium\", pod=~\"$pod\"}[1m])) by (pod, method, path, return_code)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{return_code}} ({{method}} {{path}} )", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "API return codes (sum all nodes)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "collapsed": false, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 36 + }, + "id": 72, + "panels": [], + "title": "Cilium", + "type": "row" + }, + { + "content": "", + "datasource": null, + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 37 + }, + "id": 144, + "links": [], + "mode": "markdown", + "title": "BPF", + "type": "text" + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 38 + }, + "hiddenSeries": false, + "id": 146, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": true, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "avg(rate(cilium_bpf_syscall_duration_seconds_count{k8s_app=\"cilium\", pod=~\"$pod\"}[1m])) by (pod, operation)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{operation}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "# system calls (average node)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "decimals": 2, + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 38 + }, + "hiddenSeries": false, + "id": 145, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": true, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "max(rate(cilium_bpf_syscall_duration_seconds_count{k8s_app=\"cilium\", pod=~\"$pod\"}[1m])) by (pod, operation)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{operation}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "# system calls (max node)", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 0, + "format": "ops", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 12, + "x": 0, + "y": 46 + }, + "hiddenSeries": false, + "id": 140, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": true, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "avg(rate(cilium_bpf_syscall_duration_seconds_sum{k8s_app=\"cilium\", pod=~\"$pod\"}[1m])/ rate(cilium_bpf_syscall_duration_seconds_count{k8s_app=\"cilium\", pod=~\"$pod\"}[1m])) by (pod, operation)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{operation}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "system call latency (avg node)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 12, + "x": 12, + "y": 46 + }, + "hiddenSeries": false, + "id": 148, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "max(rate(cilium_bpf_syscall_duration_seconds_sum{k8s_app=\"cilium\", pod=~\"$pod\"}[1m])/ rate(cilium_bpf_syscall_duration_seconds_count{k8s_app=\"cilium\", pod=~\"$pod\"}[1m])) by (pod, operation)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{operation}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "system call latency (max node)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 8, + "x": 0, + "y": 52 + }, + "hiddenSeries": false, + "id": 142, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": true, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "topk(5, avg(rate(cilium_bpf_map_ops_total{k8s_app=\"cilium\", pod=~\"$pod\"}[5m])) by (pod, map_name, operation))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{map_name}} {{operation}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "map ops (average node)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 8, + "x": 8, + "y": 52 + }, + "hiddenSeries": false, + "id": 147, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": true, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "topk(5, max(rate(cilium_bpf_map_ops_total{k8s_app=\"cilium\", pod=~\"$pod\"}[5m])) by (pod, map_name, operation))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{map_name}} {{operation}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "map ops (max node)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 8, + "x": 16, + "y": 52 + }, + "hiddenSeries": false, + "id": 143, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(cilium_bpf_map_ops_total{k8s_app=\"cilium\",outcome=\"fail\", pod=~\"$pod\"}[5m])) by (pod, map_name, operation)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{map_name}} {{operation}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "map ops (sum failures)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "content": "", + "datasource": null, + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 58 + }, + "id": 182, + "links": [], + "mode": "markdown", + "title": "kvstore", + "type": "text" + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "decimals": 2, + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 12, + "x": 0, + "y": 59 + }, + "hiddenSeries": false, + "id": 184, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": true, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(kvstore_operations_total{pod=~\"$pod\"}[1m])) by (pod, scope, action)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{scope}} {{action}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "# operations (sum all nodes)", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 0, + "format": "ops", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "decimals": 2, + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 12, + "x": 12, + "y": 59 + }, + "hiddenSeries": false, + "id": 186, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": true, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "max(rate(kvstore_operations_total{pod=~\"$pod\"}[1m])) by (pod, scope, action)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{scope}} {{action}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "# operations (max node)", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 0, + "format": "ops", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 12, + "x": 0, + "y": 64 + }, + "hiddenSeries": false, + "id": 188, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": true, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "topk(5, avg(rate(cilium_kvstore_operations_duration_seconds_sum{pod=~\"$pod\"}[1m])) by (pod, action, scope) / avg(rate(cilium_kvstore_operations_duration_seconds_count{pod=~\"$pod\"}[1m])) by (pod, action, scope))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{action}} {{scope}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "latency (average node)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 12, + "x": 12, + "y": 64 + }, + "hiddenSeries": false, + "id": 190, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": true, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "topk(5, max(rate(cilium_kvstore_operations_duration_seconds_sum{pod=~\"$pod\"}[1m])) by (pod, action, scope) / avg(rate(cilium_kvstore_operations_duration_seconds_count{pod=~\"$pod\"}[1m])) by (pod, action, scope))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{action}} {{scope}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "latency (max node)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 12, + "x": 0, + "y": 69 + }, + "hiddenSeries": false, + "id": 192, + "legend": { + "avg": false, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "paceLength": 10, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "avg(rate(cilium_kvstore_events_queue_seconds_count{pod=~\"$pod\"}[1m])) by (pod, scope, action)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{action}} {{scope}}", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Events received (average node)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "content": "", + "datasource": null, + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 75 + }, + "id": 47, + "links": [], + "mode": "markdown", + "title": "Cilium network information", + "type": "text" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 12, + "x": 0, + "y": 76 + }, + "hiddenSeries": false, + "id": 81, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(cilium_forward_count_total{k8s_app=\"cilium\", pod=~\"$pod\"}[1m])) by (pod, direction)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{direction}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Forwarded Packets", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 12, + "x": 12, + "y": 76 + }, + "hiddenSeries": false, + "id": 111, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "EGRESS", + "yaxis": 1 + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(cilium_forward_bytes_total{k8s_app=\"cilium\", pod=~\"$pod\"}[1m])) by (pod, direction) * 8", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{direction}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Forwarded Traffic", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bps", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "Alive ipv4": "#0a50a1", + "Alive ipv4 non-TCP": "#f9d9f9", + "Alive ipv6": "#614d93", + "Alive ipv6 TCP": "#806eb7", + "Alive ipv6 non-TCP": "#614d93", + "Alive CT entries ipv6": "#badff4", + "Deleted CT entries ipv4": "#bf1b00", + "Deleted ipv4": "#890f02", + "Deleted ipv4 non-TCP": "#890f02", + "Deleted ipv6": "#bf1b00", + "L7 denied request": "#890f02", + "L7 forwarded request": "#7eb26d", + "avg": "#e0f9d7", + "deleted": "#6ed0e0", + "deleted max": "#447ebc", + "max": "#629e51", + "min": "#629e51" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 12, + "x": 0, + "y": 82 + }, + "hiddenSeries": false, + "id": 56, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "deleted", + "yaxis": 2 + }, + { + "alias": "max", + "fillBelowTo": "min", + "lines": false + }, + { + "alias": "min", + "lines": false + }, + { + "alias": "deleted max", + "yaxis": 2 + }, + { + "alias": "deleted min", + "yaxis": 2 + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "min(cilium_datapath_conntrack_gc_entries{k8s_app=\"cilium\", status=\"alive\", family=\"ipv4\", protocol=\"TCP\", pod=~\"$pod\"}) by (family,status)", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "min", + "refId": "A" + }, + { + "expr": "avg(cilium_datapath_conntrack_gc_entries{k8s_app=\"cilium\", status=\"alive\", family=\"ipv4\", protocol=\"TCP\", pod=~\"$pod\"}) by (family,status)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "avg", + "refId": "B" + }, + { + "expr": "max(cilium_datapath_conntrack_gc_entries{k8s_app=\"cilium\", status=\"alive\", family=\"ipv4\", protocol=\"TCP\", pod=~\"$pod\"}) by (family,status)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "max", + "refId": "C" + }, + { + "expr": "avg(cilium_datapath_conntrack_gc_entries{k8s_app=\"cilium\", status=\"deleted\", family=\"ipv4\", protocol=\"TCP\", pod=~\"$pod\"}) by (family,status)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "deleted", + "refId": "D" + }, + { + "expr": "max(cilium_datapath_conntrack_gc_entries{k8s_app=\"cilium\", status=\"deleted\", family=\"ipv4\", protocol=\"TCP\", pod=~\"$pod\"}) by (family,status)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "deleted max", + "refId": "E" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "IPv4 Conntrack TCP", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "Alive ipv4": "#0a50a1", + "Alive ipv4 non-TCP": "#f9d9f9", + "Alive ipv6": "#614d93", + "Alive ipv6 TCP": "#806eb7", + "Alive ipv6 non-TCP": "#614d93", + "Alive CT entries ipv6": "#badff4", + "Deleted CT entries ipv4": "#bf1b00", + "Deleted ipv4": "#890f02", + "Deleted ipv4 non-TCP": "#890f02", + "Deleted ipv6": "#bf1b00", + "L7 denied request": "#890f02", + "L7 forwarded request": "#7eb26d", + "avg": "#e0f9d7", + "deleted": "#6ed0e0", + "deleted max": "#447ebc", + "max": "#629e51", + "min": "#629e51" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 12, + "x": 12, + "y": 82 + }, + "hiddenSeries": false, + "id": 128, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "deleted", + "yaxis": 2 + }, + { + "alias": "max", + "fillBelowTo": "min", + "lines": false + }, + { + "alias": "min", + "lines": false + }, + { + "alias": "deleted max", + "yaxis": 2 + }, + { + "alias": "deleted min", + "yaxis": 2 + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "min(cilium_datapath_conntrack_gc_entries{k8s_app=\"cilium\", status=\"alive\", family=\"ipv6\", protocol=\"TCP\", pod=~\"$pod\"}) by (family,status)", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "min", + "refId": "A" + }, + { + "expr": "avg(cilium_datapath_conntrack_gc_entries{k8s_app=\"cilium\", status=\"alive\", family=\"ipv6\", protocol=\"TCP\", pod=~\"$pod\"}) by (family,status)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "avg", + "refId": "B" + }, + { + "expr": "max(cilium_datapath_conntrack_gc_entries{k8s_app=\"cilium\", status=\"alive\", family=\"ipv6\", protocol=\"TCP\", pod=~\"$pod\"}) by (family,status)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "max", + "refId": "C" + }, + { + "expr": "avg(cilium_datapath_conntrack_gc_entries{k8s_app=\"cilium\", status=\"deleted\", family=\"ipv6\", protocol=\"TCP\", pod=~\"$pod\"}) by (family,status)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "deleted", + "refId": "D" + }, + { + "expr": "max(cilium_datapath_conntrack_gc_entries{k8s_app=\"cilium\", status=\"deleted\", family=\"ipv6\", protocol=\"TCP\", pod=~\"$pod\"}) by (family,status)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "deleted max", + "refId": "E" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "IPv6 Conntrack TCP", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "Alive ipv4": "#0a50a1", + "Alive ipv4 non-TCP": "#f9d9f9", + "Alive ipv6": "#614d93", + "Alive ipv6 TCP": "#806eb7", + "Alive ipv6 non-TCP": "#614d93", + "Alive CT entries ipv6": "#badff4", + "Deleted CT entries ipv4": "#bf1b00", + "Deleted ipv4": "#890f02", + "Deleted ipv4 non-TCP": "#890f02", + "Deleted ipv6": "#bf1b00", + "L7 denied request": "#890f02", + "L7 forwarded request": "#7eb26d", + "avg": "#e0f9d7", + "deleted": "#6ed0e0", + "deleted max": "#447ebc", + "max": "#629e51", + "min": "#629e51" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 12, + "x": 0, + "y": 88 + }, + "hiddenSeries": false, + "id": 129, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "deleted", + "yaxis": 2 + }, + { + "alias": "max", + "fillBelowTo": "min", + "lines": false + }, + { + "alias": "min", + "lines": false + }, + { + "alias": "deleted max", + "yaxis": 2 + }, + { + "alias": "deleted min", + "yaxis": 2 + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "min(cilium_datapath_conntrack_gc_entries{k8s_app=\"cilium\", status=\"alive\", family=\"ipv4\", protocol=\"non-TCP\", pod=~\"$pod\"}) by (family,status)", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "min", + "refId": "A" + }, + { + "expr": "avg(cilium_datapath_conntrack_gc_entries{k8s_app=\"cilium\", status=\"alive\", family=\"ipv4\", protocol=\"non-TCP\", pod=~\"$pod\"}) by (family,status)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "avg", + "refId": "B" + }, + { + "expr": "max(cilium_datapath_conntrack_gc_entries{k8s_app=\"cilium\", status=\"alive\", family=\"ipv4\", protocol=\"non-TCP\", pod=~\"$pod\"}) by (family,status)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "max", + "refId": "C" + }, + { + "expr": "avg(cilium_datapath_conntrack_gc_entries{k8s_app=\"cilium\", status=\"deleted\", family=\"ipv4\", protocol=\"non-TCP\", pod=~\"$pod\"}) by (family,status)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "deleted", + "refId": "D" + }, + { + "expr": "max(cilium_datapath_conntrack_gc_entries{k8s_app=\"cilium\", status=\"deleted\", family=\"ipv4\", protocol=\"non-TCP\", pod=~\"$pod\"}) by (family,status)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "deleted max", + "refId": "E" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "IPv4 Conntrack Non-TCP", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "Alive ipv4": "#0a50a1", + "Alive ipv4 non-TCP": "#f9d9f9", + "Alive ipv6": "#614d93", + "Alive ipv6 TCP": "#806eb7", + "Alive ipv6 non-TCP": "#614d93", + "Alive CT entries ipv6": "#badff4", + "Deleted CT entries ipv4": "#bf1b00", + "Deleted ipv4": "#890f02", + "Deleted ipv4 non-TCP": "#890f02", + "Deleted ipv6": "#bf1b00", + "L7 denied request": "#890f02", + "L7 forwarded request": "#7eb26d", + "avg": "#e0f9d7", + "deleted": "#6ed0e0", + "deleted max": "#447ebc", + "max": "#629e51", + "min": "#629e51" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 12, + "x": 12, + "y": 88 + }, + "hiddenSeries": false, + "id": 130, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "deleted", + "yaxis": 2 + }, + { + "alias": "max", + "fillBelowTo": "min", + "lines": false + }, + { + "alias": "min", + "lines": false + }, + { + "alias": "deleted max", + "yaxis": 2 + }, + { + "alias": "deleted min", + "yaxis": 2 + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "min(cilium_datapath_conntrack_gc_entries{k8s_app=\"cilium\", status=\"alive\", family=\"ipv6\", protocol=\"non-TCP\", pod=~\"$pod\"}) by (family,status)", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "min", + "refId": "A" + }, + { + "expr": "avg(cilium_datapath_conntrack_gc_entries{k8s_app=\"cilium\", status=\"alive\", family=\"ipv6\", protocol=\"non-TCP\", pod=~\"$pod\"}) by (family,status)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "avg", + "refId": "B" + }, + { + "expr": "max(cilium_datapath_conntrack_gc_entries{k8s_app=\"cilium\", status=\"alive\", family=\"ipv6\", protocol=\"non-TCP\", pod=~\"$pod\"}) by (family,status)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "max", + "refId": "C" + }, + { + "expr": "avg(cilium_datapath_conntrack_gc_entries{k8s_app=\"cilium\", status=\"deleted\", family=\"ipv6\", protocol=\"non-TCP\", pod=~\"$pod\"}) by (family,status)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "deleted", + "refId": "D" + }, + { + "expr": "max(cilium_datapath_conntrack_gc_entries{k8s_app=\"cilium\", status=\"deleted\", family=\"ipv6\", protocol=\"non-TCP\", pod=~\"$pod\"}) by (family,status)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "deleted max", + "refId": "E" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "IPv6 Conntrack Non-TCP", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "ipv4": "#5195ce", + "ipv6": "#6d1f62" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "decimals": null, + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 12, + "x": 0, + "y": 94 + }, + "hiddenSeries": false, + "id": 87, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(cilium_ip_addresses{k8s_app=\"cilium\", pod=~\"$pod\"}) by (pod, family)\n", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{family}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Allocated Addresses", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "dump_interrupts conntrack ipv4": "#ea6460", + "dump_interrupts conntrack ipv6": "#58140c" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 12, + "x": 12, + "y": 94 + }, + "hiddenSeries": false, + "id": 79, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(cilium_datapath_conntrack_dump_resets_total{k8s_app=\"cilium\", pod=~\"$pod\"}) by (pod, area, family, name)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{name}} {{area}} {{family}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Datapath Conntrack Dump Resets", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 12, + "x": 0, + "y": 99 + }, + "hiddenSeries": false, + "id": 106, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "avg(rate(cilium_services_events_total{k8s_app=\"cilium\", pod=~\"$pod\"}[1m])) by (pod, action)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{action}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Service Updates", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 12, + "x": 12, + "y": 99 + }, + "hiddenSeries": false, + "id": 89, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "avg(cilium_unreachable_health_endpoints) by (pod)", + "yaxis": 2 + }, + { + "alias": "average unreachable health endpoints", + "yaxis": 2 + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(cilium_unreachable_nodes{k8s_app=\"cilium\", pod=~\"$pod\"}) by (pod)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "unreachable nodes", + "refId": "A" + }, + { + "expr": "sum(cilium_unreachable_health_endpoints{k8s_app=\"cilium\", pod=~\"$pod\"}) by (pod)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "unreachable health endpoints", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Connectivity Health", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 12, + "x": 0, + "y": 104 + }, + "hiddenSeries": false, + "id": 39, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(cilium_drop_count_total{direction=\"EGRESS\", k8s_app=\"cilium\", pod=~\"$pod\"}[1m])) by (reason)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{reason}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Dropped Egress Packets", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "Avg": "#cca300", + "Max": "rgb(167, 150, 111)" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 12, + "x": 12, + "y": 104 + }, + "hiddenSeries": false, + "id": 93, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Max", + "fillBelowTo": "Min", + "lines": false + }, + { + "alias": "Min", + "lines": false + }, + { + "alias": "add k8s", + "yaxis": 2 + }, + { + "alias": "delete k8s", + "yaxis": 2 + }, + { + "alias": "update k8s", + "yaxis": 2 + }, + { + "alias": "add local-node", + "yaxis": 2 + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "avg(rate(cilium_nodes_all_events_received_total{k8s_app=\"cilium\", pod=~\"$pod\"}[1m])) by (pod, event_type, source) * 60", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{eventType}} {{source}}", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Node Events", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "opm", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 12, + "x": 0, + "y": 109 + }, + "hiddenSeries": false, + "id": 113, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(cilium_drop_bytes_total{direction=\"EGRESS\", k8s_app=\"cilium\", pod=~\"$pod\"}[1m])) by (reason) * 8", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{reason}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Dropped Egress Traffic", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bps", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "Average Nodes": "#eab839", + "Max Nodes": "#c15c17" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 12, + "x": 12, + "y": 109 + }, + "hiddenSeries": false, + "id": 91, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Max Nodes", + "fillBelowTo": "Min Nodes", + "lines": false + }, + { + "alias": "Min Nodes", + "lines": false + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "avg(cilium_nodes_all_num{k8s_app=\"cilium\", pod=~\"$pod\"}) by (pod)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Average Nodes", + "refId": "A" + }, + { + "expr": "min(cilium_nodes_all_num{k8s_app=\"cilium\", pod=~\"$pod\"}) by (pod)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Min Nodes", + "refId": "B" + }, + { + "expr": "max(cilium_nodes_all_num{k8s_app=\"cilium\", pod=~\"$pod\"}) by (pod)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Max Nodes", + "refId": "C" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Nodes", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "content": "", + "datasource": null, + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 114 + }, + "id": 28, + "links": [], + "mode": "markdown", + "title": "Policy", + "type": "text" + }, + { + "aliasColors": { + "L7 denied request": "#ea6460", + "L7 forwarded request": "#7eb26d", + "denied": "#bf1b00" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 12, + "x": 0, + "y": 115 + }, + "hiddenSeries": false, + "id": 53, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "L7 denied request", + "yaxis": 2 + }, + { + "alias": "denied", + "yaxis": 2 + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(cilium_policy_l7_denied_total{k8s_app=\"cilium\", pod=~\"$pod\"}[1m]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "denied", + "refId": "A" + }, + { + "expr": "sum(rate(cilium_policy_l7_forwarded_total{k8s_app=\"cilium\", pod=~\"$pod\"}[1m]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "forwarded", + "refId": "B" + }, + { + "expr": "sum(rate(cilium_policy_l7_received_total{k8s_app=\"cilium\", pod=~\"$pod\"}[1m]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "received", + "refId": "C" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "L7 forwarded request", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "reqps", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "reqps", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 12, + "x": 12, + "y": 115 + }, + "hiddenSeries": false, + "id": 37, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(cilium_drop_count_total{direction=\"INGRESS\", k8s_app=\"cilium\", pod=~\"$pod\"}[5m])) by (reason)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{reason}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Cilium drops Ingress", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "Max per node processingTime": "#e24d42", + "Max per node upstreamTime": "#58140c", + "avg(cilium_policy_l7_parse_errors_total{pod=~\"cilium.*\"})": "#bf1b00", + "parse errors": "#bf1b00" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 12, + "x": 0, + "y": 120 + }, + "hiddenSeries": false, + "id": 94, + "legend": { + "alignAsTable": false, + "avg": true, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Max per node processingTime", + "yaxis": 2 + }, + { + "alias": "Max per node upstreamTime", + "yaxis": 2 + }, + { + "alias": "avg(cilium_policy_l7_parse_errors_total{pod=~\"cilium.*\"})", + "yaxis": 2 + }, + { + "alias": "parse errors", + "yaxis": 2 + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "avg(rate(cilium_proxy_upstream_reply_seconds_sum{k8s_app=\"cilium\", pod=~\"$pod\"}[1m])) by (pod, scope) / sum(rate(cilium_proxy_upstream_reply_seconds_count{k8s_app=\"cilium\", pod=~\"$pod\"}[1m])) by (pod, scope)", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "{{scope}}", + "refId": "A" + }, + { + "expr": "avg(cilium_policy_l7_parse_errors_total{k8s_app=\"cilium\", pod=~\"$pod\"}) by (pod)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "parse errors", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Proxy response time (Avg)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 12, + "x": 12, + "y": 120 + }, + "hiddenSeries": false, + "id": 114, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(cilium_drop_bytes_total{direction=\"INGRESS\", k8s_app=\"cilium\", pod=~\"$pod\"}[1m])) by (reason) * 8", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{reason}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Dropped Ingress Traffic", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bps", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "avg": "#64b0c8", + "count": "#9ac48a", + "max": "#5195ce", + "min": "#6ed0e0" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 12, + "x": 0, + "y": 125 + }, + "hiddenSeries": false, + "id": 104, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "max", + "fillBelowTo": "min", + "lines": false + }, + { + "alias": "min", + "lines": false + }, + { + "alias": "avg count", + "yaxis": 2 + }, + { + "alias": "max count", + "yaxis": 2 + }, + { + "alias": "avg count" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "min(rate(cilium_triggers_policy_update_call_duration_seconds_sum{k8s_app=\"cilium\", pod=~\"$pod\"}[1m])) by (pod, scope) / sum(rate(cilium_triggers_policy_update_call_duration_seconds_count{k8s_app=\"cilium\", pod=~\"$pod\"}[1m])) by (pod, scope)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "min", + "refId": "A" + }, + { + "expr": "avg(rate(cilium_triggers_policy_update_call_duration_seconds_sum{k8s_app=\"cilium\", pod=~\"$pod\"}[1m])) by (pod, scope) / sum(rate(cilium_triggers_policy_update_call_duration_seconds_count{k8s_app=\"cilium\", pod=~\"$pod\"}[1m])) by (pod, scope)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "avg", + "refId": "B" + }, + { + "expr": "max(rate(cilium_triggers_policy_update_call_duration_seconds_sum{k8s_app=\"cilium\", pod=~\"$pod\"}[1m])) by (pod, scope) / sum(rate(cilium_triggers_policy_update_call_duration_seconds_count{k8s_app=\"cilium\", pod=~\"$pod\"}[1m])) by (pod, scope)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "max", + "refId": "C" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Policy Trigger Duration", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "opm", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "Max per node processingTime": "#e24d42", + "Max per node upstreamTime": "#58140c", + "parse errors": "#bf1b00" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 12, + "x": 12, + "y": 125 + }, + "hiddenSeries": false, + "id": 66, + "legend": { + "alignAsTable": false, + "avg": true, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "parse errors", + "yaxis": 2 + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "max(rate(cilium_proxy_upstream_reply_seconds_sum{k8s_app=\"cilium\", pod=~\"$pod\"}[1m])) by (pod, scope) / sum(rate(cilium_proxy_upstream_reply_seconds_count{k8s_app=\"cilium\", pod=~\"$pod\"}[1m])) by (pod, scope)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Max {{scope}}", + "refId": "B" + }, + { + "expr": "max(rate(cilium_policy_l7_parse_errors_total{k8s_app=\"cilium\", pod=~\"$pod\"}[1m])) by (pod)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "parse errors", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Proxy response time (Max)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "both": "#7eb26d", + "egress": "#e5ac0e", + "ingress": "#e0752d", + "none": "#bf1b00" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 6, + "x": 0, + "y": 130 + }, + "hiddenSeries": false, + "id": 33, + "legend": { + "alignAsTable": false, + "avg": false, + "current": true, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sideWidth": null, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(cilium_policy_endpoint_enforcement_status{k8s_app=\"cilium\", pod=~\"$pod\"}) by (enforcement)", + "format": "time_series", + "hide": false, + "instant": true, + "interval": "1s", + "intervalFactor": 1, + "legendFormat": "{{enforcement}}", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Endpoints policy enforcement status", + "tooltip": { + "shared": false, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "series", + "name": null, + "show": true, + "values": [ + "total" + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "avg": "#b7dbab", + "max": "rgba(89, 132, 76, 0.54)", + "min": "#2f575e" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 6, + "x": 6, + "y": 130 + }, + "hiddenSeries": false, + "id": 100, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "max", + "fillBelowTo": "min", + "lines": false + }, + { + "alias": "min", + "lines": false + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "min(cilium_proxy_redirects{k8s_app=\"cilium\", pod=~\"$pod\"}) by (pod)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "min", + "refId": "A" + }, + { + "expr": "avg(cilium_proxy_redirects{k8s_app=\"cilium\", pod=~\"$pod\"}) by (pod)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "avg", + "refId": "B" + }, + { + "expr": "max(cilium_proxy_redirects{k8s_app=\"cilium\", pod=~\"$pod\"}) by (pod)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "max", + "refId": "C" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Proxy Redirects", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "average duration": "#d683ce", + "folds": "#614d93", + "max duration": "#614d93", + "max trigger": "#967302", + "min duration": "#584477", + "min trigger": "#fceaca" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 12, + "x": 12, + "y": 130 + }, + "hiddenSeries": false, + "id": 102, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "max", + "fillBelowTo": "min trigger", + "lines": false + }, + { + "alias": "min trigger", + "lines": false + }, + { + "alias": "folds", + "yaxis": 2 + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "min(rate(cilium_triggers_policy_update_total{k8s_app=\"cilium\", pod=~\"$pod\"}[1m])) by (pod) * 60", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "min trigger", + "refId": "A" + }, + { + "expr": "avg(rate(cilium_triggers_policy_update_total{k8s_app=\"cilium\", pod=~\"$pod\"}[1m])) by (pod) * 60", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "average trigger", + "refId": "B" + }, + { + "expr": "max(rate(cilium_triggers_policy_update_total{k8s_app=\"cilium\", pod=~\"$pod\"}[1m])) by (pod) * 60", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "max trigger", + "refId": "C" + }, + { + "expr": "max(rate(cilium_triggers_policy_update_folds{k8s_app=\"cilium\", pod=~\"$pod\"}[1m])) by (pod) * 60", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "folds", + "refId": "D" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Policy Trigger Runs", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "opm", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "max": "#f2c96d", + "policy errors": "#bf1b00", + "policy change errors": "#bf1b00" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 12, + "x": 0, + "y": 135 + }, + "hiddenSeries": false, + "id": 85, + "legend": { + "alignAsTable": false, + "avg": false, + "current": true, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "policy errors", + "yaxis": 2 + }, + { + "alias": "max", + "fillBelowTo": "min", + "lines": false + }, + { + "alias": "min", + "lines": false + }, + { + "alias": "policy change errors", + "yaxis": 2 + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "min(cilium_policy{k8s_app=\"cilium\", pod=~\"$pod\"}) by(pod)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "min", + "refId": "A" + }, + { + "expr": "avg(cilium_policy{k8s_app=\"cilium\", pod=~\"$pod\"}) by(pod)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "avg", + "refId": "B" + }, + { + "expr": "max(cilium_policy{k8s_app=\"cilium\", pod=~\"$pod\"}) by(pod)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "max", + "refId": "C" + }, + { + "expr": "sum(cilium_policy_change_total{k8s_app=\"cilium\", pod=~\"$pod\"}, outcome=\"fail\") by (pod)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "policy change errors", + "refId": "D" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Policies Per Node", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "Max per node processingTime": "#e24d42", + "Max per node upstreamTime": "#58140c", + "parse errors": "#bf1b00" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 12, + "x": 12, + "y": 135 + }, + "hiddenSeries": false, + "id": 123, + "legend": { + "alignAsTable": false, + "avg": true, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "parse errors", + "yaxis": 2 + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "avg(rate(cilium_proxy_upstream_reply_seconds_count{k8s_app=\"cilium\", pod=~\"$pod\"}[1m])) by (pod, scope)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{scope}}", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "DNS proxy requests", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "avg": "#f9d9f9", + "max": "#806eb7", + "min": "#806eb7" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 12, + "x": 12, + "y": 140 + }, + "hiddenSeries": false, + "id": 117, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "max", + "fillBelowTo": "min", + "lines": false + }, + { + "alias": "min", + "lines": false + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "min(cilium_policy_max_revision{k8s_app=\"cilium\", pod=~\"$pod\"}) by (pod)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "min", + "refId": "A" + }, + { + "expr": "avg(cilium_policy_max_revision{k8s_app=\"cilium\", pod=~\"$pod\"}) by (pod)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "avg", + "refId": "B" + }, + { + "expr": "max(cilium_policy_max_revision{k8s_app=\"cilium\", pod=~\"$pod\"}) by (pod)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "max", + "refId": "C" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Policy Revision", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "content": "", + "datasource": null, + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 145 + }, + "id": 73, + "links": [], + "mode": "markdown", + "title": "Endpoints", + "type": "text" + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "decimals": null, + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 146 + }, + "hiddenSeries": false, + "id": 55, + "legend": { + "alignAsTable": false, + "avg": true, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "avg(histogram_quantile(0.90, rate(cilium_endpoint_regeneration_time_stats_seconds_bucket{k8s_app=\"cilium\", scope!=\"total\", pod=~\"$pod\"}[5m]))) by (scope)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{scope}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Endpoint regeneration time (90th percentile)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "decimals": null, + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 146 + }, + "hiddenSeries": false, + "id": 115, + "legend": { + "alignAsTable": false, + "avg": true, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "avg(histogram_quantile(0.99, rate(cilium_endpoint_regeneration_time_stats_seconds_bucket{k8s_app=\"cilium\", scope!=\"total\", pod=~\"$pod\"}[5m]))) by (scope)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{scope}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Endpoint regeneration time (99th percentile)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "fail": "#bf1b00", + "fail/min": "#890f02", + "success": "#447ebc", + "success/min": "#3f6833" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 3, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 12, + "x": 0, + "y": 155 + }, + "hiddenSeries": false, + "id": 49, + "legend": { + "avg": true, + "current": false, + "max": true, + "min": false, + "show": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 2, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "fail", + "yaxis": 2 + }, + { + "alias": "success" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(cilium_endpoint_regenerations_total{k8s_app=\"cilium\", pod=~\"$pod\"}[30s])) by(outcome)", + "format": "time_series", + "instant": false, + "intervalFactor": 1, + "legendFormat": "{{outcome}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Endpoint regenerations", + "tooltip": { + "shared": false, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "opm", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "opm", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "disconnecting": "#614d93", + "ready": "rgba(81, 220, 95, 0.52)", + "waiting-to-regenerate": "#0a50a1" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 12, + "x": 12, + "y": 155 + }, + "hiddenSeries": false, + "id": 51, + "legend": { + "alignAsTable": false, + "avg": false, + "current": true, + "max": false, + "min": false, + "show": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "options": { + "dataLinks": [] + }, + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(cilium_endpoint_state{k8s_app=\"cilium\", pod=~\"$pod\"}) by (endpoint_state)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{endpoint_state}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Cilium endpoint state", + "tooltip": { + "shared": false, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "content": "", + "datasource": null, + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 160 + }, + "id": 74, + "links": [], + "mode": "markdown", + "title": "Controllers", + "type": "text" + }, + { + "aliasColors": { + "Failed": "#bf1b00", + "Failing": "#890f02", + "Runs": "#5195ce" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 3, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 12, + "x": 0, + "y": 161 + }, + "hiddenSeries": false, + "id": 70, + "legend": { + "alignAsTable": false, + "avg": true, + "current": false, + "max": true, + "min": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Failing", + "yaxis": 1 + }, + { + "alias": "Failed", + "yaxis": 2 + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(cilium_controllers_runs_total{k8s_app=\"cilium\", pod=~\"$pod\"}[1m])) by (pod)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Runs", + "refId": "A" + }, + { + "expr": "sum(cilium_controllers_failing{k8s_app=\"cilium\", pod=~\"$pod\"}) by(pod)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Failed", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Controllers", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "opm", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "opm", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "duration failure": "#890f02", + "duration success": "#508642", + "failure": "#890f02", + "runs failure": "#890f02", + "runs success": "#7eb26d", + "success": "#508642" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 12, + "x": 12, + "y": 161 + }, + "hiddenSeries": false, + "id": 68, + "legend": { + "alignAsTable": false, + "avg": true, + "current": false, + "hideEmpty": false, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "repeatDirection": "h", + "seriesOverrides": [ + { + "alias": "success", + "yaxis": 1 + }, + { + "alias": "failure", + "yaxis": 2 + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(cilium_controllers_runs_duration_seconds_sum{k8s_app=\"cilium\", pod=~\"$pod\"}[1m])) by (pod, status) / sum(rate(cilium_controllers_runs_duration_seconds_count{k8s_app=\"cilium\", pod=~\"$pod\"}[1m])) by (pod, status)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{status}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Controller Durations", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "s", + "label": "", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "s", + "label": "", + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "content": "", + "datasource": null, + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 166 + }, + "id": 60, + "links": [], + "mode": "markdown", + "title": "Kubernetes integration", + "type": "text" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 167 + }, + "hiddenSeries": false, + "id": 163, + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "avg(rate(cilium_k8s_client_api_latency_time_seconds_sum{k8s_app=\"cilium\", pod=~\"$pod\"}[1m])/rate(cilium_k8s_client_api_latency_time_seconds_count{k8s_app=\"cilium\", pod=~\"$pod\"}[1m])) by (pod, method, path)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{method}} {{path}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "apiserver latency (average node)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 167 + }, + "hiddenSeries": false, + "id": 165, + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "max(rate(cilium_k8s_client_api_latency_time_seconds_sum{k8s_app=\"cilium\", pod=~\"$pod\"}[1m])/rate(cilium_k8s_client_api_latency_time_seconds_count{k8s_app=\"cilium\", pod=~\"$pod\"}[1m])) by (pod, method, path)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{method}} {{path}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "apiserver latency (max node)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 174 + }, + "hiddenSeries": false, + "id": 168, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": true, + "min": false, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(cilium_k8s_client_api_latency_time_seconds_count{k8s_app=\"cilium\", pod=~\"$pod\"}[1m])) by (pod, method, path)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{method}} {{path}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "apiserver #calls (sum all nodes)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 174 + }, + "hiddenSeries": false, + "id": 166, + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": true, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(cilium_k8s_client_api_calls_total{k8s_app=\"cilium\", pod=~\"$pod\"}[1m])) by (pod, method, return_code)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{method}} {{return_code}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "apiserver calls (sum all nodes)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 12, + "x": 0, + "y": 182 + }, + "hiddenSeries": false, + "id": 172, + "legend": { + "alignAsTable": false, + "avg": true, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "show": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "paceLength": 10, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(cilium_kubernetes_events_received_total{k8s_app=\"cilium\", equal=\"true\", valid=\"true\", pod=~\"$pod\"}[5m])) by (pod, scope, action)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{action}} {{scope}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Valid, Unnecessary K8s Events Received", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 12, + "x": 12, + "y": 182 + }, + "hiddenSeries": false, + "id": 174, + "legend": { + "avg": true, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "show": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "paceLength": 10, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(cilium_kubernetes_events_received_total{k8s_app=\"cilium\", equal=\"true\", valid=\"false\", pod=~\"$pod\"}[5m])) by (pod, scope, action)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{action}} {{scope}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Invalid, Unnecessary K8s Events Received", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 188 + }, + "hiddenSeries": false, + "id": 175, + "legend": { + "avg": true, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "show": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "paceLength": 10, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(cilium_kubernetes_events_received_total{k8s_app=\"cilium\", equal=\"false\", valid=\"true\", pod=~\"$pod\"}[5m])) by (pod, scope, action, valid)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{action}} {{scope}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Valid, Necessary K8s Events Received", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 188 + }, + "hiddenSeries": false, + "id": 173, + "legend": { + "avg": true, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "show": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "paceLength": 10, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(cilium_kubernetes_events_received_total{k8s_app=\"cilium\", equal=\"false\", valid=\"false\", pod=~\"$pod\"}[5m])) by (pod, scope, action)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{action}} {{scope}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Invalid, Necessary K8s Events Received", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 196 + }, + "hiddenSeries": false, + "id": 108, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "avg(rate(cilium_kubernetes_events_total{k8s_app=\"cilium\", scope=\"CiliumNetworkPolicy\", pod=~\"$pod\"}[1m])) by (pod, action) * 60", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{action}} avg", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "CiliumNetworkPolicy Events", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "opm", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "create avg": "#70dbed", + "delete avg": "#e24d42", + "update avg": "#e0f9d7" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 196 + }, + "hiddenSeries": false, + "id": 119, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "avg(rate(cilium_kubernetes_events_total{k8s_app=\"cilium\", scope=\"NetworkPolicy\", pod=~\"$pod\"}[1m])) by (pod, action) * 60", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{action}} avg", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "NetworkPolicy Events", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "opm", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "create avg": "#70dbed", + "delete avg": "#e24d42", + "update avg": "#e0f9d7" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 203 + }, + "hiddenSeries": false, + "id": 109, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "avg(rate(cilium_kubernetes_events_total{k8s_app=\"cilium\", scope=\"Pod\", pod=~\"$pod\"}[1m])) by (pod, action) * 60", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{action}} avg", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Pod Events", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "opm", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "create avg": "#70dbed", + "delete avg": "#e24d42", + "update avg": "#e0f9d7" + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 203 + }, + "hiddenSeries": false, + "id": 122, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "avg(rate(cilium_kubernetes_events_total{k8s_app=\"cilium\", scope=\"Node\", pod=~\"$pod\"}[1m])) by (pod, action) * 60", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{action}} avg", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Node Events", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "opm", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 210 + }, + "hiddenSeries": false, + "id": 118, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "avg(rate(cilium_kubernetes_events_total{k8s_app=\"cilium\", scope=\"Service\", pod=~\"$pod\"}[1m])) by (pod, action) * 60", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{action}}", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Service Events", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "opm", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 210 + }, + "hiddenSeries": false, + "id": 120, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "avg(rate(cilium_kubernetes_events_total{k8s_app=\"cilium\", scope=\"Endpoint\", pod=~\"$pod\"}[1m])) by (pod, action) * 60", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{action}}", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Endpoints Events", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "opm", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 217 + }, + "hiddenSeries": false, + "id": 121, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "avg(rate(cilium_kubernetes_events_total{k8s_app=\"cilium\", scope=\"Namespace\", pod=~\"$pod\"}[1m])) by (pod, action) * 60", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{action}}", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Namespace Events", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "opm", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "refresh": false, + "schemaVersion": 25, + "style": "dark", + "tags": [], + "templating": { + "list": [ + { + "allValue": "cilium.*", + "current": { + "selected": false, + "text": "All", + "value": "$__all" + }, + "datasource": "prometheus", + "definition": "label_values(cilium_version, pod)", + "hide": 0, + "includeAll": true, + "label": null, + "multi": false, + "name": "pod", + "options": [], + "query": "label_values(cilium_version, pod)", + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + } + ] + }, + "time": { + "from": "now-30m", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "utc", + "title": "Cilium Metrics", + "uid": "vtuWtdumz", + "version": 1 +} diff --git a/packages/system/cilium/charts/cilium/files/cilium-envoy/configmap/bootstrap-config.json b/packages/system/cilium/charts/cilium/files/cilium-envoy/configmap/bootstrap-config.json new file mode 100644 index 00000000..ea8984db --- /dev/null +++ b/packages/system/cilium/charts/cilium/files/cilium-envoy/configmap/bootstrap-config.json @@ -0,0 +1,323 @@ +{ + "node": { + "id": "host~127.0.0.1~no-id~localdomain", + "cluster": "ingress-cluster" + }, + "staticResources": { + "listeners": [ + {{- if and .Values.proxy.prometheus.enabled .Values.envoy.prometheus.enabled }} + { + "name": "envoy-prometheus-metrics-listener", + "address": { + "socket_address": { + "address": "0.0.0.0", + "port_value": {{ .Values.proxy.prometheus.port | default .Values.envoy.prometheus.port }} + } + }, + "filter_chains": [ + { + "filters": [ + { + "name": "envoy.filters.network.http_connection_manager", + "typed_config": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", + "stat_prefix": "envoy-prometheus-metrics-listener", + "route_config": { + "virtual_hosts": [ + { + "name": "prometheus_metrics_route", + "domains": [ + "*" + ], + "routes": [ + { + "name": "prometheus_metrics_route", + "match": { + "prefix": "/metrics" + }, + "route": { + "cluster": "/envoy-admin", + "prefix_rewrite": "/stats/prometheus" + } + } + ] + } + ] + }, + "http_filters": [ + { + "name": "envoy.filters.http.router", + "typed_config": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" + } + } + ], + "stream_idle_timeout": "0s" + } + } + ] + } + ] + }, + {{- end }} + { + "name": "envoy-health-listener", + "address": { + "socket_address": { + "address": {{ .Values.ipv4.enabled | ternary "127.0.0.1" "::1" | quote }}, + "port_value": {{ .Values.envoy.healthPort }} + } + }, + {{- if and .Values.ipv4.enabled .Values.ipv6.enabled }} + "additional_addresses": [ + { + "address": { + "socket_address": { + "address": "::1", + "port_value": {{ .Values.envoy.healthPort }} + } + } + } + ], + {{- end }} + "filter_chains": [ + { + "filters": [ + { + "name": "envoy.filters.network.http_connection_manager", + "typed_config": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", + "stat_prefix": "envoy-health-listener", + "route_config": { + "virtual_hosts": [ + { + "name": "health", + "domains": [ + "*" + ], + "routes": [ + { + "name": "health", + "match": { + "prefix": "/healthz" + }, + "route": { + "cluster": "/envoy-admin", + "prefix_rewrite": "/ready" + } + } + ] + } + ] + }, + "http_filters": [ + { + "name": "envoy.filters.http.router", + "typed_config": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" + } + } + ], + "stream_idle_timeout": "0s" + } + } + ] + } + ] + } + ], + "clusters": [ + { + "name": "ingress-cluster", + "type": "ORIGINAL_DST", + "connectTimeout": "{{ .Values.envoy.connectTimeoutSeconds }}s", + "lbPolicy": "CLUSTER_PROVIDED", + "typedExtensionProtocolOptions": { + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "commonHttpProtocolOptions": { + "idleTimeout": "{{ .Values.envoy.idleTimeoutDurationSeconds }}s", + "maxConnectionDuration": "{{ .Values.envoy.maxConnectionDurationSeconds }}s", + "maxRequestsPerConnection": {{ .Values.envoy.maxRequestsPerConnection }} + }, + "useDownstreamProtocolConfig": {} + } + }, + "cleanupInterval": "{{ .Values.envoy.connectTimeoutSeconds }}.500s" + }, + { + "name": "egress-cluster-tls", + "type": "ORIGINAL_DST", + "connectTimeout": "{{ .Values.envoy.connectTimeoutSeconds }}s", + "lbPolicy": "CLUSTER_PROVIDED", + "typedExtensionProtocolOptions": { + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "commonHttpProtocolOptions": { + "idleTimeout": "{{ .Values.envoy.idleTimeoutDurationSeconds }}s", + "maxConnectionDuration": "{{ .Values.envoy.maxConnectionDurationSeconds }}s", + "maxRequestsPerConnection": {{ .Values.envoy.maxRequestsPerConnection }} + }, + "upstreamHttpProtocolOptions": {}, + "useDownstreamProtocolConfig": {} + } + }, + "cleanupInterval": "{{ .Values.envoy.connectTimeoutSeconds }}.500s", + "transportSocket": { + "name": "cilium.tls_wrapper", + "typedConfig": { + "@type": "type.googleapis.com/cilium.UpstreamTlsWrapperContext" + } + } + }, + { + "name": "egress-cluster", + "type": "ORIGINAL_DST", + "connectTimeout": "{{ .Values.envoy.connectTimeoutSeconds }}s", + "lbPolicy": "CLUSTER_PROVIDED", + "typedExtensionProtocolOptions": { + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "commonHttpProtocolOptions": { + "idleTimeout": "{{ .Values.envoy.idleTimeoutDurationSeconds }}s", + "maxConnectionDuration": "{{ .Values.envoy.maxConnectionDurationSeconds }}s", + "maxRequestsPerConnection": {{ .Values.envoy.maxRequestsPerConnection }} + }, + "useDownstreamProtocolConfig": {} + } + }, + "cleanupInterval": "{{ .Values.envoy.connectTimeoutSeconds }}.500s" + }, + { + "name": "ingress-cluster-tls", + "type": "ORIGINAL_DST", + "connectTimeout": "{{ .Values.envoy.connectTimeoutSeconds }}s", + "lbPolicy": "CLUSTER_PROVIDED", + "typedExtensionProtocolOptions": { + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "commonHttpProtocolOptions": { + "idleTimeout": "{{ .Values.envoy.idleTimeoutDurationSeconds }}s", + "maxConnectionDuration": "{{ .Values.envoy.maxConnectionDurationSeconds }}s", + "maxRequestsPerConnection": {{ .Values.envoy.maxRequestsPerConnection }} + }, + "upstreamHttpProtocolOptions": {}, + "useDownstreamProtocolConfig": {} + } + }, + "cleanupInterval": "{{ .Values.envoy.connectTimeoutSeconds }}.500s", + "transportSocket": { + "name": "cilium.tls_wrapper", + "typedConfig": { + "@type": "type.googleapis.com/cilium.UpstreamTlsWrapperContext" + } + } + }, + { + "name": "xds-grpc-cilium", + "type": "STATIC", + "connectTimeout": "{{ .Values.envoy.connectTimeoutSeconds }}s", + "loadAssignment": { + "clusterName": "xds-grpc-cilium", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "pipe": { + "path": "/var/run/cilium/envoy/sockets/xds.sock" + } + } + } + } + ] + } + ] + }, + "typedExtensionProtocolOptions": { + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "explicitHttpConfig": { + "http2ProtocolOptions": {} + } + } + } + }, + { + "name": "/envoy-admin", + "type": "STATIC", + "connectTimeout": "{{ .Values.envoy.connectTimeoutSeconds }}s", + "loadAssignment": { + "clusterName": "/envoy-admin", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "pipe": { + "path": "/var/run/cilium/envoy/sockets/admin.sock" + } + } + } + } + ] + } + ] + } + } + ] + }, + "dynamicResources": { + "ldsConfig": { + "apiConfigSource": { + "apiType": "GRPC", + "transportApiVersion": "V3", + "grpcServices": [ + { + "envoyGrpc": { + "clusterName": "xds-grpc-cilium" + } + } + ], + "setNodeOnFirstMessageOnly": true + }, + "resourceApiVersion": "V3" + }, + "cdsConfig": { + "apiConfigSource": { + "apiType": "GRPC", + "transportApiVersion": "V3", + "grpcServices": [ + { + "envoyGrpc": { + "clusterName": "xds-grpc-cilium" + } + } + ], + "setNodeOnFirstMessageOnly": true + }, + "resourceApiVersion": "V3" + } + }, + "layeredRuntime": { + "layers": [ + { + "name": "static_layer_0", + "staticLayer": { + "overload": { + "global_downstream_max_connections": 50000 + } + } + } + ] + }, + "admin": { + "address": { + "pipe": { + "path": "/var/run/cilium/envoy/sockets/admin.sock" + } + } + } +} diff --git a/packages/system/cilium/charts/cilium/files/cilium-operator/dashboards/cilium-operator-dashboard.json b/packages/system/cilium/charts/cilium/files/cilium-operator/dashboards/cilium-operator-dashboard.json new file mode 100644 index 00000000..e677deae --- /dev/null +++ b/packages/system/cilium/charts/cilium/files/cilium-operator/dashboards/cilium-operator-dashboard.json @@ -0,0 +1,998 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": "-- Grafana --", + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "gnetId": null, + "graphTooltip": 0, + "id": 8, + "links": [], + "panels": [ + { + "aliasColors": { + "avg": "#cffaff" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 12, + "x": 0, + "y": 0 + }, + "hiddenSeries": false, + "id": 24, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "max", + "fillBelowTo": "min", + "lines": false + }, + { + "alias": "min", + "lines": false + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "min(irate(cilium_operator_process_cpu_seconds_total{io_cilium_app=\"operator\"}[1m])) by (pod) * 100", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "min", + "refId": "A" + }, + { + "expr": "avg(irate(cilium_operator_process_cpu_seconds_total{io_cilium_app=\"operator\"}[1m])) by (pod) * 100", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "avg", + "refId": "B" + }, + { + "expr": "max(irate(cilium_operator_process_cpu_seconds_total{io_cilium_app=\"operator\"}[1m])) by (pod) * 100", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "max", + "refId": "C" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "CPU Usage per node", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "percent", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "MAX_resident_memory_bytes_max": "#e5ac0e" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 12, + "x": 12, + "y": 0 + }, + "hiddenSeries": false, + "id": 26, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "avg(cilium_operator_process_resident_memory_bytes{io_cilium_app=\"operator\"})", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "AVG_resident_memory_bytes", + "refId": "C" + }, + { + "expr": "max(cilium_operator_process_resident_memory_bytes{io_cilium_app=\"operator\"})", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "MAX_resident_memory_bytes_max", + "refId": "D" + }, + { + "expr": "min(cilium_operator_process_resident_memory_bytes{io_cilium_app=\"operator\"})", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "MIN_resident_memory_bytes_min", + "refId": "E" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Resident memory status", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "collapsed": false, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 5 + }, + "id": 6, + "panels": [], + "title": "IPAM", + "type": "row" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 6 + }, + "hiddenSeries": false, + "id": 8, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "paceLength": 10, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "avg(cilium_operator_ipam_ips) by (type)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{type}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "IP Addresses", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 6 + }, + "hiddenSeries": false, + "id": 10, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "paceLength": 10, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "rate(cilium_operator_ec2_api_duration_seconds_sum[1m])/rate(cilium_operator_ec2_api_duration_seconds_count[1m])", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{operation}} {{response_code}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "EC2 API Interactions", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "dtdurations", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 8, + "x": 0, + "y": 14 + }, + "hiddenSeries": false, + "id": 4, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "paceLength": 10, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "cilium_operator_ipam_nodes", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{category}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Number of nodes", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 8, + "x": 8, + "y": 14 + }, + "hiddenSeries": false, + "id": 12, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "paceLength": 10, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "cilium_operator_ipam_available", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "interfaces", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "# interfaces with addresses available", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 8, + "x": 16, + "y": 14 + }, + "hiddenSeries": false, + "id": 16, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "paceLength": 10, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "rate(cilium_operator_ipam_resync_total[1m])", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "operations", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Metadata Resync Operations", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 21 + }, + "hiddenSeries": false, + "id": 14, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "paceLength": 10, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "rate(cilium_operator_ec2_api_rate_limit_duration_seconds_sum[1m])/rate(cilium_operator_ec2_api_rate_limit_duration_seconds_count[1m])", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{operation}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "EC2 client side rate limiting", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "reqps", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 21 + }, + "hiddenSeries": false, + "id": 2, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "paceLength": 10, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "avg(rate(cilium_operator_ipam_interface_creation_ops[1m])) by (subnetId, status)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{status}} ({{subnetId}})", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Interface Creation", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "refresh": false, + "schemaVersion": 25, + "style": "dark", + "tags": [], + "templating": { + "list": [] + }, + "time": { + "from": "now-30m", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "", + "title": "Cilium Operator", + "uid": "1GC0TT4Wz", + "version": 2 +} diff --git a/packages/system/cilium/charts/cilium/files/hubble/dashboards/hubble-dashboard.json b/packages/system/cilium/charts/cilium/files/hubble/dashboards/hubble-dashboard.json new file mode 100644 index 00000000..12de657d --- /dev/null +++ b/packages/system/cilium/charts/cilium/files/hubble/dashboards/hubble-dashboard.json @@ -0,0 +1,3232 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": "-- Grafana --", + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "gnetId": null, + "graphTooltip": 0, + "id": 3, + "links": [], + "panels": [ + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 14, + "panels": [], + "title": "General Processing", + "type": "row" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fill": 1, + "gridPos": { + "h": 5, + "w": 12, + "x": 0, + "y": 1 + }, + "id": 12, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": {}, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "max", + "fillBelowTo": "avg", + "lines": false + }, + { + "alias": "avg", + "fill": 0, + "fillBelowTo": "min" + }, + { + "alias": "min", + "lines": false + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "avg(sum(rate(hubble_flows_processed_total[1m])) by (pod))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "avg", + "refId": "A" + }, + { + "expr": "min(sum(rate(hubble_flows_processed_total[1m])) by (pod))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "min", + "refId": "B" + }, + { + "expr": "max(sum(rate(hubble_flows_processed_total[1m])) by (pod))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "max", + "refId": "C" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Flows processed Per Node", + "tooltip": { + "shared": true, + "sort": 1, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fill": 1, + "gridPos": { + "h": 5, + "w": 12, + "x": 12, + "y": 1 + }, + "id": 32, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": {}, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(hubble_flows_processed_total[1m])) by (pod, type)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{type}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Flows Types", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fill": 1, + "gridPos": { + "h": 5, + "w": 12, + "x": 0, + "y": 6 + }, + "id": 59, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": {}, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(hubble_flows_processed_total{type=\"L7\"}[1m])) by (pod, subtype)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{subtype}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "L7 Flow Distribution", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fill": 1, + "gridPos": { + "h": 5, + "w": 12, + "x": 12, + "y": 6 + }, + "id": 60, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": {}, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(hubble_flows_processed_total{type=\"Trace\"}[1m])) by (pod, subtype)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{subtype}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Trace Flow Distribution", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 11 + }, + "id": 16, + "panels": [], + "title": "Network", + "type": "row" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fill": 1, + "gridPos": { + "h": 5, + "w": 12, + "x": 0, + "y": 12 + }, + "id": 33, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": {}, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(hubble_flows_processed_total[1m])) by (pod, verdict)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{verdict}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Forwarded vs Dropped", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fill": 1, + "gridPos": { + "h": 5, + "w": 12, + "x": 12, + "y": 12 + }, + "id": 8, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": {}, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(hubble_drop_total[1m])) by (pod, reason)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{reason}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Drop Reason", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fill": 1, + "gridPos": { + "h": 5, + "w": 12, + "x": 0, + "y": 17 + }, + "id": 34, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": {}, + "percentage": true, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum (rate(hubble_port_distribution_total[1m])) by (pod, protocol)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{protocol}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Protocol Usage", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fill": 1, + "gridPos": { + "h": 5, + "w": 12, + "x": 12, + "y": 17 + }, + "id": 18, + "legend": { + "alignAsTable": true, + "avg": false, + "current": true, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": {}, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "topk(10, sum (rate(hubble_port_distribution_total{port!=\"0\"}[1m])) by (pod, port, protocol))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{port}}/{{protocol}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Top 10 Port Distribution", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fill": 1, + "gridPos": { + "h": 5, + "w": 12, + "x": 0, + "y": 22 + }, + "id": 10, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": {}, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "fin", + "yaxis": 1 + }, + { + "alias": "FIN", + "yaxis": 2 + }, + { + "alias": "RST", + "yaxis": 2 + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(hubble_tcp_flags_total{family=\"IPv4\"}[1m])) by (pod, flag)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{flag}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "TCPv4", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "alert": { + "conditions": [ + { + "evaluator": { + "params": [ + 0.2 + ], + "type": "gt" + }, + "operator": { + "type": "and" + }, + "query": { + "params": [ + "B", + "5m", + "now" + ] + }, + "reducer": { + "params": [], + "type": "avg" + }, + "type": "query" + } + ], + "executionErrorState": "alerting", + "for": "5m", + "frequency": "1m", + "handler": 1, + "name": "Missing TCP SYN-ACK", + "noDataState": "no_data", + "notifications": [] + }, + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fill": 1, + "gridPos": { + "h": 5, + "w": 12, + "x": 12, + "y": 22 + }, + "id": 62, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": {}, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "fin", + "yaxis": 1 + }, + { + "alias": "FIN", + "yaxis": 2 + }, + { + "alias": "RST", + "yaxis": 2 + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(hubble_tcp_flags_total{family=\"IPv4\", flag=\"SYN\"}[1m])) by (pod) - sum(rate(hubble_tcp_flags_total{family=\"IPv4\", flag=\"SYN-ACK\"}[1m])) by (pod)", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "Missing SYN-ACK", + "refId": "B" + } + ], + "thresholds": [ + { + "colorMode": "critical", + "fill": true, + "line": true, + "op": "gt", + "value": 0.2 + } + ], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Missing TCPv4 SYN-ACKs", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fill": 1, + "gridPos": { + "h": 5, + "w": 12, + "x": 0, + "y": 27 + }, + "id": 35, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": {}, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "fin", + "yaxis": 1 + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(hubble_tcp_flags_total{family=\"IPv6\"}[1m])) by (pod, flag)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{flag}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "TCPv6", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "alert": { + "conditions": [ + { + "evaluator": { + "params": [ + 0.2 + ], + "type": "gt" + }, + "operator": { + "type": "and" + }, + "query": { + "params": [ + "B", + "5m", + "now" + ] + }, + "reducer": { + "params": [], + "type": "avg" + }, + "type": "query" + } + ], + "executionErrorState": "alerting", + "for": "5m", + "frequency": "1m", + "handler": 1, + "name": "Missing TCPv6 SYN-ACKs alert", + "noDataState": "no_data", + "notifications": [] + }, + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fill": 1, + "gridPos": { + "h": 5, + "w": 12, + "x": 12, + "y": 27 + }, + "id": 63, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": {}, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "fin", + "yaxis": 1 + }, + { + "alias": "FIN", + "yaxis": 2 + }, + { + "alias": "RST", + "yaxis": 2 + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(hubble_tcp_flags_total{family=\"IPv6\", flag=\"SYN\"}[1m])) by (pod) - sum(rate(hubble_tcp_flags_total{family=\"IPv6\", flag=\"SYN-ACK\"}[1m])) by (pod)", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "Missing SYN-ACK", + "refId": "B" + } + ], + "thresholds": [ + { + "colorMode": "critical", + "fill": true, + "line": true, + "op": "gt", + "value": 0.2 + } + ], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Missing TCPv6 SYN-ACKs", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fill": 1, + "gridPos": { + "h": 5, + "w": 12, + "x": 0, + "y": 32 + }, + "id": 31, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": {}, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(hubble_icmp_total{family=\"IPv4\"}[1m])) by (pod, type)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{type}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "ICMPv4", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "alert": { + "conditions": [ + { + "evaluator": { + "params": [ + 0.1 + ], + "type": "gt" + }, + "operator": { + "type": "and" + }, + "query": { + "params": [ + "B", + "5m", + "now" + ] + }, + "reducer": { + "params": [], + "type": "avg" + }, + "type": "query" + } + ], + "executionErrorState": "alerting", + "for": "5m", + "frequency": "1m", + "handler": 1, + "name": "Missing ICMPv4 Echo-Reply alert", + "noDataState": "no_data", + "notifications": [] + }, + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fill": 1, + "gridPos": { + "h": 5, + "w": 12, + "x": 12, + "y": 32 + }, + "id": 64, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": {}, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(hubble_icmp_total{family=\"IPv4\", type=\"EchoRequest\"}[1m])) by (pod) - sum(rate(hubble_icmp_total{family=\"IPv4\", type=\"EchoReply\"}[1m])) by (pod)", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "Missing ICMP Echo-Reply", + "refId": "B" + } + ], + "thresholds": [ + { + "colorMode": "critical", + "fill": true, + "line": true, + "op": "gt", + "value": 0.1 + } + ], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Missing ICMPv4 Echo-Reply", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fill": 1, + "gridPos": { + "h": 5, + "w": 12, + "x": 0, + "y": 37 + }, + "id": 36, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": {}, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(hubble_icmp_total{family=\"IPv6\"}[1m])) by (pod, type)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{type}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "ICMPv6", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fill": 1, + "gridPos": { + "h": 5, + "w": 12, + "x": 12, + "y": 37 + }, + "id": 65, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": {}, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(hubble_icmp_total{family=\"IPv6\", type=\"EchoRequest\"}[1m])) by (pod) - sum(rate(hubble_icmp_total{family=\"IPv6\", type=\"EchoReply\"}[1m])) by (pod)", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "Missing ICMP Echo-Reply", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Missing ICMPv6 Echo-Reply", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 42 + }, + "id": 42, + "panels": [], + "title": "Network Policy", + "type": "row" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fill": 1, + "gridPos": { + "h": 4, + "w": 12, + "x": 0, + "y": 43 + }, + "id": 43, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": {}, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(hubble_drop_total{reason=\"POLICY_DENIED\"}[1m])) by (pod, reason)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{reason}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Denies by Reason", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fill": 1, + "gridPos": { + "h": 4, + "w": 12, + "x": 12, + "y": 43 + }, + "id": 61, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": {}, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(hubble_drop_total{reason=\"POLICY_DENIED\"}[1m])) by (pod, protocol)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{protocol}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Denied Packets by Protocol", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fill": 1, + "gridPos": { + "h": 5, + "w": 12, + "x": 0, + "y": 47 + }, + "id": 55, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": {}, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "topk(10, sum(rate(hubble_drop_total{reason=\"POLICY_DENIED\"}[1m])) by (pod, source))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{source}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Top 10 Source Pods with Denied Packets", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fill": 1, + "gridPos": { + "h": 5, + "w": 12, + "x": 12, + "y": 47 + }, + "id": 54, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": {}, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "topk(10, sum(rate(hubble_drop_total{reason=\"POLICY_DENIED\"}[1m])) by (pod, destination))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{destination}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Top 10 Destination Pods with Denied Packets", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 52 + }, + "id": 47, + "panels": [], + "title": "HTTP", + "type": "row" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fill": 1, + "gridPos": { + "h": 6, + "w": 12, + "x": 0, + "y": 53 + }, + "id": 45, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": {}, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(hubble_http_requests_total[1m])) by (pod, method)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{method}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "HTTP Requests", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 1, + "format": "reqps", + "label": "", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fill": 1, + "gridPos": { + "h": 6, + "w": 12, + "x": 12, + "y": 53 + }, + "id": 49, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": {}, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(hubble_http_responses_total[1m])) by (pod, status)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{status}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "HTTP responses", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 1, + "format": "reqps", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fill": 1, + "gridPos": { + "h": 5, + "w": 12, + "x": 0, + "y": 59 + }, + "id": 51, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": {}, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "histogram_quantile(0.5, rate(hubble_http_request_duration_seconds_bucket[1m]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{method}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "HTTP Request/Response Latency (p50)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fill": 1, + "gridPos": { + "h": 5, + "w": 12, + "x": 12, + "y": 59 + }, + "id": 58, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": {}, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "histogram_quantile(0.99, rate(hubble_http_request_duration_seconds_bucket[1m]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{method}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "HTTP Request/Response Latency (p99)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fill": 1, + "gridPos": { + "h": 5, + "w": 12, + "x": 0, + "y": 64 + }, + "id": 53, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": {}, + "percentage": true, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(hubble_http_requests_total[5m])) by (pod, protocol)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{protocol}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "HTTP Protocol Usage", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 0, + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 69 + }, + "id": 6, + "panels": [], + "title": "DNS", + "type": "row" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fill": 1, + "gridPos": { + "h": 5, + "w": 8, + "x": 0, + "y": 70 + }, + "id": 2, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": {}, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(hubble_dns_queries_total[1m])) by (pod, qtypes)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{qtypes}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "DNS Requests", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "reqps", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fill": 1, + "gridPos": { + "h": 5, + "w": 8, + "x": 8, + "y": 70 + }, + "id": 4, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": {}, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(hubble_dns_responses_total{rcode=\"No Error\"}[1m])) by (pod, qtypes)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{qtypes}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "DNS responses", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 1, + "format": "reqps", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "alert": { + "conditions": [ + { + "evaluator": { + "params": [ + 0.5 + ], + "type": "gt" + }, + "operator": { + "type": "and" + }, + "query": { + "params": [ + "A", + "5m", + "now" + ] + }, + "reducer": { + "params": [], + "type": "avg" + }, + "type": "query" + } + ], + "executionErrorState": "alerting", + "for": "5m", + "frequency": "1m", + "handler": 1, + "name": "DNS Request/Response Symmetry alert", + "noDataState": "no_data", + "notifications": [] + }, + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fill": 1, + "gridPos": { + "h": 5, + "w": 8, + "x": 16, + "y": 70 + }, + "id": 66, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": {}, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(hubble_dns_queries_total[1m])) by (pod, qtypes) - sum(rate(hubble_dns_responses_total[1m])) by (pod, qtypes)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{qtypes}}", + "refId": "A" + } + ], + "thresholds": [ + { + "colorMode": "critical", + "fill": true, + "line": true, + "op": "gt", + "value": 0.5 + } + ], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Missing DNS Responses", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "reqps", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fill": 1, + "gridPos": { + "h": 5, + "w": 12, + "x": 0, + "y": 75 + }, + "id": 40, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": {}, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(hubble_dns_response_types_total[1m])) by (pod, type)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{type}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "DNS Response Record Type", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 1, + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fill": 1, + "gridPos": { + "h": 5, + "w": 12, + "x": 12, + "y": 75 + }, + "id": 57, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": {}, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(hubble_dns_responses_total{rcode=\"No Error\"}[1m])) by (pod,ips_returned)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{ips_returned}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "DNS Response IPs Returned", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 1, + "format": "reqps", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fill": 1, + "gridPos": { + "h": 5, + "w": 12, + "x": 0, + "y": 80 + }, + "id": 28, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": {}, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(hubble_dns_responses_total{rcode!=\"No Error\"}[1m])) by (pod, qtypes, rcode)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{rcode}} ({{qtypes}})", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "DNS Errors", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 4, + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fill": 1, + "gridPos": { + "h": 5, + "w": 12, + "x": 12, + "y": 80 + }, + "id": 56, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": {}, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "topk(10,sum(rate(hubble_dns_responses_total{rcode!=\"No Error\"}[1m])) by (pod, destination))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{destination}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Pods with DNS errors", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 4, + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "prometheus", + "fill": 1, + "gridPos": { + "h": 6, + "w": 24, + "x": 0, + "y": 85 + }, + "id": 20, + "legend": { + "alignAsTable": true, + "avg": false, + "current": true, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": {}, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "topk(10, sum(rate(hubble_dns_queries_total[10m])*60) by (query, qtypes))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{query}} ({{qtypes}})", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Top 10 DNS Queries per minute", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "none", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "refresh": "30s", + "schemaVersion": 18, + "style": "dark", + "tags": [], + "templating": { + "list": [] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "", + "title": "Hubble", + "uid": "5HftnJAWz", + "version": 24 +} diff --git a/packages/system/cilium/charts/cilium/files/hubble/dashboards/hubble-l7-http-metrics-by-workload.json b/packages/system/cilium/charts/cilium/files/hubble/dashboards/hubble-l7-http-metrics-by-workload.json new file mode 100644 index 00000000..428c58f4 --- /dev/null +++ b/packages/system/cilium/charts/cilium/files/hubble/dashboards/hubble-l7-http-metrics-by-workload.json @@ -0,0 +1,1385 @@ +{ + "__inputs": [], + "__elements": {}, + "__requires": [ + { + "type": "grafana", + "id": "grafana", + "name": "Grafana", + "version": "9.4.7" + }, + { + "type": "datasource", + "id": "prometheus", + "name": "Prometheus", + "version": "1.0.0" + }, + { + "type": "panel", + "id": "stat", + "name": "Stat", + "version": "" + }, + { + "type": "panel", + "id": "timeseries", + "name": "Time series", + "version": "" + } + ], + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "target": { + "limit": 100, + "matchAny": false, + "tags": [], + "type": "dashboard" + }, + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 1, + "id": null, + "links": [], + "liveNow": false, + "panels": [ + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 14, + "panels": [], + "title": "General", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "reqps" + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 8, + "x": 0, + "y": 1 + }, + "id": 16, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "9.4.7", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "expr": "round(sum(rate(hubble_http_requests_total{reporter=~\"${reporter}\", destination_namespace=~\"${destination_namespace}\", destination_workload=~\"${destination_workload}\"}[$__rate_interval])), 0.001)", + "refId": "A" + } + ], + "title": "Incoming Request Volume", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 8, + "x": 8, + "y": 1 + }, + "id": 17, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "9.4.7", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "sum(rate(hubble_http_requests_total{cluster=~\"${cluster}\", destination_namespace=~\"${destination_namespace}\", destination_workload=~\"${destination_workload}\", reporter=\"${reporter}\", status!~\"5.*\"}[$__rate_interval]))\n/\nsum(rate(hubble_http_requests_total{cluster=~\"${cluster}\", destination_namespace=~\"${destination_namespace}\", destination_workload=~\"${destination_workload}\", reporter=\"${reporter}\"}[$__rate_interval]))", + "interval": "", + "legendFormat": "{{ cluster }} {{ method }} {{ source_namespace }}/{{ source_workload }}", + "range": true, + "refId": "A" + } + ], + "title": "Incoming Request Success Rate (non-5xx responses)", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 8, + "x": 16, + "y": 1 + }, + "id": 18, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "9.0.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "histogram_quantile(0.50, sum(rate(hubble_http_request_duration_seconds_bucket{cluster=~\"${cluster}\", destination_namespace=~\"${destination_namespace}\", destination_workload=~\"${destination_workload}\", reporter=\"${reporter}\"}[$__rate_interval])) by (le))", + "interval": "", + "legendFormat": "P50", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "histogram_quantile(0.95, sum(rate(hubble_http_request_duration_seconds_bucket{cluster=~\"${cluster}\", destination_namespace=~\"${destination_namespace}\", destination_workload=~\"${destination_workload}\", reporter=\"${reporter}\"}[$__rate_interval])) by (le))", + "hide": false, + "interval": "", + "legendFormat": "P95", + "range": true, + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "histogram_quantile(0.99, sum(rate(hubble_http_request_duration_seconds_bucket{cluster=~\"${cluster}\", destination_namespace=~\"${destination_namespace}\", destination_workload=~\"${destination_workload}\", reporter=\"${reporter}\"}[$__rate_interval])) by (le))", + "hide": false, + "interval": "", + "legendFormat": "P99", + "range": true, + "refId": "C" + } + ], + "title": "Request Duration", + "type": "timeseries" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 6 + }, + "id": 6, + "panels": [], + "title": "Requests by Source", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "reqps" + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 7 + }, + "id": 3, + "options": { + "legend": { + "calcs": [ + "max", + "mean", + "sum", + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "round(sum(rate(hubble_http_requests_total{cluster=~\"${cluster}\", destination_namespace=~\"${destination_namespace}\", destination_workload=~\"${destination_workload}\", reporter=\"${reporter}\", source_namespace=~\"${source_namespace}\", source_workload=~\"${source_workload}\"}[$__rate_interval])) by (cluster, source_namespace, source_workload, status), 0.001)", + "interval": "", + "legendFormat": "{{ cluster }} {{ method }} {{ source_namespace }}/{{ source_workload }}: {{ status }}", + "range": true, + "refId": "A" + } + ], + "title": "Incoming Requests by Source and Response Code", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 7 + }, + "id": 7, + "options": { + "legend": { + "calcs": [ + "mean", + "min", + "max", + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "sum(rate(hubble_http_requests_total{cluster=~\"${cluster}\", destination_namespace=~\"${destination_namespace}\", destination_workload=~\"${destination_workload}\", reporter=\"${reporter}\", source_namespace=~\"${source_namespace}\", source_workload=~\"${source_workload}\",status!~\"5.*\"}[$__rate_interval])) by (cluster, source_namespace, source_workload)\n/\nsum(rate(hubble_http_requests_total{cluster=~\"${cluster}\", destination_namespace=~\"${destination_namespace}\", destination_workload=~\"${destination_workload}\", reporter=\"${reporter}\", source_namespace=~\"${source_namespace}\", source_workload=~\"${source_workload}\"}[$__rate_interval])) by (cluster, source_namespace, source_workload)", + "interval": "", + "legendFormat": "{{ cluster }} {{ method }} {{ source_namespace }}/{{ source_workload }}", + "range": true, + "refId": "A" + } + ], + "title": "Incoming Request Success Rate (non-5xx responses) By Source", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 17 + }, + "id": 4, + "options": { + "legend": { + "calcs": [ + "min", + "max", + "mean", + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "exemplar": true, + "expr": "histogram_quantile(0.50, sum(rate(hubble_http_request_duration_seconds_bucket{cluster=~\"${cluster}\", destination_namespace=~\"${destination_namespace}\", destination_workload=~\"${destination_workload}\", reporter=\"${reporter}\", source_namespace=~\"${source_namespace}\", source_workload=~\"${source_workload}\"}[$__rate_interval])) by (cluster, source_namespace, source_workload, le))", + "interval": "", + "legendFormat": "{{ cluster }} {{ source_namespace }}/{{ source_workload }} P50", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "exemplar": true, + "expr": "histogram_quantile(0.95, sum(rate(hubble_http_request_duration_seconds_bucket{cluster=~\"${cluster}\", destination_namespace=~\"${destination_namespace}\", destination_workload=~\"${destination_workload}\", reporter=\"${reporter}\", source_namespace=~\"${source_namespace}\", source_workload=~\"${source_workload}\"}[$__rate_interval])) by (cluster, source_namespace, source_workload, le))", + "hide": false, + "interval": "", + "legendFormat": "{{ cluster }} {{ source_namespace }}/{{ source_workload }} P95", + "range": true, + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "exemplar": true, + "expr": "histogram_quantile(0.99, sum(rate(hubble_http_request_duration_seconds_bucket{cluster=~\"${cluster}\", destination_namespace=~\"${destination_namespace}\", destination_workload=~\"${destination_workload}\", reporter=\"${reporter}\", source_namespace=~\"${source_namespace}\", source_workload=~\"${source_workload}\"}[$__rate_interval])) by (cluster, source_namespace, source_workload, le))", + "hide": false, + "interval": "", + "legendFormat": "{{ cluster }} {{ source_namespace }}/{{ source_workload }} P99", + "range": true, + "refId": "C" + } + ], + "title": "HTTP Request Duration by Source", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 17 + }, + "id": 20, + "options": { + "legend": { + "calcs": [ + "min", + "max", + "mean", + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "sum(\n node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{cluster=~\"${cluster}\", namespace=~\"${destination_namespace}\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=~\"${cluster}\", namespace=~\"${destination_namespace}\", workload=~\"${source_workload}\"}\n) by (namespace, workload)", + "interval": "", + "legendFormat": "{{ cluster }} {{ namespace }}/{{ workload }}", + "range": true, + "refId": "A" + } + ], + "title": "CPU Usage by Source", + "type": "timeseries" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 27 + }, + "id": 9, + "panels": [], + "title": "Requests by Destination", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "reqps" + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 28 + }, + "id": 10, + "options": { + "legend": { + "calcs": [ + "max", + "mean", + "sum", + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "round(sum(rate(hubble_http_requests_total{cluster=~\"${cluster}\", destination_namespace=~\"${destination_namespace}\", destination_workload=~\"${destination_workload}\", reporter=\"${reporter}\", source_namespace=~\"${source_namespace}\", source_workload=~\"${source_workload}\"}[$__rate_interval])) by (cluster, destination_namespace, destination_workload, status), 0.001)", + "interval": "", + "legendFormat": "{{ cluster }} {{ method }} {{ destination_namespace }}/{{ destination_workload }}: {{ status }}", + "range": true, + "refId": "A" + } + ], + "title": "Incoming Requests by Destination and Response Code", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 28 + }, + "id": 11, + "options": { + "legend": { + "calcs": [ + "mean", + "min", + "max", + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "sum(rate(hubble_http_requests_total{cluster=~\"${cluster}\", destination_namespace=~\"${destination_namespace}\", destination_workload=~\"${destination_workload}\", reporter=\"${reporter}\", source_namespace=~\"${source_namespace}\", source_workload=~\"${source_workload}\",status!~\"5.*\"}[$__rate_interval])) by (cluster, destination_namespace, destination_workload)\n/\nsum(rate(hubble_http_requests_total{cluster=~\"${cluster}\", destination_namespace=~\"${destination_namespace}\", destination_workload=~\"${destination_workload}\", reporter=\"${reporter}\", source_namespace=~\"${source_namespace}\", source_workload=~\"${source_workload}\"}[$__rate_interval])) by (cluster, destination_namespace, destination_workload)", + "interval": "", + "legendFormat": "{{ cluster }} {{ method }} {{ destination_namespace }}/{{ destination_workload }}", + "range": true, + "refId": "A" + } + ], + "title": "Incoming Request Success Rate (non-5xx responses) By Destination", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 38 + }, + "id": 12, + "options": { + "legend": { + "calcs": [ + "min", + "max", + "mean", + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "exemplar": true, + "expr": "histogram_quantile(0.50, sum(rate(hubble_http_request_duration_seconds_bucket{cluster=~\"${cluster}\", destination_namespace=~\"${destination_namespace}\", destination_workload=~\"${destination_workload}\", reporter=\"${reporter}\", source_namespace=~\"${source_namespace}\", source_workload=~\"${source_workload}\"}[$__rate_interval])) by (cluster, destination_namespace, destination_workload, le))", + "interval": "", + "legendFormat": "{{ cluster }} {{ destination_namespace }}/{{ destination_workload }} P50", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "exemplar": true, + "expr": "histogram_quantile(0.95, sum(rate(hubble_http_request_duration_seconds_bucket{cluster=~\"${cluster}\", destination_namespace=~\"${destination_namespace}\", destination_workload=~\"${destination_workload}\", reporter=\"${reporter}\", source_namespace=~\"${source_namespace}\", source_workload=~\"${source_workload}\"}[$__rate_interval])) by (cluster, destination_namespace, destination_workload, le))", + "hide": false, + "interval": "", + "legendFormat": "{{ cluster }} {{ destination_namespace }}/{{ destination_workload }} P95", + "range": true, + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "exemplar": true, + "expr": "histogram_quantile(0.99, sum(rate(hubble_http_request_duration_seconds_bucket{cluster=~\"${cluster}\", destination_namespace=~\"${destination_namespace}\", destination_workload=~\"${destination_workload}\", reporter=\"${reporter}\", source_namespace=~\"${source_namespace}\", source_workload=~\"${source_workload}\"}[$__rate_interval])) by (cluster, destination_namespace, destination_workload, le))", + "hide": false, + "interval": "", + "legendFormat": "{{ cluster }} {{ destination_namespace }}/{{ destination_workload }} P99", + "range": true, + "refId": "C" + } + ], + "title": "HTTP Request Duration by Destination", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 38 + }, + "id": 19, + "options": { + "legend": { + "calcs": [ + "min", + "max", + "mean", + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "sum(\n node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{cluster=~\"${cluster}\", namespace=~\"${destination_namespace}\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=~\"${cluster}\", namespace=~\"${destination_namespace}\", workload=\"${destination_workload}\"}\n) by (namespace, workload)", + "interval": "", + "legendFormat": "{{ cluster }} {{ namespace }}/{{ workload }}", + "range": true, + "refId": "A" + } + ], + "title": "CPU Usage by Destination", + "type": "timeseries" + } + ], + "refresh": "30s", + "revision": 1, + "schemaVersion": 38, + "style": "dark", + "tags": [], + "templating": { + "list": [ + { + "current": {}, + "hide": 0, + "includeAll": false, + "label": "Prometheus", + "multi": false, + "name": "DS_PROMETHEUS", + "options": [], + "query": "prometheus", + "queryValue": "", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + }, + { + "current": {}, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "definition": "label_values(hubble_http_requests_total, cluster)", + "hide": 0, + "includeAll": false, + "label": "Cluster", + "multi": false, + "name": "cluster", + "options": [], + "query": { + "query": "label_values(hubble_http_requests_total, cluster)", + "refId": "StandardVariableQuery" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 2, + "type": "query" + }, + { + "current": {}, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "definition": "label_values(hubble_http_requests_total{cluster=~\"${cluster}\"}, destination_namespace)", + "description": "", + "hide": 0, + "includeAll": false, + "label": "Destination Namespace", + "multi": false, + "name": "destination_namespace", + "options": [], + "query": { + "query": "label_values(hubble_http_requests_total{cluster=~\"${cluster}\"}, destination_namespace)", + "refId": "StandardVariableQuery" + }, + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 2, + "type": "query" + }, + { + "current": {}, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "definition": "label_values(hubble_http_requests_total{cluster=~\"${cluster}\", destination_namespace=~\"${destination_namespace}\"}, destination_workload)", + "hide": 0, + "includeAll": false, + "label": "Destination Workload", + "multi": false, + "name": "destination_workload", + "options": [], + "query": { + "query": "label_values(hubble_http_requests_total{cluster=~\"${cluster}\", destination_namespace=~\"${destination_namespace}\"}, destination_workload)", + "refId": "StandardVariableQuery" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 2, + "type": "query" + }, + { + "current": {}, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "definition": "label_values(hubble_http_requests_total, reporter)", + "hide": 0, + "includeAll": false, + "label": "Reporter", + "multi": false, + "name": "reporter", + "options": [], + "query": { + "query": "label_values(hubble_http_requests_total, reporter)", + "refId": "StandardVariableQuery" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "current": {}, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "definition": "label_values(hubble_http_requests_total{cluster=~\"${cluster}\", destination_namespace=~\"${destination_namespace}\", destination_workload=~\"${destination_workload}\"}, source_namespace)", + "hide": 0, + "includeAll": true, + "label": "Source Namespace", + "multi": true, + "name": "source_namespace", + "options": [], + "query": { + "query": "label_values(hubble_http_requests_total{cluster=~\"${cluster}\", destination_namespace=~\"${destination_namespace}\", destination_workload=~\"${destination_workload}\"}, source_namespace)", + "refId": "StandardVariableQuery" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "current": {}, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "definition": "label_values(hubble_http_requests_total{cluster=~\"${cluster}\", destination_namespace=~\"${destination_namespace}\", destination_workload=~\"${destination_workload}\", source_namespace=~\"${source_namespace}\"}, source_workload)", + "hide": 0, + "includeAll": true, + "label": "Source Workload", + "multi": true, + "name": "source_workload", + "options": [], + "query": { + "query": "label_values(hubble_http_requests_total{cluster=~\"${cluster}\", destination_namespace=~\"${destination_namespace}\", destination_workload=~\"${destination_workload}\", source_namespace=~\"${source_namespace}\"}, source_workload)", + "refId": "StandardVariableQuery" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + } + ] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "Hubble L7 HTTP Metrics by Workload", + "uid": "3g264CZVz", + "version": 3, + "weekStart": "" +} diff --git a/packages/system/cilium/charts/cilium/files/nodeinit/prestop.bash b/packages/system/cilium/charts/cilium/files/nodeinit/prestop.bash new file mode 100644 index 00000000..e78f178a --- /dev/null +++ b/packages/system/cilium/charts/cilium/files/nodeinit/prestop.bash @@ -0,0 +1,60 @@ +#!/bin/bash + +set -o errexit +set -o pipefail +set -o nounset + +{{ .Values.nodeinit.prestop.preScript }} + +if stat /tmp/node-deinit.cilium.io > /dev/null 2>&1; then + exit 0 +fi + +echo "Waiting on pods to stop..." +if [ ! -f /etc/crictl.yaml ] || grep -q 'docker' /etc/crictl.yaml; then + # Works for COS, ubuntu + while docker ps | grep -v "node-init" | grep -q "POD_cilium"; do sleep 1; done +else + # COS-beta (with containerd). Some versions of COS have crictl in /home/kubernetes/bin. + while PATH="${PATH}:/home/kubernetes/bin" crictl ps | grep -v "node-init" | grep -q "POD_cilium"; do sleep 1; done +fi + +if ip link show cilium_host; then + echo "Deleting cilium_host interface..." + ip link del cilium_host +fi + +{{- if not (eq .Values.nodeinit.bootstrapFile "") }} +rm -f {{ .Values.nodeinit.bootstrapFile | quote }} +{{- end }} + +rm -f /tmp/node-init.cilium.io +touch /tmp/node-deinit.cilium.io + +{{- if .Values.nodeinit.reconfigureKubelet }} +# Check if we're running on a GKE containerd flavor. +GKE_KUBERNETES_BIN_DIR="/home/kubernetes/bin" +if [[ -f "${GKE_KUBERNETES_BIN_DIR}/gke" ]] && command -v containerd &>/dev/null; then + CONTAINERD_CONFIG="/etc/containerd/config.toml" + echo "Reverting changes to the containerd configuration" + sed -Ei "s/^\#(\s+conf_template)/\1/g" "${CONTAINERD_CONFIG}" + echo "Removing the kubelet wrapper" + [[ -f "${GKE_KUBERNETES_BIN_DIR}/the-kubelet" ]] && mv "${GKE_KUBERNETES_BIN_DIR}/the-kubelet" "${GKE_KUBERNETES_BIN_DIR}/kubelet" +else + echo "Changing kubelet configuration to --network-plugin=kubenet" + sed -i "s:--network-plugin=cni\ --cni-bin-dir={{ .Values.cni.binPath }}:--network-plugin=kubenet:g" /etc/default/kubelet +fi +echo "Restarting the kubelet" +systemctl restart kubelet +{{- end }} + +{{- if (and .Values.gke.enabled (or .Values.enableIPv4Masquerade .Values.gke.disableDefaultSnat))}} +# If the IP-MASQ chain exists, add back default jump rule from the GKE instance configure script +if iptables -w -t nat -L IP-MASQ > /dev/null; then + iptables -w -t nat -A POSTROUTING -m comment --comment "ip-masq: ensure nat POSTROUTING directs all non-LOCAL destination traffic to our custom IP-MASQ chain" -m addrtype ! --dst-type LOCAL -j IP-MASQ +fi +{{- end }} + +{{ .Values.nodeinit.prestop.postScript }} + +echo "Node de-initialization complete" diff --git a/packages/system/cilium/charts/cilium/files/nodeinit/startup.bash b/packages/system/cilium/charts/cilium/files/nodeinit/startup.bash new file mode 100644 index 00000000..975b71fa --- /dev/null +++ b/packages/system/cilium/charts/cilium/files/nodeinit/startup.bash @@ -0,0 +1,206 @@ +#!/bin/bash + +set -o errexit +set -o pipefail +set -o nounset + +echo "Link information:" +ip link + +echo "Routing table:" +ip route + +echo "Addressing:" +ip -4 a +ip -6 a + +{{ .Values.nodeinit.startup.preScript }} + +{{- if .Values.nodeinit.removeCbrBridge }} +if ip link show cbr0; then + echo "Detected cbr0 bridge. Deleting interface..." + ip link del cbr0 +fi +{{- end }} + +{{- if .Values.nodeinit.reconfigureKubelet }} +# Check if we're running on a GKE containerd flavor as indicated by the presence +# of the '--container-runtime-endpoint' flag in '/etc/default/kubelet'. +GKE_KUBERNETES_BIN_DIR="/home/kubernetes/bin" +KUBELET_DEFAULTS_FILE="/etc/default/kubelet" +if [[ -f "${GKE_KUBERNETES_BIN_DIR}/gke" ]] && [[ $(grep -cF -- '--container-runtime-endpoint' "${KUBELET_DEFAULTS_FILE}") == "1" ]]; then + echo "GKE *_containerd flavor detected..." + + # (GKE *_containerd) Upon node restarts, GKE's containerd images seem to reset + # the /etc directory and our changes to the kubelet and Cilium's CNI + # configuration are removed. This leaves room for containerd and its CNI to + # take over pods previously managed by Cilium, causing Cilium to lose + # ownership over these pods. We rely on the empirical observation that + # /home/kubernetes/bin/kubelet is not changed across node reboots, and replace + # it with a wrapper script that performs some initialization steps when + # required and then hands over control to the real kubelet. + + # Only create the kubelet wrapper if we haven't previously done so. + if [[ ! -f "${GKE_KUBERNETES_BIN_DIR}/the-kubelet" ]]; + then + echo "Installing the kubelet wrapper..." + + # Rename the real kubelet. + mv "${GKE_KUBERNETES_BIN_DIR}/kubelet" "${GKE_KUBERNETES_BIN_DIR}/the-kubelet" + + # Initialize the kubelet wrapper which lives in the place of the real kubelet. + touch "${GKE_KUBERNETES_BIN_DIR}/kubelet" + chmod a+x "${GKE_KUBERNETES_BIN_DIR}/kubelet" + + # Populate the kubelet wrapper. It will perform the initialization steps we + # need and then become the kubelet. + cat <<'EOF' | tee "${GKE_KUBERNETES_BIN_DIR}/kubelet" +#!/bin/bash + +set -euo pipefail + +CNI_CONF_DIR="/etc/cni/net.d" +CONTAINERD_CONFIG="/etc/containerd/config.toml" + +# kubelet version string format is "Kubernetes v1.24-gke.900" +K8S_VERSION=$(/home/kubernetes/bin/the-kubelet --version) + +# Helper to check if a version string, passed as first parameter, is greater than or +# equal the one passed as second parameter. +function version_gte() { + [[ "$(printf '%s\n' "${2}" "${1}" | sort -V | head -n1)" = "${2}" ]] && return +} + +# Only stop and start containerd if the Cilium CNI configuration does not exist, +# or if the 'conf_template' property is present in the containerd config file, +# in order to avoid unnecessarily restarting containerd. +if [[ -z "$(find "${CNI_CONF_DIR}" -type f -name '*cilium*')" || \ + "$(grep -cE '^\s+conf_template' "${CONTAINERD_CONFIG}")" != "0" ]]; +then + # Stop containerd as it starts by creating a CNI configuration from a template + # causing pods to start with IPs assigned by GKE's CNI. + # 'disable --now' is used instead of stop as this script runs concurrently + # with containerd on node startup, and hence containerd might not have been + # started yet, in which case 'disable' prevents it from starting. + echo "Disabling and stopping containerd" + systemctl disable --now containerd + + # Remove any pre-existing files in the CNI configuration directory. We skip + # any possibly existing Cilium configuration file for the obvious reasons. + echo "Removing undesired CNI configuration files" + find "${CNI_CONF_DIR}" -type f -not -name '*cilium*' -exec rm {} \; + + # As mentioned above, the containerd configuration needs a little tweak in + # order not to create the default CNI configuration, so we update its config. + echo "Fixing containerd configuration" + sed -Ei 's/^(\s+conf_template)/\#\1/g' "${CONTAINERD_CONFIG}" + + if version_gte "${K8S_VERSION#"Kubernetes "}" "v1.24"; then + # Starting from GKE node version 1.24, containerd version used is 1.6. + # Since that version containerd no longer allows missing configuration for the CNI, + # not even for pods with hostNetwork set to true. Thus, we add a temporary one. + # This will be replaced with the real config by the agent pod. + echo -e "{\n\t"cniVersion": "0.3.1",\n\t"name": "cilium",\n\t"type": "cilium-cni"\n}" > /etc/cni/net.d/05-cilium.conf + fi + + # Start containerd. It won't create it's CNI configuration file anymore. + echo "Enabling and starting containerd" + systemctl enable --now containerd +fi + +# Become the real kubelet and, for k8s < 1.24, pass it additional dockershim +# flags (and place these last so they have precedence). +if version_gte "${K8S_VERSION#"Kubernetes "}" "v1.24"; then + exec /home/kubernetes/bin/the-kubelet "${@}" +else + exec /home/kubernetes/bin/the-kubelet "${@}" --network-plugin=cni --cni-bin-dir={{ .Values.cni.binPath }} +fi +EOF + else + echo "Kubelet wrapper already exists, skipping..." + fi +else + # kubelet version string format is "Kubernetes v1.24-gke.900" + K8S_VERSION=$(kubelet --version) + + # Helper to check if a version string, passed as first parameter, is greater than or + # equal the one passed as second parameter. + function version_gte() { + [[ "$(printf '%s\n' "${2}" "${1}" | sort -V | head -n1)" = "${2}" ]] && return + } + + # Dockershim flags have been removed since k8s 1.24. + if ! version_gte "${K8S_VERSION#"Kubernetes "}" "v1.24"; then + # (Generic) Alter the kubelet configuration to run in CNI mode + echo "Changing kubelet configuration to --network-plugin=cni --cni-bin-dir={{ .Values.cni.binPath }}" + mkdir -p {{ .Values.cni.binPath }} + sed -i "s:--network-plugin=kubenet:--network-plugin=cni\ --cni-bin-dir={{ .Values.cni.binPath }}:g" "${KUBELET_DEFAULTS_FILE}" + fi +fi +echo "Restarting the kubelet..." +systemctl restart kubelet +{{- end }} + +{{- if (and .Values.gke.enabled (or .Values.enableIPv4Masquerade .Values.gke.disableDefaultSnat))}} +# If Cilium is configured to manage masquerading of traffic leaving the node, +# we need to disable the IP-MASQ chain because even if ip-masq-agent +# is not installed, the node init script installs some default rules into +# the IP-MASQ chain. +# If we remove the jump to that ip-masq chain, then we ensure the ip masquerade +# configuration is solely managed by Cilium. +# Also, if Cilium is installed, it may be expected that it would be solely responsible +# for the networking configuration on that node. So provide the same functionality +# as the --disable-snat-flag for existing GKE clusters. +iptables -w -t nat -D POSTROUTING -m comment --comment "ip-masq: ensure nat POSTROUTING directs all non-LOCAL destination traffic to our custom IP-MASQ chain" -m addrtype ! --dst-type LOCAL -j IP-MASQ || true +{{- end }} + +{{- if not (eq .Values.nodeinit.bootstrapFile "") }} +mkdir -p {{ .Values.nodeinit.bootstrapFile | dir | quote }} +date > {{ .Values.nodeinit.bootstrapFile | quote }} +{{- end }} + +{{- if .Values.azure.enabled }} +# AKS: If azure-vnet is installed on the node, and (still) configured in bridge mode, +# configure it as 'transparent' to be consistent with Cilium's CNI chaining config. +# If the azure-vnet CNI config is not removed, kubelet will execute CNI CHECK commands +# against it every 5 seconds and write 'bridge' to its state file, causing inconsistent +# behaviour when Pods are removed. +if [ -f /etc/cni/net.d/10-azure.conflist ]; then + echo "Ensuring azure-vnet is configured in 'transparent' mode..." + sed -i 's/"mode":\s*"bridge"/"mode":"transparent"/g' /etc/cni/net.d/10-azure.conflist +fi + +# The azure0 interface being present means the node was booted with azure-vnet configured +# in bridge mode. This means there might be ebtables rules and neight entries interfering +# with pod connectivity if we deploy with Azure IPAM. +if ip l show dev azure0 >/dev/null 2>&1; then + + # In Azure IPAM mode, also remove the azure-vnet state file, otherwise ebtables rules get + # restored by the azure-vnet CNI plugin on every CNI CHECK, which can cause connectivity + # issues in Cilium-managed Pods. Since azure-vnet is no longer called on scheduling events, + # this file can be removed. + rm -f /var/run/azure-vnet.json + + # This breaks connectivity for existing workload Pods when Cilium is scheduled, but we need + # to flush these to prevent Cilium-managed Pod IPs conflicting with Pod IPs previously allocated + # by azure-vnet. These ebtables DNAT rules contain fixed MACs that are no longer bound on the node, + # causing packets for these Pods to be redirected back out to the gateway, where they are dropped. + echo 'Flushing ebtables pre/postrouting rules in nat table.. (disconnecting non-Cilium Pods!)' + ebtables -t nat -F PREROUTING || true + ebtables -t nat -F POSTROUTING || true + + # ip-masq-agent periodically injects PERM neigh entries towards the gateway + # for all other k8s nodes in the cluster. These are safe to flush, as ARP can + # resolve these nodes as usual. PERM entries will be automatically restored later. + echo 'Deleting all permanent neighbour entries on azure0...' + ip neigh show dev azure0 nud permanent | cut -d' ' -f1 | xargs -r -n1 ip neigh del dev azure0 to || true +fi +{{- end }} + +{{- if .Values.nodeinit.revertReconfigureKubelet }} +rm -f /tmp/node-deinit.cilium.io +{{- end }} + +{{ .Values.nodeinit.startup.postScript }} + +echo "Node initialization complete" diff --git a/packages/system/cilium/charts/cilium/files/spire/init.bash b/packages/system/cilium/charts/cilium/files/spire/init.bash new file mode 100644 index 00000000..4b6f57bd --- /dev/null +++ b/packages/system/cilium/charts/cilium/files/spire/init.bash @@ -0,0 +1,48 @@ +# shellcheck disable=SC2086 +# shellcheck disable=SC2139 +set -e + +echo "Waiting for spire process to start" +while ! pgrep spire-server > /dev/null; do sleep 5; done + +SPIRE_SERVER_ROOT_PATH="/proc/$(pgrep spire-server)/root" + +alias spire_server="${SPIRE_SERVER_ROOT_PATH}/opt/spire/bin/spire-server" +SOCKET_PATH="${SPIRE_SERVER_ROOT_PATH}/tmp/spire-server/private/api.sock" +SOCKET_FLAG="-socketPath ${SOCKET_PATH}" + +echo "Checking spire-server status" +while ! spire_server entry show ${SOCKET_FLAG} &> /dev/null; do + echo "Waiting for spire-server to start..." + sleep 5 +done + +echo "Spire Server is up, initializing cilium spire entries..." + +AGENT_SPIFFE_ID="spiffe://{{ .Values.authentication.mutual.spire.trustDomain }}/ns/{{ .Values.authentication.mutual.spire.install.namespace }}/sa/spire-agent" +AGENT_SELECTORS="-selector k8s_psat:agent_ns:{{ .Values.authentication.mutual.spire.install.namespace }} -selector k8s_psat:agent_sa:spire-agent" +CILIUM_AGENT_SPIFFE_ID="spiffe://{{ .Values.authentication.mutual.spire.trustDomain }}/cilium-agent" +CILIUM_AGENT_SELECTORS="-selector k8s:ns:{{ .Release.Namespace }} -selector k8s:sa:{{ .Values.serviceAccounts.cilium.name }}" +CILIUM_OPERATOR_SPIFFE_ID="spiffe://{{ .Values.authentication.mutual.spire.trustDomain }}/cilium-operator" +CILIUM_OPERATOR_SELECTORS="-selector k8s:ns:{{ .Release.Namespace }} -selector k8s:sa:{{ .Values.serviceAccounts.operator.name }}" + +while pgrep spire-server > /dev/null; +do + echo "Ensuring agent entry" + if spire_server entry show ${SOCKET_FLAG} -spiffeID $AGENT_SPIFFE_ID $AGENT_SELECTORS | grep -q "Found 0 entries" &> /dev/null; then + spire_server entry create ${SOCKET_FLAG} -spiffeID $AGENT_SPIFFE_ID $AGENT_SELECTORS -node + fi + + echo "Ensuring cilium-agent entry (required for the delegated identity to work)" + if spire_server entry show ${SOCKET_FLAG} -spiffeID $CILIUM_AGENT_SPIFFE_ID $CILIUM_AGENT_SELECTORS | grep -q "Found 0 entries" &> /dev/null; then + spire_server entry create ${SOCKET_FLAG} -spiffeID $CILIUM_AGENT_SPIFFE_ID -parentID $AGENT_SPIFFE_ID $CILIUM_AGENT_SELECTORS + fi + + echo "Ensuring cilium-operator entry (required for creating SPIFFE identities)" + if spire_server entry show ${SOCKET_FLAG} -spiffeID $CILIUM_OPERATOR_SPIFFE_ID $CILIUM_OPERATOR_SELECTORS | grep -q "Found 0 entries" &> /dev/null; then + spire_server entry create ${SOCKET_FLAG} -spiffeID $CILIUM_OPERATOR_SPIFFE_ID -parentID $AGENT_SPIFFE_ID $CILIUM_OPERATOR_SELECTORS + fi + + echo "Cilium Spire entries are initialized successfully or already in-sync" + sleep 30; +done diff --git a/packages/system/cilium/charts/cilium/files/spire/wait-for-spire.bash b/packages/system/cilium/charts/cilium/files/spire/wait-for-spire.bash new file mode 100644 index 00000000..3507af1c --- /dev/null +++ b/packages/system/cilium/charts/cilium/files/spire/wait-for-spire.bash @@ -0,0 +1,35 @@ +set -e + +echo "Waiting for spire server to be reachable to start" + +{{- if .Values.authentication.mutual.spire.serverAddress }} +ADDR="{{ .Values.authentication.mutual.spire.serverAddress }}" +{{- else }} +ADDR="spire-server.{{ .Values.authentication.mutual.spire.install.namespace}}.svc:8081" +{{- end }} +CONN_TIMEOUT="3" +TIMEOUT="60" + +call_tcp_endpoint_with_timeout() { + local addr="$1" + local timeout="$2" + + nc -z "$addr" -w "$timeout" &> /dev/null +} + +# wait for SPIRE server to be reachable till $TIMEOUT is reached +start_time=$(date +%s) +while true; do + if call_tcp_endpoint_with_timeout "$ADDR" "$CONN_TIMEOUT"; then + echo "SPIRE server is reachable" + break + fi + + if [ $(( $(date +%s) - start_time )) -gt "$TIMEOUT" ]; then + echo "Timed out waiting for spire server to be reachable" + exit 1 + fi + + echo "Waiting for spire server to be reachable" + sleep 1 +done diff --git a/packages/system/cilium/charts/cilium/templates/NOTES.txt b/packages/system/cilium/charts/cilium/templates/NOTES.txt new file mode 100644 index 00000000..f5405074 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/NOTES.txt @@ -0,0 +1,22 @@ +{{- if (and (.Values.preflight.enabled) (not (.Values.agent)) (not (.Values.operator.enabled))) }} + You have successfully ran the preflight check. + Now make sure to check the number of READY pods is the same as the number of running cilium pods. + Then make sure the cilium preflight deployment is also marked READY 1/1. + If you have an issues please refer to the CNP Validation section in the upgrade guide. +{{- else if (and (.Values.hubble.enabled) (.Values.hubble.relay.enabled)) }} + {{- if (.Values.hubble.ui.enabled) }} + You have successfully installed {{ title .Chart.Name }} with Hubble Relay and Hubble UI. + {{- else }} + You have successfully installed {{ title .Chart.Name }} with Hubble Relay. + {{- end }} +{{- else if .Values.hubble.enabled }} + You have successfully installed {{ title .Chart.Name }} with Hubble. +{{- else if (and (.Values.hubble.ui.enabled) (.Values.hubble.ui.standalone.enabled)) }} + You have successfully installed {{ title .Chart.Name }} with standalone Hubble UI. +{{- else }} + You have successfully installed {{ title .Chart.Name }}. +{{- end }} + +Your release version is {{ .Chart.Version }}. + +For any further help, visit https://docs.cilium.io/en/v{{ (semver .Chart.Version).Major }}.{{ (semver .Chart.Version).Minor }}/gettinghelp diff --git a/packages/system/cilium/charts/cilium/templates/_helpers.tpl b/packages/system/cilium/charts/cilium/templates/_helpers.tpl new file mode 100644 index 00000000..3e5429e2 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/_helpers.tpl @@ -0,0 +1,156 @@ +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "cilium.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Render full image name from given values, e.g: +``` +image: + repository: quay.io/cilium/cilium + tag: v1.10.1 + useDigest: true + digest: abcdefgh +``` +then `include "cilium.image" .Values.image` +will return `quay.io/cilium/cilium:v1.10.1@abcdefgh` +*/}} +{{- define "cilium.image" -}} +{{- $digest := (.useDigest | default false) | ternary (printf "@%s" .digest) "" -}} +{{- if .override -}} +{{- printf "%s" .override -}} +{{- else -}} +{{- printf "%s:%s%s" .repository .tag $digest -}} +{{- end -}} +{{- end -}} + +{{/* +Return user specify priorityClass or default criticalPriorityClass +Usage: + include "cilium.priorityClass" (list $ ) +where: +* `priorityClass`: is user specify priorityClass e.g `.Values.operator.priorityClassName` +* `criticalPriorityClass`: default criticalPriorityClass, e.g `"system-cluster-critical"` + This value is used when `priorityClass` is `nil` and + `.Values.enableCriticalPriorityClass=true` and kubernetes supported it. +*/}} +{{- define "cilium.priorityClass" -}} +{{- $root := index . 0 -}} +{{- $priorityClass := index . 1 -}} +{{- $criticalPriorityClass := index . 2 -}} +{{- if $priorityClass }} + {{- $priorityClass }} +{{- else if and $root.Values.enableCriticalPriorityClass $criticalPriorityClass -}} + {{- if and (eq $root.Release.Namespace "kube-system") (semverCompare ">=1.10-0" $root.Capabilities.KubeVersion.Version) -}} + {{- $criticalPriorityClass }} + {{- else if semverCompare ">=1.17-0" $root.Capabilities.KubeVersion.Version -}} + {{- $criticalPriorityClass }} + {{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for ingress. +*/}} +{{- define "ingress.apiVersion" -}} +{{- if semverCompare ">=1.16-0, <1.19-0" .Capabilities.KubeVersion.Version -}} +{{- print "networking.k8s.io/v1beta1" -}} +{{- else if semverCompare "^1.19-0" .Capabilities.KubeVersion.Version -}} +{{- print "networking.k8s.io/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate backend for Hubble UI ingress. +*/}} +{{- define "ingress.paths" -}} +{{ if semverCompare ">=1.4-0, <1.19-0" .Capabilities.KubeVersion.Version -}} +backend: + serviceName: hubble-ui + servicePort: http +{{- else if semverCompare "^1.19-0" .Capabilities.KubeVersion.Version -}} +pathType: Prefix +backend: + service: + name: hubble-ui + port: + name: http +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for cronjob. +*/}} +{{- define "cronjob.apiVersion" -}} +{{- if semverCompare ">=1.21-0" .Capabilities.KubeVersion.Version -}} +{{- print "batch/v1" -}} +{{- else -}} +{{- print "batch/v1beta1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for podDisruptionBudget. +*/}} +{{- define "podDisruptionBudget.apiVersion" -}} +{{- if semverCompare ">=1.21-0" .Capabilities.KubeVersion.Version -}} +{{- print "policy/v1" -}} +{{- else -}} +{{- print "policy/v1beta1" -}} +{{- end -}} +{{- end -}} + +{{/* +Generate TLS CA for Cilium +Note: Always use this template as follows: + {{- $_ := include "cilium.ca.setup" . -}} + +The assignment to `$_` is required because we store the generated CI in a global `commonCA` +and `commonCASecretName` variables. + +*/}} +{{- define "cilium.ca.setup" }} + {{- if not .commonCA -}} + {{- $ca := "" -}} + {{- $secretName := "cilium-ca" -}} + {{- $crt := .Values.tls.ca.cert -}} + {{- $key := .Values.tls.ca.key -}} + {{- if and $crt $key }} + {{- $ca = buildCustomCert $crt $key -}} + {{- else }} + {{- with lookup "v1" "Secret" .Release.Namespace $secretName }} + {{- $crt := index .data "ca.crt" }} + {{- $key := index .data "ca.key" }} + {{- $ca = buildCustomCert $crt $key -}} + {{- else }} + {{- $validity := ( .Values.tls.ca.certValidityDuration | int) -}} + {{- $ca = genCA "Cilium CA" $validity -}} + {{- end }} + {{- end -}} + {{- $_ := set (set . "commonCA" $ca) "commonCASecretName" $secretName -}} + {{- end -}} +{{- end -}} + +{{/* +Check if duration is non zero value, return duration, empty when zero. +*/}} +{{- define "hasDuration" }} +{{- $now := now }} +{{- if ne $now ($now | dateModify (toString .)) }} +{{- . }} +{{- end }} +{{- end }} + +{{/* +Validate duration field, return validated duration, 0s when provided duration is empty. +*/}} +{{- define "validateDuration" }} +{{- if . }} +{{- $_ := now | mustDateModify (toString .) }} +{{- . }} +{{- else -}} +0s +{{- end }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/cilium-agent/clusterrole.yaml b/packages/system/cilium/charts/cilium/templates/cilium-agent/clusterrole.yaml new file mode 100644 index 00000000..89e604a7 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/cilium-agent/clusterrole.yaml @@ -0,0 +1,142 @@ +{{- if and .Values.agent (not .Values.preflight.enabled) }} +{{- /* +Keep file in sync with cilium-preflight/clusterrole.yaml +*/ -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: cilium + labels: + app.kubernetes.io/part-of: cilium +rules: +- apiGroups: + - networking.k8s.io + resources: + - networkpolicies + verbs: + - get + - list + - watch +- apiGroups: + - discovery.k8s.io + resources: + - endpointslices + verbs: + - get + - list + - watch +- apiGroups: + - "" + resources: + - namespaces + - services + - pods + - endpoints + - nodes + verbs: + - get + - list + - watch +{{- if .Values.annotateK8sNode }} +- apiGroups: + - "" + resources: + - nodes/status + verbs: + # To annotate the k8s node with Cilium's metadata + - patch +{{- end }} +{{- if .Values.l2announcements.enabled }} +- apiGroups: + - coordination.k8s.io + resources: + - leases + verbs: + - create + - get + - update + - list + - delete +{{- end }} +- apiGroups: + - apiextensions.k8s.io + resources: + - customresourcedefinitions + verbs: + - list + - watch + # This is used when validating policies in preflight. This will need to stay + # until we figure out how to avoid "get" inside the preflight, and then + # should be removed ideally. + - get +{{- if eq "k8s" .Values.tls.secretsBackend }} +- apiGroups: + - "" + resources: + - secrets + verbs: + - get +{{- end }} +- apiGroups: + - cilium.io + resources: + - ciliumloadbalancerippools + - ciliumbgppeeringpolicies + - ciliumclusterwideenvoyconfigs + - ciliumclusterwidenetworkpolicies + - ciliumegressgatewaypolicies + - ciliumendpoints + - ciliumendpointslices + - ciliumenvoyconfigs + - ciliumidentities + - ciliumlocalredirectpolicies + - ciliumnetworkpolicies + - ciliumnodes + - ciliumnodeconfigs + - ciliumcidrgroups + - ciliuml2announcementpolicies + - ciliumpodippools + verbs: + - list + - watch +- apiGroups: + - cilium.io + resources: + - ciliumidentities + - ciliumendpoints + - ciliumnodes + verbs: + - create +- apiGroups: + - cilium.io + # To synchronize garbage collection of such resources + resources: + - ciliumidentities + verbs: + - update +- apiGroups: + - cilium.io + resources: + - ciliumendpoints + verbs: + - delete + - get +- apiGroups: + - cilium.io + resources: + - ciliumnodes + - ciliumnodes/status + verbs: + - get + - update +- apiGroups: + - cilium.io + resources: + - ciliumnetworkpolicies/status + - ciliumclusterwidenetworkpolicies/status + - ciliumendpoints/status + - ciliumendpoints + - ciliuml2announcementpolicies/status + verbs: + - patch +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/cilium-agent/clusterrolebinding.yaml b/packages/system/cilium/charts/cilium/templates/cilium-agent/clusterrolebinding.yaml new file mode 100644 index 00000000..ecc32441 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/cilium-agent/clusterrolebinding.yaml @@ -0,0 +1,16 @@ +{{- if and .Values.agent (not .Values.preflight.enabled) .Values.serviceAccounts.cilium.create }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: cilium + labels: + app.kubernetes.io/part-of: cilium +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: cilium +subjects: +- kind: ServiceAccount + name: {{ .Values.serviceAccounts.cilium.name | quote }} + namespace: {{ .Release.Namespace }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/cilium-agent/daemonset.yaml b/packages/system/cilium/charts/cilium/templates/cilium-agent/daemonset.yaml new file mode 100644 index 00000000..32c9e2c0 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/cilium-agent/daemonset.yaml @@ -0,0 +1,955 @@ +{{- if and .Values.agent (not .Values.preflight.enabled) }} + +{{- /* Default values with backwards compatibility */ -}} +{{- $defaultKeepDeprecatedProbes := true -}} + +{{- /* Default values when 1.8 was initially deployed */ -}} +{{- if semverCompare ">=1.8" (default "1.8" .Values.upgradeCompatibility) -}} + {{- $defaultKeepDeprecatedProbes = false -}} +{{- end -}} + +{{- $kubeProxyReplacement := (coalesce .Values.kubeProxyReplacement "false") -}} + +--- +apiVersion: apps/v1 +kind: DaemonSet +metadata: + name: cilium + namespace: {{ .Release.Namespace }} + labels: + k8s-app: cilium + app.kubernetes.io/part-of: cilium + app.kubernetes.io/name: cilium-agent + {{- if .Values.keepDeprecatedLabels }} + kubernetes.io/cluster-service: "true" + {{- if and .Values.gke.enabled (eq .Release.Namespace "kube-system" ) }} + {{- fail "Invalid configuration: Installing Cilium on GKE with 'kubernetes.io/cluster-service' labels on 'kube-system' namespace causes Cilium DaemonSet to be removed by GKE. Either install Cilium on a different Namespace or install with '--set keepDeprecatedLabels=false'" }} + {{- end }} + {{- end }} +spec: + selector: + matchLabels: + k8s-app: cilium + {{- if .Values.keepDeprecatedLabels }} + kubernetes.io/cluster-service: "true" + {{- end }} + {{- with .Values.updateStrategy }} + updateStrategy: + {{- toYaml . | trim | nindent 4 }} + {{- end }} + template: + metadata: + annotations: + {{- if and .Values.prometheus.enabled (not .Values.prometheus.serviceMonitor.enabled) }} + prometheus.io/port: "{{ .Values.prometheus.port }}" + prometheus.io/scrape: "true" + {{- end }} + {{- if .Values.rollOutCiliumPods }} + # ensure pods roll when configmap updates + cilium.io/cilium-configmap-checksum: {{ include (print $.Template.BasePath "/cilium-configmap.yaml") . | sha256sum | quote }} + {{- end }} + {{- if not .Values.securityContext.privileged }} + # Set app AppArmor's profile to "unconfined". The value of this annotation + # can be modified as long users know which profiles they have available + # in AppArmor. + container.apparmor.security.beta.kubernetes.io/cilium-agent: "unconfined" + container.apparmor.security.beta.kubernetes.io/clean-cilium-state: "unconfined" + {{- if .Values.cgroup.autoMount.enabled }} + container.apparmor.security.beta.kubernetes.io/mount-cgroup: "unconfined" + container.apparmor.security.beta.kubernetes.io/apply-sysctl-overwrites: "unconfined" + {{- end }} + {{- end }} + {{- with .Values.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + k8s-app: cilium + app.kubernetes.io/name: cilium-agent + app.kubernetes.io/part-of: cilium + {{- if .Values.keepDeprecatedLabels }} + kubernetes.io/cluster-service: "true" + {{- end }} + {{- with .Values.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.podSecurityContext }} + securityContext: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: cilium-agent + image: {{ include "cilium.image" .Values.image | quote }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + {{- if .Values.sleepAfterInit }} + command: + - /bin/bash + - -c + - -- + args: + - | + while true; do + sleep 30; + done + livenessProbe: + exec: + command: + - "true" + readinessProbe: + exec: + command: + - "true" + {{- else }} + command: + # Workaround: https://github.com/cilium/cilium/pull/27561 + - /bin/sh + - -c + - | + rm -rf /run/cilium/cgroupv2 + ln -sf /sys/fs/cgroup /run/cilium/cgroupv2 + exec cilium-agent --config-dir=/tmp/cilium/config-map + {{- with .Values.extraArgs }} + {{- toYaml . | trim | nindent 8 }} + {{- end }} + {{- if semverCompare ">=1.20-0" .Capabilities.KubeVersion.Version }} + startupProbe: + httpGet: + host: {{ .Values.ipv4.enabled | ternary "127.0.0.1" "::1" | quote }} + path: /healthz + port: {{ .Values.healthPort }} + scheme: HTTP + httpHeaders: + - name: "brief" + value: "true" + failureThreshold: {{ .Values.startupProbe.failureThreshold }} + periodSeconds: {{ .Values.startupProbe.periodSeconds }} + successThreshold: 1 + {{- end }} + livenessProbe: + {{- if or .Values.keepDeprecatedProbes $defaultKeepDeprecatedProbes }} + exec: + command: + - cilium + - status + - --brief + {{- else }} + httpGet: + host: {{ .Values.ipv4.enabled | ternary "127.0.0.1" "::1" | quote }} + path: /healthz + port: {{ .Values.healthPort }} + scheme: HTTP + httpHeaders: + - name: "brief" + value: "true" + {{- end }} + {{- if semverCompare "<1.20-0" .Capabilities.KubeVersion.Version }} + # The initial delay for the liveness probe is intentionally large to + # avoid an endless kill & restart cycle if in the event that the initial + # bootstrapping takes longer than expected. + # Starting from Kubernetes 1.20, we are using startupProbe instead + # of this field. + initialDelaySeconds: 120 + {{- end }} + periodSeconds: {{ .Values.livenessProbe.periodSeconds }} + successThreshold: 1 + failureThreshold: {{ .Values.livenessProbe.failureThreshold }} + timeoutSeconds: 5 + readinessProbe: + {{- if or .Values.keepDeprecatedProbes $defaultKeepDeprecatedProbes }} + exec: + command: + - cilium + - status + - --brief + {{- else }} + httpGet: + host: {{ .Values.ipv4.enabled | ternary "127.0.0.1" "::1" | quote }} + path: /healthz + port: {{ .Values.healthPort }} + scheme: HTTP + httpHeaders: + - name: "brief" + value: "true" + {{- end }} + {{- if semverCompare "<1.20-0" .Capabilities.KubeVersion.Version }} + initialDelaySeconds: 5 + {{- end }} + periodSeconds: {{ .Values.readinessProbe.periodSeconds }} + successThreshold: 1 + failureThreshold: {{ .Values.readinessProbe.failureThreshold }} + timeoutSeconds: 5 + {{- end }} + env: + - name: K8S_NODE_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: spec.nodeName + - name: CILIUM_K8S_NAMESPACE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + - name: CILIUM_CLUSTERMESH_CONFIG + value: /var/lib/cilium/clustermesh/ + {{- if .Values.k8sServiceHost }} + - name: KUBERNETES_SERVICE_HOST + value: {{ .Values.k8sServiceHost | quote }} + {{- end }} + {{- if .Values.k8sServicePort }} + - name: KUBERNETES_SERVICE_PORT + value: {{ .Values.k8sServicePort | quote }} + {{- end }} + {{- with .Values.extraEnv }} + {{- toYaml . | trim | nindent 8 }} + {{- end }} + {{- if .Values.cni.install }} + lifecycle: + {{- if ne .Values.cni.chainingMode "aws-cni" }} + postStart: + exec: + command: + - "bash" + - "-c" + - | + {{- tpl (.Files.Get "files/agent/poststart-eni.bash") . | nindent 20 }} + {{- end }} + preStop: + exec: + command: + - /cni-uninstall.sh + {{- end }} + {{- with .Values.resources }} + resources: + {{- toYaml . | trim | nindent 10 }} + {{- end }} + {{- if or .Values.prometheus.enabled .Values.hubble.metrics.enabled }} + ports: + - name: peer-service + containerPort: {{ .Values.hubble.peerService.targetPort }} + hostPort: {{ .Values.hubble.peerService.targetPort }} + protocol: TCP + {{- if .Values.prometheus.enabled }} + - name: prometheus + containerPort: {{ .Values.prometheus.port }} + hostPort: {{ .Values.prometheus.port }} + protocol: TCP + {{- if and .Values.proxy.prometheus.enabled .Values.envoy.prometheus.enabled (not .Values.envoy.enabled) }} + - name: envoy-metrics + containerPort: {{ .Values.proxy.prometheus.port | default .Values.envoy.prometheus.port }} + hostPort: {{ .Values.proxy.prometheus.port | default .Values.envoy.prometheus.port }} + protocol: TCP + {{- end }} + {{- end }} + {{- if .Values.hubble.metrics.enabled }} + - name: hubble-metrics + containerPort: {{ .Values.hubble.metrics.port }} + hostPort: {{ .Values.hubble.metrics.port }} + protocol: TCP + {{- end }} + {{- end }} + securityContext: + {{- if .Values.securityContext.privileged }} + privileged: true + {{- else }} + seLinuxOptions: + {{- with .Values.securityContext.seLinuxOptions }} + {{- toYaml . | nindent 12 }} + {{- end }} + capabilities: + add: + {{- with .Values.securityContext.capabilities.ciliumAgent }} + {{- toYaml . | nindent 14 }} + {{- end }} + drop: + - ALL + {{- end }} + terminationMessagePolicy: FallbackToLogsOnError + volumeMounts: + {{- if .Values.authentication.mutual.spire.enabled }} + - name: spire-agent-socket + mountPath: {{ dir .Values.authentication.mutual.spire.adminSocketPath }} + readOnly: false + {{- end }} + {{- if .Values.envoy.enabled }} + - name: envoy-sockets + mountPath: /var/run/cilium/envoy/sockets + readOnly: false + {{- end }} + {{- if not .Values.securityContext.privileged }} + # Unprivileged containers need to mount /proc/sys/net from the host + # to have write access + - mountPath: /host/proc/sys/net + name: host-proc-sys-net + # Unprivileged containers need to mount /proc/sys/kernel from the host + # to have write access + - mountPath: /host/proc/sys/kernel + name: host-proc-sys-kernel + {{- end}} + {{- /* CRI-O already mounts the BPF filesystem */ -}} + {{- if and .Values.bpf.autoMount.enabled (not (eq .Values.containerRuntime.integration "crio")) }} + - name: bpf-maps + mountPath: /sys/fs/bpf + {{- if .Values.securityContext.privileged }} + mountPropagation: Bidirectional + {{- else }} + # Unprivileged containers can't set mount propagation to bidirectional + # in this case we will mount the bpf fs from an init container that + # is privileged and set the mount propagation from host to container + # in Cilium. + mountPropagation: HostToContainer + {{- end}} + {{- end }} + {{- if not (contains "/run/cilium/cgroupv2" .Values.cgroup.hostRoot) }} + # Check for duplicate mounts before mounting + - name: cilium-cgroup + mountPath: {{ .Values.cgroup.hostRoot }} + {{- end}} + - name: cilium-run + mountPath: /var/run/cilium + - name: etc-cni-netd + mountPath: {{ .Values.cni.hostConfDirMountPath }} + {{- if .Values.etcd.enabled }} + - name: etcd-config-path + mountPath: /var/lib/etcd-config + readOnly: true + {{- if or .Values.etcd.ssl .Values.etcd.managed }} + - name: etcd-secrets + mountPath: /var/lib/etcd-secrets + readOnly: true + {{- end }} + {{- end }} + - name: clustermesh-secrets + mountPath: /var/lib/cilium/clustermesh + readOnly: true + {{- if .Values.ipMasqAgent.enabled }} + - name: ip-masq-agent + mountPath: /etc/config + readOnly: true + {{- end }} + {{- if .Values.cni.configMap }} + - name: cni-configuration + mountPath: {{ .Values.cni.confFileMountPath }} + readOnly: true + {{- end }} + # Needed to be able to load kernel modules + - name: lib-modules + mountPath: /lib/modules + readOnly: true + - name: xtables-lock + mountPath: /run/xtables.lock + {{- if and .Values.encryption.enabled (eq .Values.encryption.type "ipsec") }} + - name: cilium-ipsec-secrets + mountPath: {{ .Values.encryption.ipsec.mountPath | default .Values.encryption.mountPath }} + {{- end }} + {{- if .Values.kubeConfigPath }} + - name: kube-config + mountPath: {{ .Values.kubeConfigPath }} + readOnly: true + {{- end }} + {{- if .Values.bgp.enabled }} + - name: bgp-config-path + mountPath: /var/lib/cilium/bgp + readOnly: true + {{- end }} + {{- if and .Values.hubble.enabled .Values.hubble.tls.enabled (hasKey .Values.hubble "listenAddress") }} + - name: hubble-tls + mountPath: /var/lib/cilium/tls/hubble + readOnly: true + {{- end }} + - name: tmp + mountPath: /tmp + {{- range .Values.extraHostPathMounts }} + - name: {{ .name }} + mountPath: {{ .mountPath }} + readOnly: {{ .readOnly }} + {{- if .mountPropagation }} + mountPropagation: {{ .mountPropagation }} + {{- end }} + {{- end }} + {{- with .Values.extraVolumeMounts }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if .Values.monitor.enabled }} + - name: cilium-monitor + image: {{ include "cilium.image" .Values.image | quote }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + command: + - /bin/bash + - -c + - -- + args: + - |- + for i in {1..5}; do \ + [ -S /var/run/cilium/monitor1_2.sock ] && break || sleep 10;\ + done; \ + cilium monitor + {{- range $type := .Values.monitor.eventTypes -}} + {{ " " }}--type={{ $type }} + {{- end }} + terminationMessagePolicy: FallbackToLogsOnError + volumeMounts: + - name: cilium-run + mountPath: /var/run/cilium + {{- with .Values.extraVolumeMounts }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.monitor.resources }} + resources: + {{- toYaml . | trim | nindent 10 }} + {{- end }} + {{- end }} + {{- if .Values.extraContainers }} + {{- toYaml .Values.extraContainers | nindent 6 }} + {{- end }} + initContainers: + - name: config + image: {{ include "cilium.image" .Values.image | quote }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + command: + - cilium + - build-config + {{- if (not (kindIs "invalid" .Values.daemon.configSources)) }} + - "--source={{.Values.daemon.configSources}}" + {{- end }} + {{- if (not (kindIs "invalid" .Values.daemon.allowedConfigOverrides)) }} + - "--allow-config-keys={{.Values.daemon.allowedConfigOverrides}}" + {{- end }} + {{- if (not (kindIs "invalid" .Values.daemon.blockedConfigOverrides)) }} + - "--deny-config-keys={{.Values.daemon.blockedConfigOverrides}}" + {{- end }} + env: + - name: K8S_NODE_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: spec.nodeName + - name: CILIUM_K8S_NAMESPACE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + {{- if .Values.k8sServiceHost }} + - name: KUBERNETES_SERVICE_HOST + value: {{ .Values.k8sServiceHost | quote }} + {{- end }} + {{- if .Values.k8sServicePort }} + - name: KUBERNETES_SERVICE_PORT + value: {{ .Values.k8sServicePort | quote }} + {{- end }} + {{- with .Values.extraEnv }} + {{- toYaml . | nindent 8 }} + {{- end }} + volumeMounts: + - name: tmp + mountPath: /tmp + terminationMessagePolicy: FallbackToLogsOnError + {{- if .Values.cgroup.autoMount.enabled }} + # Required to mount cgroup2 filesystem on the underlying Kubernetes node. + # We use nsenter command with host's cgroup and mount namespaces enabled. + - name: mount-cgroup + image: {{ include "cilium.image" .Values.image | quote }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + env: + - name: CGROUP_ROOT + value: {{ .Values.cgroup.hostRoot }} + - name: BIN_PATH + value: {{ .Values.cni.binPath }} + {{- with .Values.cgroup.autoMount.resources }} + resources: + {{- toYaml . | trim | nindent 10 }} + {{- end }} + command: + - sh + - -ec + # The statically linked Go program binary is invoked to avoid any + # dependency on utilities like sh and mount that can be missing on certain + # distros installed on the underlying host. Copy the binary to the + # same directory where we install cilium cni plugin so that exec permissions + # are available. + - | + cp /usr/bin/cilium-mount /hostbin/cilium-mount; + nsenter --cgroup=/hostproc/1/ns/cgroup --mount=/hostproc/1/ns/mnt "${BIN_PATH}/cilium-mount" $CGROUP_ROOT; + rm /hostbin/cilium-mount + volumeMounts: + - name: hostproc + mountPath: /hostproc + - name: cni-path + mountPath: /hostbin + terminationMessagePolicy: FallbackToLogsOnError + securityContext: + {{- if .Values.securityContext.privileged }} + privileged: true + {{- else }} + seLinuxOptions: + {{- with .Values.securityContext.seLinuxOptions }} + {{- toYaml . | nindent 12 }} + {{- end }} + capabilities: + add: + {{- with .Values.securityContext.capabilities.mountCgroup }} + {{- toYaml . | nindent 14 }} + {{- end }} + drop: + - ALL + {{- end}} + - name: apply-sysctl-overwrites + image: {{ include "cilium.image" .Values.image | quote }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + {{- with .Values.initResources }} + resources: + {{- toYaml . | trim | nindent 10 }} + {{- end }} + env: + - name: BIN_PATH + value: {{ .Values.cni.binPath }} + command: + - sh + - -ec + # The statically linked Go program binary is invoked to avoid any + # dependency on utilities like sh that can be missing on certain + # distros installed on the underlying host. Copy the binary to the + # same directory where we install cilium cni plugin so that exec permissions + # are available. + - | + cp /usr/bin/cilium-sysctlfix /hostbin/cilium-sysctlfix; + nsenter --mount=/hostproc/1/ns/mnt "${BIN_PATH}/cilium-sysctlfix"; + rm /hostbin/cilium-sysctlfix + volumeMounts: + - name: hostproc + mountPath: /hostproc + - name: cni-path + mountPath: /hostbin + terminationMessagePolicy: FallbackToLogsOnError + securityContext: + {{- if .Values.securityContext.privileged }} + privileged: true + {{- else }} + seLinuxOptions: + {{- with .Values.securityContext.seLinuxOptions }} + {{- toYaml . | nindent 12 }} + {{- end }} + capabilities: + add: + {{- with .Values.securityContext.capabilities.applySysctlOverwrites }} + {{- toYaml . | nindent 14 }} + {{- end }} + drop: + - ALL + {{- end}} + {{- end }} + {{- if and .Values.bpf.autoMount.enabled (not .Values.securityContext.privileged) }} + # Mount the bpf fs if it is not mounted. We will perform this task + # from a privileged container because the mount propagation bidirectional + # only works from privileged containers. + - name: mount-bpf-fs + image: {{ include "cilium.image" .Values.image | quote }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + {{- with .Values.initResources }} + resources: + {{- toYaml . | trim | nindent 10 }} + {{- end }} + args: + - 'mount | grep "/sys/fs/bpf type bpf" || mount -t bpf bpf /sys/fs/bpf' + command: + - /bin/bash + - -c + - -- + terminationMessagePolicy: FallbackToLogsOnError + securityContext: + privileged: true + {{- /* CRI-O already mounts the BPF filesystem */ -}} + {{- if and .Values.bpf.autoMount.enabled (not (eq .Values.containerRuntime.integration "crio")) }} + volumeMounts: + - name: bpf-maps + mountPath: /sys/fs/bpf + mountPropagation: Bidirectional + {{- end }} + {{- end }} + {{- if and .Values.nodeinit.enabled .Values.nodeinit.bootstrapFile }} + - name: wait-for-node-init + image: {{ include "cilium.image" .Values.image | quote }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + {{- with .Values.initResources }} + resources: + {{- toYaml . | trim | nindent 10 }} + {{- end }} + command: + - sh + - -c + - | + until test -s {{ (print "/tmp/cilium-bootstrap.d/" (.Values.nodeinit.bootstrapFile | base)) | quote }}; do + echo "Waiting on node-init to run..."; + sleep 1; + done + terminationMessagePolicy: FallbackToLogsOnError + volumeMounts: + - name: cilium-bootstrap-file-dir + mountPath: "/tmp/cilium-bootstrap.d" + {{- end }} + - name: clean-cilium-state + image: {{ include "cilium.image" .Values.image | quote }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + command: + - /init-container.sh + env: + - name: CILIUM_ALL_STATE + valueFrom: + configMapKeyRef: + name: cilium-config + key: clean-cilium-state + optional: true + - name: CILIUM_BPF_STATE + valueFrom: + configMapKeyRef: + name: cilium-config + key: clean-cilium-bpf-state + optional: true + {{- if .Values.k8sServiceHost }} + - name: KUBERNETES_SERVICE_HOST + value: {{ .Values.k8sServiceHost | quote }} + {{- end }} + {{- if .Values.k8sServicePort }} + - name: KUBERNETES_SERVICE_PORT + value: {{ .Values.k8sServicePort | quote }} + {{- end }} + {{- with .Values.extraEnv }} + {{- toYaml . | nindent 8 }} + {{- end }} + terminationMessagePolicy: FallbackToLogsOnError + securityContext: + {{- if .Values.securityContext.privileged }} + privileged: true + {{- else }} + seLinuxOptions: + {{- with .Values.securityContext.seLinuxOptions }} + {{- toYaml . | nindent 12 }} + {{- end }} + capabilities: + add: + {{- with .Values.securityContext.capabilities.cleanCiliumState }} + {{- toYaml . | nindent 14 }} + {{- end }} + drop: + - ALL + {{- end}} + volumeMounts: + {{- /* CRI-O already mounts the BPF filesystem */ -}} + {{- if and .Values.bpf.autoMount.enabled (not (eq .Values.containerRuntime.integration "crio")) }} + - name: bpf-maps + mountPath: /sys/fs/bpf + {{- end }} + # Required to mount cgroup filesystem from the host to cilium agent pod + - name: cilium-cgroup + mountPath: {{ .Values.cgroup.hostRoot }} + mountPropagation: HostToContainer + - name: cilium-run + mountPath: /var/run/cilium + {{- with .Values.extraVolumeMounts }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.initResources }} + resources: + {{- toYaml . | trim | nindent 10 }} + {{- end }} + {{- if and .Values.waitForKubeProxy (ne $kubeProxyReplacement "strict") }} + - name: wait-for-kube-proxy + image: {{ include "cilium.image" .Values.image | quote }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + {{- with .Values.initResources }} + resources: + {{- toYaml . | trim | nindent 10 }} + {{- end }} + securityContext: + privileged: true + command: + - bash + - -c + - | + while true + do + if iptables-nft-save -t mangle | grep -E '^:(KUBE-IPTABLES-HINT|KUBE-PROXY-CANARY)'; then + echo "Found KUBE-IPTABLES-HINT or KUBE-PROXY-CANARY iptables rule in 'iptables-nft-save -t mangle'" + exit 0 + fi + if ip6tables-nft-save -t mangle | grep -E '^:(KUBE-IPTABLES-HINT|KUBE-PROXY-CANARY)'; then + echo "Found KUBE-IPTABLES-HINT or KUBE-PROXY-CANARY iptables rule in 'ip6tables-nft-save -t mangle'" + exit 0 + fi + if iptables-legacy-save | grep -E '^:KUBE-PROXY-CANARY'; then + echo "Found KUBE-PROXY-CANARY iptables rule in 'iptables-legacy-save" + exit 0 + fi + if ip6tables-legacy-save | grep -E '^:KUBE-PROXY-CANARY'; then + echo "KUBE-PROXY-CANARY iptables rule in 'ip6tables-legacy-save'" + exit 0 + fi + echo "Waiting for kube-proxy to create iptables rules..."; + sleep 1; + done + terminationMessagePolicy: FallbackToLogsOnError + {{- end }} # wait-for-kube-proxy + {{- if .Values.cni.install }} + # Install the CNI binaries in an InitContainer so we don't have a writable host mount in the agent + - name: install-cni-binaries + image: {{ include "cilium.image" .Values.image | quote }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + command: + - "/install-plugin.sh" + resources: + requests: + cpu: 100m + memory: 10Mi + securityContext: + {{- if .Values.securityContext.privileged }} + privileged: true + {{- else }} + seLinuxOptions: + {{- with .Values.securityContext.seLinuxOptions }} + {{- toYaml . | nindent 12 }} + {{- end }} + {{- end }} + capabilities: + drop: + - ALL + terminationMessagePolicy: FallbackToLogsOnError + volumeMounts: + - name: cni-path + mountPath: /host/opt/cni/bin + {{- end }} # .Values.cni.install + restartPolicy: Always + priorityClassName: {{ include "cilium.priorityClass" (list $ .Values.priorityClassName "system-node-critical") }} + serviceAccount: {{ .Values.serviceAccounts.cilium.name | quote }} + serviceAccountName: {{ .Values.serviceAccounts.cilium.name | quote }} + automountServiceAccountToken: {{ .Values.serviceAccounts.cilium.automount }} + terminationGracePeriodSeconds: {{ .Values.terminationGracePeriodSeconds }} + hostNetwork: true + {{- if and .Values.etcd.managed (not .Values.etcd.k8sService) }} + # In managed etcd mode, Cilium must be able to resolve the DNS name of + # the etcd service + dnsPolicy: ClusterFirstWithHostNet + {{- else if .Values.dnsPolicy }} + dnsPolicy: {{ .Values.dnsPolicy }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | trim | nindent 8 }} + {{- end }} + {{- if and .Values.clustermesh.useAPIServer .Values.clustermesh.config.enabled (not .Values.clustermesh.apiserver.kvstoremesh.enabled) }} + hostAliases: + {{- range $cluster := .Values.clustermesh.config.clusters }} + {{- range $ip := $cluster.ips }} + - ip: {{ $ip }} + hostnames: [ "{{ $cluster.name }}.{{ $.Values.clustermesh.config.domain }}" ] + {{- end }} + {{- end }} + {{- end }} + volumes: + # For sharing configuration between the "config" initContainer and the agent + - name: tmp + emptyDir: {} + # To keep state between restarts / upgrades + - name: cilium-run + hostPath: + path: {{ .Values.daemon.runPath }} + type: DirectoryOrCreate + {{- /* CRI-O already mounts the BPF filesystem */ -}} + {{- if and .Values.bpf.autoMount.enabled (not (eq .Values.containerRuntime.integration "crio")) }} + # To keep state between restarts / upgrades for bpf maps + - name: bpf-maps + hostPath: + path: /sys/fs/bpf + type: DirectoryOrCreate + {{- end }} + {{- if .Values.cgroup.autoMount.enabled }} + # To mount cgroup2 filesystem on the host + - name: hostproc + hostPath: + path: /proc + type: Directory + {{- end }} + # To keep state between restarts / upgrades for cgroup2 filesystem + - name: cilium-cgroup + hostPath: + path: {{ .Values.cgroup.hostRoot}} + type: DirectoryOrCreate + # To install cilium cni plugin in the host + - name: cni-path + hostPath: + path: {{ .Values.cni.binPath }} + type: DirectoryOrCreate + # To install cilium cni configuration in the host + - name: etc-cni-netd + hostPath: + path: {{ .Values.cni.confPath }} + type: DirectoryOrCreate + # To be able to load kernel modules + - name: lib-modules + hostPath: + path: /lib/modules + # To access iptables concurrently with other processes (e.g. kube-proxy) + - name: xtables-lock + hostPath: + path: /run/xtables.lock + type: FileOrCreate + {{- if .Values.authentication.mutual.spire.enabled }} + - name: spire-agent-socket + hostPath: + path: {{ dir .Values.authentication.mutual.spire.adminSocketPath }} + type: DirectoryOrCreate + {{- end }} + {{- if .Values.envoy.enabled }} + # Sharing socket with Cilium Envoy on the same node by using a host path + - name: envoy-sockets + hostPath: + path: "{{ .Values.daemon.runPath }}/envoy/sockets" + type: DirectoryOrCreate + {{- end }} + {{- if .Values.kubeConfigPath }} + - name: kube-config + hostPath: + path: {{ .Values.kubeConfigPath }} + type: FileOrCreate + {{- end }} + {{- if and .Values.nodeinit.enabled .Values.nodeinit.bootstrapFile }} + - name: cilium-bootstrap-file-dir + hostPath: + path: {{ .Values.nodeinit.bootstrapFile | dir | quote }} + type: DirectoryOrCreate + {{- end }} + {{- if .Values.etcd.enabled }} + # To read the etcd config stored in config maps + - name: etcd-config-path + configMap: + name: cilium-config + # note: the leading zero means this number is in octal representation: do not remove it + defaultMode: 0400 + items: + - key: etcd-config + path: etcd.config + # To read the k8s etcd secrets in case the user might want to use TLS + {{- if or .Values.etcd.ssl .Values.etcd.managed }} + - name: etcd-secrets + secret: + secretName: cilium-etcd-secrets + # note: the leading zero means this number is in octal representation: do not remove it + defaultMode: 0400 + optional: true + {{- end }} + {{- end }} + # To read the clustermesh configuration + - name: clustermesh-secrets + projected: + # note: the leading zero means this number is in octal representation: do not remove it + defaultMode: 0400 + sources: + - secret: + name: cilium-clustermesh + optional: true + # note: items are not explicitly listed here, since the entries of this secret + # depend on the peers configured, and that would cause a restart of all agents + # at every addition/removal. Leaving the field empty makes each secret entry + # to be automatically projected into the volume as a file whose name is the key. + - secret: + name: clustermesh-apiserver-remote-cert + optional: true + items: + - key: tls.key + path: common-etcd-client.key + - key: tls.crt + path: common-etcd-client.crt + {{- if not .Values.tls.caBundle.enabled }} + - key: ca.crt + path: common-etcd-client-ca.crt + {{- else }} + - {{ .Values.tls.caBundle.useSecret | ternary "secret" "configMap" }}: + name: {{ .Values.tls.caBundle.name }} + optional: true + items: + - key: {{ .Values.tls.caBundle.key }} + path: common-etcd-client-ca.crt + {{- end }} + {{- if and .Values.ipMasqAgent .Values.ipMasqAgent.enabled }} + - name: ip-masq-agent + configMap: + name: ip-masq-agent + optional: true + items: + - key: config + path: ip-masq-agent + {{- end }} + {{- if and .Values.encryption.enabled (eq .Values.encryption.type "ipsec") }} + - name: cilium-ipsec-secrets + secret: + secretName: {{ .Values.encryption.ipsec.secretName | default .Values.encryption.secretName }} + {{- end }} + {{- if .Values.cni.configMap }} + - name: cni-configuration + configMap: + name: {{ .Values.cni.configMap }} + {{- end }} + {{- if .Values.bgp.enabled }} + - name: bgp-config-path + configMap: + name: bgp-config + {{- end }} + {{- if not .Values.securityContext.privileged }} + - name: host-proc-sys-net + hostPath: + path: /proc/sys/net + type: Directory + - name: host-proc-sys-kernel + hostPath: + path: /proc/sys/kernel + type: Directory + {{- end }} + {{- if and .Values.hubble.enabled .Values.hubble.tls.enabled (hasKey .Values.hubble "listenAddress") }} + - name: hubble-tls + projected: + # note: the leading zero means this number is in octal representation: do not remove it + defaultMode: 0400 + sources: + - secret: + name: hubble-server-certs + optional: true + items: + - key: tls.crt + path: server.crt + - key: tls.key + path: server.key + {{- if not .Values.tls.caBundle.enabled }} + - key: ca.crt + path: client-ca.crt + {{- else }} + - {{ .Values.tls.caBundle.useSecret | ternary "secret" "configMap" }}: + name: {{ .Values.tls.caBundle.name }} + optional: true + items: + - key: {{ .Values.tls.caBundle.key }} + path: client-ca.crt + {{- end }} + {{- end }} + {{- range .Values.extraHostPathMounts }} + - name: {{ .name }} + hostPath: + path: {{ .hostPath }} + {{- if .hostPathType }} + type: {{ .hostPathType }} + {{- end }} + {{- end }} + {{- with .Values.extraVolumes }} + {{- toYaml . | nindent 6 }} + {{- end }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/cilium-agent/dashboards-configmap.yaml b/packages/system/cilium/charts/cilium/templates/cilium-agent/dashboards-configmap.yaml new file mode 100644 index 00000000..7f1ff7c5 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/cilium-agent/dashboards-configmap.yaml @@ -0,0 +1,25 @@ +{{- if .Values.dashboards.enabled }} +{{- $files := .Files.Glob "files/cilium-agent/dashboards/*.json" }} +{{- range $path, $fileContents := $files }} +{{- $dashboardName := regexReplaceAll "(^.*/)(.*)\\.json$" $path "${2}" }} +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ $dashboardName | trunc 63 | trimSuffix "-" }} + namespace: {{ $.Values.dashboards.namespace | default $.Release.Namespace }} + labels: + k8s-app: cilium + app.kubernetes.io/name: cilium-agent + app.kubernetes.io/part-of: cilium + {{- if $.Values.dashboards.label }} + {{ $.Values.dashboards.label }}: {{ ternary $.Values.dashboards.labelValue "1" (not (empty $.Values.dashboards.labelValue)) | quote }} + {{- end }} + {{- with $.Values.dashboards.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +data: + {{ $dashboardName }}.json: {{ $.Files.Get $path | toJson }} +{{- end }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/cilium-agent/role.yaml b/packages/system/cilium/charts/cilium/templates/cilium-agent/role.yaml new file mode 100644 index 00000000..abbf37d8 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/cilium-agent/role.yaml @@ -0,0 +1,80 @@ +{{- if and .Values.agent (not .Values.preflight.enabled) }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: cilium-config-agent + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/part-of: cilium +rules: +- apiGroups: + - "" + resources: + - configmaps + verbs: + - get + - list + - watch + +{{- end }} + +{{- if and .Values.agent (not .Values.preflight.enabled) .Values.serviceAccounts.cilium.create .Values.ingressController.enabled .Values.ingressController.secretsNamespace.name }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: cilium-ingress-secrets + namespace: {{ .Values.ingressController.secretsNamespace.name | quote }} + labels: + app.kubernetes.io/part-of: cilium +rules: +- apiGroups: + - "" + resources: + - secrets + verbs: + - get + - list + - watch +{{- end }} + +{{- if and .Values.agent (not .Values.preflight.enabled) .Values.serviceAccounts.cilium.create .Values.gatewayAPI.enabled .Values.gatewayAPI.secretsNamespace.name }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: cilium-gateway-secrets + namespace: {{ .Values.gatewayAPI.secretsNamespace.name | quote }} + labels: + app.kubernetes.io/part-of: cilium +rules: +- apiGroups: + - "" + resources: + - secrets + verbs: + - get + - list + - watch +{{- end}} + +{{- if and .Values.agent (not .Values.preflight.enabled) .Values.serviceAccounts.cilium.create .Values.envoyConfig.enabled .Values.envoyConfig.secretsNamespace.name }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: cilium-envoy-config-secrets + namespace: {{ .Values.envoyConfig.secretsNamespace.name | quote }} + labels: + app.kubernetes.io/part-of: cilium +rules: +- apiGroups: + - "" + resources: + - secrets + verbs: + - get + - list + - watch +{{- end}} diff --git a/packages/system/cilium/charts/cilium/templates/cilium-agent/rolebinding.yaml b/packages/system/cilium/charts/cilium/templates/cilium-agent/rolebinding.yaml new file mode 100644 index 00000000..ec8c5d80 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/cilium-agent/rolebinding.yaml @@ -0,0 +1,75 @@ +{{- if and .Values.agent (not .Values.preflight.enabled) }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: cilium-config-agent + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/part-of: cilium +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: cilium-config-agent +subjects: + - kind: ServiceAccount + name: {{ .Values.serviceAccounts.cilium.name | quote }} + namespace: {{ .Release.Namespace }} +{{- end}} + +{{- if and .Values.agent (not .Values.preflight.enabled) .Values.serviceAccounts.cilium.create .Values.ingressController.enabled .Values.ingressController.secretsNamespace.name}} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: cilium-secrets + namespace: {{ .Values.ingressController.secretsNamespace.name | quote }} + labels: + app.kubernetes.io/part-of: cilium +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: cilium-ingress-secrets +subjects: + - kind: ServiceAccount + name: {{ .Values.serviceAccounts.cilium.name | quote }} + namespace: {{ .Release.Namespace }} +{{- end }} + +{{- if and .Values.agent (not .Values.preflight.enabled) .Values.serviceAccounts.cilium.create .Values.gatewayAPI.enabled .Values.gatewayAPI.secretsNamespace.name}} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: cilium-gateway-secrets + namespace: {{ .Values.gatewayAPI.secretsNamespace.name | quote }} + labels: + app.kubernetes.io/part-of: cilium +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: cilium-gateway-secrets +subjects: +- kind: ServiceAccount + name: {{ .Values.serviceAccounts.cilium.name | quote }} + namespace: {{ .Release.Namespace }} +{{- end}} + +{{- if and .Values.agent (not .Values.preflight.enabled) .Values.serviceAccounts.cilium.create .Values.envoyConfig.enabled .Values.envoyConfig.secretsNamespace.name}} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: cilium-envoy-config-secrets + namespace: {{ .Values.envoyConfig.secretsNamespace.name | quote }} + labels: + app.kubernetes.io/part-of: cilium +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: cilium-envoy-config-secrets +subjects: +- kind: ServiceAccount + name: {{ .Values.serviceAccounts.cilium.name | quote }} + namespace: {{ .Release.Namespace }} +{{- end}} diff --git a/packages/system/cilium/charts/cilium/templates/cilium-agent/service.yaml b/packages/system/cilium/charts/cilium/templates/cilium-agent/service.yaml new file mode 100644 index 00000000..e0a55803 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/cilium-agent/service.yaml @@ -0,0 +1,52 @@ +{{- if and .Values.agent (not .Values.preflight.enabled) .Values.prometheus.enabled }} +{{- if .Values.prometheus.serviceMonitor.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: cilium-agent + namespace: {{ .Release.Namespace }} + labels: + k8s-app: cilium + app.kubernetes.io/name: cilium-agent + app.kubernetes.io/part-of: cilium +spec: + clusterIP: None + type: ClusterIP + selector: + k8s-app: cilium + ports: + - name: metrics + port: {{ .Values.prometheus.port }} + protocol: TCP + targetPort: prometheus + {{- if not .Values.envoy.enabled }} + - name: envoy-metrics + port: {{ .Values.proxy.prometheus.port | default .Values.envoy.prometheus.port }} + protocol: TCP + targetPort: envoy-metrics + {{- end }} +{{- else if and .Values.proxy.prometheus.enabled .Values.envoy.prometheus.enabled (not .Values.envoy.enabled) }} +apiVersion: v1 +kind: Service +metadata: + name: cilium-agent + namespace: {{ .Release.Namespace }} + annotations: + prometheus.io/scrape: "true" + prometheus.io/port: {{ .Values.proxy.prometheus.port | default .Values.envoy.prometheus.port | quote }} + labels: + k8s-app: cilium + app.kubernetes.io/name: cilium-agent + app.kubernetes.io/part-of: cilium +spec: + clusterIP: None + type: ClusterIP + selector: + k8s-app: cilium + ports: + - name: envoy-metrics + port: {{ .Values.proxy.prometheus.port | default .Values.envoy.prometheus.port }} + protocol: TCP + targetPort: envoy-metrics +{{- end }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/cilium-agent/serviceaccount.yaml b/packages/system/cilium/charts/cilium/templates/cilium-agent/serviceaccount.yaml new file mode 100644 index 00000000..605506f1 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/cilium-agent/serviceaccount.yaml @@ -0,0 +1,11 @@ +{{- if and .Values.agent (not .Values.preflight.enabled) .Values.serviceAccounts.cilium.create }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ .Values.serviceAccounts.cilium.name | quote }} + namespace: {{ .Release.Namespace }} + {{- if .Values.serviceAccounts.cilium.annotations }} + annotations: + {{- toYaml .Values.serviceAccounts.cilium.annotations | nindent 4 }} + {{- end }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/cilium-agent/servicemonitor.yaml b/packages/system/cilium/charts/cilium/templates/cilium-agent/servicemonitor.yaml new file mode 100644 index 00000000..39a8dcc1 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/cilium-agent/servicemonitor.yaml @@ -0,0 +1,39 @@ +{{- if and .Values.agent (not .Values.preflight.enabled) .Values.prometheus.enabled .Values.prometheus.serviceMonitor.enabled }} +--- +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: cilium-agent + namespace: {{ .Values.prometheus.serviceMonitor.namespace | default .Release.Namespace }} + labels: + app.kubernetes.io/part-of: cilium + {{- with .Values.prometheus.serviceMonitor.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + annotations: + {{- with .Values.prometheus.serviceMonitor.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + selector: + matchLabels: + k8s-app: cilium + namespaceSelector: + matchNames: + - {{ .Release.Namespace }} + endpoints: + - port: metrics + interval: {{ .Values.prometheus.serviceMonitor.interval | quote }} + honorLabels: true + path: /metrics + {{- with .Values.prometheus.serviceMonitor.relabelings }} + relabelings: + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.prometheus.serviceMonitor.metricRelabelings }} + metricRelabelings: + {{- toYaml . | nindent 4 }} + {{- end }} + targetLabels: + - k8s-app +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/cilium-ca-bundle-configmap.yaml b/packages/system/cilium/charts/cilium/templates/cilium-ca-bundle-configmap.yaml new file mode 100644 index 00000000..38522458 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/cilium-ca-bundle-configmap.yaml @@ -0,0 +1,11 @@ +{{- if and .Values.tls.caBundle.enabled .Values.tls.caBundle.content -}} +--- +apiVersion: v1 +kind: {{ .Values.tls.caBundle.useSecret | ternary "Secret" "ConfigMap" }} +metadata: + name: {{ .Values.tls.caBundle.name }} + namespace: {{ .Release.Namespace }} +{{ .Values.tls.caBundle.useSecret | ternary "stringData" "data" }}: + {{ .Values.tls.caBundle.key }}: | + {{- .Values.tls.caBundle.content | nindent 4 }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/cilium-ca-secret.yaml b/packages/system/cilium/charts/cilium/templates/cilium-ca-secret.yaml new file mode 100644 index 00000000..5a74f787 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/cilium-ca-secret.yaml @@ -0,0 +1,17 @@ +{{- if or + (and (or .Values.externalWorkloads.enabled .Values.clustermesh.useAPIServer) .Values.clustermesh.apiserver.tls.auto.enabled (eq .Values.clustermesh.apiserver.tls.auto.method "helm") (not .Values.clustermesh.apiserver.tls.ca.cert)) + (and (or .Values.agent .Values.hubble.relay.enabled .Values.hubble.ui.enabled) .Values.hubble.enabled .Values.hubble.tls.enabled .Values.hubble.tls.auto.enabled (eq .Values.hubble.tls.auto.method "helm")) + (and .Values.tls.ca.key .Values.tls.ca.cert) +-}} + +{{- $_ := include "cilium.ca.setup" . -}} +--- +apiVersion: v1 +kind: Secret +metadata: + name: {{ .commonCASecretName }} + namespace: {{ .Release.Namespace }} +data: + ca.crt: {{ .commonCA.Cert | b64enc }} + ca.key: {{ .commonCA.Key | b64enc }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/cilium-configmap.yaml b/packages/system/cilium/charts/cilium/templates/cilium-configmap.yaml new file mode 100644 index 00000000..09043940 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/cilium-configmap.yaml @@ -0,0 +1,1172 @@ +{{- if and (.Values.agent) (not .Values.preflight.enabled) }} +{{- /* Default values with backwards compatibility */ -}} +{{- $defaultEnableCnpStatusUpdates := "true" -}} +{{- $defaultBpfMapDynamicSizeRatio := 0.0 -}} +{{- $defaultBpfMasquerade := "false" -}} +{{- $defaultBpfClockProbe := "false" -}} +{{- $defaultBpfTProxy := "false" -}} +{{- $defaultIPAM := "cluster-pool" -}} +{{- $defaultOperatorApiServeAddr := "localhost:9234" -}} +{{- $defaultBpfCtTcpMax := 524288 -}} +{{- $defaultBpfCtAnyMax := 262144 -}} +{{- $enableIdentityMark := "true" -}} +{{- $fragmentTracking := "true" -}} +{{- $defaultKubeProxyReplacement := "false" -}} +{{- $azureUsePrimaryAddress := "true" -}} + +{{- /* Default values when 1.8 was initially deployed */ -}} +{{- if semverCompare ">=1.8" (default "1.8" .Values.upgradeCompatibility) -}} + {{- $defaultEnableCnpStatusUpdates = "false" -}} + {{- $defaultBpfMapDynamicSizeRatio = 0.0025 -}} + {{- $defaultBpfMasquerade = "true" -}} + {{- $defaultBpfClockProbe = "true" -}} + {{- $defaultIPAM = "cluster-pool" -}} + {{- if .Values.ipv4.enabled }} + {{- $defaultOperatorApiServeAddr = "127.0.0.1:9234" -}} + {{- else -}} + {{- $defaultOperatorApiServeAddr = "[::1]:9234" -}} + {{- end }} + {{- $defaultBpfCtTcpMax = 0 -}} + {{- $defaultBpfCtAnyMax = 0 -}} + {{- $defaultKubeProxyReplacement = "probe" -}} +{{- end -}} + +{{- /* Default values when 1.9 was initially deployed */ -}} +{{- if semverCompare ">=1.9" (default "1.9" .Values.upgradeCompatibility) -}} + {{- $defaultKubeProxyReplacement = "probe" -}} +{{- end -}} + +{{- /* Default values when 1.10 was initially deployed */ -}} +{{- if semverCompare ">=1.10" (default "1.10" .Values.upgradeCompatibility) -}} + {{- /* Needs to be explicitly disabled because it was enabled on all versions >=v1.8 above. */ -}} + {{- $defaultBpfMasquerade = "false" -}} +{{- end -}} + +{{- /* Default values when 1.12 was initially deployed */ -}} +{{- if semverCompare ">=1.12" (default "1.12" .Values.upgradeCompatibility) -}} + {{- if .Values.azure.enabled }} + {{- $azureUsePrimaryAddress = "false" -}} + {{- end }} + {{- $defaultKubeProxyReplacement = "disabled" -}} +{{- end -}} + +{{- /* Default values when 1.14 was initially deployed */ -}} +{{- if semverCompare ">=1.14" (default "1.14" .Values.upgradeCompatibility) -}} + {{- /* KPR default for 1.14 needed to override earlier version defaults set above when upgradeCompatibility is not specified */ -}} + {{- $defaultKubeProxyReplacement = "false" -}} +{{- end -}} + +{{- $ipam := (coalesce .Values.ipam.mode $defaultIPAM) -}} +{{- $bpfCtTcpMax := (coalesce .Values.bpf.ctTcpMax $defaultBpfCtTcpMax) -}} +{{- $bpfCtAnyMax := (coalesce .Values.bpf.ctAnyMax $defaultBpfCtAnyMax) -}} +{{- $stringValueKPR := (toString .Values.kubeProxyReplacement) -}} +{{- if (eq $stringValueKPR "") }} + {{- $stringValueKPR = "" -}} +{{- end}} +{{- $kubeProxyReplacement := (coalesce $stringValueKPR $defaultKubeProxyReplacement) -}} +{{- if and (ne $kubeProxyReplacement "disabled") (ne $kubeProxyReplacement "partial") (ne $kubeProxyReplacement "strict") (ne $kubeProxyReplacement "true") (ne $kubeProxyReplacement "false") }} + {{ fail "kubeProxyReplacement must be explicitly set to a valid value (true, false, disabled (deprecated), partial (deprecated), or strict (deprecated)) to continue." }} +{{- end }} +{{- $azureUsePrimaryAddress = (coalesce .Values.azure.usePrimaryAddress $azureUsePrimaryAddress) -}} +{{- $socketLB := (coalesce .Values.socketLB .Values.hostServices) -}} + +{{- $cniChainingMode := "none" -}} +{{- if (not (kindIs "invalid" .Values.cni.chainingMode)) -}} + {{- $cniChainingMode = .Values.cni.chainingMode -}} +{{- else if (not (kindIs "invalid" .Values.cni.chainingTarget)) -}} + {{- $cniChainingMode = "generic-veth" -}} +{{- end -}} +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: cilium-config + namespace: {{ .Release.Namespace }} +data: +{{- if .Values.etcd.enabled }} + # The kvstore configuration is used to enable use of a kvstore for state + # storage. This can either be provided with an external kvstore or with the + # help of cilium-etcd-operator which operates an etcd cluster automatically. + kvstore: etcd + {{- if .Values.etcd.k8sService }} + kvstore-opt: '{"etcd.config": "/var/lib/etcd-config/etcd.config", "etcd.operator": "true"}' + {{- else }} + kvstore-opt: '{"etcd.config": "/var/lib/etcd-config/etcd.config"}' + {{- end }} + + # This etcd-config contains the etcd endpoints of your cluster. If you use + # TLS please make sure you follow the tutorial in https://cilium.link/etcd-config + etcd-config: |- + --- + endpoints: + {{- if .Values.etcd.managed }} + - https://cilium-etcd-client.{{ .Release.Namespace }}.svc:2379 + {{- else }} + {{- range .Values.etcd.endpoints }} + - {{ . }} + {{- end }} + {{- end }} + {{- if or .Values.etcd.ssl .Values.etcd.managed }} + trusted-ca-file: '/var/lib/etcd-secrets/etcd-client-ca.crt' + key-file: '/var/lib/etcd-secrets/etcd-client.key' + cert-file: '/var/lib/etcd-secrets/etcd-client.crt' + {{- end }} +{{- end }} + +{{- if .Values.conntrackGCInterval }} + conntrack-gc-interval: {{ include "validateDuration" .Values.conntrackGCInterval | quote }} +{{- end }} + +{{- if .Values.conntrackGCMaxInterval }} + conntrack-gc-max-interval: {{ include "validateDuration" .Values.conntrackGCMaxInterval | quote }} +{{- end }} + +{{- if hasKey .Values "disableEnvoyVersionCheck" }} + disable-envoy-version-check: {{ .Values.disableEnvoyVersionCheck | quote }} +{{- end }} + + # Identity allocation mode selects how identities are shared between cilium + # nodes by setting how they are stored. The options are "crd" or "kvstore". + # - "crd" stores identities in kubernetes as CRDs (custom resource definition). + # These can be queried with: + # kubectl get ciliumid + # - "kvstore" stores identities in an etcd kvstore, that is + # configured below. Cilium versions before 1.6 supported only the kvstore + # backend. Upgrades from these older cilium versions should continue using + # the kvstore by commenting out the identity-allocation-mode below, or + # setting it to "kvstore". + identity-allocation-mode: {{ .Values.identityAllocationMode }} + identity-heartbeat-timeout: {{ include "validateDuration" .Values.operator.identityHeartbeatTimeout | quote }} + identity-gc-interval: {{ include "validateDuration" .Values.operator.identityGCInterval | quote }} + cilium-endpoint-gc-interval: {{ include "validateDuration" .Values.operator.endpointGCInterval | quote }} + nodes-gc-interval: {{ include "validateDuration" .Values.operator.nodeGCInterval | quote }} + +{{- if hasKey .Values.operator "skipCNPStatusStartupClean" }} + skip-cnp-status-startup-clean: "{{ .Values.operator.skipCNPStatusStartupClean }}" +{{- end }} + +{{- if eq .Values.disableEndpointCRD true }} + # Disable the usage of CiliumEndpoint CRD + disable-endpoint-crd: "true" +{{- end }} + +{{- if .Values.identityChangeGracePeriod }} + # identity-change-grace-period is the grace period that needs to pass + # before an endpoint that has changed its identity will start using + # that new identity. During the grace period, the new identity has + # already been allocated and other nodes in the cluster have a chance + # to whitelist the new upcoming identity of the endpoint. + identity-change-grace-period: {{ include "validateDuration" .Values.identityChangeGracePeriod | quote }} +{{- end }} + +{{- if hasKey .Values "labels" }} + # To include or exclude matched resources from cilium identity evaluation + labels: {{ .Values.labels | quote }} +{{- end }} + + # If you want to run cilium in debug mode change this value to true + debug: {{ .Values.debug.enabled | quote }} + +{{- if hasKey .Values.debug "verbose" }} + debug-verbose: "{{ .Values.debug.verbose }}" +{{- end }} + +{{- if ne (int .Values.healthPort) 9879 }} + # Set the TCP port for the agent health status API. This is not the port used + # for cilium-health. + agent-health-port: "{{ .Values.healthPort }}" +{{- end }} + +{{- if hasKey .Values "clusterHealthPort" }} + # Set the TCP port for the agent health API. This port is used for cilium-health. + cluster-health-port: "{{ .Values.clusterHealthPort }}" +{{- end }} + +{{- if hasKey .Values "policyEnforcementMode" }} + # The agent can be put into the following three policy enforcement modes + # default, always and never. + # https://docs.cilium.io/en/latest/security/policy/intro/#policy-enforcement-modes + enable-policy: "{{ lower .Values.policyEnforcementMode }}" +{{- end }} + +{{- if .Values.prometheus.enabled }} + # If you want metrics enabled in all of your Cilium agents, set the port for + # which the Cilium agents will have their metrics exposed. + # This option deprecates the "prometheus-serve-addr" in the + # "cilium-metrics-config" ConfigMap + # NOTE that this will open the port on ALL nodes where Cilium pods are + # scheduled. + prometheus-serve-addr: ":{{ .Values.prometheus.port }}" + {{- if .Values.prometheus.metrics }} + # Metrics that should be enabled or disabled from the default metric + # list. (+metric_foo to enable metric_foo , -metric_bar to disable + # metric_bar). + metrics: {{- range .Values.prometheus.metrics }} + {{ . }} + {{- end }} + {{- end }} +{{- end }} + +{{- if not .Values.envoy.enabled }} + # Port to expose Envoy metrics (e.g. "9964"). Envoy metrics listener will be disabled if this + # field is not set. + {{- if and .Values.proxy.prometheus.enabled .Values.envoy.prometheus.enabled }} + proxy-prometheus-port: "{{ .Values.proxy.prometheus.port | default .Values.envoy.prometheus.port }}" + {{- end }} +{{- end }} + +{{- if .Values.operator.prometheus.enabled }} + # If you want metrics enabled in cilium-operator, set the port for + # which the Cilium Operator will have their metrics exposed. + # NOTE that this will open the port on the nodes where Cilium operator pod + # is scheduled. + operator-prometheus-serve-addr: ":{{ .Values.operator.prometheus.port }}" + enable-metrics: "true" +{{- end }} + +{{- if .Values.operator.skipCRDCreation }} + skip-crd-creation: "true" +{{- end }} + +{{- if or .Values.envoyConfig.enabled .Values.ingressController.enabled .Values.gatewayAPI.enabled (and (hasKey .Values "loadBalancer") (eq .Values.loadBalancer.l7.backend "envoy")) }} + enable-envoy-config: "true" + {{- if .Values.envoyConfig.enabled }} + envoy-secrets-namespace: {{ .Values.envoyConfig.secretsNamespace.name | quote }} + {{- end }} +{{- end }} + +{{- if .Values.ingressController.enabled }} + enable-ingress-controller: "true" + enforce-ingress-https: {{ .Values.ingressController.enforceHttps | quote }} + enable-ingress-secrets-sync: {{ .Values.ingressController.secretsNamespace.sync | quote }} + ingress-secrets-namespace: {{ .Values.ingressController.secretsNamespace.name | quote }} + ingress-lb-annotation-prefixes: {{ .Values.ingressController.ingressLBAnnotationPrefixes | join " " | quote }} + ingress-default-lb-mode: {{ .Values.ingressController.loadbalancerMode }} + ingress-shared-lb-service-name: {{ .Values.ingressController.service.name }} + {{- if and .Values.ingressController.defaultSecretNamespace .Values.ingressController.defaultSecretName }} + ingress-default-secret-namespace: {{ .Values.ingressController.defaultSecretNamespace | quote }} + ingress-default-secret-name: {{ .Values.ingressController.defaultSecretName | quote }} + {{- end }} +{{- end }} + +{{- if .Values.gatewayAPI.enabled }} + enable-gateway-api: "true" + enable-gateway-api-secrets-sync: {{ .Values.gatewayAPI.secretsNamespace.sync | quote }} + gateway-api-secrets-namespace: {{ .Values.gatewayAPI.secretsNamespace.name | quote }} +{{- end }} + +{{- if hasKey .Values "loadBalancer" }} +{{- if eq .Values.loadBalancer.l7.backend "envoy" }} + loadbalancer-l7: "envoy" + loadbalancer-l7-ports: {{ .Values.loadBalancer.l7.ports | join " " | quote }} + loadbalancer-l7-algorithm: {{ .Values.loadBalancer.l7.algorithm | quote }} +{{- end }} +{{- end }} + + # Enable IPv4 addressing. If enabled, all endpoints are allocated an IPv4 + # address. + enable-ipv4: {{ .Values.ipv4.enabled | quote }} + + # Enable IPv6 addressing. If enabled, all endpoints are allocated an IPv6 + # address. + enable-ipv6: {{ .Values.ipv6.enabled | quote }} + +{{- if .Values.cleanState }} + # If a serious issue occurs during Cilium startup, this + # invasive option may be set to true to remove all persistent + # state. Endpoints will not be restored using knowledge from a + # prior Cilium run, so they may receive new IP addresses upon + # restart. This also triggers clean-cilium-bpf-state. + clean-cilium-state: "true" +{{- end }} + +{{- if .Values.cleanBpfState }} + # If you want to clean cilium BPF state, set this to true; + # Removes all BPF maps from the filesystem. Upon restart, + # endpoints are restored with the same IP addresses, however + # any ongoing connections may be disrupted briefly. + # Loadbalancing decisions will be reset, so any ongoing + # connections via a service may be loadbalanced to a different + # backend after restart. + clean-cilium-bpf-state: "true" +{{- end }} + +{{- if hasKey .Values.cni "customConf" }} + # Users who wish to specify their own custom CNI configuration file must set + # custom-cni-conf to "true", otherwise Cilium may overwrite the configuration. + custom-cni-conf: "{{ .Values.cni.customConf }}" +{{- end }} + +{{- if hasKey .Values "bpfClockProbe" }} + enable-bpf-clock-probe: {{ .Values.bpfClockProbe | quote }} +{{- else if eq $defaultBpfClockProbe "true" }} + enable-bpf-clock-probe: {{ $defaultBpfClockProbe | quote }} +{{- end }} + +{{- if (not (kindIs "invalid" .Values.bpf.tproxy)) }} + enable-bpf-tproxy: {{ .Values.bpf.tproxy | quote }} +{{- else if eq $defaultBpfTProxy "true" }} + enable-bpf-tproxy: {{ $defaultBpfTProxy | quote }} +{{- end }} + # If you want cilium monitor to aggregate tracing for packets, set this level + # to "low", "medium", or "maximum". The higher the level, the less packets + # that will be seen in monitor output. + monitor-aggregation: {{ .Values.bpf.monitorAggregation }} + + # The monitor aggregation interval governs the typical time between monitor + # notification events for each allowed connection. + # + # Only effective when monitor aggregation is set to "medium" or higher. + monitor-aggregation-interval: {{ include "validateDuration" .Values.bpf.monitorInterval | quote }} + + # The monitor aggregation flags determine which TCP flags which, upon the + # first observation, cause monitor notifications to be generated. + # + # Only effective when monitor aggregation is set to "medium" or higher. + monitor-aggregation-flags: {{ .Values.bpf.monitorFlags }} + + + + +{{- if .Values.bpf.mapDynamicSizeRatio }} + # Specifies the ratio (0.0-1.0] of total system memory to use for dynamic + # sizing of the TCP CT, non-TCP CT, NAT and policy BPF maps. + bpf-map-dynamic-size-ratio: {{ .Values.bpf.mapDynamicSizeRatio | quote }} +{{- else if ne $defaultBpfMapDynamicSizeRatio 0.0 }} + # Specifies the ratio (0.0-1.0] of total system memory to use for dynamic + # sizing of the TCP CT, non-TCP CT, NAT and policy BPF maps. + bpf-map-dynamic-size-ratio: {{ $defaultBpfMapDynamicSizeRatio | quote }} +{{- end }} + +{{- if (not (kindIs "invalid" .Values.bpf.hostLegacyRouting)) }} + enable-host-legacy-routing: {{ .Values.bpf.hostLegacyRouting | quote }} +{{- else if ne $cniChainingMode "none" }} + # In cni chaining mode, the other chained plugin is responsible for underlying connectivity, + # so cilium eBPF host routing shoud not work, and let it fall back to the legacy routing mode + enable-host-legacy-routing: "true" +{{- end }} + +{{- if .Values.bpf.authMapMax }} + # bpf-auth-map-max specifies the maximum number of entries in the auth map + bpf-auth-map-max: {{ .Values.bpf.authMapMax | quote }} +{{- end }} +{{- if or $bpfCtTcpMax $bpfCtAnyMax }} + # bpf-ct-global-*-max specifies the maximum number of connections + # supported across all endpoints, split by protocol: tcp or other. One pair + # of maps uses these values for IPv4 connections, and another pair of maps + # use these values for IPv6 connections. + # + # If these values are modified, then during the next Cilium startup the + # tracking of ongoing connections may be disrupted. As a result, reply + # packets may be dropped and the load-balancing decisions for established + # connections may change. + # + # For users upgrading from Cilium 1.2 or earlier, to minimize disruption + # during the upgrade process, set bpf-ct-global-tcp-max to 1000000. +{{- if $bpfCtTcpMax }} + bpf-ct-global-tcp-max: {{ $bpfCtTcpMax | quote }} +{{- end }} +{{- if $bpfCtAnyMax }} + bpf-ct-global-any-max: {{ $bpfCtAnyMax | quote }} +{{- end }} +{{- end }} +{{- if .Values.bpf.natMax }} + # bpf-nat-global-max specified the maximum number of entries in the + # BPF NAT table. + bpf-nat-global-max: "{{ .Values.bpf.natMax }}" +{{- end }} +{{- if .Values.bpf.neighMax }} + # bpf-neigh-global-max specified the maximum number of entries in the + # BPF neighbor table. + bpf-neigh-global-max: "{{ .Values.bpf.neighMax }}" +{{- end }} +{{- if hasKey .Values.bpf "policyMapMax" }} + # bpf-policy-map-max specifies the maximum number of entries in endpoint + # policy map (per endpoint) + bpf-policy-map-max: "{{ .Values.bpf.policyMapMax }}" +{{- end }} +{{- if hasKey .Values.bpf "lbMapMax" }} + # bpf-lb-map-max specifies the maximum number of entries in bpf lb service, + # backend and affinity maps. + bpf-lb-map-max: "{{ .Values.bpf.lbMapMax }}" +{{- end }} +{{- if hasKey .Values.bpf "lbExternalClusterIP" }} + bpf-lb-external-clusterip: {{ .Values.bpf.lbExternalClusterIP | quote }} +{{- end }} + + # Pre-allocation of map entries allows per-packet latency to be reduced, at + # the expense of up-front memory allocation for the entries in the maps. The + # default value below will minimize memory usage in the default installation; + # users who are sensitive to latency may consider setting this to "true". + # + # This option was introduced in Cilium 1.4. Cilium 1.3 and earlier ignore + # this option and behave as though it is set to "true". + # + # If this value is modified, then during the next Cilium startup the restore + # of existing endpoints and tracking of ongoing connections may be disrupted. + # As a result, reply packets may be dropped and the load-balancing decisions + # for established connections may change. + # + # If this option is set to "false" during an upgrade from 1.3 or earlier to + # 1.4 or later, then it may cause one-time disruptions during the upgrade. + preallocate-bpf-maps: "{{ .Values.bpf.preallocateMaps }}" + + # Regular expression matching compatible Istio sidecar istio-proxy + # container image names + sidecar-istio-proxy-image: "{{ .Values.proxy.sidecarImageRegex }}" + + # Name of the cluster. Only relevant when building a mesh of clusters. + cluster-name: {{ .Values.cluster.name }} + +{{- if hasKey .Values.cluster "id" }} + # Unique ID of the cluster. Must be unique across all conneted clusters and + # in the range of 1 and 255. Only relevant when building a mesh of clusters. + cluster-id: "{{ .Values.cluster.id }}" +{{- end }} + + # Encapsulation mode for communication between nodes + # Possible values: + # - disabled + # - vxlan (default) + # - geneve +{{- if .Values.gke.enabled }} + routing-mode: "native" + enable-endpoint-routes: "true" + enable-local-node-route: "false" +{{- else if .Values.aksbyocni.enabled }} + routing-mode: "tunnel" + tunnel-protocol: "vxlan" +{{- else if .Values.routingMode }} + routing-mode: {{ .Values.routingMode | quote }} +{{- else }} + {{- if eq .Values.tunnel "disabled" }} + routing-mode: "native" + {{- else if eq .Values.tunnel "vxlan" }} + routing-mode: "tunnel" + tunnel-protocol: "vxlan" + {{- else if eq .Values.tunnel "geneve" }} + routing-mode: "tunnel" + tunnel-protocol: "geneve" + {{- else }} + # Default case + routing-mode: "tunnel" + tunnel-protocol: "vxlan" + {{- end }} +{{- end }} + +{{- if .Values.tunnelProtocol }} + tunnel-protocol: {{ .Values.tunnelProtocol | quote }} +{{- end }} + +{{- if .Values.tunnelPort }} + tunnel-port: {{ .Values.tunnelPort | quote }} +{{- end }} + +{{- if .Values.MTU }} + mtu: {{ .Values.MTU | quote }} +{{- end }} + +{{- if .Values.eni.enabled }} + enable-endpoint-routes: "true" + auto-create-cilium-node-resource: "true" +{{- if .Values.eni.updateEC2AdapterLimitViaAPI }} + update-ec2-adapter-limit-via-api: "true" +{{- end }} +{{- if .Values.eni.awsReleaseExcessIPs }} + aws-release-excess-ips: "true" +{{- end }} +{{- if .Values.eni.awsEnablePrefixDelegation }} + aws-enable-prefix-delegation: "true" +{{- end }} + ec2-api-endpoint: {{ .Values.eni.ec2APIEndpoint | quote }} + eni-tags: {{ .Values.eni.eniTags | toRawJson | quote }} +{{- if .Values.eni.subnetIDsFilter }} + subnet-ids-filter: {{ .Values.eni.subnetIDsFilter | join " " | quote }} +{{- end }} +{{- if .Values.eni.subnetTagsFilter }} + subnet-tags-filter: {{ .Values.eni.subnetTagsFilter | join " " | quote }} +{{- end }} +{{- if .Values.eni.instanceTagsFilter }} + instance-tags-filter: {{ .Values.eni.instanceTagsFilter | join " " | quote }} +{{- end }} +{{- end }} +{{ if .Values.eni.gcInterval }} + eni-gc-interval: {{ .Values.eni.gcInterval | quote }} +{{- end }} +{{ if .Values.eni.gcTags }} + eni-gc-tags: {{ .Values.eni.gcTags | toRawJson | quote }} +{{- end }} + +{{- if .Values.azure.enabled }} + enable-endpoint-routes: "true" + auto-create-cilium-node-resource: "true" + enable-local-node-route: "false" +{{- if .Values.azure.userAssignedIdentityID }} + azure-user-assigned-identity-id: {{ .Values.azure.userAssignedIdentityID | quote }} +{{- end }} + azure-use-primary-address: {{ $azureUsePrimaryAddress | quote }} +{{- end }} + +{{- if .Values.alibabacloud.enabled }} + enable-endpoint-routes: "true" + auto-create-cilium-node-resource: "true" +{{- end }} + +{{- if hasKey .Values "l7Proxy" }} + # Enables L7 proxy for L7 policy enforcement and visibility + enable-l7-proxy: {{ .Values.l7Proxy | quote }} +{{- end }} + +{{- if ne $cniChainingMode "none" }} + # Enable chaining with another CNI plugin + # + # Supported modes: + # - none + # - aws-cni + # - flannel + # - generic-veth + # - portmap (Enables HostPort support for Cilium) + cni-chaining-mode: {{ $cniChainingMode }} + +{{- if hasKey .Values "enableIdentityMark" }} + enable-identity-mark: {{ .Values.enableIdentityMark | quote }} +{{- else if (ne $enableIdentityMark "true") }} + enable-identity-mark: "false" +{{- end }} +{{- if ne $cniChainingMode "portmap" }} + # Disable the PodCIDR route to the cilium_host interface as it is not + # required. While chaining, it is the responsibility of the underlying plugin + # to enable routing. + enable-local-node-route: "false" +{{- end }} +{{- end }} + + enable-ipv4-masquerade: {{ .Values.enableIPv4Masquerade | quote }} + enable-ipv4-big-tcp: {{ .Values.enableIPv4BIGTCP | quote }} + enable-ipv6-big-tcp: {{ .Values.enableIPv6BIGTCP | quote }} + enable-ipv6-masquerade: {{ .Values.enableIPv6Masquerade | quote }} + +{{- if (not (kindIs "invalid" .Values.bpf.masquerade)) }} + enable-bpf-masquerade: {{ .Values.bpf.masquerade | quote }} +{{- else if eq $defaultBpfMasquerade "true" }} + enable-bpf-masquerade: {{ $defaultBpfMasquerade | quote }} +{{- end }} +{{- if hasKey .Values "egressMasqueradeInterfaces" }} + egress-masquerade-interfaces: {{ .Values.egressMasqueradeInterfaces }} +{{- end }} +{{- if and .Values.ipMasqAgent .Values.ipMasqAgent.enabled }} + enable-ip-masq-agent: "true" +{{- end }} + +{{- if .Values.encryption.enabled }} + {{- if eq .Values.encryption.type "ipsec" }} + enable-ipsec: {{ .Values.encryption.enabled | quote }} + + {{- if and .Values.encryption.ipsec.mountPath .Values.encryption.ipsec.keyFile }} + ipsec-key-file: {{ .Values.encryption.ipsec.mountPath }}/{{ .Values.encryption.ipsec.keyFile }} + {{- else }} + ipsec-key-file: {{ .Values.encryption.mountPath }}/{{ .Values.encryption.keyFile }} + {{- end }} + {{- if .Values.encryption.ipsec.interface }} + encrypt-interface: {{ .Values.encryption.ipsec.interface }} + {{- else if .Values.encryption.interface }} + encrypt-interface: {{ .Values.encryption.interface }} + {{- end }} + {{- if hasKey .Values.encryption.ipsec "keyWatcher" }} + enable-ipsec-key-watcher: {{ .Values.encryption.ipsec.keyWatcher | quote }} + {{- end }} + {{- if .Values.encryption.ipsec.keyRotationDuration }} + ipsec-key-rotation-duration: {{ include "validateDuration" .Values.encryption.ipsec.keyRotationDuration | quote }} + {{- end }} + {{- else if eq .Values.encryption.type "wireguard" }} + enable-wireguard: {{ .Values.encryption.enabled | quote }} + {{- if .Values.encryption.wireguard.userspaceFallback }} + enable-wireguard-userspace-fallback: {{ .Values.encryption.wireguard.userspaceFallback | quote }} + {{- end }} + {{- if .Values.encryption.wireguard.encapsulate }} + wireguard-encapsulate: {{ .Values.encryption.wireguard.encapsulate | quote }} + {{- end }} + {{- end }} + {{- if .Values.encryption.nodeEncryption }} + encrypt-node: {{ .Values.encryption.nodeEncryption | quote }} + {{- end }} +{{- end }} + + enable-xt-socket-fallback: {{ .Values.enableXTSocketFallback | quote }} +{{- if or (.Values.azure.enabled) (.Values.eni.enabled) (.Values.gke.enabled) (ne $cniChainingMode "none") }} + install-no-conntrack-iptables-rules: "false" +{{- else }} + install-no-conntrack-iptables-rules: {{ .Values.installNoConntrackIptablesRules | quote }} +{{- end}} + +{{- if hasKey .Values "iptablesRandomFully" }} + iptables-random-fully: {{ .Values.iptablesRandomFully | quote }} +{{- end }} + +{{- if hasKey .Values "iptablesLockTimeout" }} + iptables-lock-timeout: {{ .Values.iptablesLockTimeout | quote }} +{{- end }} + + auto-direct-node-routes: {{ .Values.autoDirectNodeRoutes | quote }} + +{{- if hasKey .Values "bandwidthManager" }} +{{- if .Values.bandwidthManager.enabled }} + enable-bandwidth-manager: {{ .Values.bandwidthManager.enabled | quote }} + enable-bbr: {{ .Values.bandwidthManager.bbr | quote }} +{{- end }} +{{- end }} + +{{- if .Values.highScaleIPcache.enabled }} + enable-high-scale-ipcache: {{ .Values.highScaleIPcache.enabled | quote }} +{{- end }} + +{{- if hasKey .Values "localRedirectPolicy" }} + enable-local-redirect-policy: {{ .Values.localRedirectPolicy | quote }} +{{- end }} + +{{- if .Values.ipv4NativeRoutingCIDR }} + ipv4-native-routing-cidr: {{ .Values.ipv4NativeRoutingCIDR }} +{{- end }} + +{{- if .Values.ipv6NativeRoutingCIDR }} + ipv6-native-routing-cidr: {{ .Values.ipv6NativeRoutingCIDR }} +{{- end }} + +{{- if hasKey .Values "fragmentTracking" }} + enable-ipv4-fragment-tracking: {{ .Values.fragmentTracking | quote }} +{{- else if (ne $fragmentTracking "true") }} + enable-ipv4-fragment-tracking: "false" +{{- end }} + +{{- if .Values.nat46x64Gateway.enabled }} + enable-nat46x64-gateway: {{ .Values.nat46x64Gateway.enabled | quote }} +{{- end }} + +{{- if and .Values.hostFirewall .Values.hostFirewall.enabled }} + enable-host-firewall: {{ .Values.hostFirewall.enabled | quote }} +{{- end}} + +{{- if hasKey .Values "devices" }} + # List of devices used to attach bpf_host.o (implements BPF NodePort, + # host-firewall and BPF masquerading) + devices: {{ join " " .Values.devices | quote }} +{{- end }} + +{{- if .Values.enableRuntimeDeviceDetection }} + enable-runtime-device-detection: "true" +{{- end }} + + kube-proxy-replacement: {{ $kubeProxyReplacement | quote }} + +{{- if ne $kubeProxyReplacement "disabled" }} + kube-proxy-replacement-healthz-bind-address: {{ default "" .Values.kubeProxyReplacementHealthzBindAddr | quote}} +{{- end }} + +{{- if $socketLB }} +{{- if hasKey $socketLB "enabled" }} + bpf-lb-sock: {{ $socketLB.enabled | quote }} +{{- end }} +{{- if hasKey $socketLB "hostNamespaceOnly" }} + bpf-lb-sock-hostns-only: {{ $socketLB.hostNamespaceOnly | quote }} +{{- end }} +{{- end }} + +{{- if hasKey .Values "hostPort" }} +{{- if or (eq $kubeProxyReplacement "partial") (eq $kubeProxyReplacement "false") }} + enable-host-port: {{ .Values.hostPort.enabled | quote }} +{{- end }} +{{- end }} +{{- if hasKey .Values "externalIPs" }} +{{- if or (eq $kubeProxyReplacement "partial") (eq $kubeProxyReplacement "false") }} + enable-external-ips: {{ .Values.externalIPs.enabled | quote }} +{{- end }} +{{- end }} +{{- if hasKey .Values "nodePort" }} +{{- if or (eq $kubeProxyReplacement "partial") (eq $kubeProxyReplacement "false") }} + enable-node-port: {{ .Values.nodePort.enabled | quote }} +{{- end }} +{{- if hasKey .Values.nodePort "range" }} + node-port-range: {{ get .Values.nodePort "range" | quote }} +{{- end }} +{{- if hasKey .Values.nodePort "directRoutingDevice" }} + direct-routing-device: {{ .Values.nodePort.directRoutingDevice | quote }} +{{- end }} +{{- if hasKey .Values.nodePort "enableHealthCheck" }} + enable-health-check-nodeport: {{ .Values.nodePort.enableHealthCheck | quote}} +{{- end }} + node-port-bind-protection: {{ .Values.nodePort.bindProtection | quote }} + enable-auto-protect-node-port-range: {{ .Values.nodePort.autoProtectPortRange | quote }} +{{- end }} +{{- if hasKey .Values "loadBalancer" }} +{{- if .Values.loadBalancer.standalone }} + datapath-mode: lb-only +{{- end }} +{{- if hasKey .Values.loadBalancer "mode" }} + bpf-lb-mode: {{ .Values.loadBalancer.mode | quote }} +{{- end }} +{{- if hasKey .Values.loadBalancer "algorithm" }} + bpf-lb-algorithm: {{ .Values.loadBalancer.algorithm | quote }} +{{- end }} +{{- if hasKey .Values.loadBalancer "acceleration" }} + bpf-lb-acceleration: {{ .Values.loadBalancer.acceleration | quote }} +{{- end }} +{{- if hasKey .Values.loadBalancer "dsrDispatch" }} + bpf-lb-dsr-dispatch: {{ .Values.loadBalancer.dsrDispatch | quote }} +{{- end }} +{{- if hasKey .Values.loadBalancer "serviceTopology" }} + enable-service-topology: {{ .Values.loadBalancer.serviceTopology | quote }} +{{- end }} + +{{- end }} +{{- if hasKey .Values.maglev "tableSize" }} + bpf-lb-maglev-table-size: {{ .Values.maglev.tableSize | quote}} +{{- end }} +{{- if hasKey .Values.maglev "hashSeed" }} + bpf-lb-maglev-hash-seed: {{ .Values.maglev.hashSeed | quote}} +{{- end }} +{{- if .Values.sessionAffinity }} + enable-session-affinity: {{ .Values.sessionAffinity | quote }} +{{- end }} +{{- if .Values.svcSourceRangeCheck }} + enable-svc-source-range-check: {{ .Values.svcSourceRangeCheck | quote }} +{{- end }} + +{{- if hasKey .Values "l2NeighDiscovery" }} +{{- if hasKey .Values.l2NeighDiscovery "enabled" }} + enable-l2-neigh-discovery: {{ .Values.l2NeighDiscovery.enabled | quote }} +{{- end }} + arping-refresh-period: {{ include "validateDuration" .Values.l2NeighDiscovery.refreshPeriod | quote }} +{{- end }} + +{{- if .Values.pprof.enabled }} + pprof: {{ .Values.pprof.enabled | quote }} + pprof-address: {{ .Values.pprof.address | quote }} + pprof-port: {{ .Values.pprof.port | quote }} +{{- end }} + +{{- if .Values.operator.pprof.enabled }} + operator-pprof: {{ .Values.operator.pprof.enabled | quote }} + operator-pprof-address: {{ .Values.operator.pprof.address | quote }} + operator-pprof-port: {{ .Values.operator.pprof.port | quote }} +{{- end }} + +{{- if .Values.logSystemLoad }} + log-system-load: {{ .Values.logSystemLoad | quote }} +{{- end }} +{{- if .Values.logOptions }} + log-opt: {{ .Values.logOptions | toJson | quote }} +{{- end }} +{{- if hasKey .Values.k8s "requireIPv4PodCIDR" }} + k8s-require-ipv4-pod-cidr: {{ .Values.k8s.requireIPv4PodCIDR | quote }} +{{- end }} +{{- if hasKey .Values.k8s "requireIPv6PodCIDR" }} + k8s-require-ipv6-pod-cidr: {{ .Values.k8s.requireIPv6PodCIDR | quote }} +{{- end }} +{{- if .Values.endpointStatus.enabled }} + endpoint-status: {{ required "endpointStatus.status required: policy, health, controllers, log and / or state. For 2 or more options use a space: \"policy health\"" .Values.endpointStatus.status | quote }} +{{- end }} +{{- if and .Values.endpointRoutes .Values.endpointRoutes.enabled }} + enable-endpoint-routes: {{ .Values.endpointRoutes.enabled | quote }} +{{- end }} +{{- if and .Values.k8sNetworkPolicy .Values.k8sNetworkPolicy.enabled }} + enable-k8s-networkpolicy: {{ .Values.k8sNetworkPolicy.enabled | quote }} +{{- end }} +{{- if .Values.cni.configMap }} + read-cni-conf: {{ .Values.cni.confFileMountPath }}/{{ .Values.cni.configMapKey }} +{{- if .Values.cni.customConf }} + # legacy: v1.13 and before needed cni.customConf: true with cni.configMap + write-cni-conf-when-ready: {{ .Values.cni.hostConfDirMountPath }}/05-cilium.conflist +{{- end }} +{{- else if .Values.cni.readCniConf }} + read-cni-conf: {{ .Values.cni.readCniConf }} +{{- end }} +{{- if and (not .Values.cni.customConf) .Values.cni.install }} + # Tell the agent to generate and write a CNI configuration file + write-cni-conf-when-ready: {{ .Values.cni.hostConfDirMountPath }}/05-cilium.conflist + cni-exclusive: {{ .Values.cni.exclusive | quote }} + cni-log-file: {{ .Values.cni.logFile | quote }} +{{- end }} +{{- if .Values.cni.uninstall }} + cni-uninstall: {{ .Values.cni.uninstall | quote }} +{{- end }} +{{- if (not (kindIs "invalid" .Values.cni.chainingTarget)) }} + cni-chaining-target: {{ .Values.cni.chainingTarget | quote }} +{{- end}} +{{- if (not (kindIs "invalid" .Values.cni.externalRouting)) }} + cni-external-routing: {{ .Values.cni.externalRouting | quote }} +{{- end}} +{{- if .Values.kubeConfigPath }} + k8s-kubeconfig-path: {{ .Values.kubeConfigPath | quote }} +{{- end }} +{{- if and ( .Values.endpointHealthChecking.enabled ) (or (eq $cniChainingMode "portmap") (eq $cniChainingMode "none")) }} + enable-endpoint-health-checking: "true" +{{- else}} + # Disable health checking, when chaining mode is not set to portmap or none + enable-endpoint-health-checking: "false" +{{- end }} +{{- if hasKey .Values "healthChecking" }} + enable-health-checking: {{ .Values.healthChecking | quote }} +{{- end }} +{{- if or .Values.wellKnownIdentities.enabled .Values.etcd.managed }} + enable-well-known-identities: "true" +{{- else }} + enable-well-known-identities: "false" +{{- end }} + enable-remote-node-identity: {{ .Values.remoteNodeIdentity | quote }} + +{{- if hasKey .Values "synchronizeK8sNodes" }} + synchronize-k8s-nodes: {{ .Values.synchronizeK8sNodes | quote }} +{{- end }} + +{{- if hasKey .Values "policyAuditMode" }} + policy-audit-mode: {{ .Values.policyAuditMode | quote }} +{{- end }} + +{{- if ne $defaultOperatorApiServeAddr "localhost:9234" }} + operator-api-serve-addr: {{ $defaultOperatorApiServeAddr | quote }} +{{- end }} + +{{- if .Values.hubble.enabled }} + # Enable Hubble gRPC service. + enable-hubble: {{ .Values.hubble.enabled | quote }} + # UNIX domain socket for Hubble server to listen to. + hubble-socket-path: {{ .Values.hubble.socketPath | quote }} +{{- if hasKey .Values.hubble "eventQueueSize" }} + # Buffer size of the channel for Hubble to receive monitor events. If this field is not set, + # the buffer size is set to the default monitor queue size. + hubble-event-queue-size: {{ .Values.hubble.eventQueueSize | quote }} +{{- end }} +{{- if hasKey .Values.hubble "eventBufferCapacity" }} + # Capacity of the buffer to store recent events. + hubble-event-buffer-capacity: {{ .Values.hubble.eventBufferCapacity | quote }} +{{- end }} +{{- if .Values.hubble.metrics.enabled }} + # Address to expose Hubble metrics (e.g. ":7070"). Metrics server will be disabled if this + # field is not set. + hubble-metrics-server: ":{{ .Values.hubble.metrics.port }}" + # A space separated list of metrics to enable. See [0] for available metrics. + # + # https://github.com/cilium/hubble/blob/master/Documentation/metrics.md + hubble-metrics: {{- range .Values.hubble.metrics.enabled }} + {{.}} +{{- end }} + enable-hubble-open-metrics: {{ .Values.hubble.metrics.enableOpenMetrics | quote }} +{{- end }} +{{- if hasKey .Values.hubble "listenAddress" }} + # An additional address for Hubble server to listen to (e.g. ":4244"). + hubble-listen-address: {{ .Values.hubble.listenAddress | quote }} +{{- if .Values.hubble.tls.enabled }} + hubble-disable-tls: "false" + hubble-tls-cert-file: /var/lib/cilium/tls/hubble/server.crt + hubble-tls-key-file: /var/lib/cilium/tls/hubble/server.key + hubble-tls-client-ca-files: /var/lib/cilium/tls/hubble/client-ca.crt +{{- else }} + hubble-disable-tls: "true" +{{- end }} +{{- end }} +{{- if .Values.hubble.preferIpv6 }} + hubble-prefer-ipv6: "true" +{{- end }} +{{- if (not (kindIs "invalid" .Values.hubble.skipUnknownCGroupIDs)) }} + hubble-skip-unknown-cgroup-ids: {{ .Values.hubble.skipUnknownCGroupIDs | quote }} +{{- end }} +{{- end }} +{{- if hasKey .Values "disableIptablesFeederRules" }} + # A space separated list of iptables chains to disable when installing feeder rules. + disable-iptables-feeder-rules: {{ .Values.disableIptablesFeederRules | join " " | quote }} +{{- end }} +{{- if .Values.aksbyocni.enabled }} + ipam: "cluster-pool" +{{- else }} + ipam: {{ $ipam | quote }} +{{- end }} + +{{- if .Values.ipam.ciliumNodeUpdateRate }} + ipam-cilium-node-update-rate: {{ include "validateDuration" .Values.ipam.ciliumNodeUpdateRate | quote }} +{{- end }} + +{{- if or (eq $ipam "cluster-pool") (eq $ipam "cluster-pool-v2beta") }} +{{- if .Values.ipv4.enabled }} + {{- if hasKey .Values.ipam.operator "clusterPoolIPv4PodCIDR" }} + {{- /* ipam.operator.clusterPoolIPv4PodCIDR removed in v1.14, remove this failsafe around v1.17 */ -}} + {{- fail "Value ipam.operator.clusterPoolIPv4PodCIDR removed, use ipam.operator.clusterPoolIPv4PodCIDRList instead" }} + {{- end }} + cluster-pool-ipv4-cidr: {{ .Values.ipam.operator.clusterPoolIPv4PodCIDRList | join " " | quote }} + cluster-pool-ipv4-mask-size: {{ .Values.ipam.operator.clusterPoolIPv4MaskSize | quote }} +{{- end }} +{{- if .Values.ipv6.enabled }} + {{- if hasKey .Values.ipam.operator "clusterPoolIPv6PodCIDR" }} + {{- /* ipam.operator.clusterPoolIPv6PodCIDR removed in v1.14, remove this failsafe around v1.17 */ -}} + {{- fail "Value ipam.operator.clusterPoolIPv6PodCIDR removed, use ipam.operator.clusterPoolIPv6PodCIDRList instead" }} + {{- end }} + cluster-pool-ipv6-cidr: {{ .Values.ipam.operator.clusterPoolIPv6PodCIDRList | join " " | quote }} + cluster-pool-ipv6-mask-size: {{ .Values.ipam.operator.clusterPoolIPv6MaskSize | quote }} +{{- end }} +{{- end }} +{{- if (eq $ipam "multi-pool") }} + {{- $pools := list }} + {{- range $pool, $spec := .Values.ipam.operator.autoCreateCiliumPodIPPools }} + {{- $attrs := list }} + {{- if hasKey $spec "ipv4" }} + {{- $attrs = append $attrs (printf "ipv4-cidrs:%s" (join "," $spec.ipv4.cidrs)) }} + {{- $attrs = append $attrs (printf "ipv4-mask-size:%s" (toString $spec.ipv4.maskSize)) }} + {{- end }} + {{- if hasKey $spec "ipv6" }} + {{- $attrs = append $attrs (printf "ipv6-cidrs:%s" (join "," $spec.ipv6.cidrs)) }} + {{- $attrs = append $attrs (printf "ipv6-mask-size:%s" (toString $spec.ipv6.maskSize)) }} + {{- end }} + {{- $pools = append $pools (printf "%s=%s" $pool (join ";" $attrs)) }} + {{- end }} + auto-create-cilium-pod-ip-pools: {{ join "," $pools | quote }} +{{- end }} + +{{- if .Values.ipam.operator.externalAPILimitBurstSize }} + limit-ipam-api-burst: {{ .Values.ipam.operator.externalAPILimitBurstSize | quote }} +{{- end }} +{{- if .Values.ipam.operator.externalAPILimitQPS }} + limit-ipam-api-qps: {{ .Values.ipam.operator.externalAPILimitQPS | quote }} +{{- end }} + +{{- if .Values.enableCnpStatusUpdates }} + disable-cnp-status-updates: "false" +{{- else if (eq $defaultEnableCnpStatusUpdates "false") }} + disable-cnp-status-updates: "true" + cnp-node-status-gc-interval: "0s" +{{- end }} + +{{- if .Values.egressGateway.enabled }} + enable-ipv4-egress-gateway: "true" +{{- end }} +{{- if .Values.egressGateway.installRoutes }} + install-egress-gateway-routes: "true" +{{- end }} +{{- if hasKey .Values.egressGateway "reconciliationTriggerInterval" }} + egress-gateway-reconciliation-trigger-interval: {{ .Values.egressGateway.reconciliationTriggerInterval | quote }} +{{- end }} +{{- if .Values.egressGateway.maxPolicyEntries }} + egress-gateway-policy-map-max: {{ .Values.egressGateway.maxPolicyEntries }} +{{- end }} + +{{- if hasKey .Values "vtep" }} + enable-vtep: {{ .Values.vtep.enabled | quote }} +{{- if hasKey .Values.vtep "endpoint" }} + vtep-endpoint: {{ .Values.vtep.endpoint | quote }} +{{- end }} +{{- if hasKey .Values.vtep "cidr" }} + vtep-cidr: {{ .Values.vtep.cidr | quote }} +{{- end }} +{{- if hasKey .Values.vtep "mask" }} + vtep-mask: {{ .Values.vtep.mask | quote }} +{{- end }} +{{- if hasKey .Values.vtep "mac" }} + vtep-mac: {{ .Values.vtep.mac | quote }} +{{- end }} +{{- end }} + +{{- if .Values.enableK8sEventHandover }} + enable-k8s-event-handover: "true" +{{- end }} + +{{- if .Values.crdWaitTimeout }} + crd-wait-timeout: {{ include "validateDuration" .Values.crdWaitTimeout | quote }} +{{- end }} + +{{- if .Values.enableK8sEndpointSlice }} + enable-k8s-endpoint-slice: {{ .Values.enableK8sEndpointSlice | quote }} +{{- end }} + +{{- if hasKey .Values.k8s "serviceProxyName" }} + # Configure service proxy name for Cilium. + k8s-service-proxy-name: {{ .Values.k8s.serviceProxyName | quote }} +{{- end }} + +{{- if and .Values.customCalls .Values.customCalls.enabled }} + # Enable tail call hooks for custom eBPF programs. + enable-custom-calls: {{ .Values.customCalls.enabled | quote }} +{{- end }} + +{{- if .Values.l2announcements.enabled }} + # Enable L2 announcements + enable-l2-announcements: {{ .Values.l2announcements.enabled | quote }} + {{- if .Values.l2announcements.leaseDuration }} + l2-announcements-lease-duration: {{ .Values.l2announcements.leaseDuration | quote }} + {{- end}} + {{- if .Values.l2announcements.leaseRenewDeadline }} + l2-announcements-renew-deadline: {{ .Values.l2announcements.leaseRenewDeadline | quote }} + {{- end}} + {{- if .Values.l2announcements.leaseRetryPeriod }} + l2-announcements-retry-period: {{ .Values.l2announcements.leaseRetryPeriod | quote }} + {{- end}} +{{- end}} + +{{- if .Values.l2podAnnouncements.enabled }} + enable-l2-pod-announcements: {{ .Values.l2podAnnouncements.enabled | quote }} + l2-pod-announcements-interface: {{ .Values.l2podAnnouncements.interface | quote }} +{{- end }} + +{{- if and .Values.bgp.enabled (and (not .Values.bgp.announce.loadbalancerIP) (not .Values.bgp.announce.podCIDR)) }} + {{ fail "BGP was enabled, but no announcements were enabled. Please enable one or more announcements." }} +{{- end }} + +{{- if and .Values.bgp.enabled .Values.bgp.announce.loadbalancerIP }} + bgp-announce-lb-ip: {{ .Values.bgp.announce.loadbalancerIP | quote }} +{{- end }} + +{{- if and .Values.bgp.enabled .Values.bgp.announce.podCIDR }} + bgp-announce-pod-cidr: {{ .Values.bgp.announce.podCIDR | quote }} +{{- end}} + +{{- if .Values.bgpControlPlane.enabled }} + enable-bgp-control-plane: "true" +{{- else }} + enable-bgp-control-plane: "false" +{{- end }} + +{{- if .Values.pmtuDiscovery.enabled }} + enable-pmtu-discovery: "true" +{{- end }} + +{{- if not .Values.securityContext.privileged }} + procfs: "/host/proc" +{{- end }} + +{{- if hasKey .Values.bpf "root" }} + bpf-root: {{ .Values.bpf.root | quote }} +{{- end }} + +{{- if hasKey .Values.cgroup "hostRoot" }} + cgroup-root: {{ .Values.cgroup.hostRoot | quote }} +{{- end }} + +{{- if .Values.bpf.vlanBypass }} + # A space separated list of explicitly allowed vlan id's + vlan-bpf-bypass: {{ .Values.bpf.vlanBypass | join " " | quote }} +{{- end }} + +{{- if .Values.enableCiliumEndpointSlice }} + enable-cilium-endpoint-slice: "true" +{{- end }} + +{{- if hasKey .Values "enableK8sTerminatingEndpoint" }} + enable-k8s-terminating-endpoint: {{ .Values.enableK8sTerminatingEndpoint | quote }} +{{- end }} + +{{- if hasKey .Values.sctp "enabled" }} + enable-sctp: {{ .Values.sctp.enabled | quote }} +{{- end }} + +{{- if hasKey .Values "dnsPolicyUnloadOnShutdown" }} + # Unload DNS policy rules on graceful shutdown + dns-policy-unload-on-shutdown: {{.Values.dnsPolicyUnloadOnShutdown | quote }} +{{- end }} + +{{- if .Values.annotateK8sNode }} + annotate-k8s-node: "true" +{{- end }} + +{{- if hasKey .Values "k8sClientRateLimit" }} + k8s-client-qps: {{ .Values.k8sClientRateLimit.qps | quote }} + k8s-client-burst: {{ .Values.k8sClientRateLimit.burst | quote }} +{{- end }} + +{{- if and .Values.operator.setNodeTaints (not .Values.operator.removeNodeTaints) -}} + {{ fail "Cannot have operator.setNodeTaintsMaxNodes and not operator.removeNodeTaints = false" }} +{{- end -}} +{{- if .Values.operator.removeNodeTaints }} + remove-cilium-node-taints: "true" +{{- end }} +{{- /* set node taints if setNodeTaints is explicitly enabled or removeNodeTaints is set */ -}} +{{- if or .Values.operator.setNodeTaints + ( and (kindIs "invalid" .Values.operator.setNodeTaints) + .Values.operator.removeNodeTaints ) }} + set-cilium-node-taints: "true" +{{- end }} +{{- if .Values.operator.setNodeNetworkStatus }} + set-cilium-is-up-condition: "true" +{{- end }} + +{{- if .Values.operator.unmanagedPodWatcher.restart }} + unmanaged-pod-watcher-interval: {{ .Values.operator.unmanagedPodWatcher.intervalSeconds | quote }} +{{- else }} + unmanaged-pod-watcher-interval: "0" +{{- end }} + +{{- if .Values.dnsProxy }} + {{- if .Values.dnsProxy.dnsRejectResponseCode }} + tofqdns-dns-reject-response-code: {{ .Values.dnsProxy.dnsRejectResponseCode | quote }} + {{- end }} + {{- if hasKey .Values.dnsProxy "enableDnsCompression" }} + tofqdns-enable-dns-compression: {{ .Values.dnsProxy.enableDnsCompression | quote }} + {{- end }} + {{- if .Values.dnsProxy.endpointMaxIpPerHostname }} + tofqdns-endpoint-max-ip-per-hostname: {{ .Values.dnsProxy.endpointMaxIpPerHostname | quote }} + {{- end }} + {{- if .Values.dnsProxy.idleConnectionGracePeriod }} + tofqdns-idle-connection-grace-period: {{ .Values.dnsProxy.idleConnectionGracePeriod | quote }} + {{- end }} + {{- if .Values.dnsProxy.maxDeferredConnectionDeletes }} + tofqdns-max-deferred-connection-deletes: {{ .Values.dnsProxy.maxDeferredConnectionDeletes | quote }} + {{- end }} + {{- if .Values.dnsProxy.minTtl }} + tofqdns-min-ttl: {{ .Values.dnsProxy.minTtl | quote }} + {{- end }} + {{- if .Values.dnsProxy.preCache }} + tofqdns-pre-cache: {{ .Values.dnsProxy.preCache | quote }} + {{- end }} + {{- if .Values.dnsProxy.proxyPort }} + tofqdns-proxy-port: {{ .Values.dnsProxy.proxyPort | quote }} + {{- end }} + {{- if .Values.dnsProxy.proxyResponseMaxDelay }} + tofqdns-proxy-response-max-delay: {{ .Values.dnsProxy.proxyResponseMaxDelay | quote }} + {{- end }} +{{- end }} + +{{- if .Values.extraConfig }} + {{ toYaml .Values.extraConfig | nindent 2 }} +{{- end }} + +{{- if hasKey .Values "agentNotReadyTaintKey" }} + agent-not-ready-taint-key: {{ .Values.agentNotReadyTaintKey | quote }} +{{- end }} + + mesh-auth-enabled: {{ .Values.authentication.enabled | quote }} + mesh-auth-queue-size: {{ .Values.authentication.queueSize | quote }} + mesh-auth-rotated-identities-queue-size: {{ .Values.authentication.rotatedIdentitiesQueueSize | quote }} + mesh-auth-gc-interval: {{ include "validateDuration" .Values.authentication.gcInterval | quote }} + +{{- if .Values.authentication.mutual.spire.enabled }} + mesh-auth-mutual-enabled: "true" + mesh-auth-mutual-listener-port: {{ .Values.authentication.mutual.port | quote }} + mesh-auth-spire-agent-socket: {{ .Values.authentication.mutual.spire.agentSocketPath | quote }} + {{- if .Values.authentication.mutual.spire.serverAddress }} + mesh-auth-spire-server-address: {{ .Values.authentication.mutual.spire.serverAddress | quote }} + {{- else }} + mesh-auth-spire-server-address: "spire-server.{{ .Values.authentication.mutual.spire.install.namespace}}.svc:8081" + {{- end }} + mesh-auth-spire-server-connection-timeout: {{ .Values.authentication.mutual.spire.connectionTimeout }} + mesh-auth-spire-admin-socket: {{ .Values.authentication.mutual.spire.adminSocketPath | quote }} + mesh-auth-spiffe-trust-domain: {{ .Values.authentication.mutual.spire.trustDomain | quote }} +{{- end }} + + proxy-connect-timeout: {{ .Values.envoy.connectTimeoutSeconds | quote }} + proxy-max-requests-per-connection: {{ .Values.envoy.maxRequestsPerConnection | quote }} + proxy-max-connection-duration-seconds: {{ .Values.envoy.maxConnectionDurationSeconds | quote }} + + external-envoy-proxy: {{ .Values.envoy.enabled | quote }} + +{{- if .Values.envoy.log.path }} + envoy-log: {{ .Values.envoy.log.path | quote }} +{{- end }} + +{{- end }} +--- +{{- if and .Values.ipMasqAgent.enabled .Values.ipMasqAgent.config }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: ip-masq-agent + namespace: {{ .Release.Namespace }} +data: + config: |- +{{ toJson .Values.ipMasqAgent.config | indent 4 }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/cilium-envoy/configmap.yaml b/packages/system/cilium/charts/cilium/templates/cilium-envoy/configmap.yaml new file mode 100644 index 00000000..7aa0f046 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/cilium-envoy/configmap.yaml @@ -0,0 +1,12 @@ +{{- if and .Values.envoy.enabled (not .Values.preflight.enabled) }} + +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: cilium-envoy-config + namespace: {{ .Release.Namespace }} +data: +{{- (tpl (.Files.Glob "files/cilium-envoy/configmap/bootstrap-config.json").AsConfig .) | nindent 2 }} + +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/cilium-envoy/daemonset.yaml b/packages/system/cilium/charts/cilium/templates/cilium-envoy/daemonset.yaml new file mode 100644 index 00000000..2ff9692e --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/cilium-envoy/daemonset.yaml @@ -0,0 +1,254 @@ +{{- if and .Values.envoy.enabled (not .Values.preflight.enabled) }} + +--- +apiVersion: apps/v1 +kind: DaemonSet +metadata: + name: cilium-envoy + namespace: {{ .Release.Namespace }} + labels: + k8s-app: cilium-envoy + app.kubernetes.io/part-of: cilium + app.kubernetes.io/name: cilium-envoy + name: cilium-envoy +spec: + selector: + matchLabels: + k8s-app: cilium-envoy + {{- with .Values.envoy.updateStrategy }} + updateStrategy: + {{- toYaml . | trim | nindent 4 }} + {{- end }} + template: + metadata: + annotations: + {{- if and .Values.proxy.prometheus.enabled .Values.envoy.prometheus.enabled (not .Values.envoy.prometheus.serviceMonitor.enabled) }} + prometheus.io/port: "{{ .Values.proxy.prometheus.port | default .Values.envoy.prometheus.port }}" + prometheus.io/scrape: "true" + {{- end }} + {{- if .Values.envoy.rollOutPods }} + # ensure pods roll when configmap updates + cilium.io/cilium-envoy-configmap-checksum: {{ include (print $.Template.BasePath "/cilium-envoy/configmap.yaml") . | sha256sum | quote }} + {{- end }} + {{- if not .Values.envoy.securityContext.privileged }} + # Set app AppArmor's profile to "unconfined". The value of this annotation + # can be modified as long users know which profiles they have available + # in AppArmor. + container.apparmor.security.beta.kubernetes.io/cilium-envoy: "unconfined" + {{- end }} + {{- with .Values.envoy.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + k8s-app: cilium-envoy + name: cilium-envoy + app.kubernetes.io/name: cilium-envoy + app.kubernetes.io/part-of: cilium + {{- with .Values.envoy.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.envoy.podSecurityContext }} + securityContext: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: cilium-envoy + image: {{ include "cilium.image" .Values.envoy.image | quote }} + imagePullPolicy: {{ .Values.envoy.image.pullPolicy }} + command: + - /usr/bin/cilium-envoy + args: + - '-c /var/run/cilium/envoy/bootstrap-config.json' + - '--base-id 0' + {{- if and (hasKey .Values.debug "verbose") (.Values.debug.verbose) (has "envoy" ( splitList " " .Values.debug.verbose )) }} + - '--log-level trace' + {{- else if and (.Values.debug.enabled) (hasKey .Values.debug "verbose") (.Values.debug.verbose) (has "flow" ( splitList " " .Values.debug.verbose )) }} + - '--log-level debug' + {{- else }} + - '--log-level info' + {{- end }} + - '--log-format {{ .Values.envoy.log.format }}' + {{- if .Values.envoy.log.path }} + - '--log-path {{ .Values.envoy.log.path }}' + {{- end }} + {{- with .Values.envoy.extraArgs }} + {{- toYaml . | trim | nindent 8 }} + {{- end }} + {{- if semverCompare ">=1.20-0" .Capabilities.KubeVersion.Version }} + startupProbe: + httpGet: + host: "localhost" + path: /healthz + port: {{ .Values.envoy.healthPort }} + scheme: HTTP + failureThreshold: {{ .Values.envoy.startupProbe.failureThreshold }} + periodSeconds: {{ .Values.envoy.startupProbe.periodSeconds }} + successThreshold: 1 + {{- end }} + livenessProbe: + httpGet: + host: "localhost" + path: /healthz + port: {{ .Values.envoy.healthPort }} + scheme: HTTP + {{- if semverCompare "<1.20-0" .Capabilities.KubeVersion.Version }} + # The initial delay for the liveness probe is intentionally large to + # avoid an endless kill & restart cycle if in the event that the initial + # bootstrapping takes longer than expected. + # Starting from Kubernetes 1.20, we are using startupProbe instead + # of this field. + initialDelaySeconds: 120 + {{- end }} + periodSeconds: {{ .Values.envoy.livenessProbe.periodSeconds }} + successThreshold: 1 + failureThreshold: {{ .Values.envoy.livenessProbe.failureThreshold }} + timeoutSeconds: 5 + readinessProbe: + httpGet: + host: "localhost" + path: /healthz + port: {{ .Values.envoy.healthPort }} + scheme: HTTP + {{- if semverCompare "<1.20-0" .Capabilities.KubeVersion.Version }} + initialDelaySeconds: 5 + {{- end }} + periodSeconds: {{ .Values.envoy.readinessProbe.periodSeconds }} + successThreshold: 1 + failureThreshold: {{ .Values.envoy.readinessProbe.failureThreshold }} + timeoutSeconds: 5 + env: + - name: K8S_NODE_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: spec.nodeName + - name: CILIUM_K8S_NAMESPACE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + {{- if .Values.k8sServiceHost }} + - name: KUBERNETES_SERVICE_HOST + value: {{ .Values.k8sServiceHost | quote }} + {{- end }} + {{- if .Values.k8sServicePort }} + - name: KUBERNETES_SERVICE_PORT + value: {{ .Values.k8sServicePort | quote }} + {{- end }} + {{- with .Values.envoy.extraEnv }} + {{- toYaml . | trim | nindent 8 }} + {{- end }} + {{- with .Values.envoy.resources }} + resources: + {{- toYaml . | trim | nindent 10 }} + {{- end }} + {{- if and .Values.proxy.prometheus.enabled .Values.envoy.prometheus.enabled }} + ports: + - name: envoy-metrics + containerPort: {{ .Values.proxy.prometheus.port | default .Values.envoy.prometheus.port }} + hostPort: {{ .Values.proxy.prometheus.port | default .Values.envoy.prometheus.port }} + protocol: TCP + {{- end }} + securityContext: + {{- if .Values.envoy.securityContext.privileged }} + privileged: true + {{- else }} + seLinuxOptions: + {{- with .Values.envoy.securityContext.seLinuxOptions }} + {{- toYaml . | nindent 12 }} + {{- end }} + capabilities: + add: + {{- with .Values.envoy.securityContext.capabilities.envoy }} + {{- toYaml . | nindent 14 }} + {{- end }} + drop: + - ALL + {{- end }} + terminationMessagePolicy: FallbackToLogsOnError + volumeMounts: + - name: envoy-sockets + mountPath: /var/run/cilium/envoy/sockets + readOnly: false + - name: envoy-config + mountPath: /var/run/cilium/envoy/ + readOnly: true + {{- if .Values.bpf.autoMount.enabled }} + - name: bpf-maps + mountPath: /sys/fs/bpf + mountPropagation: HostToContainer + {{- end }} + {{- range .Values.envoy.extraHostPathMounts }} + - name: {{ .name }} + mountPath: {{ .mountPath }} + readOnly: {{ .readOnly }} + {{- if .mountPropagation }} + mountPropagation: {{ .mountPropagation }} + {{- end }} + {{- end }} + {{- with .Values.envoy.extraVolumeMounts }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if .Values.envoy.extraContainers }} + {{- toYaml .Values.envoy.extraContainers | nindent 6 }} + {{- end }} + restartPolicy: Always + priorityClassName: {{ include "cilium.priorityClass" (list $ .Values.envoy.priorityClassName "system-node-critical") }} + serviceAccount: {{ .Values.serviceAccounts.envoy.name | quote }} + serviceAccountName: {{ .Values.serviceAccounts.envoy.name | quote }} + automountServiceAccountToken: {{ .Values.serviceAccounts.envoy.automount }} + terminationGracePeriodSeconds: {{ .Values.envoy.terminationGracePeriodSeconds }} + hostNetwork: true + {{- if .Values.envoy.dnsPolicy }} + dnsPolicy: {{ .Values.envoy.dnsPolicy }} + {{- end }} + {{- with .Values.envoy.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.envoy.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.envoy.tolerations }} + tolerations: + {{- toYaml . | trim | nindent 8 }} + {{- end }} + volumes: + - name: envoy-sockets + hostPath: + path: "{{ .Values.daemon.runPath }}/envoy/sockets" + type: DirectoryOrCreate + - name: envoy-config + configMap: + name: cilium-envoy-config + # note: the leading zero means this number is in octal representation: do not remove it + defaultMode: 0400 + items: + - key: bootstrap-config.json + path: bootstrap-config.json + # To keep state between restarts / upgrades + {{- if and .Values.bpf.autoMount.enabled }} + # To keep state between restarts / upgrades for bpf maps + - name: bpf-maps + hostPath: + path: /sys/fs/bpf + type: DirectoryOrCreate + {{- end }} + {{- range .Values.envoy.extraHostPathMounts }} + - name: {{ .name }} + hostPath: + path: {{ .hostPath }} + {{- if .hostPathType }} + type: {{ .hostPathType }} + {{- end }} + {{- end }} + {{- with .Values.envoy.extraVolumes }} + {{- toYaml . | nindent 6 }} + {{- end }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/cilium-envoy/service.yaml b/packages/system/cilium/charts/cilium/templates/cilium-envoy/service.yaml new file mode 100644 index 00000000..f5c2a09b --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/cilium-envoy/service.yaml @@ -0,0 +1,27 @@ +{{- if and .Values.envoy.enabled (not .Values.preflight.enabled) .Values.proxy.prometheus.enabled .Values.envoy.prometheus.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: cilium-envoy + namespace: {{ .Release.Namespace }} + {{- if not .Values.envoy.prometheus.serviceMonitor.enabled }} + annotations: + prometheus.io/scrape: "true" + prometheus.io/port: {{ .Values.proxy.prometheus.port | default .Values.envoy.prometheus.port | quote }} + {{- end }} + labels: + k8s-app: cilium-envoy + app.kubernetes.io/name: cilium-envoy + app.kubernetes.io/part-of: cilium + io.cilium/app: proxy +spec: + clusterIP: None + type: ClusterIP + selector: + k8s-app: cilium-envoy + ports: + - name: envoy-metrics + port: {{ .Values.proxy.prometheus.port | default .Values.envoy.prometheus.port }} + protocol: TCP + targetPort: envoy-metrics +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/cilium-envoy/serviceaccount.yaml b/packages/system/cilium/charts/cilium/templates/cilium-envoy/serviceaccount.yaml new file mode 100644 index 00000000..6094ba20 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/cilium-envoy/serviceaccount.yaml @@ -0,0 +1,11 @@ +{{- if and .Values.envoy.enabled (not .Values.preflight.enabled) .Values.serviceAccounts.envoy.create }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ .Values.serviceAccounts.envoy.name | quote }} + namespace: {{ .Release.Namespace }} + {{- if .Values.serviceAccounts.envoy.annotations }} + annotations: + {{- toYaml .Values.serviceAccounts.envoy.annotations | nindent 4 }} + {{- end }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/cilium-envoy/servicemonitor.yaml b/packages/system/cilium/charts/cilium/templates/cilium-envoy/servicemonitor.yaml new file mode 100644 index 00000000..363b3776 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/cilium-envoy/servicemonitor.yaml @@ -0,0 +1,39 @@ +{{- if and .Values.envoy.enabled (not .Values.preflight.enabled) .Values.proxy.prometheus.enabled .Values.envoy.prometheus.enabled .Values.envoy.prometheus.serviceMonitor.enabled }} +--- +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: cilium-envoy + namespace: {{ .Values.envoy.prometheus.serviceMonitor.namespace | default .Release.Namespace }} + labels: + app.kubernetes.io/part-of: cilium + {{- with .Values.envoy.prometheus.serviceMonitor.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + annotations: + {{- with .Values.envoy.prometheus.serviceMonitor.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + selector: + matchLabels: + k8s-app: cilium-envoy + namespaceSelector: + matchNames: + - {{ .Release.Namespace }} + endpoints: + - port: metrics + interval: {{ .Values.envoy.prometheus.serviceMonitor.interval | quote }} + honorLabels: true + path: /metrics + {{- with .Values.envoy.prometheus.serviceMonitor.relabelings }} + relabelings: + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.envoy.prometheus.serviceMonitor.metricRelabelings }} + metricRelabelings: + {{- toYaml . | nindent 4 }} + {{- end }} + targetLabels: + - k8s-app +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/cilium-gateway-api-class.yaml b/packages/system/cilium/charts/cilium/templates/cilium-gateway-api-class.yaml new file mode 100644 index 00000000..089649ff --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/cilium-gateway-api-class.yaml @@ -0,0 +1,10 @@ +{{- if .Values.gatewayAPI.enabled -}} +{{- if .Capabilities.APIVersions.Has "gateway.networking.k8s.io/v1beta1/GatewayClass" }} +apiVersion: gateway.networking.k8s.io/v1beta1 +kind: GatewayClass +metadata: + name: cilium +spec: + controllerName: io.cilium/gateway-controller +{{- end}} +{{- end}} diff --git a/packages/system/cilium/charts/cilium/templates/cilium-ingress-class.yaml b/packages/system/cilium/charts/cilium/templates/cilium-ingress-class.yaml new file mode 100644 index 00000000..9243b377 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/cilium-ingress-class.yaml @@ -0,0 +1,12 @@ +{{- if .Values.ingressController.enabled -}} +apiVersion: networking.k8s.io/v1 +kind: IngressClass +metadata: + name: cilium + {{- if .Values.ingressController.default }} + annotations: + ingressclass.kubernetes.io/is-default-class: "true" + {{- end}} +spec: + controller: cilium.io/ingress-controller +{{- end}} diff --git a/packages/system/cilium/charts/cilium/templates/cilium-ingress-service.yaml b/packages/system/cilium/charts/cilium/templates/cilium-ingress-service.yaml new file mode 100644 index 00000000..ff6269d2 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/cilium-ingress-service.yaml @@ -0,0 +1,57 @@ +{{- if .Values.ingressController.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ .Values.ingressController.service.name }} + namespace: {{ .Release.Namespace }} + labels: + cilium.io/ingress: "true" + {{- if .Values.ingressController.service.labels }} + {{- toYaml .Values.ingressController.service.labels | nindent 4 }} + {{- end }} + {{- if .Values.ingressController.service.annotations }} + annotations: + {{- toYaml .Values.ingressController.service.annotations | nindent 4 }} + {{- end }} +spec: + ports: + - name: http + port: 80 + protocol: TCP + nodePort: {{ .Values.ingressController.service.insecureNodePort }} + - name: https + port: 443 + protocol: TCP + nodePort: {{ .Values.ingressController.service.secureNodePort }} + type: {{ .Values.ingressController.service.type }} + {{- if semverCompare ">=1.24-0" .Capabilities.KubeVersion.Version -}} + {{- if .Values.ingressController.service.loadBalancerClass }} + loadBalancerClass: {{ .Values.ingressController.service.loadBalancerClass }} + {{- end }} + {{- if (not (kindIs "invalid" .Values.ingressController.service.allocateLoadBalancerNodePorts)) }} + allocateLoadBalancerNodePorts: {{ .Values.ingressController.service.allocateLoadBalancerNodePorts }} + {{- end }} + {{- end -}} + {{- if .Values.ingressController.service.loadBalancerIP }} + loadBalancerIP: {{ .Values.ingressController.service.loadBalancerIP }} + {{- end }} +--- +apiVersion: v1 +kind: Endpoints +metadata: + name: {{ .Values.ingressController.service.name }} + namespace: {{ .Release.Namespace }} + {{- if .Values.ingressController.service.labels }} + labels: + {{- toYaml .Values.ingressController.service.labels | nindent 4 }} + {{- end }} + {{- if .Values.ingressController.service.annotations }} + annotations: + {{- toYaml .Values.ingressController.service.annotations | nindent 4 }} + {{- end }} +subsets: +- addresses: + - ip: "192.192.192.192" + ports: + - port: 9999 +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/cilium-nodeinit/daemonset.yaml b/packages/system/cilium/charts/cilium/templates/cilium-nodeinit/daemonset.yaml new file mode 100644 index 00000000..63de5715 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/cilium-nodeinit/daemonset.yaml @@ -0,0 +1,110 @@ +{{- if .Values.nodeinit.enabled }} +--- +kind: DaemonSet +apiVersion: apps/v1 +metadata: + name: cilium-node-init + namespace: {{ .Release.Namespace }} + labels: + app: cilium-node-init + app.kubernetes.io/part-of: cilium + app.kubernetes.io/name: cilium-node-init +spec: + selector: + matchLabels: + app: cilium-node-init + {{- with .Values.nodeinit.updateStrategy }} + updateStrategy: + {{- toYaml . | trim | nindent 4 }} + {{- end }} + template: + metadata: + annotations: + {{- with .Values.nodeinit.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if not .Values.securityContext.privileged }} + # Set app AppArmor's profile to "unconfined". The value of this annotation + # can be modified as long users know which profiles they have available + # in AppArmor. + container.apparmor.security.beta.kubernetes.io/node-init: "unconfined" + {{- end }} + labels: + app: cilium-node-init + app.kubernetes.io/part-of: cilium + app.kubernetes.io/name: cilium-node-init + {{- with .Values.nodeinit.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: node-init + image: {{ include "cilium.image" .Values.nodeinit.image | quote }} + imagePullPolicy: {{ .Values.nodeinit.image.pullPolicy }} + lifecycle: + {{- if .Values.nodeinit.revertReconfigureKubelet }} + preStop: + exec: + command: + - nsenter + - --target=1 + - --mount + - -- + - /bin/bash + - -c + - | + {{- tpl (.Files.Get "files/nodeinit/prestop.bash") . | nindent 20 }} + {{- end }} + env: + {{- with .Values.nodeinit.extraEnv }} + {{- toYaml . | trim | nindent 10 }} + {{- end }} + # STARTUP_SCRIPT is the script run on node bootstrap. Node + # bootstrapping can be customized in this script. This script is invoked + # using nsenter, so it runs in the host's network and mount namespace using + # the host's userland tools! + - name: STARTUP_SCRIPT + value: | + {{- tpl (.Files.Get "files/nodeinit/startup.bash") . | nindent 14 }} + {{- with .Values.nodeinit.resources }} + resources: + {{- toYaml . | trim | nindent 12 }} + {{- end }} + {{- with .Values.nodeinit.securityContext }} + securityContext: + {{- toYaml . | trim | nindent 12 }} + {{- end }} + terminationMessagePolicy: FallbackToLogsOnError + {{- with .Values.nodeinit.extraVolumeMounts }} + volumeMounts: + {{- toYaml . | nindent 10 }} + {{- end }} + {{- with .Values.nodeinit.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.nodeinit.nodeSelector }} + nodeSelector: + {{- toYaml . | trim | nindent 8 }} + {{- end }} + {{- with .Values.nodeinit.tolerations }} + tolerations: + {{- toYaml . | trim | nindent 8 }} + {{- end }} + hostPID: true + hostNetwork: true + priorityClassName: {{ include "cilium.priorityClass" (list $ .Values.nodeinit.priorityClassName "system-node-critical") }} + {{- if .Values.serviceAccounts.nodeinit.enabled }} + serviceAccount: {{ .Values.serviceAccounts.nodeinit.name | quote }} + serviceAccountName: {{ .Values.serviceAccounts.nodeinit.name | quote }} + automountServiceAccountToken: {{ .Values.serviceAccounts.nodeinit.automount }} + {{- end }} + {{- with .Values.nodeinit.extraVolumes }} + volumes: + {{- toYaml . | nindent 6 }} + {{- end }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/cilium-nodeinit/serviceaccount.yaml b/packages/system/cilium/charts/cilium/templates/cilium-nodeinit/serviceaccount.yaml new file mode 100644 index 00000000..806e3706 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/cilium-nodeinit/serviceaccount.yaml @@ -0,0 +1,11 @@ +{{- if and .Values.nodeinit.enabled .Values.serviceAccounts.nodeinit.enabled .Values.serviceAccounts.nodeinit.create }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ .Values.serviceAccounts.nodeinit.name | quote }} + namespace: {{ .Release.Namespace }} + {{- if .Values.serviceAccounts.nodeinit.annotations }} + annotations: + {{- toYaml .Values.serviceAccounts.nodeinit.annotations | nindent 4 }} + {{- end }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/cilium-operator/_helpers.tpl b/packages/system/cilium/charts/cilium/templates/cilium-operator/_helpers.tpl new file mode 100644 index 00000000..0910de63 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/cilium-operator/_helpers.tpl @@ -0,0 +1,36 @@ +{{- define "cilium.operator.cloud" -}} +{{- $cloud := "generic" -}} +{{- if .Values.eni.enabled -}} + {{- $cloud = "aws" -}} +{{- else if .Values.azure.enabled -}} + {{- $cloud = "azure" -}} +{{- else if .Values.alibabacloud.enabled -}} + {{- $cloud = "alibabacloud" -}} +{{- end -}} +{{- $cloud -}} +{{- end -}} + +{{- define "cilium.operator.imageDigestName" -}} +{{- $imageDigest := (.Values.operator.image.useDigest | default false) | ternary (printf "@%s" .Values.operator.image.genericDigest) "" -}} +{{- if .Values.eni.enabled -}} + {{- $imageDigest = (.Values.operator.image.useDigest | default false) | ternary (printf "@%s" .Values.operator.image.awsDigest) "" -}} +{{- else if .Values.azure.enabled -}} + {{- $imageDigest = (.Values.operator.image.useDigest | default false) | ternary (printf "@%s" .Values.operator.image.azureDigest) "" -}} +{{- else if .Values.alibabacloud.enabled -}} + {{- $imageDigest = (.Values.operator.image.useDigest | default false) | ternary (printf "@%s" .Values.operator.image.alibabacloudDigest) "" -}} +{{- end -}} +{{- $imageDigest -}} +{{- end -}} + +{{/* +Return cilium operator image +*/}} +{{- define "cilium.operator.image" -}} +{{- if .Values.operator.image.override -}} +{{- printf "%s" .Values.operator.image.override -}} +{{- else -}} +{{- $cloud := include "cilium.operator.cloud" . }} +{{- $imageDigest := include "cilium.operator.imageDigestName" . }} +{{- printf "%s-%s%s:%s%s" .Values.operator.image.repository $cloud .Values.operator.image.suffix .Values.operator.image.tag $imageDigest -}} +{{- end -}} +{{- end -}} diff --git a/packages/system/cilium/charts/cilium/templates/cilium-operator/clusterrole.yaml b/packages/system/cilium/charts/cilium/templates/cilium-operator/clusterrole.yaml new file mode 100644 index 00000000..862fac10 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/cilium-operator/clusterrole.yaml @@ -0,0 +1,278 @@ +{{- if and .Values.operator.enabled .Values.serviceAccounts.operator.create }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: cilium-operator + labels: + app.kubernetes.io/part-of: cilium +rules: +- apiGroups: + - "" + resources: + - pods + verbs: + - get + - list + - watch +{{- if hasKey .Values "disableEndpointCRD" }} +{{- if not .Values.disableEndpointCRD }} +{{- if (and .Values.operator.unmanagedPodWatcher.restart (ne (.Values.operator.unmanagedPodWatcher.intervalSeconds | int64) 0 ) ) }} + # to automatically delete [core|kube]dns pods so that are starting to being + # managed by Cilium + - delete +{{- end }} +{{- end }} +{{- end }} +{{- if or .Values.operator.removeNodeTaints .Values.operator.setNodeNetworkStatus (include "hasDuration" .Values.operator.endpointGCInterval) }} +- apiGroups: + - "" + resources: + - nodes + verbs: + - list + - watch +{{- end }} +{{- if or .Values.operator.removeNodeTaints .Values.operator.setNodeNetworkStatus }} +- apiGroups: + - "" + resources: +{{- if .Values.operator.removeNodeTaints }} + # To remove node taints + - nodes +{{- end }} +{{- if .Values.operator.setNodeNetworkStatus }} + # To set NetworkUnavailable false on startup + - nodes/status +{{- end }} + verbs: + - patch +{{- end }} +- apiGroups: + - discovery.k8s.io + resources: + - endpointslices + verbs: + - get + - list + - watch +- apiGroups: + - "" + resources: + # to perform LB IP allocation for BGP + - services/status + verbs: + - update + - patch +- apiGroups: + - "" + resources: + # to check apiserver connectivity + - namespaces +{{- if or .Values.ingressController.enabled .Values.gatewayAPI.enabled }} + - secrets +{{- end }} + verbs: + - get + - list + - watch +- apiGroups: + - "" + resources: + # to perform the translation of a CNP that contains `ToGroup` to its endpoints + - services + - endpoints + verbs: + - get + - list + - watch +{{- if or .Values.ingressController.enabled .Values.gatewayAPI.enabled }} + - create + - update + - delete + - patch +{{- end }} +- apiGroups: + - cilium.io + resources: + - ciliumnetworkpolicies + - ciliumclusterwidenetworkpolicies + verbs: + # Create auto-generated CNPs and CCNPs from Policies that have 'toGroups' + - create + - update + - deletecollection + # To update the status of the CNPs and CCNPs + - patch + - get + - list + - watch +- apiGroups: + - cilium.io + resources: + - ciliumnetworkpolicies/status + - ciliumclusterwidenetworkpolicies/status + verbs: + # Update the auto-generated CNPs and CCNPs status. + - patch + - update +- apiGroups: + - cilium.io + resources: + - ciliumendpoints + - ciliumidentities + verbs: + # To perform garbage collection of such resources + - delete + - list + - watch +- apiGroups: + - cilium.io + resources: + - ciliumidentities + verbs: + # To synchronize garbage collection of such resources + - update +- apiGroups: + - cilium.io + resources: + - ciliumnodes + verbs: + - create + - update + - get + - list + - watch +{{- if include "hasDuration" .Values.operator.nodeGCInterval }} + # To perform CiliumNode garbage collector + - delete +{{- end }} +- apiGroups: + - cilium.io + resources: + - ciliumnodes/status + verbs: + - update +- apiGroups: + - cilium.io + resources: + - ciliumendpointslices + - ciliumenvoyconfigs + verbs: + - create + - update + - get + - list + - watch + - delete + - patch +- apiGroups: + - apiextensions.k8s.io + resources: + - customresourcedefinitions + verbs: + - create + - get + - list + - watch +- apiGroups: + - apiextensions.k8s.io + resources: + - customresourcedefinitions + verbs: + - update + resourceNames: + - ciliumloadbalancerippools.cilium.io + - ciliumbgppeeringpolicies.cilium.io + - ciliumclusterwideenvoyconfigs.cilium.io + - ciliumclusterwidenetworkpolicies.cilium.io + - ciliumegressgatewaypolicies.cilium.io + - ciliumendpoints.cilium.io + - ciliumendpointslices.cilium.io + - ciliumenvoyconfigs.cilium.io + - ciliumexternalworkloads.cilium.io + - ciliumidentities.cilium.io + - ciliumlocalredirectpolicies.cilium.io + - ciliumnetworkpolicies.cilium.io + - ciliumnodes.cilium.io + - ciliumnodeconfigs.cilium.io + - ciliumcidrgroups.cilium.io + - ciliuml2announcementpolicies.cilium.io + - ciliumpodippools.cilium.io +- apiGroups: + - cilium.io + resources: + - ciliumloadbalancerippools + - ciliumpodippools + verbs: + - get + - list + - watch +- apiGroups: + - cilium.io + resources: + - ciliumpodippools + verbs: + - create +- apiGroups: + - cilium.io + resources: + - ciliumloadbalancerippools/status + verbs: + - patch +# For cilium-operator running in HA mode. +# +# Cilium operator running in HA mode requires the use of ResourceLock for Leader Election +# between multiple running instances. +# The preferred way of doing this is to use LeasesResourceLock as edits to Leases are less +# common and fewer objects in the cluster watch "all Leases". +- apiGroups: + - coordination.k8s.io + resources: + - leases + verbs: + - create + - get + - update +{{- if .Values.ingressController.enabled }} +- apiGroups: + - networking.k8s.io + resources: + - ingresses + - ingressclasses + verbs: + - get + - list + - watch +- apiGroups: + - networking.k8s.io + resources: + - ingresses/status # To update ingress status with load balancer IP. + verbs: + - update +{{- end }} +{{- if .Values.gatewayAPI.enabled }} +- apiGroups: + - gateway.networking.k8s.io + resources: + - gatewayclasses + - gateways + - tlsroutes + - httproutes + - referencegrants + - referencepolicies + verbs: + - get + - list + - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - gatewayclasses/status + - gateways/status + - httproutes/status + - tlsroutes/status + verbs: + - update + - patch +{{- end }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/cilium-operator/clusterrolebinding.yaml b/packages/system/cilium/charts/cilium/templates/cilium-operator/clusterrolebinding.yaml new file mode 100644 index 00000000..a8a51bd4 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/cilium-operator/clusterrolebinding.yaml @@ -0,0 +1,16 @@ +{{- if and .Values.operator.enabled .Values.serviceAccounts.operator.create }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: cilium-operator + labels: + app.kubernetes.io/part-of: cilium +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: cilium-operator +subjects: +- kind: ServiceAccount + name: {{ .Values.serviceAccounts.operator.name | quote }} + namespace: {{ .Release.Namespace }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/cilium-operator/dashboards-configmap.yaml b/packages/system/cilium/charts/cilium/templates/cilium-operator/dashboards-configmap.yaml new file mode 100644 index 00000000..37402bed --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/cilium-operator/dashboards-configmap.yaml @@ -0,0 +1,25 @@ +{{- if .Values.operator.dashboards.enabled }} +{{- $files := .Files.Glob "files/cilium-operator/dashboards/*.json" }} +{{- range $path, $fileContents := $files }} +{{- $dashboardName := regexReplaceAll "(^.*/)(.*)\\.json$" $path "${2}" }} +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ $dashboardName | trunc 63 | trimSuffix "-" }} + namespace: {{ $.Values.operator.dashboards.namespace | default $.Release.Namespace }} + labels: + k8s-app: cilium + app.kubernetes.io/name: cilium-operator + app.kubernetes.io/part-of: cilium + {{- if $.Values.operator.dashboards.label }} + {{ $.Values.operator.dashboards.label }}: {{ ternary $.Values.operator.dashboards.labelValue "1" (not (empty $.Values.operator.dashboards.labelValue)) | quote }} + {{- end }} + {{- with $.Values.operator.dashboards.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +data: + {{ $dashboardName }}.json: {{ $.Files.Get $path | toJson }} +{{- end }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/cilium-operator/deployment.yaml b/packages/system/cilium/charts/cilium/templates/cilium-operator/deployment.yaml new file mode 100644 index 00000000..44b1da2a --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/cilium-operator/deployment.yaml @@ -0,0 +1,333 @@ +{{- if .Values.operator.enabled }} +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: cilium-operator + namespace: {{ .Release.Namespace }} + labels: + io.cilium/app: operator + name: cilium-operator + app.kubernetes.io/part-of: cilium + app.kubernetes.io/name: cilium-operator +spec: + # See docs on ServerCapabilities.LeasesResourceLock in file pkg/k8s/version/version.go + # for more details. + replicas: {{ .Values.operator.replicas }} + selector: + matchLabels: + io.cilium/app: operator + name: cilium-operator + # ensure operator update on single node k8s clusters, by using rolling update with maxUnavailable=100% in case + # of one replica and no user configured Recreate strategy. + # otherwise an update might get stuck due to the default maxUnavailable=50% in combination with the + # podAntiAffinity which prevents deployments of multiple operator replicas on the same node. + {{- if and (eq (.Values.operator.replicas | toString) "1") (eq .Values.operator.updateStrategy.type "RollingUpdate") }} + strategy: + rollingUpdate: + maxSurge: {{ .Values.operator.updateStrategy.rollingUpdate.maxSurge }} + maxUnavailable: 100% + type: RollingUpdate + {{- else }} + {{- with .Values.operator.updateStrategy }} + strategy: + {{- toYaml . | trim | nindent 4 }} + {{- end }} + {{- end }} + template: + metadata: + annotations: + {{- if .Values.operator.rollOutPods }} + # ensure pods roll when configmap updates + cilium.io/cilium-configmap-checksum: {{ include (print $.Template.BasePath "/cilium-configmap.yaml") . | sha256sum | quote }} + {{- end }} + {{- if and .Values.operator.prometheus.enabled (not .Values.operator.prometheus.serviceMonitor.enabled) }} + prometheus.io/port: {{ .Values.operator.prometheus.port | quote }} + prometheus.io/scrape: "true" + {{- end }} + {{- with .Values.operator.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + io.cilium/app: operator + name: cilium-operator + app.kubernetes.io/part-of: cilium + app.kubernetes.io/name: cilium-operator + {{- with .Values.operator.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.operator.podSecurityContext }} + securityContext: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: cilium-operator + image: {{ include "cilium.operator.image" . | quote }} + imagePullPolicy: {{ .Values.operator.image.pullPolicy }} + command: + - cilium-operator-{{ include "cilium.operator.cloud" . }} + args: + - --config-dir=/tmp/cilium/config-map + - --debug=$(CILIUM_DEBUG) + {{- with .Values.operator.extraArgs }} + {{- toYaml . | trim | nindent 8 }} + {{- end }} + env: + - name: K8S_NODE_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: spec.nodeName + - name: CILIUM_K8S_NAMESPACE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + - name: CILIUM_DEBUG + valueFrom: + configMapKeyRef: + key: debug + name: cilium-config + optional: true + {{- if and .Values.eni.enabled (not .Values.eni.iamRole ) }} + - name: AWS_ACCESS_KEY_ID + valueFrom: + secretKeyRef: + name: cilium-aws + key: AWS_ACCESS_KEY_ID + optional: true + - name: AWS_SECRET_ACCESS_KEY + valueFrom: + secretKeyRef: + name: cilium-aws + key: AWS_SECRET_ACCESS_KEY + optional: true + - name: AWS_DEFAULT_REGION + valueFrom: + secretKeyRef: + name: cilium-aws + key: AWS_DEFAULT_REGION + optional: true + {{- end }} + {{- if .Values.alibabacloud.enabled }} + - name: ALIBABA_CLOUD_ACCESS_KEY_ID + valueFrom: + secretKeyRef: + name: cilium-alibabacloud + key: ALIBABA_CLOUD_ACCESS_KEY_ID + optional: true + - name: ALIBABA_CLOUD_ACCESS_KEY_SECRET + valueFrom: + secretKeyRef: + name: cilium-alibabacloud + key: ALIBABA_CLOUD_ACCESS_KEY_SECRET + optional: true + {{- end }} + {{- if .Values.k8sServiceHost }} + - name: KUBERNETES_SERVICE_HOST + value: {{ .Values.k8sServiceHost | quote }} + {{- end }} + {{- if .Values.k8sServicePort }} + - name: KUBERNETES_SERVICE_PORT + value: {{ .Values.k8sServicePort | quote }} + {{- end }} + {{- if .Values.azure.enabled }} + {{- if .Values.azure.subscriptionID }} + - name: AZURE_SUBSCRIPTION_ID + value: {{ .Values.azure.subscriptionID }} + {{- end }} + {{- if .Values.azure.tenantID }} + - name: AZURE_TENANT_ID + value: {{ .Values.azure.tenantID }} + {{- end }} + {{- if .Values.azure.resourceGroup }} + - name: AZURE_RESOURCE_GROUP + value: {{ .Values.azure.resourceGroup }} + {{- end }} + - name: AZURE_CLIENT_ID + valueFrom: + secretKeyRef: + name: cilium-azure + key: AZURE_CLIENT_ID + - name: AZURE_CLIENT_SECRET + valueFrom: + secretKeyRef: + name: cilium-azure + key: AZURE_CLIENT_SECRET + {{- end }} + {{- with .Values.operator.extraEnv }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if .Values.operator.prometheus.enabled }} + ports: + - name: prometheus + containerPort: {{ .Values.operator.prometheus.port }} + hostPort: {{ .Values.operator.prometheus.port }} + protocol: TCP + {{- end }} + livenessProbe: + httpGet: + host: {{ .Values.ipv4.enabled | ternary "127.0.0.1" "::1" | quote }} + path: /healthz + port: 9234 + scheme: HTTP + initialDelaySeconds: 60 + periodSeconds: 10 + timeoutSeconds: 3 + readinessProbe: + httpGet: + host: {{ .Values.ipv4.enabled | ternary "127.0.0.1" "::1" | quote }} + path: /healthz + port: 9234 + scheme: HTTP + initialDelaySeconds: 0 + periodSeconds: 5 + timeoutSeconds: 3 + failureThreshold: 5 + volumeMounts: + - name: cilium-config-path + mountPath: /tmp/cilium/config-map + readOnly: true + {{- if .Values.etcd.enabled }} + - name: etcd-config-path + mountPath: /var/lib/etcd-config + readOnly: true + {{- if or .Values.etcd.ssl .Values.etcd.managed }} + - name: etcd-secrets + mountPath: /var/lib/etcd-secrets + readOnly: true + {{- end }} + {{- end }} + {{- if .Values.kubeConfigPath }} + - name: kube-config + mountPath: {{ .Values.kubeConfigPath }} + readOnly: true + {{- end }} + {{- if .Values.authentication.mutual.spire.enabled }} + - name: spire-agent-socket + mountPath: {{ dir .Values.authentication.mutual.spire.agentSocketPath }} + readOnly: true + {{- end }} + {{- range .Values.operator.extraHostPathMounts }} + - name: {{ .name }} + mountPath: {{ .mountPath }} + readOnly: {{ .readOnly }} + {{- if .mountPropagation }} + mountPropagation: {{ .mountPropagation }} + {{- end }} + {{- end }} + {{- if .Values.bgp.enabled }} + - name: bgp-config-path + mountPath: /var/lib/cilium/bgp + readOnly: true + {{- end }} + {{- with .Values.operator.extraVolumeMounts }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.operator.resources }} + resources: + {{- toYaml . | trim | nindent 10 }} + {{- end }} + {{- with .Values.operator.securityContext }} + securityContext: + {{- toYaml . | trim | nindent 10 }} + {{- end }} + terminationMessagePolicy: FallbackToLogsOnError + hostNetwork: true + {{- if and .Values.etcd.managed (not .Values.etcd.k8sService) }} + # In managed etcd mode, Cilium must be able to resolve the DNS name of + # the etcd service + dnsPolicy: ClusterFirstWithHostNet + {{- else if .Values.operator.dnsPolicy }} + dnsPolicy: {{ .Values.operator.dnsPolicy }} + {{- end }} + restartPolicy: Always + priorityClassName: {{ include "cilium.priorityClass" (list $ .Values.operator.priorityClassName "system-cluster-critical") }} + serviceAccount: {{ .Values.serviceAccounts.operator.name | quote }} + serviceAccountName: {{ .Values.serviceAccounts.operator.name | quote }} + automountServiceAccountToken: {{ .Values.serviceAccounts.operator.automount }} + {{- with .Values.operator.affinity }} + # In HA mode, cilium-operator pods must not be scheduled on the same + # node as they will clash with each other. + affinity: + {{- toYaml . | trim | nindent 8 }} + {{- end }} + {{- with .Values.operator.topologySpreadConstraints }} + topologySpreadConstraints: + {{- range $constraint := . }} + - {{ toYaml $constraint | nindent 8 | trim }} + {{- if not $constraint.labelSelector }} + labelSelector: + matchLabels: + io.cilium/app: operator + name: cilium-operator + {{- end }} + {{- end }} + {{- end }} + {{- with .Values.operator.nodeSelector }} + nodeSelector: + {{- toYaml . | trim | nindent 8 }} + {{- end }} + {{- with .Values.operator.tolerations }} + tolerations: + {{- toYaml . | trim | nindent 8 }} + {{- end }} + volumes: + # To read the configuration from the config map + - name: cilium-config-path + configMap: + name: cilium-config + {{- if .Values.etcd.enabled }} + # To read the etcd config stored in config maps + - name: etcd-config-path + configMap: + name: cilium-config + # note: the leading zero means this number is in octal representation: do not remove it + defaultMode: 0400 + items: + - key: etcd-config + path: etcd.config + {{- if or .Values.etcd.ssl .Values.etcd.managed }} + # To read the k8s etcd secrets in case the user might want to use TLS + - name: etcd-secrets + secret: + secretName: cilium-etcd-secrets + # note: the leading zero means this number is in octal representation: do not remove it + defaultMode: 0400 + optional: true + {{- end }} + {{- end }} + {{- if .Values.kubeConfigPath }} + - name: kube-config + hostPath: + path: {{ .Values.kubeConfigPath }} + type: FileOrCreate + {{- end }} + {{- range .Values.operator.extraHostPathMounts }} + - name: {{ .name }} + hostPath: + path: {{ .hostPath }} + {{- if .hostPathType }} + type: {{ .hostPathType }} + {{- end }} + {{- end }} + {{- if .Values.bgp.enabled }} + - name: bgp-config-path + configMap: + name: bgp-config + {{- end }} + {{- if .Values.authentication.mutual.spire.enabled }} + - name: spire-agent-socket + hostPath: + path: {{ dir .Values.authentication.mutual.spire.agentSocketPath }} + type: DirectoryOrCreate + {{- end }} + {{- with .Values.operator.extraVolumes }} + {{- toYaml . | nindent 6 }} + {{- end }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/cilium-operator/poddisruptionbudget.yaml b/packages/system/cilium/charts/cilium/templates/cilium-operator/poddisruptionbudget.yaml new file mode 100644 index 00000000..cb63aaf0 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/cilium-operator/poddisruptionbudget.yaml @@ -0,0 +1,24 @@ +{{- if and .Values.operator.enabled .Values.operator.podDisruptionBudget.enabled }} +{{- $component := .Values.operator.podDisruptionBudget }} +apiVersion: {{ include "podDisruptionBudget.apiVersion" . }} +kind: PodDisruptionBudget +metadata: + name: cilium-operator + namespace: {{ .Release.Namespace }} + labels: + io.cilium/app: operator + name: cilium-operator + app.kubernetes.io/name: cilium-operator + app.kubernetes.io/part-of: cilium +spec: + {{- with $component.maxUnavailable }} + maxUnavailable: {{ . }} + {{- end }} + {{- with $component.minAvailable }} + minAvailable: {{ . }} + {{- end }} + selector: + matchLabels: + io.cilium/app: operator + name: cilium-operator +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/cilium-operator/role.yaml b/packages/system/cilium/charts/cilium/templates/cilium-operator/role.yaml new file mode 100644 index 00000000..cf2526d9 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/cilium-operator/role.yaml @@ -0,0 +1,41 @@ +{{- if and .Values.operator.enabled .Values.serviceAccounts.operator.create .Values.ingressController.enabled .Values.ingressController.secretsNamespace.sync .Values.ingressController.secretsNamespace.name }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: cilium-operator-ingress-secrets + namespace: {{ .Values.ingressController.secretsNamespace.name | quote }} + labels: + app.kubernetes.io/part-of: cilium +rules: +- apiGroups: + - "" + resources: + - secrets + verbs: + - create + - delete + - update + - patch +{{- end }} + +{{- if and .Values.operator.enabled .Values.serviceAccounts.operator.create .Values.gatewayAPI.enabled .Values.gatewayAPI.secretsNamespace.sync .Values.gatewayAPI.secretsNamespace.name }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: cilium-operator-gateway-secrets + namespace: {{ .Values.gatewayAPI.secretsNamespace.name | quote }} + labels: + app.kubernetes.io/part-of: cilium +rules: +- apiGroups: + - "" + resources: + - secrets + verbs: + - create + - delete + - update + - patch +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/cilium-operator/rolebinding.yaml b/packages/system/cilium/charts/cilium/templates/cilium-operator/rolebinding.yaml new file mode 100644 index 00000000..aa826906 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/cilium-operator/rolebinding.yaml @@ -0,0 +1,37 @@ +{{- if and .Values.operator.enabled .Values.serviceAccounts.operator.create .Values.ingressController.enabled .Values.ingressController.secretsNamespace.sync .Values.ingressController.secretsNamespace.name }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: cilium-operator-ingress-secrets + namespace: {{ .Values.ingressController.secretsNamespace.name | quote }} + labels: + app.kubernetes.io/part-of: cilium +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: cilium-operator-ingress-secrets +subjects: + - kind: ServiceAccount + name: {{ .Values.serviceAccounts.operator.name | quote }} + namespace: {{ .Release.Namespace }} +{{- end }} + +{{- if and .Values.operator.enabled .Values.serviceAccounts.operator.create .Values.gatewayAPI.enabled .Values.gatewayAPI.secretsNamespace.sync .Values.gatewayAPI.secretsNamespace.name }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: cilium-operator-gateway-secrets + namespace: {{ .Values.gatewayAPI.secretsNamespace.name | quote }} + labels: + app.kubernetes.io/part-of: cilium +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: cilium-operator-gateway-secrets +subjects: +- kind: ServiceAccount + name: {{ .Values.serviceAccounts.operator.name | quote }} + namespace: {{ .Release.Namespace }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/cilium-operator/secret.yaml b/packages/system/cilium/charts/cilium/templates/cilium-operator/secret.yaml new file mode 100644 index 00000000..42096412 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/cilium-operator/secret.yaml @@ -0,0 +1,13 @@ +{{- if .Values.operator.enabled }} +{{- if .Values.azure.enabled }} +apiVersion: v1 +kind: Secret +metadata: + name: cilium-azure + namespace: {{ .Release.Namespace }} +type: Opaque +data: + AZURE_CLIENT_ID: {{ default "" .Values.azure.clientID | b64enc | quote }} + AZURE_CLIENT_SECRET: {{ default "" .Values.azure.clientSecret | b64enc | quote }} +{{- end }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/cilium-operator/service.yaml b/packages/system/cilium/charts/cilium/templates/cilium-operator/service.yaml new file mode 100644 index 00000000..61514916 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/cilium-operator/service.yaml @@ -0,0 +1,23 @@ +{{- if and .Values.operator.enabled .Values.operator.prometheus.enabled .Values.operator.prometheus.serviceMonitor.enabled }} +kind: Service +apiVersion: v1 +metadata: + name: cilium-operator + namespace: {{ .Release.Namespace }} + labels: + io.cilium/app: operator + name: cilium-operator + app.kubernetes.io/part-of: cilium + app.kubernetes.io/name: cilium-operator +spec: + clusterIP: None + type: ClusterIP + ports: + - name: metrics + port: 9963 + protocol: TCP + targetPort: prometheus + selector: + io.cilium/app: operator + name: cilium-operator +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/cilium-operator/serviceaccount.yaml b/packages/system/cilium/charts/cilium/templates/cilium-operator/serviceaccount.yaml new file mode 100644 index 00000000..4bb3551c --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/cilium-operator/serviceaccount.yaml @@ -0,0 +1,15 @@ +{{- if and .Values.operator.enabled .Values.serviceAccounts.operator.create }} +{{- if and .Values.eni.enabled .Values.eni.iamRole }} + {{ $_ := set .Values.serviceAccounts.operator.annotations "eks.amazonaws.com/role-arn" .Values.eni.iamRole }} +{{- end}} +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ .Values.serviceAccounts.operator.name | quote }} + namespace: {{ .Release.Namespace }} + {{- if .Values.serviceAccounts.operator.annotations }} + annotations: + {{- toYaml .Values.serviceAccounts.operator.annotations | nindent 4 }} + {{- end }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/cilium-operator/servicemonitor.yaml b/packages/system/cilium/charts/cilium/templates/cilium-operator/servicemonitor.yaml new file mode 100644 index 00000000..a3edaec5 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/cilium-operator/servicemonitor.yaml @@ -0,0 +1,40 @@ +{{- if and .Values.operator.enabled .Values.operator.prometheus.enabled .Values.operator.prometheus.serviceMonitor.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: cilium-operator + namespace: {{ .Values.operator.prometheus.serviceMonitor.namespace | default .Release.Namespace }} + labels: + app.kubernetes.io/part-of: cilium + app.kubernetes.io/name: cilium-operator + {{- with .Values.operator.prometheus.serviceMonitor.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + annotations: + {{- with .Values.operator.prometheus.serviceMonitor.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + selector: + matchLabels: + io.cilium/app: operator + name: cilium-operator + namespaceSelector: + matchNames: + - {{ .Release.Namespace }} + endpoints: + - port: metrics + interval: {{ .Values.operator.prometheus.serviceMonitor.interval | quote }} + honorLabels: true + path: /metrics + {{- with .Values.operator.prometheus.serviceMonitor.relabelings }} + relabelings: + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.operator.prometheus.serviceMonitor.metricRelabelings }} + metricRelabelings: + {{- toYaml . | nindent 4 }} + {{- end }} + targetLabels: + - io.cilium/app +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/cilium-preflight/clusterrole.yaml b/packages/system/cilium/charts/cilium/templates/cilium-preflight/clusterrole.yaml new file mode 100644 index 00000000..379814c8 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/cilium-preflight/clusterrole.yaml @@ -0,0 +1,142 @@ +{{- if .Values.preflight.enabled }} +{{- /* +Keep file in sync with cilium-agent/clusterrole.yaml +*/ -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: cilium-pre-flight + labels: + app.kubernetes.io/part-of: cilium +rules: +- apiGroups: + - networking.k8s.io + resources: + - networkpolicies + verbs: + - get + - list + - watch +- apiGroups: + - discovery.k8s.io + resources: + - endpointslices + verbs: + - get + - list + - watch +- apiGroups: + - "" + resources: + - namespaces + - services + - pods + - endpoints + - nodes + verbs: + - get + - list + - watch +{{- if .Values.annotateK8sNode }} +- apiGroups: + - "" + resources: + - nodes/status + verbs: + # To annotate the k8s node with Cilium's metadata + - patch +{{- end }} +{{- if .Values.l2announcements.enabled }} +- apiGroups: + - coordination.k8s.io + resources: + - leases + verbs: + - create + - get + - update + - list + - delete +{{- end }} +- apiGroups: + - apiextensions.k8s.io + resources: + - customresourcedefinitions + verbs: + - list + - watch + # This is used when validating policies in preflight. This will need to stay + # until we figure out how to avoid "get" inside the preflight, and then + # should be removed ideally. + - get +{{- if eq "k8s" .Values.tls.secretsBackend }} +- apiGroups: + - "" + resources: + - secrets + verbs: + - get +{{- end }} +- apiGroups: + - cilium.io + resources: + - ciliumloadbalancerippools + - ciliumbgppeeringpolicies + - ciliumclusterwideenvoyconfigs + - ciliumclusterwidenetworkpolicies + - ciliumegressgatewaypolicies + - ciliumendpoints + - ciliumendpointslices + - ciliumenvoyconfigs + - ciliumidentities + - ciliumlocalredirectpolicies + - ciliumnetworkpolicies + - ciliumnodes + - ciliumnodeconfigs + - ciliumcidrgroups + - ciliuml2announcementpolicies + - ciliumpodippools + verbs: + - list + - watch +- apiGroups: + - cilium.io + resources: + - ciliumidentities + - ciliumendpoints + - ciliumnodes + verbs: + - create +- apiGroups: + - cilium.io + # To synchronize garbage collection of such resources + resources: + - ciliumidentities + verbs: + - update +- apiGroups: + - cilium.io + resources: + - ciliumendpoints + verbs: + - delete + - get +- apiGroups: + - cilium.io + resources: + - ciliumnodes + - ciliumnodes/status + verbs: + - get + - update +- apiGroups: + - cilium.io + resources: + - ciliumnetworkpolicies/status + - ciliumclusterwidenetworkpolicies/status + - ciliumendpoints/status + - ciliumendpoints + - ciliuml2announcementpolicies/status + verbs: + - patch +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/cilium-preflight/clusterrolebinding.yaml b/packages/system/cilium/charts/cilium/templates/cilium-preflight/clusterrolebinding.yaml new file mode 100644 index 00000000..ef5be1de --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/cilium-preflight/clusterrolebinding.yaml @@ -0,0 +1,16 @@ +{{- if and .Values.preflight.enabled .Values.serviceAccounts.preflight.create }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: cilium-pre-flight + labels: + app.kubernetes.io/part-of: cilium +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: cilium-pre-flight +subjects: +- kind: ServiceAccount + name: {{ .Values.serviceAccounts.preflight.name | quote }} + namespace: {{ .Release.Namespace }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/cilium-preflight/daemonset.yaml b/packages/system/cilium/charts/cilium/templates/cilium-preflight/daemonset.yaml new file mode 100644 index 00000000..efca1ba5 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/cilium-preflight/daemonset.yaml @@ -0,0 +1,211 @@ +{{- if .Values.preflight.enabled }} +apiVersion: apps/v1 +kind: DaemonSet +metadata: + name: cilium-pre-flight-check + namespace: {{ .Release.Namespace }} +spec: + selector: + matchLabels: + k8s-app: cilium-pre-flight-check + kubernetes.io/cluster-service: "true" + template: + metadata: + {{- with .Values.preflight.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + app.kubernetes.io/part-of: cilium + k8s-app: cilium-pre-flight-check + app.kubernetes.io/name: cilium-pre-flight-check + kubernetes.io/cluster-service: "true" + {{- with .Values.preflight.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.preflight.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.preflight.podSecurityContext }} + securityContext: + {{- toYaml . | nindent 8 }} + {{- end }} + initContainers: + - name: clean-cilium-state + image: {{ include "cilium.image" .Values.preflight.image | quote }} + imagePullPolicy: {{ .Values.preflight.image.pullPolicy }} + command: ["/bin/echo"] + args: + - "hello" + terminationMessagePolicy: FallbackToLogsOnError + containers: + - name: cilium-pre-flight-check + image: {{ include "cilium.image" .Values.preflight.image | quote }} + imagePullPolicy: {{ .Values.preflight.image.pullPolicy }} + command: ["/bin/sh"] + args: + - -c + - "touch /tmp/ready; sleep 1h" + livenessProbe: + exec: + command: + - cat + - /tmp/ready + initialDelaySeconds: 5 + periodSeconds: 5 + readinessProbe: + exec: + command: + - cat + - /tmp/ready + initialDelaySeconds: 5 + periodSeconds: 5 + {{- with .Values.preflight.extraEnv }} + env: + {{- toYaml . | trim | nindent 12 }} + {{- end }} + volumeMounts: + - name: cilium-run + mountPath: /var/run/cilium + {{- if .Values.etcd.enabled }} + - name: etcd-config-path + mountPath: /var/lib/etcd-config + readOnly: true + {{- if or .Values.etcd.ssl .Values.etcd.managed }} + - name: etcd-secrets + mountPath: /var/lib/etcd-secrets + readOnly: true + {{- end }} + {{- end }} + {{- with .Values.preflight.extraVolumeMounts }} + {{- toYaml . | nindent 10 }} + {{- end }} + {{- with .Values.preflight.resources }} + resources: + {{- toYaml . | trim | nindent 12 }} + {{- end }} + {{- with .Values.preflight.securityContext }} + securityContext: + {{- toYaml . | trim | nindent 14 }} + {{- end }} + terminationMessagePolicy: FallbackToLogsOnError + {{- if ne .Values.preflight.tofqdnsPreCache "" }} + - name: cilium-pre-flight-fqdn-precache + image: {{ include "cilium.image" .Values.preflight.image | quote }} + imagePullPolicy: {{ .Values.preflight.image.pullPolicy }} + name: cilium-pre-flight-fqdn-precache + command: ["/bin/sh"] + args: + - -ec + - | + cilium preflight fqdn-poller --tofqdns-pre-cache {{ .Values.preflight.tofqdnsPreCache }}; + touch /tmp/ready-tofqdns-precache; + livenessProbe: + exec: + command: + - cat + - /tmp/read-tofqdns-precachey + initialDelaySeconds: 5 + periodSeconds: 5 + readinessProbe: + exec: + command: + - cat + - /tmp/read-tofqdns-precachey + initialDelaySeconds: 5 + periodSeconds: 5 + env: + {{- if .Values.k8sServiceHost }} + - name: KUBERNETES_SERVICE_HOST + value: {{ .Values.k8sServiceHost | quote }} + {{- end }} + {{- if .Values.k8sServicePort }} + - name: KUBERNETES_SERVICE_PORT + value: {{ .Values.k8sServicePort | quote }} + {{- end }} + volumeMounts: + - name: cilium-run + mountPath: /var/run/cilium + {{- if .Values.etcd.enabled }} + - name: etcd-config-path + mountPath: /var/lib/etcd-config + readOnly: true + {{- if or .Values.etcd.ssl .Values.etcd.managed }} + - name: etcd-secrets + mountPath: /var/lib/etcd-secrets + readOnly: true + {{- end }} + {{- end }} + {{- with .Values.preflight.extraVolumeMounts }} + {{- toYaml . | nindent 10 }} + {{- end }} + {{- with .Values.preflight.extraEnv }} + {{- toYaml . | trim | nindent 10 }} + {{- end }} + {{- with .Values.preflight.resources }} + resources: + {{- toYaml . | trim | nindent 12 }} + {{- end }} + {{- with .Values.preflight.securityContext }} + securityContext: + {{- toYaml . | trim | nindent 14 }} + {{- end }} + terminationMessagePolicy: FallbackToLogsOnError + {{- end }} + hostNetwork: true + # This is here to seamlessly allow migrate-identity to work with + # etcd-operator setups. The assumption is that other cases would also + # work since the cluster DNS would forward the request on. + # This differs from the cilium-agent daemonset, where this is only + # enabled when etcd.managed=true + dnsPolicy: ClusterFirstWithHostNet + restartPolicy: Always + priorityClassName: {{ include "cilium.priorityClass" (list $ .Values.preflight.priorityClassName "system-node-critical") }} + serviceAccount: {{ .Values.serviceAccounts.preflight.name | quote }} + serviceAccountName: {{ .Values.serviceAccounts.preflight.name | quote }} + automountServiceAccountToken: {{ .Values.serviceAccounts.preflight.automount }} + terminationGracePeriodSeconds: {{ .Values.preflight.terminationGracePeriodSeconds }} + {{- with .Values.preflight.tolerations }} + tolerations: + {{- toYaml . | trim | nindent 8 }} + {{- end }} + volumes: + # To keep state between restarts / upgrades + - name: cilium-run + hostPath: + path: /var/run/cilium + type: DirectoryOrCreate + - name: bpf-maps + hostPath: + path: /sys/fs/bpf + type: DirectoryOrCreate + {{- if .Values.etcd.enabled }} + # To read the etcd config stored in config maps + - name: etcd-config-path + configMap: + name: cilium-config + # note: the leading zero means this number is in octal representation: do not remove it + defaultMode: 0400 + items: + - key: etcd-config + path: etcd.config + # To read the k8s etcd secrets in case the user might want to use TLS + {{- if or .Values.etcd.ssl .Values.etcd.managed }} + - name: etcd-secrets + secret: + secretName: cilium-etcd-secrets + # note: the leading zero means this number is in octal representation: do not remove it + defaultMode: 0400 + optional: true + {{- end }} + {{- with .Values.preflight.extraVolumes }} + {{- toYaml . | nindent 6 }} + {{- end }} + {{- end }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/cilium-preflight/deployment.yaml b/packages/system/cilium/charts/cilium/templates/cilium-preflight/deployment.yaml new file mode 100644 index 00000000..b4f542ea --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/cilium-preflight/deployment.yaml @@ -0,0 +1,103 @@ +{{- if and .Values.preflight.enabled .Values.preflight.validateCNPs }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: cilium-pre-flight-check + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/part-of: cilium + app.kubernetes.io/name: cilium-pre-flight-check +spec: + selector: + matchLabels: + k8s-app: cilium-pre-flight-check-deployment + kubernetes.io/cluster-service: "true" + template: + metadata: + {{- with .Values.preflight.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + app.kubernetes.io/part-of: cilium + k8s-app: cilium-pre-flight-check-deployment + kubernetes.io/cluster-service: "true" + app.kubernetes.io/name: cilium-pre-flight-check + {{- with .Values.preflight.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: cnp-validator + image: {{ include "cilium.image" .Values.preflight.image | quote }} + imagePullPolicy: {{ .Values.preflight.image.pullPolicy }} + command: ["/bin/sh"] + args: + - -ec + - | + cilium preflight validate-cnp; + touch /tmp/ready-validate-cnp; + sleep 1h; + livenessProbe: + exec: + command: + - cat + - /tmp/ready-validate-cnp + initialDelaySeconds: 5 + periodSeconds: 5 + readinessProbe: + exec: + command: + - cat + - /tmp/ready-validate-cnp + initialDelaySeconds: 5 + periodSeconds: 5 + {{- with .Values.preflight.extraVolumeMounts }} + volumeMounts: + {{- toYaml . | nindent 10 }} + {{- end }} + env: + {{- if .Values.k8sServiceHost }} + - name: KUBERNETES_SERVICE_HOST + value: {{ .Values.k8sServiceHost | quote }} + {{- end }} + {{- if .Values.k8sServicePort }} + - name: KUBERNETES_SERVICE_PORT + value: {{ .Values.k8sServicePort | quote }} + {{- end }} + {{- with .Values.preflight.extraEnv }} + {{- toYaml . | trim | nindent 10 }} + {{- end }} + {{- with .Values.preflight.resources }} + resources: + {{- toYaml . | trim | nindent 12 }} + {{- end }} + terminationMessagePolicy: FallbackToLogsOnError + {{- with .Values.preflight.extraVolumes }} + volumes: + {{- toYaml . | trim | nindent 6 }} + {{- end }} + hostNetwork: true + restartPolicy: Always + priorityClassName: {{ include "cilium.priorityClass" (list $ .Values.preflight.priorityClassName "system-cluster-critical") }} + serviceAccount: {{ .Values.serviceAccounts.preflight.name | quote }} + serviceAccountName: {{ .Values.serviceAccounts.preflight.name | quote }} + automountServiceAccountToken: {{ .Values.serviceAccounts.preflight.automount }} + terminationGracePeriodSeconds: {{ .Values.preflight.terminationGracePeriodSeconds }} + {{- with .Values.preflight.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.preflight.nodeSelector }} + nodeSelector: + {{- toYaml . | trim | nindent 8 }} + {{- end }} + {{- with .Values.preflight.tolerations }} + tolerations: + {{- toYaml . | trim | nindent 8 }} + {{- end }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/cilium-preflight/poddisruptionbudget.yaml b/packages/system/cilium/charts/cilium/templates/cilium-preflight/poddisruptionbudget.yaml new file mode 100644 index 00000000..d939a9a2 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/cilium-preflight/poddisruptionbudget.yaml @@ -0,0 +1,24 @@ +{{- if and .Values.preflight.enabled .Values.preflight.validateCNPs .Values.preflight.podDisruptionBudget.enabled }} +{{- $component := .Values.preflight.podDisruptionBudget }} +apiVersion: {{ include "podDisruptionBudget.apiVersion" . }} +kind: PodDisruptionBudget +metadata: + name: cilium-pre-flight-check + namespace: {{ .Release.Namespace }} + labels: + k8s-app: cilium-pre-flight-check-deployment + app.kubernetes.io/part-of: cilium + app.kubernetes.io/name: cilium-pre-flight-check + kubernetes.io/cluster-service: "true" +spec: + {{- with $component.maxUnavailable }} + maxUnavailable: {{ . }} + {{- end }} + {{- with $component.minAvailable }} + minAvailable: {{ . }} + {{- end }} + selector: + matchLabels: + k8s-app: cilium-pre-flight-check-deployment + kubernetes.io/cluster-service: "true" +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/cilium-preflight/serviceaccount.yaml b/packages/system/cilium/charts/cilium/templates/cilium-preflight/serviceaccount.yaml new file mode 100644 index 00000000..a55aaa40 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/cilium-preflight/serviceaccount.yaml @@ -0,0 +1,11 @@ +{{- if and .Values.preflight.enabled .Values.serviceAccounts.preflight.create }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ .Values.serviceAccounts.preflight.name | quote }} + namespace: {{ .Release.Namespace }} + {{- if .Values.serviceAccounts.preflight.annotations }} + annotations: + {{ toYaml .Values.serviceAccounts.preflight.annotations | nindent 4 }} + {{- end }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/cilium-resource-quota.yaml b/packages/system/cilium/charts/cilium/templates/cilium-resource-quota.yaml new file mode 100644 index 00000000..a9856967 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/cilium-resource-quota.yaml @@ -0,0 +1,35 @@ +{{- if or .Values.resourceQuotas.enabled (and (ne .Release.Namespace "kube-system") .Values.gke.enabled) }} +{{- if .Values.agent }} +apiVersion: v1 +kind: ResourceQuota +metadata: + name: cilium-resource-quota + namespace: {{ .Release.Namespace }} +spec: + hard: + pods: {{ .Values.resourceQuotas.cilium.hard.pods | quote }} + scopeSelector: + matchExpressions: + - operator: In + scopeName: PriorityClass + values: + - system-node-critical +{{- end }} +{{- if .Values.operator.enabled }} +--- +apiVersion: v1 +kind: ResourceQuota +metadata: + name: cilium-operator-resource-quota + namespace: {{ .Release.Namespace }} +spec: + hard: + pods: {{ .Values.resourceQuotas.operator.hard.pods | quote }} + scopeSelector: + matchExpressions: + - operator: In + scopeName: PriorityClass + values: + - system-cluster-critical +{{- end }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/cilium-secrets-namespace.yaml b/packages/system/cilium/charts/cilium/templates/cilium-secrets-namespace.yaml new file mode 100644 index 00000000..6e1aa43d --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/cilium-secrets-namespace.yaml @@ -0,0 +1,32 @@ +{{- if and .Values.ingressController.enabled .Values.ingressController.secretsNamespace.create .Values.ingressController.secretsNamespace.name }} +--- +apiVersion: v1 +kind: Namespace +metadata: + name: {{ .Values.ingressController.secretsNamespace.name | quote }} +{{- end}} + +# Only create the namespace if it's different from Ingress secret namespace or Ingress is not enabled. +{{- if and .Values.gatewayAPI.enabled .Values.gatewayAPI.secretsNamespace.create .Values.gatewayAPI.secretsNamespace.name + (or (not (and .Values.ingressController.enabled .Values.ingressController.secretsNamespace.create .Values.ingressController.secretsNamespace.name)) + (ne .Values.gatewayAPI.secretsNamespace.name .Values.ingressController.secretsNamespace.name)) }} +--- +apiVersion: v1 +kind: Namespace +metadata: + name: {{ .Values.gatewayAPI.secretsNamespace.name | quote }} +{{- end}} + +# Only create the namespace if it's different from Ingress and Gateway API secret namespaces (if enabled). +{{- if and .Values.envoyConfig.enabled .Values.envoyConfig.secretsNamespace.create .Values.envoyConfig.secretsNamespace.name + (and + (or (not (and .Values.ingressController.enabled .Values.ingressController.secretsNamespace.create .Values.ingressController.secretsNamespace.name)) + (ne .Values.envoyConfig.secretsNamespace.name .Values.ingressController.secretsNamespace.name)) + (or (not (and .Values.gatewayAPI.enabled .Values.gatewayAPI.secretsNamespace.create .Values.gatewayAPI.secretsNamespace.name)) + (ne .Values.envoyConfig.secretsNamespace.name .Values.gatewayAPI.secretsNamespace.name))) }} +--- +apiVersion: v1 +kind: Namespace +metadata: + name: {{ .Values.envoyConfig.secretsNamespace.name | quote }} +{{- end}} diff --git a/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/_helpers.tpl b/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/_helpers.tpl new file mode 100644 index 00000000..19cce1f7 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/_helpers.tpl @@ -0,0 +1,11 @@ +{{- define "clustermesh-apiserver-generate-certs.admin-common-name" -}} +admin-{{ .Values.cluster.name }} +{{- end -}} + +{{- define "clustermesh-apiserver-generate-certs.remote-common-name" -}} +{{- if eq .Values.clustermesh.apiserver.tls.authMode "cluster" -}} +remote-{{ .Values.cluster.name }} +{{- else -}} +remote +{{- end -}} +{{- end -}} diff --git a/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/clusterrole.yaml b/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/clusterrole.yaml new file mode 100644 index 00000000..c00c8a51 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/clusterrole.yaml @@ -0,0 +1,68 @@ +{{- if and (or .Values.externalWorkloads.enabled .Values.clustermesh.useAPIServer) .Values.serviceAccounts.clustermeshApiserver.create }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: clustermesh-apiserver + labels: + app.kubernetes.io/part-of: cilium +rules: +- apiGroups: + - cilium.io + resources: + - ciliumnodes + - ciliumendpoints + - ciliumidentities + verbs: + - create +- apiGroups: + - cilium.io + resources: + - ciliumexternalworkloads/status + - ciliumnodes + - ciliumidentities + verbs: + - update +- apiGroups: + - cilium.io + resources: + - ciliumendpoints + - ciliumendpoints/status + verbs: + - patch +- apiGroups: + - cilium.io + resources: + - ciliumidentities + - ciliumexternalworkloads + - ciliumendpoints + - ciliumnodes + verbs: + - get + - list + - watch +- apiGroups: + - apiextensions.k8s.io + resources: + - customresourcedefinitions + verbs: + - list + - watch +- apiGroups: + - "" + resources: + - endpoints + - namespaces + - services + verbs: + - get + - list + - watch +- apiGroups: + - discovery.k8s.io + resources: + - endpointslices + verbs: + - get + - list + - watch +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/clusterrolebinding.yaml b/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/clusterrolebinding.yaml new file mode 100644 index 00000000..8ef03cb2 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/clusterrolebinding.yaml @@ -0,0 +1,16 @@ +{{- if and (or .Values.externalWorkloads.enabled .Values.clustermesh.useAPIServer) .Values.serviceAccounts.clustermeshApiserver.create }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: clustermesh-apiserver + labels: + app.kubernetes.io/part-of: cilium +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: clustermesh-apiserver +subjects: +- kind: ServiceAccount + name: {{ .Values.serviceAccounts.clustermeshApiserver.name | quote }} + namespace: {{ .Release.Namespace }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/deployment.yaml b/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/deployment.yaml new file mode 100644 index 00000000..7783a9e5 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/deployment.yaml @@ -0,0 +1,407 @@ +{{- if (or .Values.externalWorkloads.enabled .Values.clustermesh.useAPIServer) }} +{{- if not (list "legacy" "migration" "cluster" | has .Values.clustermesh.apiserver.tls.authMode) -}} +{{- fail ".Values.clustermesh.apiserver.tls.authMode must be one of legacy, migration, cluster" -}} +{{- end -}} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: clustermesh-apiserver + namespace: {{ .Release.Namespace }} + labels: + k8s-app: clustermesh-apiserver + app.kubernetes.io/part-of: cilium + app.kubernetes.io/name: clustermesh-apiserver +spec: + replicas: {{ .Values.clustermesh.apiserver.replicas }} + selector: + matchLabels: + k8s-app: clustermesh-apiserver + {{- with .Values.clustermesh.apiserver.updateStrategy }} + strategy: + {{- toYaml . | nindent 4 }} + {{- end }} + template: + metadata: + annotations: + {{- with .Values.clustermesh.apiserver.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + app.kubernetes.io/part-of: cilium + app.kubernetes.io/name: clustermesh-apiserver + k8s-app: clustermesh-apiserver + {{- with .Values.clustermesh.apiserver.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.clustermesh.apiserver.podSecurityContext }} + securityContext: + {{- toYaml . | nindent 8 }} + {{- end }} + initContainers: + - name: etcd-init + image: {{ include "cilium.image" .Values.clustermesh.apiserver.etcd.image | quote }} + imagePullPolicy: {{ .Values.clustermesh.apiserver.etcd.image.pullPolicy }} + command: ["/bin/sh", "-c"] + args: + - | + rm -rf /var/run/etcd/*; + /usr/local/bin/etcd --data-dir=/var/run/etcd --name=clustermesh-apiserver --listen-client-urls=http://127.0.0.1:2379 --advertise-client-urls=http://127.0.0.1:2379 --initial-cluster-token=clustermesh-apiserver --initial-cluster-state=new --auto-compaction-retention=1 & + + # The following key needs to be created before that the cilium agents + # have the possibility of connecting to etcd. + etcdctl put cilium/.has-cluster-config true + + etcdctl user add root --no-password; + etcdctl user grant-role root root; + etcdctl user add admin-{{ .Values.cluster.name }} --no-password; + etcdctl user grant-role admin-{{ .Values.cluster.name }} root; + etcdctl user add externalworkload --no-password; + etcdctl role add externalworkload; + etcdctl role grant-permission externalworkload --from-key read ''; + etcdctl role grant-permission externalworkload readwrite --prefix cilium/state/noderegister/v1/; + etcdctl role grant-permission externalworkload readwrite --prefix cilium/.initlock/; + etcdctl user grant-role externalworkload externalworkload; + etcdctl user add remote --no-password; + etcdctl role add remote; + etcdctl role grant-permission remote --from-key read ''; + etcdctl user grant-role remote remote; + etcdctl auth enable; + exit + env: + - name: ETCDCTL_API + value: "3" + - name: HOSTNAME_IP + valueFrom: + fieldRef: + fieldPath: status.podIP + volumeMounts: + - name: etcd-data-dir + mountPath: /var/run/etcd + {{- with .Values.clustermesh.apiserver.extraVolumeMounts }} + {{- toYaml . | nindent 8 }} + {{- end }} + terminationMessagePolicy: FallbackToLogsOnError + {{- with .Values.clustermesh.apiserver.etcd.init.resources }} + resources: + {{- toYaml . | nindent 10 }} + {{- end }} + containers: + - name: etcd + image: {{ include "cilium.image" .Values.clustermesh.apiserver.etcd.image | quote }} + imagePullPolicy: {{ .Values.clustermesh.apiserver.etcd.image.pullPolicy }} + command: + - /usr/local/bin/etcd + args: + - --data-dir=/var/run/etcd + - --name=clustermesh-apiserver + - --client-cert-auth + - --trusted-ca-file=/var/lib/etcd-secrets/ca.crt + - --cert-file=/var/lib/etcd-secrets/tls.crt + - --key-file=/var/lib/etcd-secrets/tls.key + # Surrounding the IPv4 address with brackets works in this case, since etcd + # uses net.SplitHostPort() internally and it accepts the that format. + - --listen-client-urls=https://127.0.0.1:2379,https://[$(HOSTNAME_IP)]:2379 + - --advertise-client-urls=https://[$(HOSTNAME_IP)]:2379 + - --initial-cluster-token=clustermesh-apiserver + - --auto-compaction-retention=1 + {{- if .Values.clustermesh.apiserver.metrics.etcd.enabled }} + - --listen-metrics-urls=http://[$(HOSTNAME_IP)]:{{ .Values.clustermesh.apiserver.metrics.etcd.port }} + - --metrics={{ .Values.clustermesh.apiserver.metrics.etcd.mode }} + {{- end }} + env: + - name: ETCDCTL_API + value: "3" + - name: HOSTNAME_IP + valueFrom: + fieldRef: + fieldPath: status.podIP + ports: + - name: etcd + containerPort: 2379 + protocol: TCP + {{- if .Values.clustermesh.apiserver.metrics.etcd.enabled }} + - name: etcd-metrics + containerPort: {{ .Values.clustermesh.apiserver.metrics.etcd.port }} + protocol: TCP + {{- end }} + volumeMounts: + - name: etcd-server-secrets + mountPath: /var/lib/etcd-secrets + readOnly: true + - name: etcd-data-dir + mountPath: /var/run/etcd + {{- with .Values.clustermesh.apiserver.extraVolumeMounts }} + {{- toYaml . | nindent 8 }} + {{- end }} + terminationMessagePolicy: FallbackToLogsOnError + {{- with .Values.clustermesh.apiserver.etcd.resources }} + resources: + {{- toYaml . | nindent 10 }} + {{- end }} + {{- with .Values.clustermesh.apiserver.etcd.securityContext }} + securityContext: + {{- toYaml . | nindent 10 }} + {{- end }} + - name: apiserver + image: {{ include "cilium.image" .Values.clustermesh.apiserver.image | quote }} + imagePullPolicy: {{ .Values.clustermesh.apiserver.image.pullPolicy }} + command: + - /usr/bin/clustermesh-apiserver + args: + {{- if .Values.debug.enabled }} + - --debug + {{- end }} + - --cluster-name=$(CLUSTER_NAME) + - --cluster-id=$(CLUSTER_ID) + - --kvstore-opt + - etcd.config=/var/lib/cilium/etcd-config.yaml + {{- if ne .Values.clustermesh.apiserver.tls.authMode "legacy" }} + - --cluster-users-enabled + - --cluster-users-config-path=/var/lib/cilium/etcd-config/users.yaml + {{- end }} + - --enable-external-workloads={{ .Values.externalWorkloads.enabled }} + {{- if .Values.clustermesh.apiserver.metrics.enabled }} + - --prometheus-serve-addr=:{{ .Values.clustermesh.apiserver.metrics.port }} + {{- end }} + {{- with .Values.clustermesh.apiserver.extraArgs }} + {{- toYaml . | trim | nindent 8 }} + {{- end }} + env: + - name: CLUSTER_NAME + valueFrom: + configMapKeyRef: + name: cilium-config + key: cluster-name + - name: CLUSTER_ID + valueFrom: + configMapKeyRef: + name: cilium-config + key: cluster-id + optional: true + - name: IDENTITY_ALLOCATION_MODE + valueFrom: + configMapKeyRef: + name: cilium-config + key: identity-allocation-mode + - name: ENABLE_K8S_ENDPOINT_SLICE + valueFrom: + configMapKeyRef: + name: cilium-config + key: enable-k8s-endpoint-slice + optional: true + {{- with .Values.clustermesh.apiserver.extraEnv }} + {{- toYaml . | trim | nindent 8 }} + {{- end }} + {{- if .Values.clustermesh.apiserver.metrics.enabled }} + ports: + - name: apiserv-metrics + containerPort: {{ .Values.clustermesh.apiserver.metrics.port }} + protocol: TCP + {{- end }} + {{- with .Values.clustermesh.apiserver.resources }} + resources: + {{- toYaml . | nindent 10 }} + {{- end }} + volumeMounts: + - name: etcd-admin-client + mountPath: /var/lib/cilium/etcd-secrets + readOnly: true + {{- if ne .Values.clustermesh.apiserver.tls.authMode "legacy" }} + - name: etcd-users-config + mountPath: /var/lib/cilium/etcd-config + readOnly: true + {{- end }} + {{- with .Values.clustermesh.apiserver.extraVolumeMounts }} + {{- toYaml . | nindent 8 }} + {{- end }} + terminationMessagePolicy: FallbackToLogsOnError + {{- with .Values.clustermesh.apiserver.securityContext }} + securityContext: + {{- toYaml . | nindent 10 }} + {{- end }} + {{- if .Values.clustermesh.apiserver.kvstoremesh.enabled }} + - name: kvstoremesh + image: {{ include "cilium.image" .Values.clustermesh.apiserver.kvstoremesh.image | quote }} + imagePullPolicy: {{ .Values.clustermesh.apiserver.kvstoremesh.image.pullPolicy }} + command: + - /usr/bin/kvstoremesh + args: + {{- if .Values.debug.enabled }} + - --debug + {{- end }} + - --cluster-name=$(CLUSTER_NAME) + - --cluster-id=$(CLUSTER_ID) + - --kvstore-opt=etcd.config=/var/lib/cilium/etcd-config.yaml + - --kvstore-opt=etcd.qps=100 + - --kvstore-opt=etcd.maxInflight=10 + - --clustermesh-config=/var/lib/cilium/clustermesh + {{- if .Values.clustermesh.apiserver.metrics.kvstoremesh.enabled }} + - --prometheus-serve-addr=:{{ .Values.clustermesh.apiserver.metrics.kvstoremesh.port }} + {{- end }} + {{- with .Values.clustermesh.apiserver.kvstoremesh.extraArgs }} + {{- toYaml . | trim | nindent 8 }} + {{- end }} + env: + - name: CLUSTER_NAME + valueFrom: + configMapKeyRef: + name: cilium-config + key: cluster-name + - name: CLUSTER_ID + valueFrom: + configMapKeyRef: + name: cilium-config + key: cluster-id + {{- with .Values.clustermesh.apiserver.kvstoremesh.extraEnv }} + {{- toYaml . | trim | nindent 8 }} + {{- end }} + {{- if .Values.clustermesh.apiserver.metrics.kvstoremesh.enabled }} + ports: + - name: kvmesh-metrics + containerPort: {{ .Values.clustermesh.apiserver.metrics.kvstoremesh.port }} + protocol: TCP + {{- end }} + {{- with .Values.clustermesh.apiserver.kvstoremesh.resources }} + resources: + {{- toYaml . | nindent 10 }} + {{- end }} + volumeMounts: + - name: etcd-admin-client + mountPath: /var/lib/cilium/etcd-secrets + readOnly: true + - name: kvstoremesh-secrets + mountPath: /var/lib/cilium/clustermesh + readOnly: true + {{- with .Values.clustermesh.apiserver.kvstoremesh.extraVolumeMounts }} + {{- toYaml . | nindent 8 }} + {{- end }} + terminationMessagePolicy: FallbackToLogsOnError + {{- with .Values.clustermesh.apiserver.kvstoremesh.securityContext }} + securityContext: + {{- toYaml . | nindent 10 }} + {{- end }} + {{- end }} + volumes: + - name: etcd-server-secrets + projected: + # note: the leading zero means this number is in octal representation: do not remove it + defaultMode: 0400 + sources: + - secret: + name: clustermesh-apiserver-server-cert + items: + - key: tls.crt + path: tls.crt + - key: tls.key + path: tls.key + {{- if not .Values.tls.caBundle.enabled }} + - key: ca.crt + path: ca.crt + {{- else }} + - {{ .Values.tls.caBundle.useSecret | ternary "secret" "configMap" }}: + name: {{ .Values.tls.caBundle.name }} + items: + - key: {{ .Values.tls.caBundle.key }} + path: ca.crt + {{- end }} + - name: etcd-admin-client + projected: + # note: the leading zero means this number is in octal representation: do not remove it + defaultMode: 0400 + sources: + - secret: + name: clustermesh-apiserver-admin-cert + items: + - key: tls.crt + path: tls.crt + - key: tls.key + path: tls.key + {{- if not .Values.tls.caBundle.enabled }} + - key: ca.crt + path: ca.crt + {{- else }} + - {{ .Values.tls.caBundle.useSecret | ternary "secret" "configMap" }}: + name: {{ .Values.tls.caBundle.name }} + items: + - key: {{ .Values.tls.caBundle.key }} + path: ca.crt + {{- end }} + {{- if ne .Values.clustermesh.apiserver.tls.authMode "legacy" }} + - name: etcd-users-config + configMap: + name: clustermesh-remote-users + # note: the leading zero means this number is in octal representation: do not remove it + defaultMode: 0400 + {{- end }} + - name: etcd-data-dir + emptyDir: {} + {{- if .Values.clustermesh.apiserver.kvstoremesh.enabled }} + - name: kvstoremesh-secrets + projected: + # note: the leading zero means this number is in octal representation: do not remove it + defaultMode: 0400 + sources: + - secret: + name: cilium-kvstoremesh + optional: true + # note: items are not explicitly listed here, since the entries of this secret + # depend on the peers configured, and that would cause a restart of this pod + # at every addition/removal. Leaving the field empty makes each secret entry + # to be automatically projected into the volume as a file whose name is the key. + - secret: + name: clustermesh-apiserver-remote-cert + optional: true + items: + - key: tls.key + path: common-etcd-client.key + - key: tls.crt + path: common-etcd-client.crt + - key: ca.crt + path: common-etcd-client-ca.crt + {{- end }} + {{- with .Values.clustermesh.apiserver.extraVolumes }} + {{- toYaml . | nindent 6 }} + {{- end }} + restartPolicy: Always + priorityClassName: {{ include "cilium.priorityClass" (list $ .Values.clustermesh.apiserver.priorityClassName "system-cluster-critical") }} + serviceAccount: {{ .Values.serviceAccounts.clustermeshApiserver.name | quote }} + serviceAccountName: {{ .Values.serviceAccounts.clustermeshApiserver.name | quote }} + automountServiceAccountToken: {{ .Values.serviceAccounts.clustermeshApiserver.automount }} + {{- with .Values.clustermesh.apiserver.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.clustermesh.apiserver.topologySpreadConstraints }} + topologySpreadConstraints: + {{- range $constraint := . }} + - {{ toYaml $constraint | nindent 8 | trim }} + {{- if not $constraint.labelSelector }} + labelSelector: + matchLabels: + k8s-app: clustermesh-apiserver + {{- end }} + {{- end }} + {{- end }} + {{- with .Values.clustermesh.apiserver.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.clustermesh.apiserver.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if and .Values.clustermesh.config.enabled .Values.clustermesh.apiserver.kvstoremesh.enabled }} + hostAliases: + {{- range $cluster := .Values.clustermesh.config.clusters }} + {{- range $ip := $cluster.ips }} + - ip: {{ $ip }} + hostnames: [ "{{ $cluster.name }}.{{ $.Values.clustermesh.config.domain }}" ] + {{- end }} + {{- end }} + {{- end }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/metrics-service.yaml b/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/metrics-service.yaml new file mode 100644 index 00000000..63b50ace --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/metrics-service.yaml @@ -0,0 +1,39 @@ +{{- $kvstoreMetricsEnabled := and .Values.clustermesh.apiserver.kvstoremesh.enabled .Values.clustermesh.apiserver.metrics.kvstoremesh.enabled -}} +{{- if and + (or .Values.externalWorkloads.enabled .Values.clustermesh.useAPIServer) + (or .Values.clustermesh.apiserver.metrics.enabled $kvstoreMetricsEnabled .Values.clustermesh.apiserver.metrics.etcd.enabled) }} +apiVersion: v1 +kind: Service +metadata: + name: clustermesh-apiserver-metrics + namespace: {{ .Release.Namespace }} + labels: + k8s-app: clustermesh-apiserver + app.kubernetes.io/part-of: cilium + app.kubernetes.io/name: clustermesh-apiserver + app.kubernetes.io/component: metrics +spec: + clusterIP: None + type: ClusterIP + ports: + {{- if .Values.clustermesh.apiserver.metrics.enabled }} + - name: apiserv-metrics + port: {{ .Values.clustermesh.apiserver.metrics.port }} + protocol: TCP + targetPort: apiserv-metrics + {{- end }} + {{- if $kvstoreMetricsEnabled }} + - name: kvmesh-metrics + port: {{ .Values.clustermesh.apiserver.metrics.kvstoremesh.port }} + protocol: TCP + targetPort: kvmesh-metrics + {{- end }} + {{- if .Values.clustermesh.apiserver.metrics.etcd.enabled }} + - name: etcd-metrics + port: {{ .Values.clustermesh.apiserver.metrics.etcd.port }} + protocol: TCP + targetPort: etcd-metrics + {{- end }} + selector: + k8s-app: clustermesh-apiserver +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/poddisruptionbudget.yaml b/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/poddisruptionbudget.yaml new file mode 100644 index 00000000..243e1b23 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/poddisruptionbudget.yaml @@ -0,0 +1,22 @@ +{{- if and (or .Values.externalWorkloads.enabled .Values.clustermesh.useAPIServer) .Values.clustermesh.apiserver.podDisruptionBudget.enabled }} +{{- $component := .Values.clustermesh.apiserver.podDisruptionBudget }} +apiVersion: {{ include "podDisruptionBudget.apiVersion" . }} +kind: PodDisruptionBudget +metadata: + name: clustermesh-apiserver + namespace: {{ .Release.Namespace }} + labels: + k8s-app: clustermesh-apiserver + app.kubernetes.io/part-of: cilium + app.kubernetes.io/name: clustermesh-apiserver +spec: + {{- with $component.maxUnavailable }} + maxUnavailable: {{ . }} + {{- end }} + {{- with $component.minAvailable }} + minAvailable: {{ . }} + {{- end }} + selector: + matchLabels: + k8s-app: clustermesh-apiserver +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/service.yaml b/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/service.yaml new file mode 100644 index 00000000..466841d9 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/service.yaml @@ -0,0 +1,33 @@ +{{- if (or .Values.externalWorkloads.enabled .Values.clustermesh.useAPIServer) }} +apiVersion: v1 +kind: Service +metadata: + name: clustermesh-apiserver + namespace: {{ .Release.Namespace }} + labels: + k8s-app: clustermesh-apiserver + app.kubernetes.io/part-of: cilium + app.kubernetes.io/name: clustermesh-apiserver + {{- with .Values.clustermesh.apiserver.service.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + type: {{ .Values.clustermesh.apiserver.service.type }} + selector: + k8s-app: clustermesh-apiserver + ports: + - port: 2379 + {{- if and (eq "NodePort" .Values.clustermesh.apiserver.service.type) .Values.clustermesh.apiserver.service.nodePort }} + nodePort: {{ .Values.clustermesh.apiserver.service.nodePort }} + {{- end }} + {{- if and (eq "LoadBalancer" .Values.clustermesh.apiserver.service.type) .Values.clustermesh.apiserver.service.loadBalancerIP }} + loadBalancerIP: {{ .Values.clustermesh.apiserver.service.loadBalancerIP }} + {{- end }} + {{- if .Values.clustermesh.apiserver.service.externalTrafficPolicy }} + externalTrafficPolicy: {{ .Values.clustermesh.apiserver.service.externalTrafficPolicy }} + {{- end }} + {{- if .Values.clustermesh.apiserver.service.internalTrafficPolicy }} + internalTrafficPolicy: {{ .Values.clustermesh.apiserver.service.internalTrafficPolicy }} + {{- end }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/serviceaccount.yaml b/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/serviceaccount.yaml new file mode 100644 index 00000000..b6153c39 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/serviceaccount.yaml @@ -0,0 +1,11 @@ +{{- if and (or .Values.externalWorkloads.enabled .Values.clustermesh.useAPIServer) .Values.serviceAccounts.clustermeshApiserver.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ .Values.serviceAccounts.clustermeshApiserver.name | quote }} + namespace: {{ .Release.Namespace }} + {{- with .Values.serviceAccounts.clustermeshApiserver.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/servicemonitor.yaml b/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/servicemonitor.yaml new file mode 100644 index 00000000..d5ba6420 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/servicemonitor.yaml @@ -0,0 +1,72 @@ +{{- $kvstoreMetricsEnabled := and .Values.clustermesh.apiserver.kvstoremesh.enabled .Values.clustermesh.apiserver.metrics.kvstoremesh.enabled -}} +{{- if and + (or .Values.externalWorkloads.enabled .Values.clustermesh.useAPIServer) + (or .Values.clustermesh.apiserver.metrics.enabled $kvstoreMetricsEnabled .Values.clustermesh.apiserver.metrics.etcd.enabled) + .Values.clustermesh.apiserver.metrics.serviceMonitor.enabled }} +--- +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: clustermesh-apiserver + namespace: {{ .Values.clustermesh.apiserver.metrics.serviceMonitor.namespace | default .Release.Namespace }} + labels: + app.kubernetes.io/part-of: cilium + {{- with .Values.clustermesh.apiserver.metrics.serviceMonitor.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + annotations: + {{- with .Values.clustermesh.apiserver.metrics.serviceMonitor.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + selector: + matchLabels: + app.kubernetes.io/name: clustermesh-apiserver + app.kubernetes.io/component: metrics + namespaceSelector: + matchNames: + - {{ .Release.Namespace }} + endpoints: + {{- if .Values.clustermesh.apiserver.metrics.enabled }} + - port: apiserv-metrics + interval: {{ .Values.clustermesh.apiserver.metrics.serviceMonitor.interval | quote }} + honorLabels: true + path: /metrics + {{- with .Values.clustermesh.apiserver.metrics.serviceMonitor.relabelings }} + relabelings: + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.clustermesh.apiserver.metrics.serviceMonitor.metricRelabelings }} + metricRelabelings: + {{- toYaml . | nindent 4 }} + {{- end }} + {{- end }} + {{- if $kvstoreMetricsEnabled }} + - port: kvmesh-metrics + interval: {{ .Values.clustermesh.apiserver.metrics.serviceMonitor.kvstoremesh.interval | quote }} + honorLabels: true + path: /metrics + {{- with .Values.clustermesh.apiserver.metrics.serviceMonitor.kvstoremesh.relabelings }} + relabelings: + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.clustermesh.apiserver.metrics.serviceMonitor.kvstoremesh.metricRelabelings }} + metricRelabelings: + {{- toYaml . | nindent 4 }} + {{- end }} + {{- end }} + {{- if .Values.clustermesh.apiserver.metrics.etcd.enabled }} + - port: etcd-metrics + interval: {{ .Values.clustermesh.apiserver.metrics.serviceMonitor.etcd.interval | quote }} + honorLabels: true + path: /metrics + {{- with .Values.clustermesh.apiserver.metrics.serviceMonitor.etcd.relabelings }} + relabelings: + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.clustermesh.apiserver.metrics.serviceMonitor.etcd.metricRelabelings }} + metricRelabelings: + {{- toYaml . | nindent 4 }} + {{- end }} + {{- end }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-certmanager/admin-secret.yaml b/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-certmanager/admin-secret.yaml new file mode 100644 index 00000000..3bc84ae1 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-certmanager/admin-secret.yaml @@ -0,0 +1,16 @@ +{{- if and (or .Values.externalWorkloads.enabled .Values.clustermesh.useAPIServer) .Values.clustermesh.apiserver.tls.auto.enabled (eq .Values.clustermesh.apiserver.tls.auto.method "certmanager") }} +--- +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: clustermesh-apiserver-admin-cert + namespace: {{ .Release.Namespace }} +spec: + issuerRef: + {{- toYaml .Values.clustermesh.apiserver.tls.auto.certManagerIssuerRef | nindent 4 }} + secretName: clustermesh-apiserver-admin-cert + commonName: {{ include "clustermesh-apiserver-generate-certs.admin-common-name" . }} + dnsNames: + - localhost + duration: {{ printf "%dh0m0s" (mul .Values.clustermesh.apiserver.tls.auto.certValidityDuration 24) }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-certmanager/client-secret.yaml b/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-certmanager/client-secret.yaml new file mode 100644 index 00000000..3c2cf643 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-certmanager/client-secret.yaml @@ -0,0 +1,14 @@ +{{- if and .Values.externalWorkloads.enabled .Values.clustermesh.apiserver.tls.auto.enabled (eq .Values.clustermesh.apiserver.tls.auto.method "certmanager") }} +--- +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: clustermesh-apiserver-client-cert + namespace: {{ .Release.Namespace }} +spec: + issuerRef: + {{- toYaml .Values.clustermesh.apiserver.tls.auto.certManagerIssuerRef | nindent 4 }} + secretName: clustermesh-apiserver-client-cert + commonName: externalworkload + duration: {{ printf "%dh0m0s" (mul .Values.clustermesh.apiserver.tls.auto.certValidityDuration 24) }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-certmanager/remote-secret.yaml b/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-certmanager/remote-secret.yaml new file mode 100644 index 00000000..0a5e42e2 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-certmanager/remote-secret.yaml @@ -0,0 +1,14 @@ +{{- if and .Values.clustermesh.useAPIServer .Values.clustermesh.apiserver.tls.auto.enabled (eq .Values.clustermesh.apiserver.tls.auto.method "certmanager") }} +--- +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: clustermesh-apiserver-remote-cert + namespace: {{ .Release.Namespace }} +spec: + issuerRef: + {{- toYaml .Values.clustermesh.apiserver.tls.auto.certManagerIssuerRef | nindent 4 }} + secretName: clustermesh-apiserver-remote-cert + commonName: {{ include "clustermesh-apiserver-generate-certs.remote-common-name" . }} + duration: {{ printf "%dh0m0s" (mul .Values.clustermesh.apiserver.tls.auto.certValidityDuration 24) }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-certmanager/server-secret.yaml b/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-certmanager/server-secret.yaml new file mode 100644 index 00000000..86fe56f5 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-certmanager/server-secret.yaml @@ -0,0 +1,27 @@ +{{- if and (or .Values.externalWorkloads.enabled .Values.clustermesh.useAPIServer) .Values.clustermesh.apiserver.tls.auto.enabled (eq .Values.clustermesh.apiserver.tls.auto.method "certmanager") }} +--- +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: clustermesh-apiserver-server-cert + namespace: {{ .Release.Namespace }} +spec: + issuerRef: + {{- toYaml .Values.clustermesh.apiserver.tls.auto.certManagerIssuerRef | nindent 4 }} + secretName: clustermesh-apiserver-server-cert + commonName: clustermesh-apiserver.cilium.io + dnsNames: + - clustermesh-apiserver.cilium.io + - "*.mesh.cilium.io" + - "clustermesh-apiserver.{{ .Release.Namespace }}.svc" + {{- range $dns := .Values.clustermesh.apiserver.tls.server.extraDnsNames }} + - {{ $dns | quote }} + {{- end }} + ipAddresses: + - "127.0.0.1" + - "::1" + {{- range $ip := .Values.clustermesh.apiserver.tls.server.extraIpAddresses }} + - {{ $ip | quote }} + {{- end }} + duration: {{ printf "%dh0m0s" (mul .Values.clustermesh.apiserver.tls.auto.certValidityDuration 24) }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-cronjob/_job-spec.tpl b/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-cronjob/_job-spec.tpl new file mode 100644 index 00000000..67503e33 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-cronjob/_job-spec.tpl @@ -0,0 +1,73 @@ +{{- define "clustermesh-apiserver-generate-certs.job.spec" }} +{{- $certValiditySecondsStr := printf "%ds" (mul .Values.clustermesh.apiserver.tls.auto.certValidityDuration 24 60 60) -}} +{{- $clustermeshServerSANs := concat (list "*.mesh.cilium.io" (printf "clustermesh-apiserver.%s.svc" .Release.Namespace)) + .Values.clustermesh.apiserver.tls.server.extraDnsNames + .Values.clustermesh.apiserver.tls.server.extraIpAddresses +-}} +spec: + template: + metadata: + labels: + k8s-app: clustermesh-apiserver-generate-certs + {{- with .Values.clustermesh.apiserver.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + containers: + - name: certgen + image: {{ include "cilium.image" .Values.certgen.image | quote }} + imagePullPolicy: {{ .Values.certgen.image.pullPolicy }} + command: + - "/usr/bin/cilium-certgen" + args: + - "--cilium-namespace={{ .Release.Namespace }}" + {{- if .Values.debug.enabled }} + - "--debug" + {{- end }} + - "--ca-generate" + - "--ca-reuse-secret" + {{- if .Values.clustermesh.apiserver.tls.ca.cert }} + - "--ca-secret-name=clustermesh-apiserver-ca-cert" + {{- else -}} + {{- if and .Values.tls.ca.cert .Values.tls.ca.key }} + - "--ca-secret-name=cilium-ca" + {{- end }} + {{- end }} + - "--clustermesh-apiserver-server-cert-generate" + - "--clustermesh-apiserver-server-cert-validity-duration={{ $certValiditySecondsStr }}" + - "--clustermesh-apiserver-server-cert-sans={{ join "," $clustermeshServerSANs }}" + - "--clustermesh-apiserver-admin-cert-generate" + - "--clustermesh-apiserver-admin-cert-validity-duration={{ $certValiditySecondsStr }}" + - "--clustermesh-apiserver-admin-cert-common-name={{ include "clustermesh-apiserver-generate-certs.admin-common-name" . }}" + {{- if .Values.externalWorkloads.enabled }} + - "--clustermesh-apiserver-client-cert-generate" + - "--clustermesh-apiserver-client-cert-validity-duration={{ $certValiditySecondsStr }}" + {{- end }} + {{- if .Values.clustermesh.useAPIServer }} + - "--clustermesh-apiserver-remote-cert-generate" + - "--clustermesh-apiserver-remote-cert-validity-duration={{ $certValiditySecondsStr }}" + - "--clustermesh-apiserver-remote-cert-common-name={{ include "clustermesh-apiserver-generate-certs.remote-common-name" . }}" + {{- end }} + {{- with .Values.certgen.extraVolumeMounts }} + volumeMounts: + {{- toYaml . | nindent 10 }} + {{- end }} + hostNetwork: true + {{- with .Values.certgen.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccount: {{ .Values.serviceAccounts.clustermeshcertgen.name | quote }} + serviceAccountName: {{ .Values.serviceAccounts.clustermeshcertgen.name | quote }} + automountServiceAccountToken: {{ .Values.serviceAccounts.clustermeshcertgen.automount }} + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + restartPolicy: OnFailure + {{- with .Values.certgen.extraVolumes }} + volumes: + {{- toYaml . | nindent 6 }} + {{- end }} + ttlSecondsAfterFinished: {{ .Values.certgen.ttlSecondsAfterFinished }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-cronjob/ca-secret.yaml b/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-cronjob/ca-secret.yaml new file mode 100644 index 00000000..6f499cd8 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-cronjob/ca-secret.yaml @@ -0,0 +1,15 @@ +{{- if and (or .Values.externalWorkloads.enabled .Values.clustermesh.useAPIServer) .Values.clustermesh.apiserver.tls.auto.enabled (eq .Values.clustermesh.apiserver.tls.auto.method "cronJob") }} +{{- $crt := .Values.clustermesh.apiserver.tls.ca.cert | default .Values.tls.ca.cert -}} +{{- $key := .Values.clustermesh.apiserver.tls.ca.key | default .Values.tls.ca.key -}} +{{- if and $crt $key }} +--- +apiVersion: v1 +kind: Secret +metadata: + name: clustermesh-apiserver-ca-cert + namespace: {{ .Release.Namespace }} +data: + ca.crt: {{ $crt }} + ca.key: {{ $key }} +{{- end }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-cronjob/cronjob.yaml b/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-cronjob/cronjob.yaml new file mode 100644 index 00000000..7711bc93 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-cronjob/cronjob.yaml @@ -0,0 +1,15 @@ +{{- if and (or .Values.externalWorkloads.enabled .Values.clustermesh.useAPIServer) .Values.clustermesh.apiserver.tls.auto.enabled (eq .Values.clustermesh.apiserver.tls.auto.method "cronJob") .Values.clustermesh.apiserver.tls.auto.schedule }} +apiVersion: {{ include "cronjob.apiVersion" . }} +kind: CronJob +metadata: + name: clustermesh-apiserver-generate-certs + namespace: {{ .Release.Namespace }} + labels: + k8s-app: clustermesh-apiserver-generate-certs + app.kubernetes.io/part-of: cilium +spec: + schedule: {{ .Values.clustermesh.apiserver.tls.auto.schedule | quote }} + concurrencyPolicy: Forbid + jobTemplate: +{{- include "clustermesh-apiserver-generate-certs.job.spec" . | nindent 4 }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-cronjob/job.yaml b/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-cronjob/job.yaml new file mode 100644 index 00000000..06235f29 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-cronjob/job.yaml @@ -0,0 +1,17 @@ +{{- if and (or .Values.externalWorkloads.enabled .Values.clustermesh.useAPIServer) .Values.clustermesh.apiserver.tls.auto.enabled (eq .Values.clustermesh.apiserver.tls.auto.method "cronJob") }} +--- +apiVersion: batch/v1 +kind: Job +metadata: + name: clustermesh-apiserver-generate-certs + namespace: {{ .Release.Namespace }} + labels: + k8s-app: clustermesh-apiserver-generate-certs + app.kubernetes.io/part-of: cilium + annotations: + "helm.sh/hook": post-install,post-upgrade + {{- with .Values.certgen.annotations.job }} + {{- toYaml . | nindent 4 }} + {{- end }} +{{ include "clustermesh-apiserver-generate-certs.job.spec" . }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-cronjob/role.yaml b/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-cronjob/role.yaml new file mode 100644 index 00000000..0d0565a6 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-cronjob/role.yaml @@ -0,0 +1,37 @@ +{{- if and (or .Values.externalWorkloads.enabled .Values.clustermesh.useAPIServer) .Values.clustermesh.apiserver.tls.auto.enabled (eq .Values.clustermesh.apiserver.tls.auto.method "cronJob") .Values.serviceAccounts.clustermeshcertgen.create }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: clustermesh-apiserver-generate-certs + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/part-of: cilium +rules: + - apiGroups: + - "" + resources: + - secrets + verbs: + - create + - apiGroups: + - "" + resources: + - secrets + resourceNames: + - cilium-ca + - clustermesh-apiserver-ca-cert + verbs: + - get + - update + - apiGroups: + - "" + resources: + - secrets + resourceNames: + - clustermesh-apiserver-server-cert + - clustermesh-apiserver-admin-cert + - clustermesh-apiserver-remote-cert + - clustermesh-apiserver-client-cert + verbs: + - update +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-cronjob/rolebinding.yaml b/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-cronjob/rolebinding.yaml new file mode 100644 index 00000000..22fc3ed7 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-cronjob/rolebinding.yaml @@ -0,0 +1,17 @@ +{{- if and (or .Values.externalWorkloads.enabled .Values.clustermesh.useAPIServer) .Values.clustermesh.apiserver.tls.auto.enabled (eq .Values.clustermesh.apiserver.tls.auto.method "cronJob") .Values.serviceAccounts.clustermeshcertgen.create }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: clustermesh-apiserver-generate-certs + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/part-of: cilium +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: clustermesh-apiserver-generate-certs +subjects: +- kind: ServiceAccount + name: {{ .Values.serviceAccounts.clustermeshcertgen.name | quote }} + namespace: {{ .Release.Namespace }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-cronjob/serviceaccount.yaml b/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-cronjob/serviceaccount.yaml new file mode 100644 index 00000000..a6f79a66 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-cronjob/serviceaccount.yaml @@ -0,0 +1,11 @@ +{{- if and (or .Values.externalWorkloads.enabled .Values.clustermesh.useAPIServer) .Values.clustermesh.apiserver.tls.auto.enabled (eq .Values.clustermesh.apiserver.tls.auto.method "cronJob") .Values.serviceAccounts.clustermeshcertgen.create }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ .Values.serviceAccounts.clustermeshcertgen.name | quote }} + namespace: {{ .Release.Namespace }} + {{- with .Values.serviceAccounts.clustermeshcertgen.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-helm/_helpers.tpl b/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-helm/_helpers.tpl new file mode 100644 index 00000000..576160f9 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-helm/_helpers.tpl @@ -0,0 +1,37 @@ +{{/* +Generate TLS certificates for ClusterMesh. + +Note: Always use this template as follows: + + {{- $_ := include "clustermesh-apiserver-generate-certs.helm.setup-ca" . -}} + +The assignment to `$_` is required because we store the generated CI in a global `cmca` variable. +Please, don't try to "simplify" this, as without this trick, every generated +certificate would be signed by a different CA. +*/}} +{{- define "clustermesh-apiserver-generate-certs.helm.setup-ca" }} + {{- if not .cmca }} + {{- $ca := "" -}} + {{- $crt := .Values.clustermesh.apiserver.tls.ca.cert | default .Values.tls.ca.cert -}} + {{- $key := .Values.clustermesh.apiserver.tls.ca.key | default .Values.tls.ca.key -}} + {{- if and $crt $key }} + {{- $ca = buildCustomCert $crt $key -}} + {{- else }} + {{- with lookup "v1" "Secret" .Release.Namespace "clustermesh-apiserver-ca-cert" }} + {{- $crt := index .data "ca.crt" }} + {{- $key := index .data "ca.key" }} + {{- $ca = buildCustomCert $crt $key -}} + {{- else }} + {{- $_ := include "cilium.ca.setup" . -}} + {{- with lookup "v1" "Secret" .Release.Namespace .commonCASecretName }} + {{- $crt := index .data "ca.crt" }} + {{- $key := index .data "ca.key" }} + {{- $ca = buildCustomCert $crt $key -}} + {{- else }} + {{- $ca = .commonCA -}} + {{- end }} + {{- end }} + {{- end }} + {{- $_ := set . "cmca" $ca -}} + {{- end }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-helm/admin-secret.yaml b/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-helm/admin-secret.yaml new file mode 100644 index 00000000..dfa1d987 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-helm/admin-secret.yaml @@ -0,0 +1,17 @@ +{{- if and (or .Values.externalWorkloads.enabled .Values.clustermesh.useAPIServer) .Values.clustermesh.apiserver.tls.auto.enabled (eq .Values.clustermesh.apiserver.tls.auto.method "helm") }} +{{- $_ := include "clustermesh-apiserver-generate-certs.helm.setup-ca" . -}} +{{- $cn := include "clustermesh-apiserver-generate-certs.admin-common-name" . -}} +{{- $dns := list "localhost" }} +{{- $cert := genSignedCert $cn nil $dns (.Values.clustermesh.apiserver.tls.auto.certValidityDuration | int) .cmca -}} +--- +apiVersion: v1 +kind: Secret +metadata: + name: clustermesh-apiserver-admin-cert + namespace: {{ .Release.Namespace }} +type: kubernetes.io/tls +data: + ca.crt: {{ .cmca.Cert | b64enc }} + tls.crt: {{ $cert.Cert | b64enc }} + tls.key: {{ $cert.Key | b64enc }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-helm/ca-secret.yaml b/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-helm/ca-secret.yaml new file mode 100644 index 00000000..832c6bb5 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-helm/ca-secret.yaml @@ -0,0 +1,12 @@ +{{- if and (or .Values.externalWorkloads.enabled .Values.clustermesh.useAPIServer) .Values.clustermesh.apiserver.tls.auto.enabled (eq .Values.clustermesh.apiserver.tls.auto.method "helm") }} +{{- $_ := include "clustermesh-apiserver-generate-certs.helm.setup-ca" . -}} +--- +apiVersion: v1 +kind: Secret +metadata: + name: clustermesh-apiserver-ca-cert + namespace: {{ .Release.Namespace }} +data: + ca.crt: {{ .cmca.Cert | b64enc }} + ca.key: {{ .cmca.Key | b64enc }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-helm/client-secret.yaml b/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-helm/client-secret.yaml new file mode 100644 index 00000000..fd943340 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-helm/client-secret.yaml @@ -0,0 +1,16 @@ +{{- if and .Values.externalWorkloads.enabled .Values.clustermesh.apiserver.tls.auto.enabled (eq .Values.clustermesh.apiserver.tls.auto.method "helm") }} +{{- $_ := include "clustermesh-apiserver-generate-certs.helm.setup-ca" . -}} +{{- $cn := "externalworkload" }} +{{- $cert := genSignedCert $cn nil nil (.Values.clustermesh.apiserver.tls.auto.certValidityDuration | int) .cmca -}} +--- +apiVersion: v1 +kind: Secret +metadata: + name: clustermesh-apiserver-client-cert + namespace: {{ .Release.Namespace }} +type: kubernetes.io/tls +data: + ca.crt: {{ .cmca.Cert | b64enc }} + tls.crt: {{ $cert.Cert | b64enc }} + tls.key: {{ $cert.Key | b64enc }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-helm/remote-secret.yaml b/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-helm/remote-secret.yaml new file mode 100644 index 00000000..4a68c747 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-helm/remote-secret.yaml @@ -0,0 +1,16 @@ +{{- if and .Values.clustermesh.useAPIServer .Values.clustermesh.apiserver.tls.auto.enabled (eq .Values.clustermesh.apiserver.tls.auto.method "helm") }} +{{- $_ := include "clustermesh-apiserver-generate-certs.helm.setup-ca" . -}} +{{- $cn := include "clustermesh-apiserver-generate-certs.remote-common-name" . -}} +{{- $cert := genSignedCert $cn nil nil (.Values.clustermesh.apiserver.tls.auto.certValidityDuration | int) .cmca -}} +--- +apiVersion: v1 +kind: Secret +metadata: + name: clustermesh-apiserver-remote-cert + namespace: {{ .Release.Namespace }} +type: kubernetes.io/tls +data: + ca.crt: {{ .cmca.Cert | b64enc }} + tls.crt: {{ $cert.Cert | b64enc }} + tls.key: {{ $cert.Key | b64enc }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-helm/server-secret.yaml b/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-helm/server-secret.yaml new file mode 100644 index 00000000..beacb063 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-helm/server-secret.yaml @@ -0,0 +1,18 @@ +{{- if and (or .Values.externalWorkloads.enabled .Values.clustermesh.useAPIServer) .Values.clustermesh.apiserver.tls.auto.enabled (eq .Values.clustermesh.apiserver.tls.auto.method "helm") }} +{{- $_ := include "clustermesh-apiserver-generate-certs.helm.setup-ca" . -}} +{{- $cn := "clustermesh-apiserver.cilium.io" }} +{{- $ip := concat (list "127.0.0.1" "::1") .Values.clustermesh.apiserver.tls.server.extraIpAddresses }} +{{- $dns := concat (list $cn "*.mesh.cilium.io" (printf "clustermesh-apiserver.%s.svc" .Release.Namespace)) .Values.clustermesh.apiserver.tls.server.extraDnsNames }} +{{- $cert := genSignedCert $cn $ip $dns (.Values.clustermesh.apiserver.tls.auto.certValidityDuration | int) .cmca -}} +--- +apiVersion: v1 +kind: Secret +metadata: + name: clustermesh-apiserver-server-cert + namespace: {{ .Release.Namespace }} +type: kubernetes.io/tls +data: + ca.crt: {{ .cmca.Cert | b64enc }} + tls.crt: {{ $cert.Cert | b64enc }} + tls.key: {{ $cert.Key | b64enc }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-provided/admin-secret.yaml b/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-provided/admin-secret.yaml new file mode 100644 index 00000000..4ff56ab2 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-provided/admin-secret.yaml @@ -0,0 +1,12 @@ +{{- if and (or .Values.externalWorkloads.enabled .Values.clustermesh.useAPIServer) (not .Values.clustermesh.apiserver.tls.auto.enabled) }} +apiVersion: v1 +kind: Secret +metadata: + name: clustermesh-apiserver-admin-cert + namespace: {{ .Release.Namespace }} +type: kubernetes.io/tls +data: + ca.crt: {{ .Values.clustermesh.apiserver.tls.ca.cert | default .Values.tls.ca.cert }} + tls.crt: {{ .Values.clustermesh.apiserver.tls.admin.cert | required "missing clustermesh.apiserver.tls.admin.cert" }} + tls.key: {{ .Values.clustermesh.apiserver.tls.admin.key | required "missing clustermesh.apiserver.tls.admin.key" }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-provided/ca-secret.yaml b/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-provided/ca-secret.yaml new file mode 100644 index 00000000..9b29a541 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-provided/ca-secret.yaml @@ -0,0 +1,12 @@ +{{- if and (or .Values.externalWorkloads.enabled .Values.clustermesh.useAPIServer) (not .Values.clustermesh.apiserver.tls.auto.enabled) }} +apiVersion: v1 +kind: Secret +metadata: + name: clustermesh-apiserver-ca-cert + namespace: {{ .Release.Namespace }} +data: + ca.crt: {{ .Values.clustermesh.apiserver.tls.ca.cert | default .Values.tls.ca.cert }} + {{- if .Values.clustermesh.apiserver.tls.ca.key | default .Values.tls.ca.key }} + ca.key: {{ .Values.clustermesh.apiserver.tls.ca.key | default .Values.tls.ca.key }} + {{- end }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-provided/client-secret.yaml b/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-provided/client-secret.yaml new file mode 100644 index 00000000..02a180ff --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-provided/client-secret.yaml @@ -0,0 +1,12 @@ +{{- if and .Values.externalWorkloads.enabled (not .Values.clustermesh.apiserver.tls.auto.enabled) }} +apiVersion: v1 +kind: Secret +metadata: + name: clustermesh-apiserver-client-cert + namespace: {{ .Release.Namespace }} +type: kubernetes.io/tls +data: + ca.crt: {{ .Values.clustermesh.apiserver.tls.ca.cert | default .Values.tls.ca.cert }} + tls.crt: {{ .Values.clustermesh.apiserver.tls.client.cert | required "missing clustermesh.apiserver.tls.client.cert" }} + tls.key: {{ .Values.clustermesh.apiserver.tls.client.key | required "missing clustermesh.apiserver.tls.client.key" }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-provided/remote-secret.yaml b/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-provided/remote-secret.yaml new file mode 100644 index 00000000..7850b332 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-provided/remote-secret.yaml @@ -0,0 +1,12 @@ +{{- if and .Values.clustermesh.useAPIServer (not .Values.clustermesh.apiserver.tls.auto.enabled) }} +apiVersion: v1 +kind: Secret +metadata: + name: clustermesh-apiserver-remote-cert + namespace: {{ .Release.Namespace }} +type: kubernetes.io/tls +data: + ca.crt: {{ .Values.clustermesh.apiserver.tls.ca.cert | default .Values.tls.ca.cert }} + tls.crt: {{ .Values.clustermesh.apiserver.tls.remote.cert | required "missing clustermesh.apiserver.tls.remote.cert" }} + tls.key: {{ .Values.clustermesh.apiserver.tls.remote.key | required "missing clustermesh.apiserver.tls.remote.key" }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-provided/server-secret.yaml b/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-provided/server-secret.yaml new file mode 100644 index 00000000..bb160d62 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-provided/server-secret.yaml @@ -0,0 +1,12 @@ +{{- if and (or .Values.externalWorkloads.enabled .Values.clustermesh.useAPIServer) (not .Values.clustermesh.apiserver.tls.auto.enabled) }} +apiVersion: v1 +kind: Secret +metadata: + name: clustermesh-apiserver-server-cert + namespace: {{ .Release.Namespace }} +type: kubernetes.io/tls +data: + ca.crt: {{ .Values.clustermesh.apiserver.tls.ca.cert | default .Values.tls.ca.cert }} + tls.crt: {{ .Values.clustermesh.apiserver.tls.server.cert | required "missing clustermesh.apiserver.tls.server.cert" }} + tls.key: {{ .Values.clustermesh.apiserver.tls.server.key | required "missing clustermesh.apiserver.tls.server.key" }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/users-configmap.yaml b/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/users-configmap.yaml new file mode 100644 index 00000000..7c278978 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/users-configmap.yaml @@ -0,0 +1,21 @@ +{{- if ne .Values.clustermesh.apiserver.tls.authMode "legacy" }} +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: clustermesh-remote-users + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/part-of: cilium +data: + users.yaml: | + users: + {{- if .Values.clustermesh.apiserver.kvstoremesh.enabled }} + - name: remote-{{ .Values.cluster.name }} + role: remote + {{- end }} + {{- range .Values.clustermesh.config.clusters }} + - name: remote-{{ .name }} + role: remote + {{- end }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/clustermesh-config/_helpers.tpl b/packages/system/cilium/charts/cilium/templates/clustermesh-config/_helpers.tpl new file mode 100644 index 00000000..f492275f --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/clustermesh-config/_helpers.tpl @@ -0,0 +1,25 @@ +{{- define "clustermesh-config-generate-etcd-cfg" }} +{{- $cluster := index . 0 -}} +{{- $domain := index . 1 -}} +{{- $hasCustomCACert := index . 2 -}} +{{- $override := index . 3 -}} +{{- /* The parenthesis around $cluster.tls are required, since it can be null: https://stackoverflow.com/a/68807258 */}} +{{- $prefix := ternary "common-" (printf "%s." $cluster.name) (or (ne $override "") (empty ($cluster.tls).cert) (empty ($cluster.tls).key)) -}} + +endpoints: +{{- if ne $override "" }} +- {{ $override }} +{{- else if $cluster.ips }} +- https://{{ $cluster.name }}.{{ $domain }}:{{ $cluster.port }} +{{- else }} +- https://{{ $cluster.address | required "missing clustermesh.apiserver.config.clusters.address" }}:{{ $cluster.port }} +{{- end }} +{{- if $hasCustomCACert }} +{{- /* The custom CA configuration takes effect only if a custom certificate and key are also set */}} +trusted-ca-file: /var/lib/cilium/clustermesh/{{ $prefix }}etcd-client-ca.crt +{{- else }} +trusted-ca-file: /var/lib/cilium/clustermesh/common-etcd-client-ca.crt +{{- end }} +key-file: /var/lib/cilium/clustermesh/{{ $prefix }}etcd-client.key +cert-file: /var/lib/cilium/clustermesh/{{ $prefix }}etcd-client.crt +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/clustermesh-config/clustermesh-secret.yaml b/packages/system/cilium/charts/cilium/templates/clustermesh-config/clustermesh-secret.yaml new file mode 100644 index 00000000..36e23b4e --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/clustermesh-config/clustermesh-secret.yaml @@ -0,0 +1,22 @@ +{{- if and .Values.clustermesh.useAPIServer .Values.clustermesh.config.enabled }} +--- +apiVersion: v1 +kind: Secret +metadata: + name: cilium-clustermesh + namespace: {{ .Release.Namespace }} +data: + {{- $override := ternary (printf "https://clustermesh-apiserver.%s.svc:2379" .Release.Namespace) "" $.Values.clustermesh.apiserver.kvstoremesh.enabled }} + {{- range .Values.clustermesh.config.clusters }} + {{- $hasCustomCACert := or (.tls).caCert $.Values.clustermesh.apiserver.tls.ca.cert }} + {{ .name }}: {{ include "clustermesh-config-generate-etcd-cfg" (list . $.Values.clustermesh.config.domain $hasCustomCACert $override) | b64enc }} + {{- /* The parenthesis around .tls are required, since it can be null: https://stackoverflow.com/a/68807258 */}} + {{- if and (eq $override "") (.tls).cert (.tls).key }} + {{- if $hasCustomCACert }} + {{ .name }}.etcd-client-ca.crt: {{ .tls.caCert | default $.Values.clustermesh.apiserver.tls.ca.cert }} + {{- end }} + {{ .name }}.etcd-client.key: {{ .tls.key }} + {{ .name }}.etcd-client.crt: {{ .tls.cert }} + {{- end }} + {{- end }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/clustermesh-config/kvstoremesh-secret.yaml b/packages/system/cilium/charts/cilium/templates/clustermesh-config/kvstoremesh-secret.yaml new file mode 100644 index 00000000..f79c4ade --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/clustermesh-config/kvstoremesh-secret.yaml @@ -0,0 +1,21 @@ +{{- if and .Values.clustermesh.useAPIServer .Values.clustermesh.config.enabled .Values.clustermesh.apiserver.kvstoremesh.enabled }} +--- +apiVersion: v1 +kind: Secret +metadata: + name: cilium-kvstoremesh + namespace: {{ .Release.Namespace }} +data: + {{- range .Values.clustermesh.config.clusters }} + {{- $hasCustomCACert := or (.tls).caCert $.Values.clustermesh.apiserver.tls.ca.cert }} + {{ .name }}: {{ include "clustermesh-config-generate-etcd-cfg" (list . $.Values.clustermesh.config.domain $hasCustomCACert "") | b64enc }} + {{- /* The parenthesis around .tls are required, since it can be null: https://stackoverflow.com/a/68807258 */}} + {{- if and (.tls).cert (.tls).key }} + {{- if $hasCustomCACert }} + {{ .name }}.etcd-client-ca.crt: {{ .tls.caCert | default $.Values.clustermesh.apiserver.tls.ca.cert }} + {{- end }} + {{ .name }}.etcd-client.key: {{ .tls.key }} + {{ .name }}.etcd-client.crt: {{ .tls.cert }} + {{- end }} + {{- end }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/etcd-operator/cilium-etcd-operator-clusterrole.yaml b/packages/system/cilium/charts/cilium/templates/etcd-operator/cilium-etcd-operator-clusterrole.yaml new file mode 100644 index 00000000..2f0b6c22 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/etcd-operator/cilium-etcd-operator-clusterrole.yaml @@ -0,0 +1,75 @@ +{{- if .Values.etcd.managed }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: cilium-etcd-operator + labels: + app.kubernetes.io/part-of: cilium +rules: +- apiGroups: + - etcd.database.coreos.com + resources: + - etcdclusters + verbs: + - get + - delete + - create + - update +- apiGroups: + - apiextensions.k8s.io + resources: + - customresourcedefinitions + verbs: + - delete + - get + - create +- apiGroups: + - "" + resources: + - deployments + verbs: + - delete + - create + - get + - update +- apiGroups: + - "" + resources: + - pods + verbs: + - list + - get + - delete +- apiGroups: + - apps + resources: + - deployments + verbs: + - delete + - create + - get + - update +- apiGroups: + - "" + resources: + - componentstatuses + verbs: + - get +- apiGroups: + - extensions + resources: + - deployments + verbs: + - delete + - create + - get + - update +- apiGroups: + - "" + resources: + - secrets + verbs: + - get + - create + - delete +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/etcd-operator/cilium-etcd-operator-clusterrolebinding.yaml b/packages/system/cilium/charts/cilium/templates/etcd-operator/cilium-etcd-operator-clusterrolebinding.yaml new file mode 100644 index 00000000..e9578f7f --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/etcd-operator/cilium-etcd-operator-clusterrolebinding.yaml @@ -0,0 +1,16 @@ +{{- if and .Values.etcd.managed .Values.serviceAccounts.etcd.create }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: cilium-etcd-operator + labels: + app.kubernetes.io/part-of: cilium +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: cilium-etcd-operator +subjects: +- kind: ServiceAccount + name: {{ .Values.serviceAccounts.etcd.name | quote }} + namespace: {{ .Release.Namespace }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/etcd-operator/cilium-etcd-operator-deployment.yaml b/packages/system/cilium/charts/cilium/templates/etcd-operator/cilium-etcd-operator-deployment.yaml new file mode 100644 index 00000000..914087f6 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/etcd-operator/cilium-etcd-operator-deployment.yaml @@ -0,0 +1,124 @@ +{{- if .Values.etcd.managed }} +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + io.cilium/app: etcd-operator + name: cilium-etcd-operator + app.kubernetes.io/name: cilium-etcd-operator + app.kubernetes.io/part-of: cilium + name: cilium-etcd-operator + namespace: {{ .Release.Namespace }} +spec: + replicas: 1 + selector: + matchLabels: + io.cilium/app: etcd-operator + name: cilium-etcd-operator +{{- with .Values.etcd.updateStrategy }} + strategy: + {{- toYaml . | trim | nindent 4 }} +{{- end }} + template: + metadata: +{{- with .Values.etcd.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} +{{- end }} + labels: + io.cilium/app: etcd-operator + app.kubernetes.io/part-of: cilium + app.kubernetes.io/name: cilium-etcd-operator + name: cilium-etcd-operator +{{- with .Values.etcd.podLabels }} + {{- toYaml . | nindent 8 }} +{{- end }} + spec: +{{- if .Values.etcd.affinity }} + affinity: +{{ toYaml .Values.etcd.affinity | indent 8 }} +{{- end }} +{{- with .Values.etcd.topologySpreadConstraints }} + topologySpreadConstraints: + {{- range $constraint := . }} + - {{ toYaml $constraint | nindent 8 | trim }} + {{- if not $constraint.labelSelector }} + labelSelector: + matchLabels: + io.cilium/app: etcd-operator + name: cilium-etcd-operator + {{- end }} + {{- end }} +{{- end }} +{{- if .Values.imagePullSecrets }} + imagePullSecrets: + {{ toYaml .Values.imagePullSecrets | indent 8 }} +{{- end }} +{{- with .Values.etcd.podSecurityContext }} + securityContext: + {{- toYaml . | nindent 8 }} +{{- end }} + containers: + - args: +{{- with .Values.etcd.extraArgs }} + {{- toYaml . | trim | nindent 8 }} +{{- end }} + #- --etcd-node-selector=disktype=ssd,cputype=high + command: + - /usr/bin/cilium-etcd-operator + env: + - name: CILIUM_ETCD_OPERATOR_CLUSTER_DOMAIN + value: "{{ .Values.etcd.clusterDomain }}" + - name: CILIUM_ETCD_OPERATOR_ETCD_CLUSTER_SIZE + value: "{{ .Values.etcd.clusterSize }}" + - name: CILIUM_ETCD_OPERATOR_NAMESPACE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + - name: CILIUM_ETCD_OPERATOR_POD_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name + - name: CILIUM_ETCD_OPERATOR_POD_UID + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.uid + - name: CILIUM_ETCD_META_ETCD_AUTO_COMPACTION_MODE + value: "revision" + - name: CILIUM_ETCD_META_ETCD_AUTO_COMPACTION_RETENTION + value: "25000" + image: {{ include "cilium.image" .Values.etcd.image | quote }} + imagePullPolicy: {{ .Values.etcd.image.pullPolicy }} + name: cilium-etcd-operator + terminationMessagePolicy: FallbackToLogsOnError + {{- with .Values.etcd.securityContext }} + securityContext: + {{- toYaml . | trim | nindent 8 }} + {{- end }} + {{- with .Values.etcd.extraVolumeMounts }} + volumeMounts: + {{- toYaml . | nindent 8 }} + {{- end }} + dnsPolicy: ClusterFirst + hostNetwork: true + priorityClassName: {{ include "cilium.priorityClass" (list $ .Values.clustermesh.apiserver.priorityClassName "system-cluster-critical") }} + restartPolicy: Always + serviceAccount: {{ .Values.serviceAccounts.etcd.name | quote }} + serviceAccountName: {{ .Values.serviceAccounts.etcd.name | quote }} + automountServiceAccountToken: {{ .Values.serviceAccounts.etcd.automount }} +{{- with .Values.etcd.nodeSelector }} + nodeSelector: + {{- toYaml . | trim | nindent 8 }} +{{- end }} +{{- with .Values.etcd.tolerations }} + tolerations: + {{- toYaml . | trim | nindent 6 }} +{{- end }} + {{- with .Values.etcd.extraVolumes }} + volumes: + {{- toYaml . | nindent 6 }} + {{- end }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/etcd-operator/cilium-etcd-operator-serviceaccount.yaml b/packages/system/cilium/charts/cilium/templates/etcd-operator/cilium-etcd-operator-serviceaccount.yaml new file mode 100644 index 00000000..9bc0a3ea --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/etcd-operator/cilium-etcd-operator-serviceaccount.yaml @@ -0,0 +1,11 @@ +{{- if and .Values.etcd.managed .Values.serviceAccounts.etcd.create }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ .Values.serviceAccounts.etcd.name | quote }} + namespace: {{ .Release.Namespace }} + {{- if .Values.serviceAccounts.etcd.annotations }} + annotations: +{{ toYaml .Values.serviceAccounts.etcd.annotations | indent 4 }} + {{- end }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/etcd-operator/etcd-operator-clusterrole.yaml b/packages/system/cilium/charts/cilium/templates/etcd-operator/etcd-operator-clusterrole.yaml new file mode 100644 index 00000000..424498f6 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/etcd-operator/etcd-operator-clusterrole.yaml @@ -0,0 +1,56 @@ +{{- if .Values.etcd.managed }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: etcd-operator + labels: + app.kubernetes.io/part-of: cilium +rules: +- apiGroups: + - etcd.database.coreos.com + resources: + - etcdclusters + - etcdbackups + - etcdrestores + verbs: + - '*' +- apiGroups: + - apiextensions.k8s.io + resources: + - customresourcedefinitions + verbs: + - '*' +- apiGroups: + - "" + resources: + - pods + - services + - endpoints + - persistentvolumeclaims + - events + - deployments + verbs: + - '*' +- apiGroups: + - apps + resources: + - deployments + verbs: + - '*' +- apiGroups: + - extensions + resources: + - deployments + verbs: + - create + - get + - list + - patch + - update +- apiGroups: + - "" + resources: + - secrets + verbs: + - get +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/etcd-operator/etcd-operator-clusterrolebinding.yaml b/packages/system/cilium/charts/cilium/templates/etcd-operator/etcd-operator-clusterrolebinding.yaml new file mode 100644 index 00000000..a56624d0 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/etcd-operator/etcd-operator-clusterrolebinding.yaml @@ -0,0 +1,16 @@ +{{- if .Values.etcd.managed }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: etcd-operator + labels: + app.kubernetes.io/part-of: cilium +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: etcd-operator +subjects: +- kind: ServiceAccount + name: cilium-etcd-sa + namespace: {{ .Release.Namespace }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/etcd-operator/etcd-operator-serviceaccount.yaml b/packages/system/cilium/charts/cilium/templates/etcd-operator/etcd-operator-serviceaccount.yaml new file mode 100644 index 00000000..278d9842 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/etcd-operator/etcd-operator-serviceaccount.yaml @@ -0,0 +1,11 @@ +{{- if .Values.etcd.managed }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: cilium-etcd-sa + namespace: {{ .Release.Namespace }} + {{- if .Values.serviceAccounts.etcd.annotations }} + annotations: +{{ toYaml .Values.serviceAccounts.etcd.annotations | indent 4 }} + {{- end }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/etcd-operator/poddisruptionbudget.yaml b/packages/system/cilium/charts/cilium/templates/etcd-operator/poddisruptionbudget.yaml new file mode 100644 index 00000000..72e0b835 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/etcd-operator/poddisruptionbudget.yaml @@ -0,0 +1,24 @@ +{{- if and .Values.etcd.managed .Values.etcd.podDisruptionBudget.enabled }} +{{- $component := .Values.etcd.podDisruptionBudget }} +apiVersion: {{ include "podDisruptionBudget.apiVersion" . }} +kind: PodDisruptionBudget +metadata: + name: cilium-etcd-operator + namespace: {{ .Release.Namespace }} + labels: + io.cilium/app: etcd-operator + name: cilium-etcd-operator + app.kubernetes.io/name: cilium-etcd-operator + app.kubernetes.io/part-of: cilium +spec: + {{- with $component.maxUnavailable }} + maxUnavailable: {{ . }} + {{- end }} + {{- with $component.minAvailable }} + minAvailable: {{ . }} + {{- end }} + selector: + matchLabels: + io.cilium/app: etcd-operator + name: cilium-etcd-operator +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/hubble-relay/configmap.yaml b/packages/system/cilium/charts/cilium/templates/hubble-relay/configmap.yaml new file mode 100644 index 00000000..0f5a037d --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/hubble-relay/configmap.yaml @@ -0,0 +1,47 @@ +{{- if and .Values.hubble.enabled .Values.hubble.relay.enabled }} +{{- $peerSvcPort := .Values.hubble.peerService.servicePort -}} +{{- if not .Values.hubble.peerService.servicePort }} +{{- $peerSvcPort = (.Values.hubble.tls.enabled | ternary 443 80) -}} +{{- end }} +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: hubble-relay-config + namespace: {{ .Release.Namespace }} +data: + config.yaml: | + cluster-name: {{ .Values.cluster.name }} + peer-service: "hubble-peer.{{ .Release.Namespace }}.svc.{{ .Values.hubble.peerService.clusterDomain }}:{{ $peerSvcPort }}" + listen-address: {{ .Values.hubble.relay.listenHost }}:{{ .Values.hubble.relay.listenPort }} + gops: {{ .Values.hubble.relay.gops.enabled }} + gops-port: {{ .Values.hubble.relay.gops.port | quote }} + {{- if .Values.hubble.relay.pprof.enabled }} + pprof: {{ .Values.hubble.relay.pprof.enabled | quote }} + pprof-address: {{ .Values.hubble.relay.pprof.address | quote }} + pprof-port: {{ .Values.hubble.relay.pprof.port | quote }} + {{- end }} + {{- if .Values.hubble.relay.prometheus.enabled }} + metrics-listen-address: ":{{ .Values.hubble.relay.prometheus.port }}" + {{- end }} + dial-timeout: {{ .Values.hubble.relay.dialTimeout }} + retry-timeout: {{ .Values.hubble.relay.retryTimeout }} + sort-buffer-len-max: {{ .Values.hubble.relay.sortBufferLenMax }} + sort-buffer-drain-timeout: {{ .Values.hubble.relay.sortBufferDrainTimeout }} + {{- if .Values.hubble.tls.enabled }} + tls-hubble-client-cert-file: /var/lib/hubble-relay/tls/client.crt + tls-hubble-client-key-file: /var/lib/hubble-relay/tls/client.key + tls-hubble-server-ca-files: /var/lib/hubble-relay/tls/hubble-server-ca.crt + {{- else }} + disable-client-tls: true + {{- end }} + {{- if and .Values.hubble.tls.enabled .Values.hubble.relay.tls.server.enabled }} + tls-relay-server-cert-file: /var/lib/hubble-relay/tls/server.crt + tls-relay-server-key-file: /var/lib/hubble-relay/tls/server.key + {{- if .Values.hubble.relay.tls.server.mtls }} + tls-relay-client-ca-files: /var/lib/hubble-relay/tls/hubble-server-ca.crt + {{- end }} + {{- else }} + disable-server-tls: true + {{- end }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/hubble-relay/deployment.yaml b/packages/system/cilium/charts/cilium/templates/hubble-relay/deployment.yaml new file mode 100644 index 00000000..c72d9af8 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/hubble-relay/deployment.yaml @@ -0,0 +1,168 @@ +{{- if and .Values.hubble.enabled .Values.hubble.relay.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: hubble-relay + namespace: {{ .Release.Namespace }} + labels: + k8s-app: hubble-relay + app.kubernetes.io/name: hubble-relay + app.kubernetes.io/part-of: cilium +spec: + replicas: {{ .Values.hubble.relay.replicas }} + selector: + matchLabels: + k8s-app: hubble-relay + {{- with .Values.hubble.relay.updateStrategy }} + strategy: + {{- toYaml . | trim | nindent 4 }} + {{- end }} + template: + metadata: + annotations: + {{- if .Values.hubble.relay.rollOutPods }} + # ensure pods roll when configmap updates + cilium.io/hubble-relay-configmap-checksum: {{ include (print $.Template.BasePath "/hubble-relay/configmap.yaml") . | sha256sum | quote }} + {{- end }} + {{- with .Values.hubble.relay.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + k8s-app: hubble-relay + app.kubernetes.io/name: hubble-relay + app.kubernetes.io/part-of: cilium + {{- with .Values.hubble.relay.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.hubble.relay.podSecurityContext }} + securityContext: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: hubble-relay + {{- with .Values.hubble.relay.securityContext }} + securityContext: + {{- toYaml . | nindent 12 }} + {{- end }} + image: {{ include "cilium.image" .Values.hubble.relay.image | quote }} + imagePullPolicy: {{ .Values.hubble.relay.image.pullPolicy }} + command: + - hubble-relay + args: + - serve + {{- if .Values.debug.enabled }} + - --debug + {{- end }} + ports: + - name: grpc + containerPort: {{ .Values.hubble.relay.listenPort }} + {{- if .Values.hubble.relay.prometheus.enabled }} + - name: prometheus + containerPort: {{ .Values.hubble.relay.prometheus.port }} + protocol: TCP + {{- end }} + readinessProbe: + tcpSocket: + port: grpc + livenessProbe: + tcpSocket: + port: grpc + {{- with .Values.hubble.relay.extraEnv }} + env: + {{- toYaml . | trim | nindent 12 }} + {{- end }} + {{- with .Values.hubble.relay.resources }} + resources: + {{- toYaml . | trim | nindent 12 }} + {{- end }} + volumeMounts: + - name: config + mountPath: /etc/hubble-relay + readOnly: true + {{- if .Values.hubble.tls.enabled }} + - name: tls + mountPath: /var/lib/hubble-relay/tls + readOnly: true + {{- end }} + {{- with .Values.hubble.relay.extraVolumeMounts }} + {{- toYaml . | nindent 10 }} + {{- end }} + terminationMessagePolicy: FallbackToLogsOnError + restartPolicy: Always + priorityClassName: {{ .Values.hubble.relay.priorityClassName }} + serviceAccount: {{ .Values.serviceAccounts.relay.name | quote }} + serviceAccountName: {{ .Values.serviceAccounts.relay.name | quote }} + automountServiceAccountToken: {{ .Values.serviceAccounts.relay.automount }} + terminationGracePeriodSeconds: {{ .Values.hubble.relay.terminationGracePeriodSeconds }} + {{- with .Values.hubble.relay.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.hubble.relay.topologySpreadConstraints }} + topologySpreadConstraints: + {{- range $constraint := . }} + - {{ toYaml $constraint | nindent 8 | trim }} + {{- if not $constraint.labelSelector }} + labelSelector: + matchLabels: + k8s-app: hubble-relay + {{- end }} + {{- end }} + {{- end }} + {{- with .Values.hubble.relay.nodeSelector }} + nodeSelector: + {{- toYaml . | trim | nindent 8 }} + {{- end }} + {{- with .Values.hubble.relay.tolerations }} + tolerations: + {{- toYaml . | trim | nindent 8 }} + {{- end }} + volumes: + - name: config + configMap: + name: hubble-relay-config + items: + - key: config.yaml + path: config.yaml + {{- if .Values.hubble.tls.enabled }} + - name: tls + projected: + # note: the leading zero means this number is in octal representation: do not remove it + defaultMode: 0400 + sources: + - secret: + name: hubble-relay-client-certs + items: + - key: tls.crt + path: client.crt + - key: tls.key + path: client.key + {{- if not .Values.tls.caBundle.enabled }} + - key: ca.crt + path: hubble-server-ca.crt + {{- else }} + - {{ .Values.tls.caBundle.useSecret | ternary "secret" "configMap" }}: + name: {{ .Values.tls.caBundle.name }} + items: + - key: {{ .Values.tls.caBundle.key }} + path: hubble-server-ca.crt + {{- end }} + {{- if .Values.hubble.relay.tls.server.enabled }} + - secret: + name: hubble-relay-server-certs + items: + - key: tls.crt + path: server.crt + - key: tls.key + path: server.key + {{- end }} + {{- end }} + {{- with .Values.hubble.relay.extraVolumes }} + {{- toYaml . | nindent 6 }} + {{- end }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/hubble-relay/metrics-service.yaml b/packages/system/cilium/charts/cilium/templates/hubble-relay/metrics-service.yaml new file mode 100644 index 00000000..5b7c99c9 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/hubble-relay/metrics-service.yaml @@ -0,0 +1,20 @@ +{{- if and .Values.hubble.enabled .Values.hubble.relay.enabled .Values.hubble.relay.prometheus.enabled }} +# We use a separate service from hubble-relay which can be exposed externally +kind: Service +apiVersion: v1 +metadata: + name: hubble-relay-metrics + namespace: {{ .Release.Namespace }} + labels: + k8s-app: hubble-relay +spec: + clusterIP: None + type: ClusterIP + selector: + k8s-app: hubble-relay + ports: + - name: metrics + port: {{ .Values.hubble.relay.prometheus.port }} + protocol: TCP + targetPort: prometheus +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/hubble-relay/poddisruptionbudget.yaml b/packages/system/cilium/charts/cilium/templates/hubble-relay/poddisruptionbudget.yaml new file mode 100644 index 00000000..8a90916a --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/hubble-relay/poddisruptionbudget.yaml @@ -0,0 +1,22 @@ +{{- if and .Values.hubble.enabled .Values.hubble.relay.enabled .Values.hubble.relay.podDisruptionBudget.enabled }} +{{- $component := .Values.hubble.relay.podDisruptionBudget }} +apiVersion: {{ include "podDisruptionBudget.apiVersion" . }} +kind: PodDisruptionBudget +metadata: + name: hubble-relay + namespace: {{ .Release.Namespace }} + labels: + k8s-app: hubble-relay + app.kubernetes.io/name: hubble-relay + app.kubernetes.io/part-of: cilium +spec: + {{- with $component.maxUnavailable }} + maxUnavailable: {{ . }} + {{- end }} + {{- with $component.minAvailable }} + minAvailable: {{ . }} + {{- end }} + selector: + matchLabels: + k8s-app: hubble-relay +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/hubble-relay/service.yaml b/packages/system/cilium/charts/cilium/templates/hubble-relay/service.yaml new file mode 100644 index 00000000..d995c419 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/hubble-relay/service.yaml @@ -0,0 +1,26 @@ +{{- if and .Values.hubble.enabled .Values.hubble.relay.enabled }} +kind: Service +apiVersion: v1 +metadata: + name: hubble-relay + namespace: {{ .Release.Namespace }} + labels: + k8s-app: hubble-relay + app.kubernetes.io/name: hubble-relay + app.kubernetes.io/part-of: cilium +spec: + type: {{ .Values.hubble.relay.service.type | quote }} + selector: + k8s-app: hubble-relay + ports: + - protocol: TCP + {{- if .Values.hubble.relay.servicePort }} + port: {{ .Values.hubble.relay.servicePort }} + {{- else }} + port: {{ .Values.hubble.relay.tls.server.enabled | ternary 443 80 }} + {{- end }} + targetPort: {{ .Values.hubble.relay.listenPort }} + {{- if and (eq "NodePort" .Values.hubble.relay.service.type) .Values.hubble.relay.service.nodePort }} + nodePort: {{ .Values.hubble.relay.service.nodePort }} + {{- end }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/hubble-relay/serviceaccount.yaml b/packages/system/cilium/charts/cilium/templates/hubble-relay/serviceaccount.yaml new file mode 100644 index 00000000..f42bd1b0 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/hubble-relay/serviceaccount.yaml @@ -0,0 +1,11 @@ +{{- if and .Values.hubble.enabled .Values.hubble.relay.enabled .Values.serviceAccounts.relay.create }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ .Values.serviceAccounts.relay.name | quote }} + namespace: {{ .Release.Namespace }} + {{- with .Values.serviceAccounts.relay.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/hubble-relay/servicemonitor.yaml b/packages/system/cilium/charts/cilium/templates/hubble-relay/servicemonitor.yaml new file mode 100644 index 00000000..0b9f1622 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/hubble-relay/servicemonitor.yaml @@ -0,0 +1,34 @@ +{{- if and .Values.hubble.enabled .Values.hubble.relay.enabled .Values.hubble.relay.prometheus.enabled .Values.hubble.relay.prometheus.serviceMonitor.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: hubble-relay + namespace: {{ .Values.hubble.relay.prometheus.serviceMonitor.namespace | default .Release.Namespace }} + labels: + {{- with .Values.hubble.relay.prometheus.serviceMonitor.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + annotations: + {{- with .Values.hubble.relay.prometheus.serviceMonitor.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + selector: + matchLabels: + k8s-app: hubble-relay + namespaceSelector: + matchNames: + - {{ .Release.Namespace }} + endpoints: + - port: metrics + interval: {{ .Values.hubble.relay.prometheus.serviceMonitor.interval | quote }} + path: /metrics + {{- with .Values.hubble.relay.prometheus.serviceMonitor.relabelings }} + relabelings: + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.hubble.relay.prometheus.serviceMonitor.metricRelabelings }} + metricRelabelings: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/hubble-ui/_nginx.tpl b/packages/system/cilium/charts/cilium/templates/hubble-ui/_nginx.tpl new file mode 100644 index 00000000..3b409207 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/hubble-ui/_nginx.tpl @@ -0,0 +1,54 @@ +{{- define "hubble-ui.nginx.conf" }} +server { + listen 8081; +{{- if .Values.hubble.ui.frontend.server.ipv6.enabled }} + listen [::]:8081; +{{- end }} + server_name localhost; + root /app; + index index.html; + client_max_body_size 1G; + + location / { + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + + # CORS + add_header Access-Control-Allow-Methods "GET, POST, PUT, HEAD, DELETE, OPTIONS"; + add_header Access-Control-Allow-Origin *; + add_header Access-Control-Max-Age 1728000; + add_header Access-Control-Expose-Headers content-length,grpc-status,grpc-message; + add_header Access-Control-Allow-Headers range,keep-alive,user-agent,cache-control,content-type,content-transfer-encoding,x-accept-content-transfer-encoding,x-accept-response-streaming,x-user-agent,x-grpc-web,grpc-timeout; + if ($request_method = OPTIONS) { + return 204; + } + # /CORS + + location {{ .Values.hubble.ui.baseUrl }}api { + {{- if not (eq .Values.hubble.ui.baseUrl "/") }} + rewrite ^{{ (trimSuffix "/" .Values.hubble.ui.baseUrl) }}(/.*)$ $1 break; + {{- end }} + proxy_http_version 1.1; + proxy_pass_request_headers on; + proxy_hide_header Access-Control-Allow-Origin; + {{- if eq .Values.hubble.ui.baseUrl "/" }} + proxy_pass http://127.0.0.1:8090; + {{- else }} + proxy_pass http://127.0.0.1:8090/; + {{- end }} + } + + {{- if not (eq .Values.hubble.ui.baseUrl "/") }} + sub_filter_once on; + sub_filter '' ''; + {{- end }} + location {{ .Values.hubble.ui.baseUrl }} { + {{- if not (eq .Values.hubble.ui.baseUrl "/") }} + rewrite ^{{ (trimSuffix "/" .Values.hubble.ui.baseUrl) }}(/.*)$ $1 break; + {{- end }} + # double `/index.html` is required here + try_files $uri $uri/ /index.html /index.html; + } + } +} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/hubble-ui/clusterrole.yaml b/packages/system/cilium/charts/cilium/templates/hubble-ui/clusterrole.yaml new file mode 100644 index 00000000..c3fa7809 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/hubble-ui/clusterrole.yaml @@ -0,0 +1,46 @@ +{{- if and (or .Values.hubble.enabled .Values.hubble.ui.standalone.enabled) .Values.hubble.ui.enabled .Values.serviceAccounts.ui.create }} +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: hubble-ui + labels: + app.kubernetes.io/part-of: cilium +rules: +- apiGroups: + - networking.k8s.io + resources: + - networkpolicies + verbs: + - get + - list + - watch +- apiGroups: + - "" + resources: + - componentstatuses + - endpoints + - namespaces + - nodes + - pods + - services + verbs: + - get + - list + - watch +- apiGroups: + - apiextensions.k8s.io + resources: + - customresourcedefinitions + verbs: + - get + - list + - watch +- apiGroups: + - cilium.io + resources: + - "*" + verbs: + - get + - list + - watch +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/hubble-ui/clusterrolebinding.yaml b/packages/system/cilium/charts/cilium/templates/hubble-ui/clusterrolebinding.yaml new file mode 100644 index 00000000..16c688df --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/hubble-ui/clusterrolebinding.yaml @@ -0,0 +1,16 @@ +{{- if and (or .Values.hubble.enabled .Values.hubble.ui.standalone.enabled) .Values.hubble.ui.enabled .Values.serviceAccounts.ui.create }} +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: hubble-ui + labels: + app.kubernetes.io/part-of: cilium +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: hubble-ui +subjects: +- kind: ServiceAccount + name: {{ .Values.serviceAccounts.ui.name | quote }} + namespace: {{ .Release.Namespace }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/hubble-ui/configmap.yaml b/packages/system/cilium/charts/cilium/templates/hubble-ui/configmap.yaml new file mode 100644 index 00000000..bbab253d --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/hubble-ui/configmap.yaml @@ -0,0 +1,10 @@ +{{- if and (or .Values.hubble.enabled .Values.hubble.ui.standalone.enabled) .Values.hubble.ui.enabled }} +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: hubble-ui-nginx + namespace: {{ .Release.Namespace }} +data: + nginx.conf: {{ include "hubble-ui.nginx.conf" . | trim | quote }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/hubble-ui/deployment.yaml b/packages/system/cilium/charts/cilium/templates/hubble-ui/deployment.yaml new file mode 100644 index 00000000..9dfbcdb5 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/hubble-ui/deployment.yaml @@ -0,0 +1,192 @@ +{{- if and (or .Values.hubble.enabled .Values.hubble.ui.standalone.enabled) .Values.hubble.ui.enabled }} +kind: Deployment +apiVersion: apps/v1 +metadata: + name: hubble-ui + namespace: {{ .Release.Namespace }} + labels: + k8s-app: hubble-ui + app.kubernetes.io/name: hubble-ui + app.kubernetes.io/part-of: cilium +spec: + replicas: {{ .Values.hubble.ui.replicas }} + selector: + matchLabels: + k8s-app: hubble-ui + {{- with .Values.hubble.ui.updateStrategy }} + strategy: + {{- toYaml . | trim | nindent 4 }} + {{- end }} + template: + metadata: + annotations: + {{- if .Values.hubble.ui.rollOutPods }} + # ensure pods roll when configmap updates + cilium.io/hubble-ui-nginx-configmap-checksum: {{ include (print $.Template.BasePath "/hubble-ui/configmap.yaml") . | sha256sum | quote }} + {{- end }} + {{- with .Values.hubble.ui.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + k8s-app: hubble-ui + app.kubernetes.io/name: hubble-ui + app.kubernetes.io/part-of: cilium + {{- with .Values.hubble.ui.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.hubble.ui.securityContext }} + {{- if .enabled }} + securityContext: + {{- omit . "enabled" | toYaml | nindent 8 }} + {{- end}} + {{- end }} + priorityClassName: {{ .Values.hubble.ui.priorityClassName }} + serviceAccount: {{ .Values.serviceAccounts.ui.name | quote }} + serviceAccountName: {{ .Values.serviceAccounts.ui.name | quote }} + automountServiceAccountToken: {{ .Values.serviceAccounts.ui.automount }} + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: frontend + image: {{ include "cilium.image" .Values.hubble.ui.frontend.image | quote }} + imagePullPolicy: {{ .Values.hubble.ui.frontend.image.pullPolicy }} + ports: + - name: http + containerPort: 8081 + {{- with .Values.hubble.ui.frontend.extraEnv }} + env: + {{- toYaml . | trim | nindent 12 }} + {{- end }} + {{- with .Values.hubble.ui.frontend.resources }} + resources: + {{- toYaml . | trim | nindent 10 }} + {{- end }} + volumeMounts: + - name: hubble-ui-nginx-conf + mountPath: /etc/nginx/conf.d/default.conf + subPath: nginx.conf + - name: tmp-dir + mountPath: /tmp + {{- with .Values.hubble.ui.frontend.extraVolumeMounts }} + {{- toYaml . | nindent 8 }} + {{- end }} + terminationMessagePolicy: FallbackToLogsOnError + {{- with .Values.hubble.ui.frontend.securityContext }} + securityContext: + {{- toYaml . | trim | nindent 10 }} + {{- end }} + - name: backend + image: {{ include "cilium.image" .Values.hubble.ui.backend.image | quote }} + imagePullPolicy: {{ .Values.hubble.ui.backend.image.pullPolicy }} + env: + - name: EVENTS_SERVER_PORT + value: "8090" + {{- if .Values.hubble.relay.tls.server.enabled }} + - name: FLOWS_API_ADDR + value: "hubble-relay:443" + - name: TLS_TO_RELAY_ENABLED + value: "true" + - name: TLS_RELAY_SERVER_NAME + value: ui.hubble-relay.cilium.io + - name: TLS_RELAY_CA_CERT_FILES + value: /var/lib/hubble-ui/certs/hubble-relay-ca.crt + - name: TLS_RELAY_CLIENT_CERT_FILE + value: /var/lib/hubble-ui/certs/client.crt + - name: TLS_RELAY_CLIENT_KEY_FILE + value: /var/lib/hubble-ui/certs/client.key + {{- else }} + - name: FLOWS_API_ADDR + value: "hubble-relay:80" + {{- end }} + {{- with .Values.hubble.ui.backend.extraEnv }} + {{- toYaml . | trim | nindent 8 }} + {{- end }} + ports: + - name: grpc + containerPort: 8090 + {{- with .Values.hubble.ui.backend.resources }} + resources: + {{- toYaml . | trim | nindent 10 }} + {{- end }} + volumeMounts: + {{- if .Values.hubble.relay.tls.server.enabled }} + - name: hubble-ui-client-certs + mountPath: /var/lib/hubble-ui/certs + readOnly: true + {{- end }} + {{- with .Values.hubble.ui.backend.extraVolumeMounts }} + {{- toYaml . | nindent 8 }} + {{- end }} + terminationMessagePolicy: FallbackToLogsOnError + {{- with .Values.hubble.ui.backend.securityContext }} + securityContext: + {{- toYaml . | trim | nindent 10 }} + {{- end }} + {{- with .Values.hubble.ui.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.hubble.ui.topologySpreadConstraints }} + topologySpreadConstraints: + {{- range $constraint := . }} + - {{ toYaml $constraint | nindent 8 | trim }} + {{- if not $constraint.labelSelector }} + labelSelector: + matchLabels: + k8s-app: hubble-ui + {{- end }} + {{- end }} + {{- end }} + {{- with .Values.hubble.ui.nodeSelector }} + nodeSelector: + {{- toYaml . | trim | nindent 8 }} + {{- end }} + {{- with .Values.hubble.ui.tolerations }} + tolerations: + {{- toYaml . | trim | nindent 8 }} + {{- end }} + volumes: + - configMap: + defaultMode: 420 + name: hubble-ui-nginx + name: hubble-ui-nginx-conf + - emptyDir: {} + name: tmp-dir + {{- if .Values.hubble.relay.tls.server.enabled }} + - name: hubble-ui-client-certs + {{- if .Values.hubble.ui.standalone.enabled }} + {{- toYaml .Values.hubble.ui.standalone.tls.certsVolume | nindent 8 }} + {{- else }} + projected: + # note: the leading zero means this number is in octal representation: do not remove it + defaultMode: 0400 + sources: + - secret: + name: hubble-ui-client-certs + items: + - key: tls.crt + path: client.crt + - key: tls.key + path: client.key + {{- if not .Values.tls.caBundle.enabled }} + - key: ca.crt + path: hubble-relay-ca.crt + {{- else }} + - {{ .Values.tls.caBundle.useSecret | ternary "secret" "configMap" }}: + name: {{ .Values.tls.caBundle.name }} + items: + - key: {{ .Values.tls.caBundle.key }} + path: hubble-relay-ca.crt + {{- end }} + {{- end }} + {{- end }} + {{- with .Values.hubble.ui.frontend.extraVolumes }} + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.hubble.ui.backend.extraVolumes }} + {{- toYaml . | nindent 6 }} + {{- end }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/hubble-ui/ingress.yaml b/packages/system/cilium/charts/cilium/templates/hubble-ui/ingress.yaml new file mode 100644 index 00000000..b48e2cb4 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/hubble-ui/ingress.yaml @@ -0,0 +1,35 @@ +{{- if and (or .Values.hubble.enabled .Values.hubble.ui.standalone.enabled) .Values.hubble.ui.enabled .Values.hubble.ui.ingress.enabled }} +{{- $baseUrl := .Values.hubble.ui.baseUrl -}} +apiVersion: {{ template "ingress.apiVersion" . }} +kind: Ingress +metadata: + name: hubble-ui + namespace: {{ .Release.Namespace }} + labels: + k8s-app: hubble-ui + app.kubernetes.io/name: hubble-ui + app.kubernetes.io/part-of: cilium + {{- with .Values.hubble.ui.ingress.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.hubble.ui.ingress.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if .Values.hubble.ui.ingress.className }} + ingressClassName: {{ .Values.hubble.ui.ingress.className }} + {{- end }} + {{- if .Values.hubble.ui.ingress.tls }} + tls: + {{- toYaml .Values.hubble.ui.ingress.tls | nindent 4 }} + {{- end }} + rules: + {{- range .Values.hubble.ui.ingress.hosts }} + - host: {{ . }} + http: + paths: + - path: {{ $baseUrl | quote }} + {{- include "ingress.paths" $ | nindent 12 }} + {{- end }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/hubble-ui/poddisruptionbudget.yaml b/packages/system/cilium/charts/cilium/templates/hubble-ui/poddisruptionbudget.yaml new file mode 100644 index 00000000..3108a493 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/hubble-ui/poddisruptionbudget.yaml @@ -0,0 +1,22 @@ +{{- if and (or .Values.hubble.enabled .Values.hubble.ui.standalone.enabled) .Values.hubble.ui.enabled .Values.hubble.ui.podDisruptionBudget.enabled }} +{{- $component := .Values.hubble.ui.podDisruptionBudget }} +apiVersion: {{ include "podDisruptionBudget.apiVersion" . }} +kind: PodDisruptionBudget +metadata: + name: hubble-ui + namespace: {{ .Release.Namespace }} + labels: + k8s-app: hubble-ui + app.kubernetes.io/name: hubble-ui + app.kubernetes.io/part-of: cilium +spec: + {{- with $component.maxUnavailable }} + maxUnavailable: {{ . }} + {{- end }} + {{- with $component.minAvailable }} + minAvailable: {{ . }} + {{- end }} + selector: + matchLabels: + k8s-app: hubble-ui +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/hubble-ui/service.yaml b/packages/system/cilium/charts/cilium/templates/hubble-ui/service.yaml new file mode 100644 index 00000000..52eb6eec --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/hubble-ui/service.yaml @@ -0,0 +1,26 @@ +{{- if and (or .Values.hubble.enabled .Values.hubble.ui.standalone.enabled) .Values.hubble.ui.enabled }} +kind: Service +apiVersion: v1 +metadata: + name: hubble-ui + namespace: {{ .Release.Namespace }} + {{- if .Values.hubble.ui.service.annotations }} + annotations: + {{- toYaml .Values.hubble.ui.service.annotations | nindent 4 }} + {{- end }} + labels: + k8s-app: hubble-ui + app.kubernetes.io/name: hubble-ui + app.kubernetes.io/part-of: cilium +spec: + type: {{ .Values.hubble.ui.service.type | quote }} + selector: + k8s-app: hubble-ui + ports: + - name: http + port: 80 + targetPort: 8081 + {{- if and (eq "NodePort" .Values.hubble.ui.service.type) .Values.hubble.ui.service.nodePort }} + nodePort: {{ .Values.hubble.ui.service.nodePort }} + {{- end }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/hubble-ui/serviceaccount.yaml b/packages/system/cilium/charts/cilium/templates/hubble-ui/serviceaccount.yaml new file mode 100644 index 00000000..28f6061c --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/hubble-ui/serviceaccount.yaml @@ -0,0 +1,11 @@ +{{- if and (or .Values.hubble.enabled .Values.hubble.ui.standalone.enabled) .Values.hubble.ui.enabled .Values.serviceAccounts.ui.create }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ .Values.serviceAccounts.ui.name | quote }} + namespace: {{ .Release.Namespace }} + {{- with .Values.serviceAccounts.ui.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/hubble/dashboards-configmap.yaml b/packages/system/cilium/charts/cilium/templates/hubble/dashboards-configmap.yaml new file mode 100644 index 00000000..c8453560 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/hubble/dashboards-configmap.yaml @@ -0,0 +1,25 @@ +{{- if .Values.hubble.metrics.dashboards.enabled }} +{{- $files := .Files.Glob "files/hubble/dashboards/*.json" }} +{{- range $path, $fileContents := $files }} +{{- $dashboardName := regexReplaceAll "(^.*/)(.*)\\.json$" $path "${2}" }} +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ $dashboardName | trunc 63 | trimSuffix "-" }} + namespace: {{ $.Values.hubble.metrics.dashboards.namespace | default $.Release.Namespace }} + labels: + k8s-app: hubble + app.kubernetes.io/name: hubble + app.kubernetes.io/part-of: cilium + {{- if $.Values.hubble.metrics.dashboards.label }} + {{ $.Values.hubble.metrics.dashboards.label }}: {{ ternary $.Values.hubble.metrics.dashboards.labelValue "1" (not (empty $.Values.hubble.metrics.dashboards.labelValue)) | quote }} + {{- end }} + {{- with $.Values.hubble.metrics.dashboards.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +data: + {{ $dashboardName }}.json: {{ $.Files.Get $path | toJson }} +{{- end }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/hubble/metrics-service.yaml b/packages/system/cilium/charts/cilium/templates/hubble/metrics-service.yaml new file mode 100644 index 00000000..0c72c0de --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/hubble/metrics-service.yaml @@ -0,0 +1,29 @@ +{{- if and .Values.hubble.enabled .Values.hubble.metrics.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: hubble-metrics + namespace: {{ .Release.Namespace }} + labels: + k8s-app: hubble + app.kubernetes.io/name: hubble + app.kubernetes.io/part-of: cilium + annotations: + {{- with .Values.hubble.metrics.serviceAnnotations }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- if not .Values.hubble.metrics.serviceMonitor.enabled }} + prometheus.io/scrape: "true" + prometheus.io/port: {{ .Values.hubble.metrics.port | quote }} + {{- end }} +spec: + clusterIP: None + type: ClusterIP + ports: + - name: hubble-metrics + port: {{ .Values.hubble.metrics.port }} + protocol: TCP + targetPort: hubble-metrics + selector: + k8s-app: cilium +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/hubble/peer-service.yaml b/packages/system/cilium/charts/cilium/templates/hubble/peer-service.yaml new file mode 100644 index 00000000..f54fa6c6 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/hubble/peer-service.yaml @@ -0,0 +1,26 @@ +{{- if and .Values.agent .Values.hubble.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: hubble-peer + namespace: {{ .Release.Namespace }} + labels: + k8s-app: cilium + app.kubernetes.io/part-of: cilium + app.kubernetes.io/name: hubble-peer +spec: + selector: + k8s-app: cilium + ports: + - name: peer-service + {{- if .Values.hubble.peerService.servicePort }} + port: {{ .Values.hubble.peerService.servicePort }} + {{- else }} + port: {{ .Values.hubble.tls.enabled | ternary 443 80 }} + {{- end }} + protocol: TCP + targetPort: {{ .Values.hubble.peerService.targetPort }} +{{- if semverCompare ">=1.22-0" .Capabilities.KubeVersion.GitVersion }} + internalTrafficPolicy: Local +{{- end }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/hubble/servicemonitor.yaml b/packages/system/cilium/charts/cilium/templates/hubble/servicemonitor.yaml new file mode 100644 index 00000000..27304ee8 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/hubble/servicemonitor.yaml @@ -0,0 +1,36 @@ +{{- if and .Values.hubble.enabled .Values.hubble.metrics.enabled .Values.hubble.metrics.serviceMonitor.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: hubble + namespace: {{ .Values.prometheus.serviceMonitor.namespace | default .Release.Namespace }} + labels: + app.kubernetes.io/part-of: cilium + {{- with .Values.hubble.metrics.serviceMonitor.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + annotations: + {{- with .Values.hubble.metrics.serviceMonitor.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + selector: + matchLabels: + k8s-app: hubble + namespaceSelector: + matchNames: + - {{ .Release.Namespace }} + endpoints: + - port: hubble-metrics + interval: {{ .Values.hubble.metrics.serviceMonitor.interval | quote }} + honorLabels: true + path: /metrics + {{- with .Values.hubble.metrics.serviceMonitor.relabelings }} + relabelings: + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.hubble.metrics.serviceMonitor.metricRelabelings }} + metricRelabelings: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/hubble/tls-certmanager/relay-client-secret.yaml b/packages/system/cilium/charts/cilium/templates/hubble/tls-certmanager/relay-client-secret.yaml new file mode 100644 index 00000000..23bea64b --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/hubble/tls-certmanager/relay-client-secret.yaml @@ -0,0 +1,18 @@ +{{- if and .Values.hubble.enabled .Values.hubble.tls.enabled .Values.hubble.tls.auto.enabled (eq .Values.hubble.tls.auto.method "certmanager") .Values.hubble.relay.enabled }} +--- +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: hubble-relay-client-certs + namespace: {{ .Release.Namespace }} +spec: + issuerRef: + {{- toYaml .Values.hubble.tls.auto.certManagerIssuerRef | nindent 4 }} + secretName: hubble-relay-client-certs + commonName: "*.hubble-relay.cilium.io" + dnsNames: + - "*.hubble-relay.cilium.io" + duration: {{ printf "%dh0m0s" (mul .Values.hubble.tls.auto.certValidityDuration 24) }} + privateKey: + rotationPolicy: Always +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/hubble/tls-certmanager/relay-server-secret.yaml b/packages/system/cilium/charts/cilium/templates/hubble/tls-certmanager/relay-server-secret.yaml new file mode 100644 index 00000000..77f2800e --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/hubble/tls-certmanager/relay-server-secret.yaml @@ -0,0 +1,27 @@ +{{- if and .Values.hubble.enabled .Values.hubble.tls.enabled .Values.hubble.tls.auto.enabled (eq .Values.hubble.tls.auto.method "certmanager") .Values.hubble.relay.enabled .Values.hubble.relay.tls.server.enabled }} +--- +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: hubble-relay-server-certs + namespace: {{ .Release.Namespace }} +spec: + issuerRef: + {{- toYaml .Values.hubble.tls.auto.certManagerIssuerRef | nindent 4 }} + secretName: hubble-relay-server-certs + commonName: "*.hubble-relay.cilium.io" + dnsNames: + - "*.hubble-relay.cilium.io" + {{- range $dns := .Values.hubble.relay.tls.server.extraDnsNames }} + - {{ $dns | quote }} + {{- end }} + {{- if .Values.hubble.relay.tls.server.extraIpAddresses }} + ipAddresses: + {{- range $ip := .Values.hubble.relay.tls.server.extraIpAddresses }} + - {{ $ip | quote }} + {{- end }} + {{- end }} + duration: {{ printf "%dh0m0s" (mul .Values.hubble.tls.auto.certValidityDuration 24) }} + privateKey: + rotationPolicy: Always +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/hubble/tls-certmanager/server-secret.yaml b/packages/system/cilium/charts/cilium/templates/hubble/tls-certmanager/server-secret.yaml new file mode 100644 index 00000000..1ca815fb --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/hubble/tls-certmanager/server-secret.yaml @@ -0,0 +1,28 @@ +{{- if and .Values.hubble.enabled .Values.hubble.tls.enabled .Values.hubble.tls.auto.enabled (eq .Values.hubble.tls.auto.method "certmanager") }} +{{- $cn := list "*" (.Values.cluster.name | replace "." "-") "hubble-grpc.cilium.io" | join "." }} +--- +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: hubble-server-certs + namespace: {{ .Release.Namespace }} +spec: + issuerRef: + {{- toYaml .Values.hubble.tls.auto.certManagerIssuerRef | nindent 4 }} + secretName: hubble-server-certs + commonName: {{ $cn | quote }} + dnsNames: + - {{ $cn | quote }} + {{- range $dns := .Values.hubble.tls.server.extraDnsNames }} + - {{ $dns | quote }} + {{- end }} + {{- if .Values.hubble.tls.server.extraIpAddresses }} + ipAddresses: + {{- range $ip := .Values.hubble.tls.server.extraIpAddresses }} + - {{ $ip | quote }} + {{- end }} + {{- end }} + duration: {{ printf "%dh0m0s" (mul .Values.hubble.tls.auto.certValidityDuration 24) }} + privateKey: + rotationPolicy: Always +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/hubble/tls-certmanager/ui-client-certs.yaml b/packages/system/cilium/charts/cilium/templates/hubble/tls-certmanager/ui-client-certs.yaml new file mode 100644 index 00000000..88d59490 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/hubble/tls-certmanager/ui-client-certs.yaml @@ -0,0 +1,18 @@ +{{- if and .Values.hubble.enabled .Values.hubble.tls.enabled .Values.hubble.tls.auto.enabled (eq .Values.hubble.tls.auto.method "certmanager") .Values.hubble.ui.enabled .Values.hubble.relay.enabled .Values.hubble.relay.tls.server.enabled }} +--- +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: hubble-ui-client-certs + namespace: {{ .Release.Namespace }} +spec: + issuerRef: + {{- toYaml .Values.hubble.tls.auto.certManagerIssuerRef | nindent 4 }} + secretName: hubble-ui-client-certs + commonName: "*.hubble-ui.cilium.io" + dnsNames: + - "*.hubble-ui.cilium.io" + duration: {{ printf "%dh0m0s" (mul .Values.hubble.tls.auto.certValidityDuration 24) }} + privateKey: + rotationPolicy: Always +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/hubble/tls-cronjob/_job-spec.tpl b/packages/system/cilium/charts/cilium/templates/hubble/tls-cronjob/_job-spec.tpl new file mode 100644 index 00000000..f3d595b7 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/hubble/tls-cronjob/_job-spec.tpl @@ -0,0 +1,64 @@ +{{- define "hubble-generate-certs.job.spec" }} +{{- $certValiditySecondsStr := printf "%ds" (mul .Values.hubble.tls.auto.certValidityDuration 24 60 60) -}} +spec: + template: + metadata: + labels: + k8s-app: hubble-generate-certs + {{- with .Values.certgen.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + containers: + - name: certgen + image: {{ include "cilium.image" .Values.certgen.image | quote }} + imagePullPolicy: {{ .Values.certgen.image.pullPolicy }} + command: + - "/usr/bin/cilium-certgen" + # Because this is executed as a job, we pass the values as command + # line args instead of via config map. This allows users to inspect + # the values used in past runs by inspecting the completed pod. + args: + - "--cilium-namespace={{ .Release.Namespace }}" + {{- if .Values.debug.enabled }} + - "--debug" + {{- end }} + - "--ca-generate" + - "--ca-reuse-secret" + {{- if and .Values.tls.ca.cert .Values.tls.ca.key }} + - "--ca-secret-name=cilium-ca" + {{- end }} + - "--hubble-server-cert-generate" + - "--hubble-server-cert-common-name={{ list "*" (.Values.cluster.name | replace "." "-") "hubble-grpc.cilium.io" | join "." }}" + - "--hubble-server-cert-validity-duration={{ $certValiditySecondsStr }}" + {{- if .Values.hubble.relay.enabled }} + - "--hubble-relay-client-cert-generate" + - "--hubble-relay-client-cert-validity-duration={{ $certValiditySecondsStr }}" + {{- end }} + {{- if and .Values.hubble.relay.enabled .Values.hubble.relay.tls.server.enabled }} + - "--hubble-relay-server-cert-generate" + - "--hubble-relay-server-cert-validity-duration={{ $certValiditySecondsStr }}" + {{- end }} + {{- with .Values.certgen.extraVolumeMounts }} + volumeMounts: + {{- toYaml . | nindent 10 }} + {{- end }} + hostNetwork: true + {{- with .Values.certgen.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccount: {{ .Values.serviceAccounts.hubblecertgen.name | quote }} + serviceAccountName: {{ .Values.serviceAccounts.hubblecertgen.name | quote }} + automountServiceAccountToken: {{ .Values.serviceAccounts.hubblecertgen.automount }} + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + restartPolicy: OnFailure + {{- with .Values.certgen.extraVolumes }} + volumes: + {{- toYaml . | nindent 6 }} + {{- end }} + ttlSecondsAfterFinished: {{ .Values.certgen.ttlSecondsAfterFinished }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/hubble/tls-cronjob/clusterrole.yaml b/packages/system/cilium/charts/cilium/templates/hubble/tls-cronjob/clusterrole.yaml new file mode 100644 index 00000000..dc075670 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/hubble/tls-cronjob/clusterrole.yaml @@ -0,0 +1,34 @@ +{{- if and .Values.hubble.enabled .Values.hubble.tls.enabled .Values.hubble.tls.auto.enabled (eq .Values.hubble.tls.auto.method "cronJob") .Values.serviceAccounts.hubblecertgen.create }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: hubble-generate-certs + labels: + app.kubernetes.io/part-of: cilium +rules: + - apiGroups: + - "" + resources: + - secrets + verbs: + - create + - apiGroups: + - "" + resources: + - secrets + resourceNames: + - hubble-server-certs + - hubble-relay-client-certs + - hubble-relay-server-certs + verbs: + - update + - apiGroups: + - "" + resources: + - secrets + resourceNames: + - cilium-ca + verbs: + - get + - update +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/hubble/tls-cronjob/clusterrolebinding.yaml b/packages/system/cilium/charts/cilium/templates/hubble/tls-cronjob/clusterrolebinding.yaml new file mode 100644 index 00000000..ebe60279 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/hubble/tls-cronjob/clusterrolebinding.yaml @@ -0,0 +1,16 @@ +{{- if and .Values.hubble.enabled .Values.hubble.tls.enabled .Values.hubble.tls.auto.enabled (eq .Values.hubble.tls.auto.method "cronJob") .Values.serviceAccounts.hubblecertgen.create }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: hubble-generate-certs + labels: + app.kubernetes.io/part-of: cilium +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: hubble-generate-certs +subjects: +- kind: ServiceAccount + name: {{ .Values.serviceAccounts.hubblecertgen.name | quote }} + namespace: {{ .Release.Namespace }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/hubble/tls-cronjob/cronjob.yaml b/packages/system/cilium/charts/cilium/templates/hubble/tls-cronjob/cronjob.yaml new file mode 100644 index 00000000..5a5992cf --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/hubble/tls-cronjob/cronjob.yaml @@ -0,0 +1,20 @@ +{{- if and .Values.hubble.enabled .Values.hubble.tls.enabled .Values.hubble.tls.auto.enabled (eq .Values.hubble.tls.auto.method "cronJob") .Values.hubble.tls.auto.schedule }} +apiVersion: {{ include "cronjob.apiVersion" . }} +kind: CronJob +metadata: + name: hubble-generate-certs + namespace: {{ .Release.Namespace }} + labels: + k8s-app: hubble-generate-certs + app.kubernetes.io/name: hubble-generate-certs + app.kubernetes.io/part-of: cilium + annotations: + {{- with .Values.certgen.annotations.cronJob }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + schedule: {{ .Values.hubble.tls.auto.schedule | quote }} + concurrencyPolicy: Forbid + jobTemplate: + {{- include "hubble-generate-certs.job.spec" . | nindent 4 }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/hubble/tls-cronjob/job.yaml b/packages/system/cilium/charts/cilium/templates/hubble/tls-cronjob/job.yaml new file mode 100644 index 00000000..e748165a --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/hubble/tls-cronjob/job.yaml @@ -0,0 +1,18 @@ +{{- if and .Values.hubble.enabled .Values.hubble.tls.enabled .Values.hubble.tls.auto.enabled (eq .Values.hubble.tls.auto.method "cronJob") }} +--- +apiVersion: batch/v1 +kind: Job +metadata: + name: hubble-generate-certs + namespace: {{ .Release.Namespace }} + labels: + k8s-app: hubble-generate-certs + app.kubernetes.io/name: hubble-generate-certs + app.kubernetes.io/part-of: cilium + annotations: + "helm.sh/hook": post-install,post-upgrade + {{- with .Values.certgen.annotations.job }} + {{- toYaml . | nindent 4 }} + {{- end }} +{{ include "hubble-generate-certs.job.spec" . }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/hubble/tls-cronjob/serviceaccount.yaml b/packages/system/cilium/charts/cilium/templates/hubble/tls-cronjob/serviceaccount.yaml new file mode 100644 index 00000000..d538d67d --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/hubble/tls-cronjob/serviceaccount.yaml @@ -0,0 +1,11 @@ +{{- if and .Values.hubble.enabled .Values.hubble.tls.enabled .Values.hubble.tls.auto.enabled (eq .Values.hubble.tls.auto.method "cronJob") .Values.serviceAccounts.hubblecertgen.create }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ .Values.serviceAccounts.hubblecertgen.name | quote }} + namespace: {{ .Release.Namespace }} + {{- with .Values.serviceAccounts.hubblecertgen.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/hubble/tls-helm/_helpers.tpl b/packages/system/cilium/charts/cilium/templates/hubble/tls-helm/_helpers.tpl new file mode 100644 index 00000000..79babf94 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/hubble/tls-helm/_helpers.tpl @@ -0,0 +1,31 @@ +{{/* +Generate TLS certificates for Hubble Server and Hubble Relay. + +Note: Always use this template as follows: + + {{- $_ := include "hubble-generate-certs.helm.setup-ca" . -}} + +The assignment to `$_` is required because we store the generated CI in a global `ca` variable. +Please, don't try to "simplify" this, as without this trick, every generated +certificate would be signed by a different CA. +*/}} +{{- define "hubble-generate-certs.helm.setup-ca" }} + {{- if not .ca }} + {{- $ca := "" -}} + {{- $crt := .Values.tls.ca.cert -}} + {{- $key := .Values.tls.ca.key -}} + {{- if and $crt $key }} + {{- $ca = buildCustomCert $crt $key -}} + {{- else }} + {{- $_ := include "cilium.ca.setup" . -}} + {{- with lookup "v1" "Secret" .Release.Namespace .commonCASecretName }} + {{- $crt := index .data "ca.crt" }} + {{- $key := index .data "ca.key" }} + {{- $ca = buildCustomCert $crt $key -}} + {{- else }} + {{- $ca = .commonCA -}} + {{- end }} + {{- end }} + {{- $_ := set . "ca" $ca -}} + {{- end }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/hubble/tls-helm/relay-client-secret.yaml b/packages/system/cilium/charts/cilium/templates/hubble/tls-helm/relay-client-secret.yaml new file mode 100644 index 00000000..947565ea --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/hubble/tls-helm/relay-client-secret.yaml @@ -0,0 +1,17 @@ +{{- if and .Values.hubble.enabled .Values.hubble.tls.enabled .Values.hubble.tls.auto.enabled (eq .Values.hubble.tls.auto.method "helm") .Values.hubble.relay.enabled }} +{{- $_ := include "hubble-generate-certs.helm.setup-ca" . -}} +{{- $cn := "*.hubble-relay.cilium.io" }} +{{- $dns := list $cn }} +{{- $cert := genSignedCert $cn nil $dns (.Values.hubble.tls.auto.certValidityDuration | int) .ca -}} +--- +apiVersion: v1 +kind: Secret +metadata: + name: hubble-relay-client-certs + namespace: {{ .Release.Namespace }} +type: kubernetes.io/tls +data: + ca.crt: {{ .ca.Cert | b64enc }} + tls.crt: {{ $cert.Cert | b64enc }} + tls.key: {{ $cert.Key | b64enc }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/hubble/tls-helm/relay-server-secret.yaml b/packages/system/cilium/charts/cilium/templates/hubble/tls-helm/relay-server-secret.yaml new file mode 100644 index 00000000..2c2339d6 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/hubble/tls-helm/relay-server-secret.yaml @@ -0,0 +1,18 @@ +{{- if and .Values.hubble.enabled .Values.hubble.tls.enabled .Values.hubble.tls.auto.enabled (eq .Values.hubble.tls.auto.method "helm") .Values.hubble.relay.enabled .Values.hubble.relay.tls.server.enabled }} +{{- $_ := include "hubble-generate-certs.helm.setup-ca" . -}} +{{- $cn := "*.hubble-relay.cilium.io" }} +{{- $ip := .Values.hubble.relay.tls.server.extraIpAddresses }} +{{- $dns := prepend .Values.hubble.relay.tls.server.extraDnsNames $cn }} +{{- $cert := genSignedCert $cn $ip $dns (.Values.hubble.tls.auto.certValidityDuration | int) .ca -}} +--- +apiVersion: v1 +kind: Secret +metadata: + name: hubble-relay-server-certs + namespace: {{ .Release.Namespace }} +type: kubernetes.io/tls +data: + ca.crt: {{ .ca.Cert | b64enc }} + tls.crt: {{ $cert.Cert | b64enc }} + tls.key: {{ $cert.Key | b64enc }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/hubble/tls-helm/server-secret.yaml b/packages/system/cilium/charts/cilium/templates/hubble/tls-helm/server-secret.yaml new file mode 100644 index 00000000..cc3c1d91 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/hubble/tls-helm/server-secret.yaml @@ -0,0 +1,18 @@ +{{- if and .Values.agent .Values.hubble.enabled .Values.hubble.tls.enabled .Values.hubble.tls.auto.enabled (eq .Values.hubble.tls.auto.method "helm") }} +{{- $_ := include "hubble-generate-certs.helm.setup-ca" . -}} +{{- $cn := list "*" (.Values.cluster.name | replace "." "-") "hubble-grpc.cilium.io" | join "." }} +{{- $ip := .Values.hubble.tls.server.extraIpAddresses }} +{{- $dns := prepend .Values.hubble.tls.server.extraDnsNames $cn }} +{{- $cert := genSignedCert $cn $ip $dns (.Values.hubble.tls.auto.certValidityDuration | int) .ca -}} +--- +apiVersion: v1 +kind: Secret +metadata: + name: hubble-server-certs + namespace: {{ .Release.Namespace }} +type: kubernetes.io/tls +data: + ca.crt: {{ .ca.Cert | b64enc }} + tls.crt: {{ $cert.Cert | b64enc }} + tls.key: {{ $cert.Key | b64enc }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/hubble/tls-helm/ui-client-certs.yaml b/packages/system/cilium/charts/cilium/templates/hubble/tls-helm/ui-client-certs.yaml new file mode 100644 index 00000000..90376d65 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/hubble/tls-helm/ui-client-certs.yaml @@ -0,0 +1,17 @@ +{{- if and .Values.hubble.enabled .Values.hubble.tls.enabled .Values.hubble.tls.auto.enabled (eq .Values.hubble.tls.auto.method "helm") .Values.hubble.ui.enabled .Values.hubble.relay.enabled .Values.hubble.relay.tls.server.enabled }} +{{- $_ := include "hubble-generate-certs.helm.setup-ca" . -}} +{{- $cn := "*.hubble-ui.cilium.io" }} +{{- $dns := list $cn }} +{{- $cert := genSignedCert $cn nil $dns (.Values.hubble.tls.auto.certValidityDuration | int) .ca -}} +--- +apiVersion: v1 +kind: Secret +metadata: + name: hubble-ui-client-certs + namespace: {{ .Release.Namespace }} +type: kubernetes.io/tls +data: + ca.crt: {{ .ca.Cert | b64enc }} + tls.crt: {{ $cert.Cert | b64enc }} + tls.key: {{ $cert.Key | b64enc }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/hubble/tls-provided/relay-client-secret.yaml b/packages/system/cilium/charts/cilium/templates/hubble/tls-provided/relay-client-secret.yaml new file mode 100644 index 00000000..4a15f646 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/hubble/tls-provided/relay-client-secret.yaml @@ -0,0 +1,12 @@ +{{- if and .Values.hubble.enabled .Values.hubble.tls.enabled (not .Values.hubble.tls.auto.enabled) .Values.hubble.relay.enabled }} +apiVersion: v1 +kind: Secret +metadata: + name: hubble-relay-client-certs + namespace: {{ .Release.Namespace }} +type: kubernetes.io/tls +data: + ca.crt: {{ .Values.tls.ca.cert }} + tls.crt: {{ .Values.hubble.relay.tls.client.cert | required "missing hubble.relay.tls.client.cert" }} + tls.key: {{ .Values.hubble.relay.tls.client.key | required "missing hubble.relay.tls.client.key" }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/hubble/tls-provided/relay-server-secret.yaml b/packages/system/cilium/charts/cilium/templates/hubble/tls-provided/relay-server-secret.yaml new file mode 100644 index 00000000..2038f785 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/hubble/tls-provided/relay-server-secret.yaml @@ -0,0 +1,12 @@ +{{- if and .Values.hubble.enabled .Values.hubble.tls.enabled (not .Values.hubble.tls.auto.enabled) .Values.hubble.relay.enabled .Values.hubble.relay.tls.server.enabled }} +apiVersion: v1 +kind: Secret +metadata: + name: hubble-relay-server-certs + namespace: {{ .Release.Namespace }} +type: kubernetes.io/tls +data: + ca.crt: {{ .Values.tls.ca.cert }} + tls.crt: {{ .Values.hubble.relay.tls.server.cert | required "missing hubble.relay.tls.server.cert" }} + tls.key: {{ .Values.hubble.relay.tls.server.key | required "missing hubble.relay.tls.server.key" }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/hubble/tls-provided/server-secret.yaml b/packages/system/cilium/charts/cilium/templates/hubble/tls-provided/server-secret.yaml new file mode 100644 index 00000000..ecc0bf07 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/hubble/tls-provided/server-secret.yaml @@ -0,0 +1,12 @@ +{{- if and .Values.agent .Values.hubble.enabled .Values.hubble.tls.enabled (not .Values.hubble.tls.auto.enabled) }} +apiVersion: v1 +kind: Secret +metadata: + name: hubble-server-certs + namespace: {{ .Release.Namespace }} +type: kubernetes.io/tls +data: + ca.crt: {{ .Values.tls.ca.cert }} + tls.crt: {{ .Values.hubble.tls.server.cert | required "missing hubble.tls.server.cert" }} + tls.key: {{ .Values.hubble.tls.server.key | required "missing hubble.tls.server.key" }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/hubble/tls-provided/ui-client-certs.yaml b/packages/system/cilium/charts/cilium/templates/hubble/tls-provided/ui-client-certs.yaml new file mode 100644 index 00000000..7ed9472d --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/hubble/tls-provided/ui-client-certs.yaml @@ -0,0 +1,12 @@ +{{- if and .Values.hubble.enabled .Values.hubble.tls.enabled (not .Values.hubble.tls.auto.enabled) .Values.hubble.ui.enabled .Values.hubble.relay.enabled .Values.hubble.relay.tls.server.enabled }} +apiVersion: v1 +kind: Secret +metadata: + name: hubble-ui-client-certs + namespace: {{ .Release.Namespace }} +type: kubernetes.io/tls +data: + ca.crt: {{ .Values.tls.ca.cert }} + tls.crt: {{ .Values.hubble.ui.tls.client.cert | required "missing hubble.ui.tls.client.cert" }} + tls.key: {{ .Values.hubble.ui.tls.client.key | required "missing hubble.ui.tls.client.key" }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/spire/agent/clusterrole.yaml b/packages/system/cilium/charts/cilium/templates/spire/agent/clusterrole.yaml new file mode 100644 index 00000000..57d7ae0d --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/spire/agent/clusterrole.yaml @@ -0,0 +1,11 @@ +{{- if and .Values.authentication.mutual.spire.enabled .Values.authentication.mutual.spire.install.enabled .Values.authentication.mutual.spire.install.agent.serviceAccount.create -}} +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ .Values.authentication.mutual.spire.install.agent.serviceAccount.name }} +rules: +# Required cluster role to allow spire-agent to query k8s API server +- apiGroups: [ "" ] + resources: [ "pods","nodes","nodes/proxy" ] + verbs: [ "get" ] +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/spire/agent/clusterrolebinding.yaml b/packages/system/cilium/charts/cilium/templates/spire/agent/clusterrolebinding.yaml new file mode 100644 index 00000000..f7290825 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/spire/agent/clusterrolebinding.yaml @@ -0,0 +1,15 @@ +{{- if and .Values.authentication.mutual.spire.enabled .Values.authentication.mutual.spire.install.enabled .Values.authentication.mutual.spire.install.agent.serviceAccount.create -}} +--- +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ .Values.authentication.mutual.spire.install.agent.serviceAccount.name }} +roleRef: + kind: ClusterRole + name: {{ .Values.authentication.mutual.spire.install.agent.serviceAccount.name }} + apiGroup: rbac.authorization.k8s.io +subjects: +- kind: ServiceAccount + name: {{ .Values.authentication.mutual.spire.install.agent.serviceAccount.name }} + namespace: {{ .Values.authentication.mutual.spire.install.namespace }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/spire/agent/configmap.yaml b/packages/system/cilium/charts/cilium/templates/spire/agent/configmap.yaml new file mode 100644 index 00000000..21e1a70a --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/spire/agent/configmap.yaml @@ -0,0 +1,49 @@ +{{- if and .Values.authentication.mutual.spire.enabled .Values.authentication.mutual.spire.install.enabled -}} +apiVersion: v1 +kind: ConfigMap +metadata: + name: spire-agent + namespace: {{ .Values.authentication.mutual.spire.install.namespace }} +data: + agent.conf: | + agent { + data_dir = "/run/spire" + log_level = "ERROR" + server_address = "spire-server" + server_port = "8081" + socket_path = {{ .Values.authentication.mutual.spire.agentSocketPath | quote }} + admin_socket_path = {{ .Values.authentication.mutual.spire.adminSocketPath | quote }} + trust_bundle_path = "/run/spire/bundle/bundle.crt" + trust_domain = {{ .Values.authentication.mutual.spire.trustDomain | quote }} + authorized_delegates = [ + "spiffe://{{ .Values.authentication.mutual.spire.trustDomain }}/cilium-agent", + ] + } + + plugins { + NodeAttestor "k8s_psat" { + plugin_data { + cluster = {{ .Values.cluster.name | quote }} + } + } + + KeyManager "memory" { + plugin_data { + } + } + + WorkloadAttestor "k8s" { + plugin_data { + skip_kubelet_verification = {{ .Values.authentication.mutual.spire.install.agent.skipKubeletVerification }} + } + } + } + + health_checks { + listener_enabled = true + bind_address = "0.0.0.0" + bind_port = "4251" + live_path = "/live" + ready_path = "/ready" + } +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/spire/agent/daemonset.yaml b/packages/system/cilium/charts/cilium/templates/spire/agent/daemonset.yaml new file mode 100644 index 00000000..f186eaef --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/spire/agent/daemonset.yaml @@ -0,0 +1,113 @@ +{{- if and .Values.authentication.mutual.spire.enabled .Values.authentication.mutual.spire.install.enabled -}} +apiVersion: apps/v1 +kind: DaemonSet +metadata: + name: spire-agent + namespace: {{ .Values.authentication.mutual.spire.install.namespace }} + {{- with .Values.authentication.mutual.spire.install.server.annotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + app: spire-agent + {{- with .Values.authentication.mutual.spire.install.agent.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + selector: + matchLabels: + app: spire-agent + template: + metadata: + namespace: {{ .Values.authentication.mutual.spire.install.namespace }} + labels: + app: spire-agent + {{- with .Values.authentication.mutual.spire.install.agent.labels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + hostPID: true + hostNetwork: true + dnsPolicy: ClusterFirstWithHostNet + serviceAccountName: {{ .Values.authentication.mutual.spire.install.agent.serviceAccount.name }} + {{- with .Values.authentication.mutual.spire.install.agent.podSecurityContext }} + securityContext: + {{- toYaml . | nindent 8 }} + {{- end }} + initContainers: + - name: init + image: docker.io/library/busybox:1.35.0@sha256:223ae047b1065bd069aac01ae3ac8088b3ca4a527827e283b85112f29385fb1b + command: + - /bin/sh + - -c + - | + {{- tpl (.Files.Get "files/spire/wait-for-spire.bash") . | nindent 14 }} + containers: + - name: spire-agent + image: {{ .Values.authentication.mutual.spire.install.agent.image }} + args: ["-config", "/run/spire/config/agent.conf"] + {{- with .Values.authentication.mutual.spire.install.agent.securityContext }} + securityContext: + {{- toYaml . | nindent 12 }} + {{- end }} + volumeMounts: + - name: spire-config + mountPath: /run/spire/config + readOnly: true + - name: spire-bundle + mountPath: /run/spire/bundle + - name: spire-agent-socket + mountPath: /run/spire/sockets + readOnly: false + - name: spire-agent + mountPath: /var/run/secrets/tokens + env: + - name: MY_NODE_NAME + valueFrom: + fieldRef: + fieldPath: status.hostIP + livenessProbe: + httpGet: + path: /live + port: 4251 + failureThreshold: 2 + initialDelaySeconds: 15 + periodSeconds: 60 + timeoutSeconds: 3 + readinessProbe: + httpGet: + path: /ready + port: 4251 + initialDelaySeconds: 5 + periodSeconds: 5 + {{- with .Values.authentication.mutual.spire.install.agent.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.authentication.mutual.spire.install.agent.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.authentication.mutual.spire.install.agent.tolerations }} + tolerations: + {{- toYaml . | trim | nindent 8 }} + {{- end }} + volumes: + - name: spire-config + configMap: + name: spire-agent + - name: spire-bundle + configMap: + name: spire-bundle + - name: spire-agent-socket + hostPath: + path: /run/spire/sockets + type: DirectoryOrCreate + - name: spire-agent + projected: + sources: + - serviceAccountToken: + path: spire-agent + expirationSeconds: 600 + audience: spire-server +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/spire/agent/serviceaccount.yaml b/packages/system/cilium/charts/cilium/templates/spire/agent/serviceaccount.yaml new file mode 100644 index 00000000..f155b5e6 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/spire/agent/serviceaccount.yaml @@ -0,0 +1,7 @@ +{{- if and .Values.authentication.mutual.spire.enabled .Values.authentication.mutual.spire.install.enabled .Values.authentication.mutual.spire.install.agent.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ .Values.authentication.mutual.spire.install.agent.serviceAccount.name }} + namespace: {{ .Values.authentication.mutual.spire.install.namespace }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/spire/bundle-configmap.yaml b/packages/system/cilium/charts/cilium/templates/spire/bundle-configmap.yaml new file mode 100644 index 00000000..986e6604 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/spire/bundle-configmap.yaml @@ -0,0 +1,7 @@ +{{- if and .Values.authentication.mutual.spire.enabled .Values.authentication.mutual.spire.install.enabled -}} +apiVersion: v1 +kind: ConfigMap +metadata: + name: spire-bundle + namespace: {{ .Values.authentication.mutual.spire.install.namespace }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/spire/namespace.yaml b/packages/system/cilium/charts/cilium/templates/spire/namespace.yaml new file mode 100644 index 00000000..a0f3e23d --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/spire/namespace.yaml @@ -0,0 +1,6 @@ +{{- if and .Values.authentication.mutual.spire.enabled .Values.authentication.mutual.spire.install.enabled -}} +apiVersion: v1 +kind: Namespace +metadata: + name: {{ .Values.authentication.mutual.spire.install.namespace }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/spire/server/clusterrole.yaml b/packages/system/cilium/charts/cilium/templates/spire/server/clusterrole.yaml new file mode 100644 index 00000000..95cc911a --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/spire/server/clusterrole.yaml @@ -0,0 +1,22 @@ +{{- if and .Values.authentication.mutual.spire.enabled .Values.authentication.mutual.spire.install.enabled .Values.authentication.mutual.spire.install.server.serviceAccount.create -}} + +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ .Values.authentication.mutual.spire.install.server.serviceAccount.name }} +rules: +# ClusterRole to allow spire-server node attestor to query Token Review API +- apiGroups: [ "authentication.k8s.io" ] + resources: [ "tokenreviews" ] + verbs: [ "create" ] +# Required cluster role to allow spire-server to query k8s API server +# for pods for psat attestation +- apiGroups: [ "" ] + resources: [ "pods" ] + verbs: [ "get" ] +# Required cluster role to allow spire-server to query k8s API server +# for nodes for psat attestation +- apiGroups: [ "" ] + resources: [ "nodes","nodes/proxy" ] + verbs: [ "get" ] +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/spire/server/clusterrolebinding.yaml b/packages/system/cilium/charts/cilium/templates/spire/server/clusterrolebinding.yaml new file mode 100644 index 00000000..aaefe4ff --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/spire/server/clusterrolebinding.yaml @@ -0,0 +1,14 @@ +{{- if and .Values.authentication.mutual.spire.enabled .Values.authentication.mutual.spire.install.enabled .Values.authentication.mutual.spire.install.server.serviceAccount.create -}} +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ .Values.authentication.mutual.spire.install.server.serviceAccount.name }} +roleRef: + kind: ClusterRole + name: spire-server + apiGroup: rbac.authorization.k8s.io +subjects: +- kind: ServiceAccount + name: {{ .Values.authentication.mutual.spire.install.server.serviceAccount.name }} + namespace: {{ .Values.authentication.mutual.spire.install.namespace }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/spire/server/configmap.yaml b/packages/system/cilium/charts/cilium/templates/spire/server/configmap.yaml new file mode 100644 index 00000000..9785c11e --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/spire/server/configmap.yaml @@ -0,0 +1,68 @@ +{{- if and .Values.authentication.mutual.spire.enabled .Values.authentication.mutual.spire.install.enabled -}} +apiVersion: v1 +kind: ConfigMap +metadata: + name: spire-server + namespace: {{ .Values.authentication.mutual.spire.install.namespace }} +data: + server.conf: | + server { + bind_address = "0.0.0.0" + bind_port = "8081" + socket_path = "/tmp/spire-server/private/api.sock" + trust_domain = {{ .Values.authentication.mutual.spire.trustDomain | quote }} + data_dir = "/run/spire/data" + log_level = "INFO" + ca_key_type = {{ .Values.authentication.mutual.spire.install.server.ca.keyType | quote }} + + ca_subject = { + country = [{{ .Values.authentication.mutual.spire.install.server.ca.subject.country | quote }}], + organization = [{{ .Values.authentication.mutual.spire.install.server.ca.subject.organization | quote }}], + common_name = {{ .Values.authentication.mutual.spire.install.server.ca.subject.commonName | quote }}, + } + + admin_ids = [ + "spiffe://{{ .Values.authentication.mutual.spire.trustDomain }}/cilium-operator", + ] + } + + plugins { + DataStore "sql" { + plugin_data { + database_type = "sqlite3" + connection_string = "/run/spire/data/datastore.sqlite3" + } + } + + NodeAttestor "k8s_psat" { + plugin_data { + clusters = { + {{ .Values.cluster.name | quote }} = { + use_token_review_api_validation = true + service_account_allow_list = ["{{ .Values.authentication.mutual.spire.install.namespace}}:{{ .Values.authentication.mutual.spire.install.agent.serviceAccount.name }}"] + } + } + } + } + + KeyManager "disk" { + plugin_data { + keys_path = "/run/spire/data/keys.json" + } + } + + Notifier "k8sbundle" { + plugin_data { + namespace = {{ .Values.authentication.mutual.spire.install.namespace | quote }} + } + } + } + + health_checks { + listener_enabled = true + bind_address = "0.0.0.0" + bind_port = "8080" + live_path = "/live" + ready_path = "/ready" + } +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/spire/server/role.yaml b/packages/system/cilium/charts/cilium/templates/spire/server/role.yaml new file mode 100644 index 00000000..38e0b113 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/spire/server/role.yaml @@ -0,0 +1,12 @@ +{{- if and .Values.authentication.mutual.spire.enabled .Values.authentication.mutual.spire.install.enabled .Values.authentication.mutual.spire.install.server.serviceAccount.create -}} +kind: Role +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ .Values.authentication.mutual.spire.install.server.serviceAccount.name }} + namespace: {{ .Values.authentication.mutual.spire.install.namespace }} +rules: +# Role (namespace scoped) to be able to push certificate bundles to a configmap +- apiGroups: [ "" ] + resources: [ "configmaps" ] + verbs: [ "patch", "get", "list" ] +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/spire/server/rolebinding.yaml b/packages/system/cilium/charts/cilium/templates/spire/server/rolebinding.yaml new file mode 100644 index 00000000..a3e18731 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/spire/server/rolebinding.yaml @@ -0,0 +1,29 @@ +{{- if and .Values.authentication.mutual.spire.enabled .Values.authentication.mutual.spire.install.enabled -}} +kind: RoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ .Values.authentication.mutual.spire.install.server.serviceAccount.name }} + namespace: {{ .Values.authentication.mutual.spire.install.namespace }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: spire-server +subjects: +- kind: ServiceAccount + name: {{ .Values.authentication.mutual.spire.install.server.serviceAccount.name }} + namespace: {{ .Values.authentication.mutual.spire.install.namespace }} +--- +kind: RoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ .Values.authentication.mutual.spire.install.server.serviceAccount.name }}-pod + namespace: {{ .Values.authentication.mutual.spire.install.namespace }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ .Values.authentication.mutual.spire.install.server.serviceAccount.name }}-pod +subjects: +- kind: ServiceAccount + name: {{ .Values.authentication.mutual.spire.install.server.serviceAccount.name }} + namespace: {{ .Values.authentication.mutual.spire.install.namespace }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/spire/server/service.yaml b/packages/system/cilium/charts/cilium/templates/spire/server/service.yaml new file mode 100644 index 00000000..31fee016 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/spire/server/service.yaml @@ -0,0 +1,24 @@ +{{- if and .Values.authentication.mutual.spire.enabled .Values.authentication.mutual.spire.install.enabled -}} +apiVersion: v1 +kind: Service +metadata: + name: spire-server + namespace: {{ .Values.authentication.mutual.spire.install.namespace }} + {{- with .Values.authentication.mutual.spire.install.server.service.annotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.authentication.mutual.spire.install.server.service.labels }} + labels: + {{- toYaml . | nindent 8 }} + {{- end }} +spec: + type: {{ .Values.authentication.mutual.spire.install.server.service.type }} + ports: + - name: grpc + port: 8081 + targetPort: grpc + protocol: TCP + selector: + app: spire-server +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/spire/server/serviceaccount.yaml b/packages/system/cilium/charts/cilium/templates/spire/server/serviceaccount.yaml new file mode 100644 index 00000000..2d4aa4a3 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/spire/server/serviceaccount.yaml @@ -0,0 +1,7 @@ +{{- if and .Values.authentication.mutual.spire.enabled .Values.authentication.mutual.spire.install.enabled .Values.authentication.mutual.spire.install.server.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ .Values.authentication.mutual.spire.install.server.serviceAccount.name }} + namespace: {{ .Values.authentication.mutual.spire.install.namespace }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/spire/server/statefulset.yaml b/packages/system/cilium/charts/cilium/templates/spire/server/statefulset.yaml new file mode 100644 index 00000000..43c2c9ee --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/spire/server/statefulset.yaml @@ -0,0 +1,110 @@ +{{- if and .Values.authentication.mutual.spire.enabled .Values.authentication.mutual.spire.install.enabled -}} +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: spire-server + namespace: {{ .Values.authentication.mutual.spire.install.namespace }} + {{- with .Values.authentication.mutual.spire.install.server.annotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + app: spire-server + {{- with .Values.authentication.mutual.spire.install.server.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + replicas: 1 + selector: + matchLabels: + app: spire-server + serviceName: spire-server + template: + metadata: + labels: + app: spire-server + {{- with .Values.authentication.mutual.spire.install.server.labels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + serviceAccountName: {{ .Values.authentication.mutual.spire.install.server.serviceAccount.name }} + shareProcessNamespace: true + {{- if gt (len .Values.authentication.mutual.spire.install.server.initContainers) 0 }} + initContainers: + {{- toYaml .Values.authentication.mutual.spire.install.server.initContainers | nindent 8 }} + {{- end }} + containers: + - name: cilium-init + image: docker.io/library/busybox:1.35.0@sha256:223ae047b1065bd069aac01ae3ac8088b3ca4a527827e283b85112f29385fb1b + command: + - /bin/sh + - -c + - | + {{- tpl (.Files.Get "files/spire/init.bash") . | nindent 12 }} + - name: spire-server + image: {{ .Values.authentication.mutual.spire.install.server.image }} + args: + - -config + - /run/spire/config/server.conf + ports: + - name: grpc + containerPort: 8081 + volumeMounts: + - name: spire-config + mountPath: /run/spire/config + readOnly: true + {{- if .Values.authentication.mutual.spire.install.server.dataStorage.enabled }} + - name: spire-data + mountPath: /run/spire/data + readOnly: false + {{- end }} + - name: spire-server-socket + mountPath: /tmp/spire-server/private + readOnly: false + livenessProbe: + httpGet: + path: /live + port: 8080 + failureThreshold: 2 + initialDelaySeconds: 15 + periodSeconds: 60 + timeoutSeconds: 3 + readinessProbe: + httpGet: + path: /ready + port: 8080 + initialDelaySeconds: 5 + periodSeconds: 5 + {{- with .Values.authentication.mutual.spire.install.server.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.authentication.mutual.spire.install.server.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.authentication.mutual.spire.install.server.tolerations }} + tolerations: + {{- toYaml . | trim | nindent 8 }} + {{- end }} + volumes: + - name: spire-config + configMap: + name: spire-server + - name: spire-server-socket + hostPath: + path: /var/run/spire-server/sockets + type: DirectoryOrCreate + {{- if .Values.authentication.mutual.spire.install.server.dataStorage.enabled }} + volumeClaimTemplates: + - metadata: + name: spire-data + spec: + accessModes: + - {{ .Values.authentication.mutual.spire.install.server.dataStorage.accessMode | default "ReadWriteOnce" }} + resources: + requests: + storage: {{ .Values.authentication.mutual.spire.install.server.dataStorage.size }} + storageClassName: {{ .Values.authentication.mutual.spire.install.server.dataStorage.storageClass }} + {{- end }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/validate.yaml b/packages/system/cilium/charts/cilium/templates/validate.yaml new file mode 100644 index 00000000..dfb5cb30 --- /dev/null +++ b/packages/system/cilium/charts/cilium/templates/validate.yaml @@ -0,0 +1,76 @@ +{{/* validate hubble config */}} +{{- if and .Values.hubble.ui.enabled (not .Values.hubble.ui.standalone.enabled) }} + {{- if not .Values.hubble.relay.enabled }} + {{ fail "Hubble UI requires .Values.hubble.relay.enabled=true" }} + {{- end }} +{{- end }} +{{- if and .Values.hubble.ui.enabled .Values.hubble.ui.standalone.enabled .Values.hubble.relay.tls.server.enabled }} + {{- if not .Values.hubble.ui.standalone.tls.certsVolume }} + {{ fail "Hubble UI in standalone with Hubble Relay server TLS enabled requires providing .Values.hubble.ui.standalone.tls.certsVolume for mounting client certificates in the backend pod" }} + {{- end }} +{{- end }} +{{- if .Values.hubble.relay.enabled }} + {{- if not .Values.hubble.enabled }} + {{ fail "Hubble Relay requires .Values.hubble.enabled=true" }} + {{- end }} +{{- end }} + +{{/* validate service monitoring CRDs */}} +{{- if or (and .Values.prometheus.enabled .Values.prometheus.serviceMonitor.enabled) (and .Values.operator.prometheus.enabled .Values.operator.prometheus.serviceMonitor.enabled) (and .Values.proxy.prometheus.enabled .Values.envoy.prometheus.enabled .Values.envoy.prometheus.serviceMonitor.enabled) (and .Values.proxy.prometheus.enabled .Values.hubble.relay.prometheus.enabled .Values.hubble.relay.prometheus.serviceMonitor.enabled) }} + {{- if not (.Capabilities.APIVersions.Has "monitoring.coreos.com/v1") }} + {{- if not .Values.prometheus.serviceMonitor.trustCRDsExist }} + {{ fail "Service Monitor requires monitoring.coreos.com/v1 CRDs. Please refer to https://github.com/prometheus-operator/prometheus-operator/blob/main/example/prometheus-operator-crd/monitoring.coreos.com_servicemonitors.yaml or set .Values.prometheus.serviceMonitor.trustCRDsExist=true" }} + {{- end }} + {{- end }} +{{- end }} + +{{- if and .Values.hubble.enabled .Values.hubble.tls.enabled .Values.hubble.tls.auto.enabled (eq .Values.hubble.tls.auto.method "certmanager") }} + {{- if not .Values.hubble.tls.auto.certManagerIssuerRef }} + {{ fail "Hubble TLS certgen method=certmanager requires that user specifies .Values.hubble.tls.auto.certManagerIssuerRef" }} + {{- end }} +{{- end }} + +{{- if and (or .Values.externalWorkloads.enabled .Values.clustermesh.useAPIServer) .Values.clustermesh.apiserver.tls.auto.enabled (eq .Values.clustermesh.apiserver.tls.auto.method "certmanager") }} + {{- if not .Values.clustermesh.apiserver.tls.auto.certManagerIssuerRef }} + {{ fail "ClusterMesh TLS certgen method=certmanager requires that user specifies .Values.clustermesh.apiserver.tls.auto.certManagerIssuerRef" }} + {{- end }} +{{- end }} + +{{/* validate hubble-ui specific config */}} +{{- if and .Values.hubble.ui.enabled + (ne .Values.hubble.ui.backend.image.tag "latest") + (ne .Values.hubble.ui.frontend.image.tag "latest") }} + {{- if regexReplaceAll "@.*$" .Values.hubble.ui.backend.image.tag "" | trimPrefix "v" | semverCompare "<0.9.0" }} + {{ fail "Hubble UI requires hubble.ui.backend.image.tag to be '>=v0.9.0'" }} + {{- end }} + {{- if regexReplaceAll "@.*$" .Values.hubble.ui.frontend.image.tag "" | trimPrefix "v" | semverCompare "<0.9.0" }} + {{ fail "Hubble UI requires hubble.ui.frontend.image.tag to be '>=v0.9.0'" }} + {{- end }} +{{- end }} + +{{- if or .Values.ingressController.enabled .Values.gatewayAPI.enabled (eq .Values.loadBalancer.l7.backend "envoy") }} + {{- if hasKey .Values "l7Proxy" }} + {{- if not .Values.l7Proxy }} + {{ fail "Ingress or Gateway API controller or Envoy L7 Load Balancer requires .Values.l7Proxy to be set to 'true'" }} + {{- end }} + {{- end }} +{{- end }} + +{{- if or .Values.envoyConfig.enabled .Values.ingressController.enabled .Values.gatewayAPI.enabled }} + {{- if or (eq (toString .Values.kubeProxyReplacement) "disabled") (and (not (hasKey .Values "kubeProxyReplacement")) (not (semverCompare ">=1.14" (default "1.14" .Values.upgradeCompatibility)))) }} + {{ fail "Ingress/Gateway API controller and EnvoyConfig require .Values.kubeProxyReplacement to be explicitly set to 'false' or 'true'" }} + {{- end }} +{{- end }} + +{{- if .Values.authentication.mutual.spire.enabled }} + {{- if not .Values.authentication.enabled }} + {{ fail "SPIRE integration requires .Values.authentication.enabled=true and .Values.authentication.mutual.spire.enabled=true" }} + {{- end }} +{{- end }} + +{{/* validate Cilium operator */}} +{{- if eq .Values.enableCiliumEndpointSlice true }} + {{- if eq .Values.disableEndpointCRD true }} + {{ fail "if Cilium Endpoint Slice is enabled (.Values.enableCiliumEndpointSlice=true), it requires .Values.disableEndpointCRD=false" }} + {{- end }} +{{- end }} diff --git a/packages/system/cilium/charts/cilium/values.yaml b/packages/system/cilium/charts/cilium/values.yaml new file mode 100644 index 00000000..243991c2 --- /dev/null +++ b/packages/system/cilium/charts/cilium/values.yaml @@ -0,0 +1,3218 @@ +# File generated by install/kubernetes/Makefile; DO NOT EDIT. +# This file is based on install/kubernetes/cilium/values.yaml.tmpl. + + +# upgradeCompatibility helps users upgrading to ensure that the configMap for +# Cilium will not change critical values to ensure continued operation +# This is flag is not required for new installations. +# For example: 1.7, 1.8, 1.9 +# upgradeCompatibility: '1.8' + +debug: + # -- Enable debug logging + enabled: false + # -- Configure verbosity levels for debug logging + # This option is used to enable debug messages for operations related to such + # sub-system such as (e.g. kvstore, envoy, datapath or policy), and flow is + # for enabling debug messages emitted per request, message and connection. + # + # Applicable values: + # - flow + # - kvstore + # - envoy + # - datapath + # - policy + verbose: ~ + +rbac: + # -- Enable creation of Resource-Based Access Control configuration. + create: true + +# -- Configure image pull secrets for pulling container images +imagePullSecrets: +# - name: "image-pull-secret" + +# -- (string) Kubernetes config path +# @default -- `"~/.kube/config"` +kubeConfigPath: "" +# -- (string) Kubernetes service host +k8sServiceHost: "" +# -- (string) Kubernetes service port +k8sServicePort: "" + +# -- Configure the client side rate limit for the agent and operator +# +# If the amount of requests to the Kubernetes API server exceeds the configured +# rate limit, the agent and operator will start to throttle requests by delaying +# them until there is budget or the request times out. +k8sClientRateLimit: + # -- The sustained request rate in requests per second. + qps: 5 + # -- The burst request rate in requests per second. + # The rate limiter will allow short bursts with a higher rate. + burst: 10 + +cluster: + # -- Name of the cluster. Only required for Cluster Mesh and mutual authentication with SPIRE. + name: default + # -- (int) Unique ID of the cluster. Must be unique across all connected + # clusters and in the range of 1 to 255. Only required for Cluster Mesh, + # may be 0 if Cluster Mesh is not used. + id: 0 + +# -- Define serviceAccount names for components. +# @default -- Component's fully qualified name. +serviceAccounts: + cilium: + create: true + name: cilium + automount: true + annotations: {} + nodeinit: + create: true + # -- Enabled is temporary until https://github.com/cilium/cilium-cli/issues/1396 is implemented. + # Cilium CLI doesn't create the SAs for node-init, thus the workaround. Helm is not affected by + # this issue. Name and automount can be configured, if enabled is set to true. + # Otherwise, they are ignored. Enabled can be removed once the issue is fixed. + # Cilium-nodeinit DS must also be fixed. + enabled: false + name: cilium-nodeinit + automount: true + annotations: {} + envoy: + create: true + name: cilium-envoy + automount: true + annotations: {} + etcd: + create: true + name: cilium-etcd-operator + automount: true + annotations: {} + operator: + create: true + name: cilium-operator + automount: true + annotations: {} + preflight: + create: true + name: cilium-pre-flight + automount: true + annotations: {} + relay: + create: true + name: hubble-relay + automount: false + annotations: {} + ui: + create: true + name: hubble-ui + automount: true + annotations: {} + clustermeshApiserver: + create: true + name: clustermesh-apiserver + automount: true + annotations: {} + # -- Clustermeshcertgen is used if clustermesh.apiserver.tls.auto.method=cronJob + clustermeshcertgen: + create: true + name: clustermesh-apiserver-generate-certs + automount: true + annotations: {} + # -- Hubblecertgen is used if hubble.tls.auto.method=cronJob + hubblecertgen: + create: true + name: hubble-generate-certs + automount: true + annotations: {} + +# -- Configure termination grace period for cilium-agent DaemonSet. +terminationGracePeriodSeconds: 1 + +# -- Install the cilium agent resources. +agent: true + +# -- Agent container name. +name: cilium + +# -- Roll out cilium agent pods automatically when configmap is updated. +rollOutCiliumPods: false + +# -- Agent container image. +image: + override: ~ + repository: "quay.io/cilium/cilium" + tag: "v1.14.5" + pullPolicy: "IfNotPresent" + # cilium-digest + digest: "sha256:d3b287029755b6a47dee01420e2ea469469f1b174a2089c10af7e5e9289ef05b" + useDigest: true + +# -- Affinity for cilium-agent. +affinity: + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - topologyKey: kubernetes.io/hostname + labelSelector: + matchLabels: + k8s-app: cilium + +# -- Node selector for cilium-agent. +nodeSelector: + kubernetes.io/os: linux + +# -- Node tolerations for agent scheduling to nodes with taints +# ref: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/ +tolerations: +- operator: Exists + # - key: "key" + # operator: "Equal|Exists" + # value: "value" + # effect: "NoSchedule|PreferNoSchedule|NoExecute(1.6 only)" + +# -- The priority class to use for cilium-agent. +priorityClassName: "" + +# -- DNS policy for Cilium agent pods. +# Ref: https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-s-dns-policy +dnsPolicy: "" + +# -- Additional containers added to the cilium DaemonSet. +extraContainers: [] + +# -- Additional agent container arguments. +extraArgs: [] + +# -- Additional agent container environment variables. +extraEnv: [] + +# -- Additional agent hostPath mounts. +extraHostPathMounts: [] + # - name: host-mnt-data + # mountPath: /host/mnt/data + # hostPath: /mnt/data + # hostPathType: Directory + # readOnly: true + # mountPropagation: HostToContainer + +# -- Additional agent volumes. +extraVolumes: [] + +# -- Additional agent volumeMounts. +extraVolumeMounts: [] + +# -- extraConfig allows you to specify additional configuration parameters to be +# included in the cilium-config configmap. +extraConfig: {} +# my-config-a: "1234" +# my-config-b: |- +# test 1 +# test 2 +# test 3 + +# -- Security Context for cilium-agent pods. +podSecurityContext: {} + +# -- Annotations to be added to agent pods +podAnnotations: {} + +# -- Labels to be added to agent pods +podLabels: {} + +# -- Agent resource limits & requests +# ref: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ +resources: {} + # limits: + # cpu: 4000m + # memory: 4Gi + # requests: + # cpu: 100m + # memory: 512Mi + +# -- resources & limits for the agent init containers +initResources: {} + +securityContext: + # -- User to run the pod with + # runAsUser: 0 + # -- Run the pod with elevated privileges + privileged: false + # -- SELinux options for the `cilium-agent` and init containers + seLinuxOptions: + level: 's0' + # Running with spc_t since we have removed the privileged mode. + # Users can change it to a different type as long as they have the + # type available on the system. + type: 'spc_t' + capabilities: + # -- Capabilities for the `cilium-agent` container + ciliumAgent: + # Use to set socket permission + - CHOWN + # Used to terminate envoy child process + - KILL + # Used since cilium modifies routing tables, etc... + - NET_ADMIN + # Used since cilium creates raw sockets, etc... + - NET_RAW + # Used since cilium monitor uses mmap + - IPC_LOCK + # We need it for now but might not need it for >= 5.11 specially + # for the 'SYS_RESOURCE'. + # In >= 5.8 there's already BPF and PERMON capabilities + - SYS_ADMIN + # Could be an alternative for the SYS_ADMIN for the RLIMIT_NPROC + - SYS_RESOURCE + # Both PERFMON and BPF requires kernel 5.8, container runtime + # cri-o >= v1.22.0 or containerd >= v1.5.0. + # If available, SYS_ADMIN can be removed. + #- PERFMON + #- BPF + # Allow discretionary access control (e.g. required for package installation) + - DAC_OVERRIDE + # Allow to set Access Control Lists (ACLs) on arbitrary files (e.g. required for package installation) + - FOWNER + # Allow to execute program that changes GID (e.g. required for package installation) + - SETGID + # Allow to execute program that changes UID (e.g. required for package installation) + - SETUID + # -- Capabilities for the `mount-cgroup` init container + mountCgroup: + # Only used for 'mount' cgroup + - SYS_ADMIN + # Used for nsenter + - SYS_CHROOT + - SYS_PTRACE + # -- capabilities for the `apply-sysctl-overwrites` init container + applySysctlOverwrites: + # Required in order to access host's /etc/sysctl.d dir + - SYS_ADMIN + # Used for nsenter + - SYS_CHROOT + - SYS_PTRACE + # -- Capabilities for the `clean-cilium-state` init container + cleanCiliumState: + # Most of the capabilities here are the same ones used in the + # cilium-agent's container because this container can be used to + # uninstall all Cilium resources, and therefore it is likely that + # will need the same capabilities. + # Used since cilium modifies routing tables, etc... + - NET_ADMIN + # We need it for now but might not need it for >= 5.11 specially + # for the 'SYS_RESOURCE'. + # In >= 5.8 there's already BPF and PERMON capabilities + - SYS_ADMIN + # Could be an alternative for the SYS_ADMIN for the RLIMIT_NPROC + - SYS_RESOURCE + # Both PERFMON and BPF requires kernel 5.8, container runtime + # cri-o >= v1.22.0 or containerd >= v1.5.0. + # If available, SYS_ADMIN can be removed. + #- PERFMON + #- BPF + +# -- Cilium agent update strategy +updateStrategy: + type: RollingUpdate + rollingUpdate: + maxUnavailable: 2 + +# Configuration Values for cilium-agent + +aksbyocni: + # -- Enable AKS BYOCNI integration. + # Note that this is incompatible with AKS clusters not created in BYOCNI mode: + # use Azure integration (`azure.enabled`) instead. + enabled: false + +# -- Enable installation of PodCIDR routes between worker +# nodes if worker nodes share a common L2 network segment. +autoDirectNodeRoutes: false + +# -- Annotate k8s node upon initialization with Cilium's metadata. +annotateK8sNode: false + +azure: + # -- Enable Azure integration. + # Note that this is incompatible with AKS clusters created in BYOCNI mode: use + # AKS BYOCNI integration (`aksbyocni.enabled`) instead. + enabled: false + # usePrimaryAddress: false + # resourceGroup: group1 + # subscriptionID: 00000000-0000-0000-0000-000000000000 + # tenantID: 00000000-0000-0000-0000-000000000000 + # clientID: 00000000-0000-0000-0000-000000000000 + # clientSecret: 00000000-0000-0000-0000-000000000000 + # userAssignedIdentityID: 00000000-0000-0000-0000-000000000000 + +alibabacloud: + # -- Enable AlibabaCloud ENI integration + enabled: false + +# -- Enable bandwidth manager to optimize TCP and UDP workloads and allow +# for rate-limiting traffic from individual Pods with EDT (Earliest Departure +# Time) through the "kubernetes.io/egress-bandwidth" Pod annotation. +bandwidthManager: + # -- Enable bandwidth manager infrastructure (also prerequirement for BBR) + enabled: false + # -- Activate BBR TCP congestion control for Pods + bbr: false + +# -- Configure standalone NAT46/NAT64 gateway +nat46x64Gateway: + # -- Enable RFC8215-prefixed translation + enabled: false + +# -- EnableHighScaleIPcache enables the special ipcache mode for high scale +# clusters. The ipcache content will be reduced to the strict minimum and +# traffic will be encapsulated to carry security identities. +highScaleIPcache: + # -- Enable the high scale mode for the ipcache. + enabled: false + +# -- Configure L2 announcements +l2announcements: + # -- Enable L2 announcements + enabled: false + # -- If a lease is not renewed for X duration, the current leader is considered dead, a new leader is picked + # leaseDuration: 15s + # -- The interval at which the leader will renew the lease + # leaseRenewDeadline: 5s + # -- The timeout between retries if renewal fails + # leaseRetryPeriod: 2s + +# -- Configure L2 pod announcements +l2podAnnouncements: + # -- Enable L2 pod announcements + enabled: false + # -- Interface used for sending Gratuitous ARP pod announcements + interface: "eth0" + +# -- Configure BGP +bgp: + # -- Enable BGP support inside Cilium; embeds a new ConfigMap for BGP inside + # cilium-agent and cilium-operator + enabled: false + announce: + # -- Enable allocation and announcement of service LoadBalancer IPs + loadbalancerIP: false + # -- Enable announcement of node pod CIDR + podCIDR: false + +# -- This feature set enables virtual BGP routers to be created via +# CiliumBGPPeeringPolicy CRDs. +bgpControlPlane: + # -- Enables the BGP control plane. + enabled: false + +pmtuDiscovery: + # -- Enable path MTU discovery to send ICMP fragmentation-needed replies to + # the client. + enabled: false + +bpf: + autoMount: + # -- Enable automatic mount of BPF filesystem + # When `autoMount` is enabled, the BPF filesystem is mounted at + # `bpf.root` path on the underlying host and inside the cilium agent pod. + # If users disable `autoMount`, it's expected that users have mounted + # bpffs filesystem at the specified `bpf.root` volume, and then the + # volume will be mounted inside the cilium agent pod at the same path. + enabled: true + # -- Configure the mount point for the BPF filesystem + root: /sys/fs/bpf + + # -- Enables pre-allocation of eBPF map values. This increases + # memory usage but can reduce latency. + preallocateMaps: false + + # -- (int) Configure the maximum number of entries in auth map. + # @default -- `524288` + authMapMax: ~ + + # -- (int) Configure the maximum number of entries in the TCP connection tracking + # table. + # @default -- `524288` + ctTcpMax: ~ + + # -- (int) Configure the maximum number of entries for the non-TCP connection + # tracking table. + # @default -- `262144` + ctAnyMax: ~ + + # -- Configure the maximum number of service entries in the + # load balancer maps. + lbMapMax: 65536 + + # -- (int) Configure the maximum number of entries for the NAT table. + # @default -- `524288` + natMax: ~ + + # -- (int) Configure the maximum number of entries for the neighbor table. + # @default -- `524288` + neighMax: ~ + + # -- Configure the maximum number of entries in endpoint policy map (per endpoint). + policyMapMax: 16384 + + # -- (float64) Configure auto-sizing for all BPF maps based on available memory. + # ref: https://docs.cilium.io/en/stable/network/ebpf/maps/ + # @default -- `0.0025` + mapDynamicSizeRatio: ~ + + # -- Configure the level of aggregation for monitor notifications. + # Valid options are none, low, medium, maximum. + monitorAggregation: medium + + # -- Configure the typical time between monitor notifications for + # active connections. + monitorInterval: "5s" + + # -- Configure which TCP flags trigger notifications when seen for the + # first time in a connection. + monitorFlags: "all" + + # -- Allow cluster external access to ClusterIP services. + lbExternalClusterIP: false + + # -- (bool) Enable native IP masquerade support in eBPF + # @default -- `false` + masquerade: ~ + + # -- (bool) Configure whether direct routing mode should route traffic via + # host stack (true) or directly and more efficiently out of BPF (false) if + # the kernel supports it. The latter has the implication that it will also + # bypass netfilter in the host namespace. + # @default -- `false` + hostLegacyRouting: ~ + + # -- (bool) Configure the eBPF-based TPROXY to reduce reliance on iptables rules + # for implementing Layer 7 policy. + # @default -- `false` + tproxy: ~ + + # -- (list) Configure explicitly allowed VLAN id's for bpf logic bypass. + # [0] will allow all VLAN id's without any filtering. + # @default -- `[]` + vlanBypass: ~ + +# -- Enable BPF clock source probing for more efficient tick retrieval. +bpfClockProbe: false + +# -- Clean all eBPF datapath state from the initContainer of the cilium-agent +# DaemonSet. +# +# WARNING: Use with care! +cleanBpfState: false + +# -- Clean all local Cilium state from the initContainer of the cilium-agent +# DaemonSet. Implies cleanBpfState: true. +# +# WARNING: Use with care! +cleanState: false + +# -- Wait for KUBE-PROXY-CANARY iptables rule to appear in "wait-for-kube-proxy" +# init container before launching cilium-agent. +# More context can be found in the commit message of below PR +# https://github.com/cilium/cilium/pull/20123 +waitForKubeProxy: false + +cni: + # -- Install the CNI configuration and binary files into the filesystem. + install: true + + # -- Remove the CNI configuration and binary files on agent shutdown. Enable this + # if you're removing Cilium from the cluster. Disable this to prevent the CNI + # configuration file from being removed during agent upgrade, which can cause + # nodes to go unmanageable. + uninstall: false + + # -- Configure chaining on top of other CNI plugins. Possible values: + # - none + # - aws-cni + # - flannel + # - generic-veth + # - portmap + chainingMode: ~ + + # -- A CNI network name in to which the Cilium plugin should be added as a chained plugin. + # This will cause the agent to watch for a CNI network with this network name. When it is + # found, this will be used as the basis for Cilium's CNI configuration file. If this is + # set, it assumes a chaining mode of generic-veth. As a special case, a chaining mode + # of aws-cni implies a chainingTarget of aws-cni. + chainingTarget: ~ + + # -- Make Cilium take ownership over the `/etc/cni/net.d` directory on the + # node, renaming all non-Cilium CNI configurations to `*.cilium_bak`. + # This ensures no Pods can be scheduled using other CNI plugins during Cilium + # agent downtime. + exclusive: true + + # -- Configure the log file for CNI logging with retention policy of 7 days. + # Disable CNI file logging by setting this field to empty explicitly. + logFile: /var/run/cilium/cilium-cni.log + + # -- Skip writing of the CNI configuration. This can be used if + # writing of the CNI configuration is performed by external automation. + customConf: false + + # -- Configure the path to the CNI configuration directory on the host. + confPath: /etc/cni/net.d + + # -- Configure the path to the CNI binary directory on the host. + binPath: /opt/cni/bin + + # -- Specify the path to a CNI config to read from on agent start. + # This can be useful if you want to manage your CNI + # configuration outside of a Kubernetes environment. This parameter is + # mutually exclusive with the 'cni.configMap' parameter. The agent will + # write this to 05-cilium.conflist on startup. + # readCniConf: /host/etc/cni/net.d/05-sample.conflist.input + + # -- When defined, configMap will mount the provided value as ConfigMap and + # interpret the cniConf variable as CNI configuration file and write it + # when the agent starts up + # configMap: cni-configuration + + # -- Configure the key in the CNI ConfigMap to read the contents of + # the CNI configuration from. + configMapKey: cni-config + + # -- Configure the path to where to mount the ConfigMap inside the agent pod. + confFileMountPath: /tmp/cni-configuration + + # -- Configure the path to where the CNI configuration directory is mounted + # inside the agent pod. + hostConfDirMountPath: /host/etc/cni/net.d + +# -- (string) Configure how frequently garbage collection should occur for the datapath +# connection tracking table. +# @default -- `"0s"` +conntrackGCInterval: "" + +# -- (string) Configure the maximum frequency for the garbage collection of the +# connection tracking table. Only affects the automatic computation for the frequency +# and has no effect when 'conntrackGCInterval' is set. This can be set to more frequently +# clean up unused identities created from ToFQDN policies. +conntrackGCMaxInterval: "" + +# -- Configure container runtime specific integration. +# Deprecated in favor of bpf.autoMount.enabled. To be removed in 1.15. +containerRuntime: + # -- Enables specific integrations for container runtimes. + # Supported values: + # - crio + # - none + integration: none + +# -- (string) Configure timeout in which Cilium will exit if CRDs are not available +# @default -- `"5m"` +crdWaitTimeout: "" + +# -- Tail call hooks for custom eBPF programs. +customCalls: + # -- Enable tail call hooks for custom eBPF programs. + enabled: false + +daemon: + # -- Configure where Cilium runtime state should be stored. + runPath: "/var/run/cilium" + + # -- Configure a custom list of possible configuration override sources + # The default is "config-map:cilium-config,cilium-node-config". For supported + # values, see the help text for the build-config subcommand. + # Note that this value should be a comma-separated string. + configSources: ~ + + # -- allowedConfigOverrides is a list of config-map keys that can be overridden. + # That is to say, if this value is set, config sources (excepting the first one) can + # only override keys in this list. + # + # This takes precedence over blockedConfigOverrides. + # + # By default, all keys may be overridden. To disable overrides, set this to "none" or + # change the configSources variable. + allowedConfigOverrides: ~ + + # -- blockedConfigOverrides is a list of config-map keys that may not be overridden. + # In other words, if any of these keys appear in a configuration source excepting the + # first one, they will be ignored + # + # This is ignored if allowedConfigOverrides is set. + # + # By default, all keys may be overridden. + blockedConfigOverrides: ~ + +# -- Specify which network interfaces can run the eBPF datapath. This means +# that a packet sent from a pod to a destination outside the cluster will be +# masqueraded (to an output device IPv4 address), if the output device runs the +# program. When not specified, probing will automatically detect devices. +# devices: "" + +# -- Enables experimental support for the detection of new and removed datapath +# devices. When devices change the eBPF datapath is reloaded and services updated. +# If "devices" is set then only those devices, or devices matching a wildcard will +# be considered. +enableRuntimeDeviceDetection: false + +# -- Chains to ignore when installing feeder rules. +# disableIptablesFeederRules: "" + +# -- Limit iptables-based egress masquerading to interface selector. +# egressMasqueradeInterfaces: "" + +# -- Whether to enable CNP status updates. +enableCnpStatusUpdates: false + +# -- Configures the use of the KVStore to optimize Kubernetes event handling by +# mirroring it into the KVstore for reduced overhead in large clusters. +enableK8sEventHandover: false + +# -- Enable setting identity mark for local traffic. +# enableIdentityMark: true + +# -- Enable Kubernetes EndpointSlice feature in Cilium if the cluster supports it. +# enableK8sEndpointSlice: true + +# -- Enable CiliumEndpointSlice feature. +enableCiliumEndpointSlice: false + +envoyConfig: + # -- Enable CiliumEnvoyConfig CRD + # CiliumEnvoyConfig CRD can also be implicitly enabled by other options. + enabled: false + + # -- SecretsNamespace is the namespace in which envoy SDS will retrieve secrets from. + secretsNamespace: + # -- Create secrets namespace for CiliumEnvoyConfig CRDs. + create: true + + # -- The name of the secret namespace to which Cilium agents are given read access. + name: cilium-secrets + +ingressController: + # -- Enable cilium ingress controller + # This will automatically set enable-envoy-config as well. + enabled: false + + # -- Set cilium ingress controller to be the default ingress controller + # This will let cilium ingress controller route entries without ingress class set + default: false + + # -- Default ingress load balancer mode + # Supported values: shared, dedicated + # For granular control, use the following annotations on the ingress resource + # ingress.cilium.io/loadbalancer-mode: shared|dedicated, + loadbalancerMode: dedicated + + # -- Enforce https for host having matching TLS host in Ingress. + # Incoming traffic to http listener will return 308 http error code with respective location in header. + enforceHttps: true + + # -- IngressLBAnnotations are the annotation prefixes, which are used to filter annotations to propagate + # from Ingress to the Load Balancer service + ingressLBAnnotationPrefixes: ['service.beta.kubernetes.io', 'service.kubernetes.io', 'cloud.google.com'] + + # -- Default secret namespace for ingresses without .spec.tls[].secretName set. + defaultSecretNamespace: + + # -- Default secret name for ingresses without .spec.tls[].secretName set. + defaultSecretName: + + # -- SecretsNamespace is the namespace in which envoy SDS will retrieve TLS secrets from. + secretsNamespace: + # -- Create secrets namespace for Ingress. + create: true + + # -- Name of Ingress secret namespace. + name: cilium-secrets + + # -- Enable secret sync, which will make sure all TLS secrets used by Ingress are synced to secretsNamespace.name. + # If disabled, TLS secrets must be maintained externally. + sync: true + + # -- Load-balancer service in shared mode. + # This is a single load-balancer service for all Ingress resources. + service: + # -- Service name + name: cilium-ingress + # -- Labels to be added for the shared LB service + labels: {} + # -- Annotations to be added for the shared LB service + annotations: {} + # -- Service type for the shared LB service + type: LoadBalancer + # -- Configure a specific nodePort for insecure HTTP traffic on the shared LB service + insecureNodePort: ~ + # -- Configure a specific nodePort for secure HTTPS traffic on the shared LB service + secureNodePort : ~ + # -- Configure a specific loadBalancerClass on the shared LB service (requires Kubernetes 1.24+) + loadBalancerClass: ~ + # -- Configure a specific loadBalancerIP on the shared LB service + loadBalancerIP : ~ + # -- Configure if node port allocation is required for LB service + # ref: https://kubernetes.io/docs/concepts/services-networking/service/#load-balancer-nodeport-allocation + allocateLoadBalancerNodePorts: ~ + +gatewayAPI: + # -- Enable support for Gateway API in cilium + # This will automatically set enable-envoy-config as well. + enabled: false + + # -- SecretsNamespace is the namespace in which envoy SDS will retrieve TLS secrets from. + secretsNamespace: + # -- Create secrets namespace for Gateway API. + create: true + + # -- Name of Gateway API secret namespace. + name: cilium-secrets + + # -- Enable secret sync, which will make sure all TLS secrets used by Ingress are synced to secretsNamespace.name. + # If disabled, TLS secrets must be maintained externally. + sync: true + +# -- Enables the fallback compatibility solution for when the xt_socket kernel +# module is missing and it is needed for the datapath L7 redirection to work +# properly. See documentation for details on when this can be disabled: +# https://docs.cilium.io/en/stable/operations/system_requirements/#linux-kernel. +enableXTSocketFallback: true + +encryption: + # -- Enable transparent network encryption. + enabled: false + + # -- Encryption method. Can be either ipsec or wireguard. + type: ipsec + + # -- Enable encryption for pure node to node traffic. + # This option is only effective when encryption.type is set to "wireguard". + nodeEncryption: false + + ipsec: + # -- Name of the key file inside the Kubernetes secret configured via secretName. + keyFile: "" + + # -- Path to mount the secret inside the Cilium pod. + mountPath: "" + + # -- Name of the Kubernetes secret containing the encryption keys. + secretName: "" + + # -- The interface to use for encrypted traffic. + interface: "" + + # -- Enable the key watcher. If disabled, a restart of the agent will be + # necessary on key rotations. + keyWatcher: true + + # -- Maximum duration of the IPsec key rotation. The previous key will be + # removed after that delay. + keyRotationDuration: "5m" + + wireguard: + # -- Enables the fallback to the user-space implementation. + userspaceFallback: false + + # -- Deprecated in favor of encryption.ipsec.keyFile. To be removed in 1.15. + # Name of the key file inside the Kubernetes secret configured via secretName. + # This option is only effective when encryption.type is set to ipsec. + keyFile: keys + + # -- Deprecated in favor of encryption.ipsec.mountPath. To be removed in 1.15. + # Path to mount the secret inside the Cilium pod. + # This option is only effective when encryption.type is set to ipsec. + mountPath: /etc/ipsec + + # -- Deprecated in favor of encryption.ipsec.secretName. To be removed in 1.15. + # Name of the Kubernetes secret containing the encryption keys. + # This option is only effective when encryption.type is set to ipsec. + secretName: cilium-ipsec-keys + + # -- Deprecated in favor of encryption.ipsec.interface. To be removed in 1.15. + # The interface to use for encrypted traffic. + # This option is only effective when encryption.type is set to ipsec. + interface: "" + +endpointHealthChecking: + # -- Enable connectivity health checking between virtual endpoints. + enabled: true + +# -- Enable endpoint status. +# Status can be: policy, health, controllers, log and / or state. For 2 or more options use a space. +endpointStatus: + enabled: false + status: "" + +endpointRoutes: + # -- Enable use of per endpoint routes instead of routing via + # the cilium_host interface. + enabled: false + +k8sNetworkPolicy: + # -- Enable support for K8s NetworkPolicy + enabled: true + +eni: + # -- Enable Elastic Network Interface (ENI) integration. + enabled: false + # -- Update ENI Adapter limits from the EC2 API + updateEC2AdapterLimitViaAPI: true + # -- Release IPs not used from the ENI + awsReleaseExcessIPs: false + # -- Enable ENI prefix delegation + awsEnablePrefixDelegation: false + # -- EC2 API endpoint to use + ec2APIEndpoint: "" + # -- Tags to apply to the newly created ENIs + eniTags: {} + # -- Interval for garbage collection of unattached ENIs. Set to "0s" to disable. + # @default -- `"5m"` + gcInterval: "" + # -- Additional tags attached to ENIs created by Cilium. + # Dangling ENIs with this tag will be garbage collected + # @default -- `{"io.cilium/cilium-managed":"true,"io.cilium/cluster-name":""}` + gcTags: {} + # -- If using IAM role for Service Accounts will not try to + # inject identity values from cilium-aws kubernetes secret. + # Adds annotation to service account if managed by Helm. + # See https://github.com/aws/amazon-eks-pod-identity-webhook + iamRole: "" + # -- Filter via subnet IDs which will dictate which subnets are going to be used to create new ENIs + # Important note: This requires that each instance has an ENI with a matching subnet attached + # when Cilium is deployed. If you only want to control subnets for ENIs attached by Cilium, + # use the CNI configuration file settings (cni.customConf) instead. + subnetIDsFilter: [] + # -- Filter via tags (k=v) which will dictate which subnets are going to be used to create new ENIs + # Important note: This requires that each instance has an ENI with a matching subnet attached + # when Cilium is deployed. If you only want to control subnets for ENIs attached by Cilium, + # use the CNI configuration file settings (cni.customConf) instead. + subnetTagsFilter: [] + # -- Filter via AWS EC2 Instance tags (k=v) which will dictate which AWS EC2 Instances + # are going to be used to create new ENIs + instanceTagsFilter: [] + +externalIPs: + # -- Enable ExternalIPs service support. + enabled: false + +# fragmentTracking enables IPv4 fragment tracking support in the datapath. +# fragmentTracking: true + +gke: + # -- Enable Google Kubernetes Engine integration + enabled: false + +# -- Enable connectivity health checking. +healthChecking: true + +# -- TCP port for the agent health API. This is not the port for cilium-health. +healthPort: 9879 + +# -- Configure the host firewall. +hostFirewall: + # -- Enables the enforcement of host policies in the eBPF datapath. + enabled: false + +hostPort: + # -- Enable hostPort service support. + enabled: false + +# -- Configure socket LB +socketLB: + # -- Enable socket LB + enabled: false + + # -- Disable socket lb for non-root ns. This is used to enable Istio routing rules. + # hostNamespaceOnly: false + +# -- Configure certificate generation for Hubble integration. +# If hubble.tls.auto.method=cronJob, these values are used +# for the Kubernetes CronJob which will be scheduled regularly to +# (re)generate any certificates not provided manually. +certgen: + image: + override: ~ + repository: "quay.io/cilium/certgen" + tag: "v0.1.9" + digest: "sha256:89a0847753686444daabde9474b48340993bd19c7bea66a46e45b2974b82041f" + useDigest: true + pullPolicy: "IfNotPresent" + # -- Seconds after which the completed job pod will be deleted + ttlSecondsAfterFinished: 1800 + # -- Labels to be added to hubble-certgen pods + podLabels: {} + # -- Annotations to be added to the hubble-certgen initial Job and CronJob + annotations: + job: {} + cronJob: {} + # -- Node tolerations for pod assignment on nodes with taints + # ref: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/ + tolerations: [] + + # -- Additional certgen volumes. + extraVolumes: [] + + # -- Additional certgen volumeMounts. + extraVolumeMounts: [] + +hubble: + # -- Enable Hubble (true by default). + enabled: true + + # -- Buffer size of the channel Hubble uses to receive monitor events. If this + # value is not set, the queue size is set to the default monitor queue size. + # eventQueueSize: "" + + # -- Number of recent flows for Hubble to cache. Defaults to 4095. + # Possible values are: + # 1, 3, 7, 15, 31, 63, 127, 255, 511, 1023, + # 2047, 4095, 8191, 16383, 32767, 65535 + # eventBufferCapacity: "4095" + + # -- Hubble metrics configuration. + # See https://docs.cilium.io/en/stable/observability/metrics/#hubble-metrics + # for more comprehensive documentation about Hubble metrics. + metrics: + # -- Configures the list of metrics to collect. If empty or null, metrics + # are disabled. + # Example: + # + # enabled: + # - dns:query;ignoreAAAA + # - drop + # - tcp + # - flow + # - icmp + # - http + # + # You can specify the list of metrics from the helm CLI: + # + # --set metrics.enabled="{dns:query;ignoreAAAA,drop,tcp,flow,icmp,http}" + # + enabled: ~ + # -- Enables exporting hubble metrics in OpenMetrics format. + enableOpenMetrics: false + # -- Configure the port the hubble metric server listens on. + port: 9965 + # -- Annotations to be added to hubble-metrics service. + serviceAnnotations: {} + serviceMonitor: + # -- Create ServiceMonitor resources for Prometheus Operator. + # This requires the prometheus CRDs to be available. + # ref: https://github.com/prometheus-operator/prometheus-operator/blob/main/example/prometheus-operator-crd/monitoring.coreos.com_servicemonitors.yaml) + enabled: false + # -- Labels to add to ServiceMonitor hubble + labels: {} + # -- Annotations to add to ServiceMonitor hubble + annotations: {} + # -- Interval for scrape metrics. + interval: "10s" + # -- Relabeling configs for the ServiceMonitor hubble + relabelings: + - sourceLabels: + - __meta_kubernetes_pod_node_name + targetLabel: node + replacement: ${1} + # -- Metrics relabeling configs for the ServiceMonitor hubble + metricRelabelings: ~ + # -- Grafana dashboards for hubble + # grafana can import dashboards based on the label and value + # ref: https://github.com/grafana/helm-charts/tree/main/charts/grafana#sidecar-for-dashboards + dashboards: + enabled: false + label: grafana_dashboard + namespace: ~ + labelValue: "1" + annotations: {} + + # -- Unix domain socket path to listen to when Hubble is enabled. + socketPath: /var/run/cilium/hubble.sock + + # -- An additional address for Hubble to listen to. + # Set this field ":4244" if you are enabling Hubble Relay, as it assumes that + # Hubble is listening on port 4244. + listenAddress: ":4244" + # -- Whether Hubble should prefer to announce IPv6 or IPv4 addresses if both are available. + preferIpv6: false + # -- (bool) Skip Hubble events with unknown cgroup ids + # @default -- `true` + skipUnknownCGroupIDs: ~ + + peerService: + # -- Service Port for the Peer service. + # If not set, it is dynamically assigned to port 443 if TLS is enabled and to + # port 80 if not. + # servicePort: 80 + # -- Target Port for the Peer service, must match the hubble.listenAddress' + # port. + targetPort: 4244 + # -- The cluster domain to use to query the Hubble Peer service. It should + # be the local cluster. + clusterDomain: cluster.local + # -- TLS configuration for Hubble + tls: + # -- Enable mutual TLS for listenAddress. Setting this value to false is + # highly discouraged as the Hubble API provides access to potentially + # sensitive network flow metadata and is exposed on the host network. + enabled: true + # -- Configure automatic TLS certificates generation. + auto: + # -- Auto-generate certificates. + # When set to true, automatically generate a CA and certificates to + # enable mTLS between Hubble server and Hubble Relay instances. If set to + # false, the certs for Hubble server need to be provided by setting + # appropriate values below. + enabled: true + # -- Set the method to auto-generate certificates. Supported values: + # - helm: This method uses Helm to generate all certificates. + # - cronJob: This method uses a Kubernetes CronJob the generate any + # certificates not provided by the user at installation + # time. + # - certmanager: This method use cert-manager to generate & rotate certificates. + method: helm + # -- Generated certificates validity duration in days. + certValidityDuration: 1095 + # -- Schedule for certificates regeneration (regardless of their expiration date). + # Only used if method is "cronJob". If nil, then no recurring job will be created. + # Instead, only the one-shot job is deployed to generate the certificates at + # installation time. + # + # Defaults to midnight of the first day of every fourth month. For syntax, see + # https://kubernetes.io/docs/concepts/workloads/controllers/cron-jobs/#schedule-syntax + schedule: "0 0 1 */4 *" + + # [Example] + # certManagerIssuerRef: + # group: cert-manager.io + # kind: ClusterIssuer + # name: ca-issuer + # -- certmanager issuer used when hubble.tls.auto.method=certmanager. + certManagerIssuerRef: {} + + # -- base64 encoded PEM values for the Hubble server certificate and private key + server: + cert: "" + key: "" + # -- Extra DNS names added to certificate when it's auto generated + extraDnsNames: [] + # -- Extra IP addresses added to certificate when it's auto generated + extraIpAddresses: [] + + relay: + # -- Enable Hubble Relay (requires hubble.enabled=true) + enabled: false + + # -- Roll out Hubble Relay pods automatically when configmap is updated. + rollOutPods: false + + # -- Hubble-relay container image. + image: + override: ~ + repository: "quay.io/cilium/hubble-relay" + tag: "v1.14.5" + # hubble-relay-digest + digest: "sha256:dbef89f924a927043d02b40c18e417c1ea0e8f58b44523b80fef7e3652db24d4" + useDigest: true + pullPolicy: "IfNotPresent" + + # -- Specifies the resources for the hubble-relay pods + resources: {} + + # -- Number of replicas run for the hubble-relay deployment. + replicas: 1 + + # -- Affinity for hubble-replay + affinity: + podAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - topologyKey: kubernetes.io/hostname + labelSelector: + matchLabels: + k8s-app: cilium + + # -- Pod topology spread constraints for hubble-relay + topologySpreadConstraints: [] + # - maxSkew: 1 + # topologyKey: topology.kubernetes.io/zone + # whenUnsatisfiable: DoNotSchedule + + # -- Node labels for pod assignment + # ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#nodeselector + nodeSelector: + kubernetes.io/os: linux + + # -- Node tolerations for pod assignment on nodes with taints + # ref: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/ + tolerations: [] + + # -- Additional hubble-relay environment variables. + extraEnv: [] + + # -- Annotations to be added to hubble-relay pods + podAnnotations: {} + + # -- Labels to be added to hubble-relay pods + podLabels: {} + + # PodDisruptionBudget settings + podDisruptionBudget: + # -- enable PodDisruptionBudget + # ref: https://kubernetes.io/docs/concepts/workloads/pods/disruptions/ + enabled: false + # -- Minimum number/percentage of pods that should remain scheduled. + # When it's set, maxUnavailable must be disabled by `maxUnavailable: null` + minAvailable: null + # -- Maximum number/percentage of pods that may be made unavailable + maxUnavailable: 1 + + # -- The priority class to use for hubble-relay + priorityClassName: "" + + # -- Configure termination grace period for hubble relay Deployment. + terminationGracePeriodSeconds: 1 + + # -- hubble-relay update strategy + updateStrategy: + type: RollingUpdate + rollingUpdate: + maxUnavailable: 1 + + # -- Additional hubble-relay volumes. + extraVolumes: [] + + # -- Additional hubble-relay volumeMounts. + extraVolumeMounts: [] + + # -- hubble-relay pod security context + podSecurityContext: + fsGroup: 65532 + + # -- hubble-relay container security context + securityContext: + # readOnlyRootFilesystem: true + runAsNonRoot: true + runAsUser: 65532 + runAsGroup: 65532 + capabilities: + drop: + - ALL + + # -- hubble-relay service configuration. + service: + # --- The type of service used for Hubble Relay access, either ClusterIP or NodePort. + type: ClusterIP + # --- The port to use when the service type is set to NodePort. + nodePort: 31234 + + # -- Host to listen to. Specify an empty string to bind to all the interfaces. + listenHost: "" + + # -- Port to listen to. + listenPort: "4245" + + # -- TLS configuration for Hubble Relay + tls: + # -- base64 encoded PEM values for the hubble-relay client certificate and private key + # This keypair is presented to Hubble server instances for mTLS + # authentication and is required when hubble.tls.enabled is true. + # These values need to be set manually if hubble.tls.auto.enabled is false. + client: + cert: "" + key: "" + # -- base64 encoded PEM values for the hubble-relay server certificate and private key + server: + # When set to true, enable TLS on for Hubble Relay server + # (ie: for clients connecting to the Hubble Relay API). + enabled: false + # When set to true enforces mutual TLS between Hubble Relay server and its clients. + # False allow non-mutual TLS connections. + # This option has no effect when TLS is disabled. + mtls: false + # These values need to be set manually if hubble.tls.auto.enabled is false. + cert: "" + key: "" + # -- extra DNS names added to certificate when its auto gen + extraDnsNames: [] + # -- extra IP addresses added to certificate when its auto gen + extraIpAddresses: [] + + # -- Dial timeout to connect to the local hubble instance to receive peer information (e.g. "30s"). + dialTimeout: ~ + + # -- Backoff duration to retry connecting to the local hubble instance in case of failure (e.g. "30s"). + retryTimeout: ~ + + # -- Max number of flows that can be buffered for sorting before being sent to the + # client (per request) (e.g. 100). + sortBufferLenMax: ~ + + # -- When the per-request flows sort buffer is not full, a flow is drained every + # time this timeout is reached (only affects requests in follow-mode) (e.g. "1s"). + sortBufferDrainTimeout: ~ + + # -- Port to use for the k8s service backed by hubble-relay pods. + # If not set, it is dynamically assigned to port 443 if TLS is enabled and to + # port 80 if not. + # servicePort: 80 + + # -- Enable prometheus metrics for hubble-relay on the configured port at + # /metrics + prometheus: + enabled: false + port: 9966 + serviceMonitor: + # -- Enable service monitors. + # This requires the prometheus CRDs to be available (see https://github.com/prometheus-operator/prometheus-operator/blob/main/example/prometheus-operator-crd/monitoring.coreos.com_servicemonitors.yaml) + enabled: false + # -- Labels to add to ServiceMonitor hubble-relay + labels: {} + # -- Annotations to add to ServiceMonitor hubble-relay + annotations: {} + # -- Interval for scrape metrics. + interval: "10s" + # -- Specify the Kubernetes namespace where Prometheus expects to find + # service monitors configured. + # namespace: "" + # -- Relabeling configs for the ServiceMonitor hubble-relay + relabelings: ~ + # -- Metrics relabeling configs for the ServiceMonitor hubble-relay + metricRelabelings: ~ + + gops: + # -- Enable gops for hubble-relay + enabled: true + # -- Configure gops listen port for hubble-relay + port: 9893 + + pprof: + # -- Enable pprof for hubble-relay + enabled: false + # -- Configure pprof listen address for hubble-relay + address: localhost + # -- Configure pprof listen port for hubble-relay + port: 6062 + + ui: + # -- Whether to enable the Hubble UI. + enabled: false + + standalone: + # -- When true, it will allow installing the Hubble UI only, without checking dependencies. + # It is useful if a cluster already has cilium and Hubble relay installed and you just + # want Hubble UI to be deployed. + # When installed via helm, installing UI should be done via `helm upgrade` and when installed via the cilium cli, then `cilium hubble enable --ui` + enabled: false + + tls: + # -- When deploying Hubble UI in standalone, with tls enabled for Hubble relay, it is required + # to provide a volume for mounting the client certificates. + certsVolume: {} + # projected: + # defaultMode: 0400 + # sources: + # - secret: + # name: hubble-ui-client-certs + # items: + # - key: tls.crt + # path: client.crt + # - key: tls.key + # path: client.key + # - key: ca.crt + # path: hubble-relay-ca.crt + + # -- Roll out Hubble-ui pods automatically when configmap is updated. + rollOutPods: false + + tls: + # -- base64 encoded PEM values used to connect to hubble-relay + # This keypair is presented to Hubble Relay instances for mTLS + # authentication and is required when hubble.relay.tls.server.enabled is true. + # These values need to be set manually if hubble.tls.auto.enabled is false. + client: + cert: "" + key: "" + + backend: + # -- Hubble-ui backend image. + image: + override: ~ + repository: "quay.io/cilium/hubble-ui-backend" + tag: "v0.12.1" + digest: "sha256:1f86f3400827a0451e6332262467f894eeb7caf0eb8779bd951e2caa9d027cbe" + useDigest: true + pullPolicy: "IfNotPresent" + + # -- Hubble-ui backend security context. + securityContext: {} + + # -- Additional hubble-ui backend environment variables. + extraEnv: [] + + # -- Additional hubble-ui backend volumes. + extraVolumes: [] + + # -- Additional hubble-ui backend volumeMounts. + extraVolumeMounts: [] + + # -- Resource requests and limits for the 'backend' container of the 'hubble-ui' deployment. + resources: {} + # limits: + # cpu: 1000m + # memory: 1024M + # requests: + # cpu: 100m + # memory: 64Mi + + frontend: + # -- Hubble-ui frontend image. + image: + override: ~ + repository: "quay.io/cilium/hubble-ui" + tag: "v0.12.1" + digest: "sha256:9e5f81ee747866480ea1ac4630eb6975ff9227f9782b7c93919c081c33f38267" + useDigest: true + pullPolicy: "IfNotPresent" + + # -- Hubble-ui frontend security context. + securityContext: {} + + # -- Additional hubble-ui frontend environment variables. + extraEnv: [] + + # -- Additional hubble-ui frontend volumes. + extraVolumes: [] + + # -- Additional hubble-ui frontend volumeMounts. + extraVolumeMounts: [] + + # -- Resource requests and limits for the 'frontend' container of the 'hubble-ui' deployment. + resources: {} + # limits: + # cpu: 1000m + # memory: 1024M + # requests: + # cpu: 100m + # memory: 64Mi + server: + # -- Controls server listener for ipv6 + ipv6: + enabled: true + + # -- The number of replicas of Hubble UI to deploy. + replicas: 1 + + # -- Annotations to be added to hubble-ui pods + podAnnotations: {} + + # -- Labels to be added to hubble-ui pods + podLabels: {} + + # PodDisruptionBudget settings + podDisruptionBudget: + # -- enable PodDisruptionBudget + # ref: https://kubernetes.io/docs/concepts/workloads/pods/disruptions/ + enabled: false + # -- Minimum number/percentage of pods that should remain scheduled. + # When it's set, maxUnavailable must be disabled by `maxUnavailable: null` + minAvailable: null + # -- Maximum number/percentage of pods that may be made unavailable + maxUnavailable: 1 + + # -- Affinity for hubble-ui + affinity: {} + + # -- Pod topology spread constraints for hubble-ui + topologySpreadConstraints: [] + # - maxSkew: 1 + # topologyKey: topology.kubernetes.io/zone + # whenUnsatisfiable: DoNotSchedule + + # -- Node labels for pod assignment + # ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#nodeselector + nodeSelector: + kubernetes.io/os: linux + + # -- Node tolerations for pod assignment on nodes with taints + # ref: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/ + tolerations: [] + + # -- The priority class to use for hubble-ui + priorityClassName: "" + + # -- hubble-ui update strategy. + updateStrategy: + type: RollingUpdate + rollingUpdate: + maxUnavailable: 1 + + # -- Security context to be added to Hubble UI pods + securityContext: + runAsUser: 1001 + runAsGroup: 1001 + fsGroup: 1001 + + # -- hubble-ui service configuration. + service: + # -- Annotations to be added for the Hubble UI service + annotations: {} + # --- The type of service used for Hubble UI access, either ClusterIP or NodePort. + type: ClusterIP + # --- The port to use when the service type is set to NodePort. + nodePort: 31235 + + # -- Defines base url prefix for all hubble-ui http requests. + # It needs to be changed in case if ingress for hubble-ui is configured under some sub-path. + # Trailing `/` is required for custom path, ex. `/service-map/` + baseUrl: "/" + + # -- hubble-ui ingress configuration. + ingress: + enabled: false + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + className: "" + hosts: + - chart-example.local + labels: {} + tls: [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + +# -- Method to use for identity allocation (`crd` or `kvstore`). +identityAllocationMode: "crd" + +# -- (string) Time to wait before using new identity on endpoint identity change. +# @default -- `"5s"` +identityChangeGracePeriod: "" + +# -- Install Iptables rules to skip netfilter connection tracking on all pod +# traffic. This option is only effective when Cilium is running in direct +# routing and full KPR mode. Moreover, this option cannot be enabled when Cilium +# is running in a managed Kubernetes environment or in a chained CNI setup. +installNoConntrackIptablesRules: false + +ipam: + # -- Configure IP Address Management mode. + # ref: https://docs.cilium.io/en/stable/network/concepts/ipam/ + mode: "cluster-pool" + # -- Maximum rate at which the CiliumNode custom resource is updated. + ciliumNodeUpdateRate: "15s" + operator: + # -- IPv4 CIDR list range to delegate to individual nodes for IPAM. + clusterPoolIPv4PodCIDRList: ["10.0.0.0/8"] + # -- IPv4 CIDR mask size to delegate to individual nodes for IPAM. + clusterPoolIPv4MaskSize: 24 + # -- IPv6 CIDR list range to delegate to individual nodes for IPAM. + clusterPoolIPv6PodCIDRList: ["fd00::/104"] + # -- IPv6 CIDR mask size to delegate to individual nodes for IPAM. + clusterPoolIPv6MaskSize: 120 + # -- IP pools to auto-create in multi-pool IPAM mode. + autoCreateCiliumPodIPPools: {} + # default: + # ipv4: + # cidrs: + # - 10.10.0.0/8 + # maskSize: 24 + # other: + # ipv6: + # cidrs: + # - fd00:100::/80 + # maskSize: 96 + # -- The maximum burst size when rate limiting access to external APIs. + # Also known as the token bucket capacity. + # @default -- `20` + externalAPILimitBurstSize: ~ + # -- The maximum queries per second when rate limiting access to + # external APIs. Also known as the bucket refill rate, which is used to + # refill the bucket up to the burst size capacity. + # @default -- `4.0` + externalAPILimitQPS: ~ + +# -- Configure the eBPF-based ip-masq-agent +ipMasqAgent: + enabled: false +# the config of nonMasqueradeCIDRs +# config: + # nonMasqueradeCIDRs: [] + # masqLinkLocal: false + # masqLinkLocalIPv6: false + +# iptablesLockTimeout defines the iptables "--wait" option when invoked from Cilium. +# iptablesLockTimeout: "5s" + +ipv4: + # -- Enable IPv4 support. + enabled: true + +ipv6: + # -- Enable IPv6 support. + enabled: false + +# -- Configure Kubernetes specific configuration +k8s: {} + # -- requireIPv4PodCIDR enables waiting for Kubernetes to provide the PodCIDR + # range via the Kubernetes node resource + # requireIPv4PodCIDR: false + + # -- requireIPv6PodCIDR enables waiting for Kubernetes to provide the PodCIDR + # range via the Kubernetes node resource + # requireIPv6PodCIDR: false + +# -- Keep the deprecated selector labels when deploying Cilium DaemonSet. +keepDeprecatedLabels: false + +# -- Keep the deprecated probes when deploying Cilium DaemonSet +keepDeprecatedProbes: false + +startupProbe: + # -- failure threshold of startup probe. + # 105 x 2s translates to the old behaviour of the readiness probe (120s delay + 30 x 3s) + failureThreshold: 105 + # -- interval between checks of the startup probe + periodSeconds: 2 +livenessProbe: + # -- failure threshold of liveness probe + failureThreshold: 10 + # -- interval between checks of the liveness probe + periodSeconds: 30 +readinessProbe: + # -- failure threshold of readiness probe + failureThreshold: 3 + # -- interval between checks of the readiness probe + periodSeconds: 30 + +# -- Configure the kube-proxy replacement in Cilium BPF datapath +# Valid options are "true", "false", "disabled" (deprecated), "partial" (deprecated), "strict" (deprecated). +# ref: https://docs.cilium.io/en/stable/network/kubernetes/kubeproxy-free/ +#kubeProxyReplacement: "false" + +# -- healthz server bind address for the kube-proxy replacement. +# To enable set the value to '0.0.0.0:10256' for all ipv4 +# addresses and this '[::]:10256' for all ipv6 addresses. +# By default it is disabled. +kubeProxyReplacementHealthzBindAddr: "" + +l2NeighDiscovery: + # -- Enable L2 neighbor discovery in the agent + enabled: true + # -- Override the agent's default neighbor resolution refresh period. + refreshPeriod: "30s" + +# -- Enable Layer 7 network policy. +l7Proxy: true + +# -- Enable Local Redirect Policy. +localRedirectPolicy: false + +# To include or exclude matched resources from cilium identity evaluation +# labels: "" + +# logOptions allows you to define logging options. eg: +# logOptions: +# format: json + +# -- Enables periodic logging of system load +logSystemLoad: false + +# -- Configure maglev consistent hashing +maglev: {} + # -- tableSize is the size (parameter M) for the backend table of one + # service entry + # tableSize: + + # -- hashSeed is the cluster-wide base64 encoded seed for the hashing + # hashSeed: + +# -- Enables masquerading of IPv4 traffic leaving the node from endpoints. +enableIPv4Masquerade: true + +# -- Enables IPv6 BIG TCP support which increases maximum IPv6 GSO/GRO limits for nodes and pods +enableIPv6BIGTCP: false + +# -- Enables IPv4 BIG TCP support which increases maximum IPv4 GSO/GRO limits for nodes and pods +enableIPv4BIGTCP: false + +# -- Enables masquerading of IPv6 traffic leaving the node from endpoints. +enableIPv6Masquerade: true + +# -- Enables egress gateway to redirect and SNAT the traffic that leaves the +# cluster. +egressGateway: + enabled: false + # -- Install egress gateway IP rules and routes in order to properly steer + # egress gateway traffic to the correct ENI interface + installRoutes: false + # -- Time between triggers of egress gateway state reconciliations + reconciliationTriggerInterval: 1s + # -- Maximum number of entries in egress gateway policy map + # maxPolicyEntries: 16384 + +vtep: +# -- Enables VXLAN Tunnel Endpoint (VTEP) Integration (beta) to allow +# Cilium-managed pods to talk to third party VTEP devices over Cilium tunnel. + enabled: false + +# -- A space separated list of VTEP device endpoint IPs, for example "1.1.1.1 1.1.2.1" + endpoint: "" +# -- A space separated list of VTEP device CIDRs, for example "1.1.1.0/24 1.1.2.0/24" + cidr: "" +# -- VTEP CIDRs Mask that applies to all VTEP CIDRs, for example "255.255.255.0" + mask: "" +# -- A space separated list of VTEP device MAC addresses (VTEP MAC), for example "x:x:x:x:x:x y:y:y:y:y:y:y" + mac: "" + +# -- (string) Allows to explicitly specify the IPv4 CIDR for native routing. +# When specified, Cilium assumes networking for this CIDR is preconfigured and +# hands traffic destined for that range to the Linux network stack without +# applying any SNAT. +# Generally speaking, specifying a native routing CIDR implies that Cilium can +# depend on the underlying networking stack to route packets to their +# destination. To offer a concrete example, if Cilium is configured to use +# direct routing and the Kubernetes CIDR is included in the native routing CIDR, +# the user must configure the routes to reach pods, either manually or by +# setting the auto-direct-node-routes flag. +ipv4NativeRoutingCIDR: "" + +# -- (string) Allows to explicitly specify the IPv6 CIDR for native routing. +# When specified, Cilium assumes networking for this CIDR is preconfigured and +# hands traffic destined for that range to the Linux network stack without +# applying any SNAT. +# Generally speaking, specifying a native routing CIDR implies that Cilium can +# depend on the underlying networking stack to route packets to their +# destination. To offer a concrete example, if Cilium is configured to use +# direct routing and the Kubernetes CIDR is included in the native routing CIDR, +# the user must configure the routes to reach pods, either manually or by +# setting the auto-direct-node-routes flag. +ipv6NativeRoutingCIDR: "" + +# -- cilium-monitor sidecar. +monitor: + # -- Enable the cilium-monitor sidecar. + enabled: false + +# -- Configure service load balancing +loadBalancer: + # -- standalone enables the standalone L4LB which does not connect to + # kube-apiserver. + # standalone: false + + # -- algorithm is the name of the load balancing algorithm for backend + # selection e.g. random or maglev + # algorithm: random + + # -- mode is the operation mode of load balancing for remote backends + # e.g. snat, dsr, hybrid + # mode: snat + + # -- acceleration is the option to accelerate service handling via XDP + # e.g. native, disabled + # acceleration: disabled + + # -- dsrDispatch configures whether IP option or IPIP encapsulation is + # used to pass a service IP and port to remote backend + # dsrDispatch: opt + + # -- serviceTopology enables K8s Topology Aware Hints -based service + # endpoints filtering + # serviceTopology: false + + # -- L7 LoadBalancer + l7: + # -- Enable L7 service load balancing via envoy proxy. + # The request to a k8s service, which has specific annotation e.g. service.cilium.io/lb-l7, + # will be forwarded to the local backend proxy to be load balanced to the service endpoints. + # Please refer to docs for supported annotations for more configuration. + # + # Applicable values: + # - envoy: Enable L7 load balancing via envoy proxy. This will automatically set enable-envoy-config as well. + # - disabled: Disable L7 load balancing by way of service annotation. + backend: disabled + # -- List of ports from service to be automatically redirected to above backend. + # Any service exposing one of these ports will be automatically redirected. + # Fine-grained control can be achieved by using the service annotation. + ports: [] + # -- Default LB algorithm + # The default LB algorithm to be used for services, which can be overridden by the + # service annotation (e.g. service.cilium.io/lb-l7-algorithm) + # Applicable values: round_robin, least_request, random + algorithm: round_robin + +# -- Configure N-S k8s service loadbalancing +nodePort: + # -- Enable the Cilium NodePort service implementation. + enabled: false + + # -- Port range to use for NodePort services. + # range: "30000,32767" + + # -- Set to true to prevent applications binding to service ports. + bindProtection: true + + # -- Append NodePort range to ip_local_reserved_ports if clash with ephemeral + # ports is detected. + autoProtectPortRange: true + + # -- Enable healthcheck nodePort server for NodePort services + enableHealthCheck: true + +# policyAuditMode: false + +# -- The agent can be put into one of the three policy enforcement modes: +# default, always and never. +# ref: https://docs.cilium.io/en/stable/security/policy/intro/#policy-enforcement-modes +policyEnforcementMode: "default" + +pprof: + # -- Enable pprof for cilium-agent + enabled: false + # -- Configure pprof listen address for cilium-agent + address: localhost + # -- Configure pprof listen port for cilium-agent + port: 6060 + +# -- Configure prometheus metrics on the configured port at /metrics +prometheus: + enabled: false + port: 9962 + serviceMonitor: + # -- Enable service monitors. + # This requires the prometheus CRDs to be available (see https://github.com/prometheus-operator/prometheus-operator/blob/main/example/prometheus-operator-crd/monitoring.coreos.com_servicemonitors.yaml) + enabled: false + # -- Labels to add to ServiceMonitor cilium-agent + labels: {} + # -- Annotations to add to ServiceMonitor cilium-agent + annotations: {} + # -- Interval for scrape metrics. + interval: "10s" + # -- Specify the Kubernetes namespace where Prometheus expects to find + # service monitors configured. + # namespace: "" + # -- Relabeling configs for the ServiceMonitor cilium-agent + relabelings: + - sourceLabels: + - __meta_kubernetes_pod_node_name + targetLabel: node + replacement: ${1} + # -- Metrics relabeling configs for the ServiceMonitor cilium-agent + metricRelabelings: ~ + # -- Set to `true` and helm will not check for monitoring.coreos.com/v1 CRDs before deploying + trustCRDsExist: false + + # -- Metrics that should be enabled or disabled from the default metric list. + # The list is expected to be separated by a space. (+metric_foo to enable + # metric_foo , -metric_bar to disable metric_bar). + # ref: https://docs.cilium.io/en/stable/observability/metrics/ + metrics: ~ + +# -- Grafana dashboards for cilium-agent +# grafana can import dashboards based on the label and value +# ref: https://github.com/grafana/helm-charts/tree/main/charts/grafana#sidecar-for-dashboards +dashboards: + enabled: false + label: grafana_dashboard + namespace: ~ + labelValue: "1" + annotations: {} + +# -- Configure Istio proxy options. +proxy: + + prometheus: + # -- Deprecated in favor of envoy.prometheus.enabled + enabled: true + # -- Deprecated in favor of envoy.prometheus.port + port: ~ + # -- Regular expression matching compatible Istio sidecar istio-proxy + # container image names + sidecarImageRegex: "cilium/istio_proxy" + +# Configure Cilium Envoy options. +envoy: + # -- Enable Envoy Proxy in standalone DaemonSet. + enabled: false + + log: + # -- The format string to use for laying out the log message metadata of Envoy. + format: "[%Y-%m-%d %T.%e][%t][%l][%n] [%g:%#] %v" + # -- Path to a separate Envoy log file, if any. Defaults to /dev/stdout. + path: "" + + # -- Time in seconds after which a TCP connection attempt times out + connectTimeoutSeconds: 2 + # -- ProxyMaxRequestsPerConnection specifies the max_requests_per_connection setting for Envoy + maxRequestsPerConnection: 0 + # -- Set Envoy HTTP option max_connection_duration seconds. Default 0 (disable) + maxConnectionDurationSeconds: 0 + # -- Set Envoy upstream HTTP idle connection timeout seconds. + # Does not apply to connections with pending requests. Default 60s + idleTimeoutDurationSeconds: 60 + + # -- Envoy container image. + image: + override: ~ + repository: "quay.io/cilium/cilium-envoy" + tag: "v1.26.6-ad82c7c56e88989992fd25d8d67747de865c823b" + pullPolicy: "IfNotPresent" + digest: "sha256:992998398dadfff7117bfa9fdb7c9474fefab7f0237263f7c8114e106c67baca" + useDigest: true + + # -- Additional containers added to the cilium Envoy DaemonSet. + extraContainers: [] + + # -- Additional envoy container arguments. + extraArgs: [] + + # -- Additional envoy container environment variables. + extraEnv: [] + + # -- Additional envoy hostPath mounts. + extraHostPathMounts: [] + # - name: host-mnt-data + # mountPath: /host/mnt/data + # hostPath: /mnt/data + # hostPathType: Directory + # readOnly: true + # mountPropagation: HostToContainer + + # -- Additional envoy volumes. + extraVolumes: [] + + # -- Additional envoy volumeMounts. + extraVolumeMounts: [] + + # -- Configure termination grace period for cilium-envoy DaemonSet. + terminationGracePeriodSeconds: 1 + + # -- TCP port for the health API. + healthPort: 9878 + + # -- cilium-envoy update strategy + # ref: https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/#updating-a-daemonset + updateStrategy: + type: RollingUpdate + rollingUpdate: + maxUnavailable: 2 + # -- Roll out cilium envoy pods automatically when configmap is updated. + rollOutPods: false + + # -- Security Context for cilium-envoy pods. + podSecurityContext: {} + + # -- Annotations to be added to envoy pods + podAnnotations: {} + + # -- Labels to be added to envoy pods + podLabels: {} + + # -- Envoy resource limits & requests + # ref: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + resources: {} + # limits: + # cpu: 4000m + # memory: 4Gi + # requests: + # cpu: 100m + # memory: 512Mi + + startupProbe: + # -- failure threshold of startup probe. + # 105 x 2s translates to the old behaviour of the readiness probe (120s delay + 30 x 3s) + failureThreshold: 105 + # -- interval between checks of the startup probe + periodSeconds: 2 + livenessProbe: + # -- failure threshold of liveness probe + failureThreshold: 10 + # -- interval between checks of the liveness probe + periodSeconds: 30 + readinessProbe: + # -- failure threshold of readiness probe + failureThreshold: 3 + # -- interval between checks of the readiness probe + periodSeconds: 30 + + securityContext: + # -- User to run the pod with + # runAsUser: 0 + # -- Run the pod with elevated privileges + privileged: false + # -- SELinux options for the `cilium-envoy` container + seLinuxOptions: + level: 's0' + # Running with spc_t since we have removed the privileged mode. + # Users can change it to a different type as long as they have the + # type available on the system. + type: 'spc_t' + capabilities: + # -- Capabilities for the `cilium-envoy` container + envoy: + # Used since cilium proxy uses setting IPPROTO_IP/IP_TRANSPARENT + - NET_ADMIN + # We need it for now but might not need it for >= 5.11 specially + # for the 'SYS_RESOURCE'. + # In >= 5.8 there's already BPF and PERMON capabilities + - SYS_ADMIN + # Both PERFMON and BPF requires kernel 5.8, container runtime + # cri-o >= v1.22.0 or containerd >= v1.5.0. + # If available, SYS_ADMIN can be removed. + #- PERFMON + #- BPF + + # -- Affinity for cilium-envoy. + affinity: + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - topologyKey: kubernetes.io/hostname + labelSelector: + matchLabels: + k8s-app: cilium-envoy + + # -- Node selector for cilium-envoy. + nodeSelector: + kubernetes.io/os: linux + + # -- Node tolerations for envoy scheduling to nodes with taints + # ref: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/ + tolerations: + - operator: Exists + # - key: "key" + # operator: "Equal|Exists" + # value: "value" + # effect: "NoSchedule|PreferNoSchedule|NoExecute(1.6 only)" + + # -- The priority class to use for cilium-envoy. + priorityClassName: ~ + + # -- DNS policy for Cilium envoy pods. + # Ref: https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-s-dns-policy + dnsPolicy: ~ + + prometheus: + # -- Enable prometheus metrics for cilium-envoy + enabled: true + serviceMonitor: + # -- Enable service monitors. + # This requires the prometheus CRDs to be available (see https://github.com/prometheus-operator/prometheus-operator/blob/main/example/prometheus-operator-crd/monitoring.coreos.com_servicemonitors.yaml) + enabled: false + # -- Labels to add to ServiceMonitor cilium-envoy + labels: {} + # -- Annotations to add to ServiceMonitor cilium-envoy + annotations: {} + # -- Interval for scrape metrics. + interval: "10s" + # -- Specify the Kubernetes namespace where Prometheus expects to find + # service monitors configured. + # namespace: "" + # -- Relabeling configs for the ServiceMonitor cilium-envoy + relabelings: + - sourceLabels: + - __meta_kubernetes_pod_node_name + targetLabel: node + replacement: ${1} + # -- Metrics relabeling configs for the ServiceMonitor cilium-envoy + metricRelabelings: ~ + # -- Serve prometheus metrics for cilium-envoy on the configured port + port: "9964" + +# -- Enable use of the remote node identity. +# ref: https://docs.cilium.io/en/v1.7/install/upgrade/#configmap-remote-node-identity +remoteNodeIdentity: true + +# -- Enable resource quotas for priority classes used in the cluster. +resourceQuotas: + enabled: false + cilium: + hard: + # 5k nodes * 2 DaemonSets (Cilium and cilium node init) + pods: "10k" + operator: + hard: + # 15 "clusterwide" Cilium Operator pods for HA + pods: "15" + +# Need to document default +################## +#sessionAffinity: false + +# -- Do not run Cilium agent when running with clean mode. Useful to completely +# uninstall Cilium as it will stop Cilium from starting and create artifacts +# in the node. +sleepAfterInit: false + +# -- Enable check of service source ranges (currently, only for LoadBalancer). +svcSourceRangeCheck: true + +# -- Synchronize Kubernetes nodes to kvstore and perform CNP GC. +synchronizeK8sNodes: true + +# -- Configure TLS configuration in the agent. +tls: + # -- This configures how the Cilium agent loads the secrets used TLS-aware CiliumNetworkPolicies + # (namely the secrets referenced by terminatingTLS and originatingTLS). + # Possible values: + # - local + # - k8s + secretsBackend: local + + # -- Base64 encoded PEM values for the CA certificate and private key. + # This can be used as common CA to generate certificates used by hubble and clustermesh components. + # It is neither required nor used when cert-manager is used to generate the certificates. + ca: + # -- Optional CA cert. If it is provided, it will be used by cilium to + # generate all other certificates. Otherwise, an ephemeral CA is generated. + cert: "" + + # -- Optional CA private key. If it is provided, it will be used by cilium to + # generate all other certificates. Otherwise, an ephemeral CA is generated. + key: "" + + # -- Generated certificates validity duration in days. This will be used for auto generated CA. + certValidityDuration: 1095 + + # -- Configure the CA trust bundle used for the validation of the certificates + # leveraged by hubble and clustermesh. When enabled, it overrides the content of the + # 'ca.crt' field of the respective certificates, allowing for CA rotation with no down-time. + caBundle: + # -- Enable the use of the CA trust bundle. + enabled: false + + # -- Name of the ConfigMap containing the CA trust bundle. + name: cilium-root-ca.crt + + # -- Entry of the ConfigMap containing the CA trust bundle. + key: ca.crt + + # -- Use a Secret instead of a ConfigMap. + useSecret: false + + # If uncommented, creates the ConfigMap and fills it with the specified content. + # Otherwise, the ConfigMap is assumed to be already present in .Release.Namespace. + # + # content: | + # -----BEGIN CERTIFICATE----- + # ... + # -----END CERTIFICATE----- + # -----BEGIN CERTIFICATE----- + # ... + # -----END CERTIFICATE----- + +# -- Configure the encapsulation configuration for communication between nodes. +# Deprecated in favor of tunnelProtocol and routingMode. To be removed in 1.15. +# Possible values: +# - disabled +# - vxlan +# - geneve +# @default -- `"vxlan"` +tunnel: "" + +# -- Tunneling protocol to use in tunneling mode and for ad-hoc tunnels. +# Possible values: +# - "" +# - vxlan +# - geneve +# @default -- `"vxlan"` +tunnelProtocol: "" + +# -- Enable native-routing mode or tunneling mode. +# Possible values: +# - "" +# - native +# - tunnel +# @default -- `"tunnel"` +routingMode: "" + +# -- Configure VXLAN and Geneve tunnel port. +# @default -- Port 8472 for VXLAN, Port 6081 for Geneve +tunnelPort: 0 + +# -- Configure the underlying network MTU to overwrite auto-detected MTU. +MTU: 0 + +# -- Disable the usage of CiliumEndpoint CRD. +disableEndpointCRD: false + +wellKnownIdentities: + # -- Enable the use of well-known identities. + enabled: false + +etcd: + # -- Enable etcd mode for the agent. + enabled: false + + # -- cilium-etcd-operator image. + image: + override: ~ + repository: "quay.io/cilium/cilium-etcd-operator" + tag: "v2.0.7" + digest: "sha256:04b8327f7f992693c2cb483b999041ed8f92efc8e14f2a5f3ab95574a65ea2dc" + useDigest: true + pullPolicy: "IfNotPresent" + + # -- The priority class to use for cilium-etcd-operator + priorityClassName: "" + + # -- Additional cilium-etcd-operator container arguments. + extraArgs: [] + + # -- Additional cilium-etcd-operator volumes. + extraVolumes: [] + + # -- Additional cilium-etcd-operator volumeMounts. + extraVolumeMounts: [] + + # -- Node tolerations for cilium-etcd-operator scheduling to nodes with taints + # ref: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/ + tolerations: + - operator: Exists + # - key: "key" + # operator: "Equal|Exists" + # value: "value" + # effect: "NoSchedule|PreferNoSchedule|NoExecute(1.6 only)" + + # -- Pod topology spread constraints for cilium-etcd-operator + topologySpreadConstraints: [] + # - maxSkew: 1 + # topologyKey: topology.kubernetes.io/zone + # whenUnsatisfiable: DoNotSchedule + + # -- Node labels for cilium-etcd-operator pod assignment + # ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#nodeselector + nodeSelector: + kubernetes.io/os: linux + + # -- Security context to be added to cilium-etcd-operator pods + podSecurityContext: {} + + # -- Annotations to be added to cilium-etcd-operator pods + podAnnotations: {} + + # -- Labels to be added to cilium-etcd-operator pods + podLabels: {} + + # PodDisruptionBudget settings + podDisruptionBudget: + # -- enable PodDisruptionBudget + # ref: https://kubernetes.io/docs/concepts/workloads/pods/disruptions/ + enabled: false + # -- Minimum number/percentage of pods that should remain scheduled. + # When it's set, maxUnavailable must be disabled by `maxUnavailable: null` + minAvailable: null + # -- Maximum number/percentage of pods that may be made unavailable + maxUnavailable: 1 + + # -- cilium-etcd-operator resource limits & requests + # ref: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + resources: {} + # limits: + # cpu: 4000m + # memory: 4Gi + # requests: + # cpu: 100m + # memory: 512Mi + + # -- Security context to be added to cilium-etcd-operator pods + securityContext: {} + # runAsUser: 0 + + # -- cilium-etcd-operator update strategy + updateStrategy: + type: RollingUpdate + rollingUpdate: + maxSurge: 1 + maxUnavailable: 1 + + # -- If etcd is behind a k8s service set this option to true so that Cilium + # does the service translation automatically without requiring a DNS to be + # running. + k8sService: false + + # -- Cluster domain for cilium-etcd-operator. + clusterDomain: cluster.local + + # -- List of etcd endpoints (not needed when using managed=true). + endpoints: + - https://CHANGE-ME:2379 + + # -- Enable use of TLS/SSL for connectivity to etcd. (auto-enabled if + # managed=true) + ssl: false + +operator: + # -- Enable the cilium-operator component (required). + enabled: true + + # -- Roll out cilium-operator pods automatically when configmap is updated. + rollOutPods: false + + # -- cilium-operator image. + image: + override: ~ + repository: "quay.io/cilium/operator" + tag: "v1.14.5" + # operator-generic-digest + genericDigest: "sha256:303f9076bdc73b3fc32aaedee64a14f6f44c8bb08ee9e3956d443021103ebe7a" + # operator-azure-digest + azureDigest: "sha256:9203f5583aa34e716d7a6588ebd144e43ce3b77873f578fc12b2679e33591353" + # operator-aws-digest + awsDigest: "sha256:785ccf1267d0ed3ba9e4bd8166577cb4f9e4ce996af26b27c9d5c554a0d5b09a" + # operator-alibabacloud-digest + alibabacloudDigest: "sha256:e0152c498ba73c56a82eee2a706c8f400e9a6999c665af31a935bdf08e659bc3" + useDigest: true + pullPolicy: "IfNotPresent" + suffix: "" + + # -- Number of replicas to run for the cilium-operator deployment + replicas: 2 + + # -- The priority class to use for cilium-operator + priorityClassName: "" + + # -- DNS policy for Cilium operator pods. + # Ref: https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-s-dns-policy + dnsPolicy: "" + + # -- cilium-operator update strategy + updateStrategy: + type: RollingUpdate + rollingUpdate: + maxSurge: 25% + maxUnavailable: 50% + + # -- Affinity for cilium-operator + affinity: + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - topologyKey: kubernetes.io/hostname + labelSelector: + matchLabels: + io.cilium/app: operator + + # -- Pod topology spread constraints for cilium-operator + topologySpreadConstraints: [] + # - maxSkew: 1 + # topologyKey: topology.kubernetes.io/zone + # whenUnsatisfiable: DoNotSchedule + + # -- Node labels for cilium-operator pod assignment + # ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#nodeselector + nodeSelector: + kubernetes.io/os: linux + + # -- Node tolerations for cilium-operator scheduling to nodes with taints + # ref: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/ + tolerations: + - operator: Exists + # - key: "key" + # operator: "Equal|Exists" + # value: "value" + # effect: "NoSchedule|PreferNoSchedule|NoExecute(1.6 only)" + + # -- Additional cilium-operator container arguments. + extraArgs: [] + + # -- Additional cilium-operator environment variables. + extraEnv: [] + + # -- Additional cilium-operator hostPath mounts. + extraHostPathMounts: [] + # - name: host-mnt-data + # mountPath: /host/mnt/data + # hostPath: /mnt/data + # hostPathType: Directory + # readOnly: true + # mountPropagation: HostToContainer + + # -- Additional cilium-operator volumes. + extraVolumes: [] + + # -- Additional cilium-operator volumeMounts. + extraVolumeMounts: [] + + # -- Security context to be added to cilium-operator pods + podSecurityContext: {} + + # -- Annotations to be added to cilium-operator pods + podAnnotations: {} + + # -- Labels to be added to cilium-operator pods + podLabels: {} + + # PodDisruptionBudget settings + podDisruptionBudget: + # -- enable PodDisruptionBudget + # ref: https://kubernetes.io/docs/concepts/workloads/pods/disruptions/ + enabled: false + # -- Minimum number/percentage of pods that should remain scheduled. + # When it's set, maxUnavailable must be disabled by `maxUnavailable: null` + minAvailable: null + # -- Maximum number/percentage of pods that may be made unavailable + maxUnavailable: 1 + + # -- cilium-operator resource limits & requests + # ref: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + resources: {} + # limits: + # cpu: 1000m + # memory: 1Gi + # requests: + # cpu: 100m + # memory: 128Mi + + # -- Security context to be added to cilium-operator pods + securityContext: {} + # runAsUser: 0 + + # -- Interval for endpoint garbage collection. + endpointGCInterval: "5m0s" + + # -- Interval for cilium node garbage collection. + nodeGCInterval: "5m0s" + + # -- Skip CNP node status clean up at operator startup. + skipCNPStatusStartupClean: false + + # -- Interval for identity garbage collection. + identityGCInterval: "15m0s" + + # -- Timeout for identity heartbeats. + identityHeartbeatTimeout: "30m0s" + + pprof: + # -- Enable pprof for cilium-operator + enabled: false + # -- Configure pprof listen address for cilium-operator + address: localhost + # -- Configure pprof listen port for cilium-operator + port: 6061 + + # -- Enable prometheus metrics for cilium-operator on the configured port at + # /metrics + prometheus: + enabled: false + port: 9963 + serviceMonitor: + # -- Enable service monitors. + # This requires the prometheus CRDs to be available (see https://github.com/prometheus-operator/prometheus-operator/blob/main/example/prometheus-operator-crd/monitoring.coreos.com_servicemonitors.yaml) + enabled: false + # -- Labels to add to ServiceMonitor cilium-operator + labels: {} + # -- Annotations to add to ServiceMonitor cilium-operator + annotations: {} + # -- Interval for scrape metrics. + interval: "10s" + # -- Relabeling configs for the ServiceMonitor cilium-operator + relabelings: ~ + # -- Metrics relabeling configs for the ServiceMonitor cilium-operator + metricRelabelings: ~ + + # -- Grafana dashboards for cilium-operator + # grafana can import dashboards based on the label and value + # ref: https://github.com/grafana/helm-charts/tree/main/charts/grafana#sidecar-for-dashboards + dashboards: + enabled: false + label: grafana_dashboard + namespace: ~ + labelValue: "1" + annotations: {} + + # -- Skip CRDs creation for cilium-operator + skipCRDCreation: false + + # -- Remove Cilium node taint from Kubernetes nodes that have a healthy Cilium + # pod running. + removeNodeTaints: true + + # -- Taint nodes where Cilium is scheduled but not running. This prevents pods + # from being scheduled to nodes where Cilium is not the default CNI provider. + # @default -- same as removeNodeTaints + setNodeTaints: ~ + + # -- Set Node condition NetworkUnavailable to 'false' with the reason + # 'CiliumIsUp' for nodes that have a healthy Cilium pod. + setNodeNetworkStatus: true + + unmanagedPodWatcher: + # -- Restart any pod that are not managed by Cilium. + restart: true + # -- Interval, in seconds, to check if there are any pods that are not + # managed by Cilium. + intervalSeconds: 15 + +nodeinit: + # -- Enable the node initialization DaemonSet + enabled: false + + # -- node-init image. + image: + override: ~ + repository: "quay.io/cilium/startup-script" + tag: "62093c5c233ea914bfa26a10ba41f8780d9b737f" + pullPolicy: "IfNotPresent" + + # -- The priority class to use for the nodeinit pod. + priorityClassName: "" + + # -- node-init update strategy + updateStrategy: + type: RollingUpdate + + # -- Additional nodeinit environment variables. + extraEnv: [] + + # -- Additional nodeinit volumes. + extraVolumes: [] + + # -- Additional nodeinit volumeMounts. + extraVolumeMounts: [] + + # -- Affinity for cilium-nodeinit + affinity: {} + + # -- Node labels for nodeinit pod assignment + # ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#nodeselector + nodeSelector: + kubernetes.io/os: linux + + # -- Node tolerations for nodeinit scheduling to nodes with taints + # ref: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/ + tolerations: + - operator: Exists + # - key: "key" + # operator: "Equal|Exists" + # value: "value" + # effect: "NoSchedule|PreferNoSchedule|NoExecute(1.6 only)" + + # -- Annotations to be added to node-init pods. + podAnnotations: {} + + # -- Labels to be added to node-init pods. + podLabels: {} + + # -- nodeinit resource limits & requests + # ref: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + resources: + requests: + cpu: 100m + memory: 100Mi + + # -- Security context to be added to nodeinit pods. + securityContext: + privileged: false + seLinuxOptions: + level: 's0' + # Running with spc_t since we have removed the privileged mode. + # Users can change it to a different type as long as they have the + # type available on the system. + type: 'spc_t' + capabilities: + add: + # Used for nsenter + - NET_ADMIN + - SYS_ADMIN + - SYS_CHROOT + - SYS_PTRACE + + # -- bootstrapFile is the location of the file where the bootstrap timestamp is + # written by the node-init DaemonSet + bootstrapFile: "/tmp/cilium-bootstrap.d/cilium-bootstrap-time" + + # -- startup offers way to customize startup nodeinit script (pre and post position) + startup: + preScript: "" + postScript: "" + # -- prestop offers way to customize prestop nodeinit script (pre and post position) + prestop: + preScript: "" + postScript: "" + +preflight: + # -- Enable Cilium pre-flight resources (required for upgrade) + enabled: false + + # -- Cilium pre-flight image. + image: + override: ~ + repository: "quay.io/cilium/cilium" + tag: "v1.14.5" + # cilium-digest + digest: "sha256:d3b287029755b6a47dee01420e2ea469469f1b174a2089c10af7e5e9289ef05b" + useDigest: true + pullPolicy: "IfNotPresent" + + # -- The priority class to use for the preflight pod. + priorityClassName: "" + + # -- preflight update strategy + updateStrategy: + type: RollingUpdate + + # -- Additional preflight environment variables. + extraEnv: [] + + # -- Additional preflight volumes. + extraVolumes: [] + + # -- Additional preflight volumeMounts. + extraVolumeMounts: [] + + # -- Affinity for cilium-preflight + affinity: + podAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - topologyKey: kubernetes.io/hostname + labelSelector: + matchLabels: + k8s-app: cilium + + # -- Node labels for preflight pod assignment + # ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#nodeselector + nodeSelector: + kubernetes.io/os: linux + + # -- Node tolerations for preflight scheduling to nodes with taints + # ref: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/ + tolerations: + - key: node.kubernetes.io/not-ready + effect: NoSchedule + - key: node-role.kubernetes.io/master + effect: NoSchedule + - key: node-role.kubernetes.io/control-plane + effect: NoSchedule + - key: node.cloudprovider.kubernetes.io/uninitialized + effect: NoSchedule + value: "true" + - key: CriticalAddonsOnly + operator: "Exists" + # - key: "key" + # operator: "Equal|Exists" + # value: "value" + # effect: "NoSchedule|PreferNoSchedule|NoExecute(1.6 only)" + + # -- Security context to be added to preflight pods. + podSecurityContext: {} + + # -- Annotations to be added to preflight pods + podAnnotations: {} + + # -- Labels to be added to the preflight pod. + podLabels: {} + + # PodDisruptionBudget settings + podDisruptionBudget: + # -- enable PodDisruptionBudget + # ref: https://kubernetes.io/docs/concepts/workloads/pods/disruptions/ + enabled: false + # -- Minimum number/percentage of pods that should remain scheduled. + # When it's set, maxUnavailable must be disabled by `maxUnavailable: null` + minAvailable: null + # -- Maximum number/percentage of pods that may be made unavailable + maxUnavailable: 1 + + # -- preflight resource limits & requests + # ref: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + resources: {} + # limits: + # cpu: 4000m + # memory: 4Gi + # requests: + # cpu: 100m + # memory: 512Mi + + # -- Security context to be added to preflight pods + securityContext: {} + # runAsUser: 0 + + # -- Path to write the `--tofqdns-pre-cache` file to. + tofqdnsPreCache: "" + + # -- Configure termination grace period for preflight Deployment and DaemonSet. + terminationGracePeriodSeconds: 1 + + # -- By default we should always validate the installed CNPs before upgrading + # Cilium. This will make sure the user will have the policies deployed in the + # cluster with the right schema. + validateCNPs: true + +# -- Explicitly enable or disable priority class. +# .Capabilities.KubeVersion is unsettable in `helm template` calls, +# it depends on k8s libraries version that Helm was compiled against. +# This option allows to explicitly disable setting the priority class, which +# is useful for rendering charts for gke clusters in advance. +enableCriticalPriorityClass: true + +# disableEnvoyVersionCheck removes the check for Envoy, which can be useful +# on AArch64 as the images do not currently ship a version of Envoy. +#disableEnvoyVersionCheck: false + +clustermesh: + # -- Deploy clustermesh-apiserver for clustermesh + useAPIServer: false + + # -- Clustermesh explicit configuration. + config: + # -- Enable the Clustermesh explicit configuration. + enabled: false + # -- Default dns domain for the Clustermesh API servers + # This is used in the case cluster addresses are not provided + # and IPs are used. + domain: mesh.cilium.io + # -- List of clusters to be peered in the mesh. + clusters: [] + # clusters: + # # -- Name of the cluster + # - name: cluster1 + # # -- Address of the cluster, use this if you created DNS records for + # # the cluster Clustermesh API server. + # address: cluster1.mesh.cilium.io + # # -- Port of the cluster Clustermesh API server. + # port: 2379 + # # -- IPs of the cluster Clustermesh API server, use multiple ones when + # # you have multiple IPs to access the Clustermesh API server. + # ips: + # - 172.18.255.201 + # # -- base64 encoded PEM values for the cluster client certificate, private key and certificate authority. + # # These fields can (and should) be omitted in case the CA is shared across clusters. In that case, the + # # "remote" private key and certificate available in the local cluster are automatically used instead. + # tls: + # cert: "" + # key: "" + # caCert: "" + + apiserver: + # -- Clustermesh API server image. + image: + override: ~ + repository: "quay.io/cilium/clustermesh-apiserver" + tag: "v1.14.5" + # clustermesh-apiserver-digest + digest: "sha256:7eaa35cf5452c43b1f7d0cde0d707823ae7e49965bcb54c053e31ea4e04c3d96" + useDigest: true + pullPolicy: "IfNotPresent" + + etcd: + # -- Clustermesh API server etcd image. + image: + override: ~ + repository: "quay.io/coreos/etcd" + tag: "v3.5.4" + digest: "sha256:795d8660c48c439a7c3764c2330ed9222ab5db5bb524d8d0607cac76f7ba82a3" + useDigest: true + pullPolicy: "IfNotPresent" + + # -- Specifies the resources for etcd container in the apiserver + resources: {} + # requests: + # cpu: 200m + # memory: 256Mi + # limits: + # cpu: 1000m + # memory: 256Mi + + # -- Security context to be added to clustermesh-apiserver etcd containers + securityContext: {} + + init: + # -- Specifies the resources for etcd init container in the apiserver + resources: {} + # requests: + # cpu: 100m + # memory: 100Mi + # limits: + # cpu: 100m + # memory: 100Mi + + kvstoremesh: + # -- Enable KVStoreMesh. KVStoreMesh caches the information retrieved + # from the remote clusters in the local etcd instance. + enabled: false + + # -- KVStoreMesh image. + image: + override: ~ + repository: "quay.io/cilium/kvstoremesh" + tag: "v1.14.5" + # kvstoremesh-digest + digest: "sha256:d7137edd0efa2b1407b20088af3980a9993bb616d85bf9b55ea2891d1b99023a" + useDigest: true + pullPolicy: "IfNotPresent" + + # -- Additional KVStoreMesh arguments. + extraArgs: [] + + # -- Additional KVStoreMesh environment variables. + extraEnv: [] + + # -- Resource requests and limits for the KVStoreMesh container + resources: {} + # requests: + # cpu: 100m + # memory: 64Mi + # limits: + # cpu: 1000m + # memory: 1024M + + # -- Additional KVStoreMesh volumeMounts. + extraVolumeMounts: [] + + # -- KVStoreMesh Security context + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + + service: + # -- The type of service used for apiserver access. + type: NodePort + # -- Optional port to use as the node port for apiserver access. + # + # WARNING: make sure to configure a different NodePort in each cluster if + # kube-proxy replacement is enabled, as Cilium is currently affected by a known + # bug (#24692) when NodePorts are handled by the KPR implementation. If a service + # with the same NodePort exists both in the local and the remote cluster, all + # traffic originating from inside the cluster and targeting the corresponding + # NodePort will be redirected to a local backend, regardless of whether the + # destination node belongs to the local or the remote cluster. + nodePort: 32379 + # -- Optional loadBalancer IP address to use with type LoadBalancer. + # loadBalancerIP: + + # -- Annotations for the clustermesh-apiserver + # For GKE LoadBalancer, use annotation cloud.google.com/load-balancer-type: "Internal" + # For EKS LoadBalancer, use annotation service.beta.kubernetes.io/aws-load-balancer-internal: 0.0.0.0/0 + annotations: {} + + # -- The externalTrafficPolicy of service used for apiserver access. + externalTrafficPolicy: + + # -- The internalTrafficPolicy of service used for apiserver access. + internalTrafficPolicy: + + # -- Number of replicas run for the clustermesh-apiserver deployment. + replicas: 1 + + # -- Additional clustermesh-apiserver arguments. + extraArgs: [] + + # -- Additional clustermesh-apiserver environment variables. + extraEnv: [] + + # -- Additional clustermesh-apiserver volumes. + extraVolumes: [] + + # -- Additional clustermesh-apiserver volumeMounts. + extraVolumeMounts: [] + + # -- Security context to be added to clustermesh-apiserver containers + securityContext: {} + + # -- Security context to be added to clustermesh-apiserver pods + podSecurityContext: {} + + # -- Annotations to be added to clustermesh-apiserver pods + podAnnotations: {} + + # -- Labels to be added to clustermesh-apiserver pods + podLabels: {} + + # PodDisruptionBudget settings + podDisruptionBudget: + # -- enable PodDisruptionBudget + # ref: https://kubernetes.io/docs/concepts/workloads/pods/disruptions/ + enabled: false + # -- Minimum number/percentage of pods that should remain scheduled. + # When it's set, maxUnavailable must be disabled by `maxUnavailable: null` + minAvailable: null + # -- Maximum number/percentage of pods that may be made unavailable + maxUnavailable: 1 + + # -- Resource requests and limits for the clustermesh-apiserver container of the clustermesh-apiserver deployment, such as + # resources: + # limits: + # cpu: 1000m + # memory: 1024M + # requests: + # cpu: 100m + # memory: 64Mi + # -- Resource requests and limits for the clustermesh-apiserver + resources: {} + # requests: + # cpu: 100m + # memory: 64Mi + # limits: + # cpu: 1000m + # memory: 1024M + + # -- Affinity for clustermesh.apiserver + affinity: + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - topologyKey: kubernetes.io/hostname + labelSelector: + matchLabels: + k8s-app: clustermesh-apiserver + + # -- Pod topology spread constraints for clustermesh-apiserver + topologySpreadConstraints: [] + # - maxSkew: 1 + # topologyKey: topology.kubernetes.io/zone + # whenUnsatisfiable: DoNotSchedule + + # -- Node labels for pod assignment + # ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#nodeselector + nodeSelector: + kubernetes.io/os: linux + + # -- Node tolerations for pod assignment on nodes with taints + # ref: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/ + tolerations: [] + + # -- clustermesh-apiserver update strategy + updateStrategy: + type: RollingUpdate + rollingUpdate: + maxUnavailable: 1 + + # -- The priority class to use for clustermesh-apiserver + priorityClassName: "" + + tls: + # -- Configure the clustermesh authentication mode. + # Supported values: + # - legacy: All clusters access remote clustermesh instances with the same + # username (i.e., remote). The "remote" certificate must be + # generated with CN=remote if provided manually. + # - migration: Intermediate mode required to upgrade from legacy to cluster + # (and vice versa) with no disruption. Specifically, it enables + # the creation of the per-cluster usernames, while still using + # the common one for authentication. The "remote" certificate must + # be generated with CN=remote if provided manually (same as legacy). + # - cluster: Each cluster accesses remote etcd instances with a username + # depending on the local cluster name (i.e., remote-). + # The "remote" certificate must be generated with CN=remote- + # if provided manually. Cluster mode is meaningful only when the same + # CA is shared across all clusters part of the mesh. + authMode: legacy + + # -- Configure automatic TLS certificates generation. + # A Kubernetes CronJob is used the generate any + # certificates not provided by the user at installation + # time. + auto: + # -- When set to true, automatically generate a CA and certificates to + # enable mTLS between clustermesh-apiserver and external workload instances. + # If set to false, the certs to be provided by setting appropriate values below. + enabled: true + # Sets the method to auto-generate certificates. Supported values: + # - helm: This method uses Helm to generate all certificates. + # - cronJob: This method uses a Kubernetes CronJob the generate any + # certificates not provided by the user at installation + # time. + # - certmanager: This method use cert-manager to generate & rotate certificates. + method: helm + # -- Generated certificates validity duration in days. + certValidityDuration: 1095 + # -- Schedule for certificates regeneration (regardless of their expiration date). + # Only used if method is "cronJob". If nil, then no recurring job will be created. + # Instead, only the one-shot job is deployed to generate the certificates at + # installation time. + # + # Due to the out-of-band distribution of client certs to external workloads the + # CA is (re)regenerated only if it is not provided as a helm value and the k8s + # secret is manually deleted. + # + # Defaults to none. Commented syntax gives midnight of the first day of every + # fourth month. For syntax, see + # https://kubernetes.io/docs/concepts/workloads/controllers/cron-jobs/#schedule-syntax + # schedule: "0 0 1 */4 *" + + # [Example] + # certManagerIssuerRef: + # group: cert-manager.io + # kind: ClusterIssuer + # name: ca-issuer + # -- certmanager issuer used when clustermesh.apiserver.tls.auto.method=certmanager. + certManagerIssuerRef: {} + # -- Deprecated in favor of tls.ca. To be removed in 1.15. + # base64 encoded PEM values for the ExternalWorkload CA certificate and private key. + ca: + # -- Deprecated in favor of tls.ca.cert. To be removed in 1.15. + # Optional CA cert. If it is provided, it will be used by the 'cronJob' method to + # generate all other certificates. Otherwise, an ephemeral CA is generated. + cert: "" + # -- Deprecated in favor of tls.ca.key. To be removed in 1.15. + # Optional CA private key. If it is provided, it will be used by the 'cronJob' method to + # generate all other certificates. Otherwise, an ephemeral CA is generated. + key: "" + # -- base64 encoded PEM values for the clustermesh-apiserver server certificate and private key. + # Used if 'auto' is not enabled. + server: + cert: "" + key: "" + # -- Extra DNS names added to certificate when it's auto generated + extraDnsNames: [] + # -- Extra IP addresses added to certificate when it's auto generated + extraIpAddresses: [] + # -- base64 encoded PEM values for the clustermesh-apiserver admin certificate and private key. + # Used if 'auto' is not enabled. + admin: + cert: "" + key: "" + # -- base64 encoded PEM values for the clustermesh-apiserver client certificate and private key. + # Used if 'auto' is not enabled. + client: + cert: "" + key: "" + # -- base64 encoded PEM values for the clustermesh-apiserver remote cluster certificate and private key. + # Used if 'auto' is not enabled. + remote: + cert: "" + key: "" + + # clustermesh-apiserver Prometheus metrics configuration + metrics: + # -- Enables exporting apiserver metrics in OpenMetrics format. + enabled: true + # -- Configure the port the apiserver metric server listens on. + port: 9962 + + kvstoremesh: + # -- Enables exporting KVStoreMesh metrics in OpenMetrics format. + enabled: true + # -- Configure the port the KVStoreMesh metric server listens on. + port: 9964 + + etcd: + # -- Enables exporting etcd metrics in OpenMetrics format. + enabled: false + # -- Set level of detail for etcd metrics; specify 'extensive' to include server side gRPC histogram metrics. + mode: basic + # -- Configure the port the etcd metric server listens on. + port: 9963 + + serviceMonitor: + # -- Enable service monitor. + # This requires the prometheus CRDs to be available (see https://github.com/prometheus-operator/prometheus-operator/blob/main/example/prometheus-operator-crd/monitoring.coreos.com_servicemonitors.yaml) + enabled: false + # -- Labels to add to ServiceMonitor clustermesh-apiserver + labels: {} + # -- Annotations to add to ServiceMonitor clustermesh-apiserver + annotations: {} + # -- Specify the Kubernetes namespace where Prometheus expects to find + # service monitors configured. + # namespace: "" + + # -- Interval for scrape metrics (apiserver metrics) + interval: "10s" + # -- Relabeling configs for the ServiceMonitor clustermesh-apiserver (apiserver metrics) + relabelings: ~ + # -- Metrics relabeling configs for the ServiceMonitor clustermesh-apiserver (apiserver metrics) + metricRelabelings: ~ + + kvstoremesh: + # -- Interval for scrape metrics (KVStoreMesh metrics) + interval: "10s" + # -- Relabeling configs for the ServiceMonitor clustermesh-apiserver (KVStoreMesh metrics) + relabelings: ~ + # -- Metrics relabeling configs for the ServiceMonitor clustermesh-apiserver (KVStoreMesh metrics) + metricRelabelings: ~ + + etcd: + # -- Interval for scrape metrics (etcd metrics) + interval: "10s" + # -- Relabeling configs for the ServiceMonitor clustermesh-apiserver (etcd metrics) + relabelings: ~ + # -- Metrics relabeling configs for the ServiceMonitor clustermesh-apiserver (etcd metrics) + metricRelabelings: ~ + +# -- Configure external workloads support +externalWorkloads: + # -- Enable support for external workloads, such as VMs (false by default). + enabled: false + +# -- Configure cgroup related configuration +cgroup: + autoMount: + # -- Enable auto mount of cgroup2 filesystem. + # When `autoMount` is enabled, cgroup2 filesystem is mounted at + # `cgroup.hostRoot` path on the underlying host and inside the cilium agent pod. + # If users disable `autoMount`, it's expected that users have mounted + # cgroup2 filesystem at the specified `cgroup.hostRoot` volume, and then the + # volume will be mounted inside the cilium agent pod at the same path. + enabled: true + # -- Init Container Cgroup Automount resource limits & requests + resources: {} + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + # -- Configure cgroup root where cgroup2 filesystem is mounted on the host (see also: `cgroup.autoMount`) + hostRoot: /run/cilium/cgroupv2 + +# -- Configure whether to enable auto detect of terminating state for endpoints +# in order to support graceful termination. +enableK8sTerminatingEndpoint: true + +# -- Configure whether to unload DNS policy rules on graceful shutdown +# dnsPolicyUnloadOnShutdown: false + +# -- Configure the key of the taint indicating that Cilium is not ready on the node. +# When set to a value starting with `ignore-taint.cluster-autoscaler.kubernetes.io/`, the Cluster Autoscaler will ignore the taint on its decisions, allowing the cluster to scale up. +agentNotReadyTaintKey: "node.cilium.io/agent-not-ready" + +dnsProxy: + # -- DNS response code for rejecting DNS requests, available options are '[nameError refused]'. + dnsRejectResponseCode: refused + # -- Allow the DNS proxy to compress responses to endpoints that are larger than 512 Bytes or the EDNS0 option, if present. + enableDnsCompression: true + # -- Maximum number of IPs to maintain per FQDN name for each endpoint. + endpointMaxIpPerHostname: 50 + # -- Time during which idle but previously active connections with expired DNS lookups are still considered alive. + idleConnectionGracePeriod: 0s + # -- Maximum number of IPs to retain for expired DNS lookups with still-active connections. + maxDeferredConnectionDeletes: 10000 + # -- The minimum time, in seconds, to use DNS data for toFQDNs policies. If + # the upstream DNS server returns a DNS record with a shorter TTL, Cilium + # overwrites the TTL with this value. Setting this value to zero means that + # Cilium will honor the TTLs returned by the upstream DNS server. + minTtl: 0 + # -- DNS cache data at this path is preloaded on agent startup. + preCache: "" + # -- Global port on which the in-agent DNS proxy should listen. Default 0 is a OS-assigned port. + proxyPort: 0 + # -- The maximum time the DNS proxy holds an allowed DNS response before sending it along. Responses are sent as soon as the datapath is updated with the new IP information. + proxyResponseMaxDelay: 100ms + +# -- SCTP Configuration Values +sctp: + # -- Enable SCTP support. NOTE: Currently, SCTP support does not support rewriting ports or multihoming. + enabled: false + +# Configuration for types of authentication for Cilium (beta) +authentication: + # -- Enable authentication processing and garbage collection. + # Note that if disabled, policy enforcement will still block requests that require authentication. + # But the resulting authentication requests for these requests will not be processed, therefore the requests not be allowed. + enabled: true + # -- Buffer size of the channel Cilium uses to receive authentication events from the signal map. + queueSize: 1024 + # -- Buffer size of the channel Cilium uses to receive certificate expiration events from auth handlers. + rotatedIdentitiesQueueSize: 1024 + # -- Interval for garbage collection of auth map entries. + gcInterval: "5m0s" + # Configuration for Cilium's service-to-service mutual authentication using TLS handshakes. + # Note that this is not full mTLS support without also enabling encryption of some form. + # Current encryption options are Wireguard or IPSec, configured in encryption block above. + mutual: + # -- Port on the agent where mutual authentication handshakes between agents will be performed + port: 4250 + # Settings for SPIRE + spire: + # -- Enable SPIRE integration (beta) + enabled: false + # Settings to control the SPIRE installation and configuration + install: + # -- Enable SPIRE installation. + # This will only take effect only if authentication.mutual.spire.enabled is true + enabled: true + # -- SPIRE namespace to install into + namespace: cilium-spire + # SPIRE agent configuration + agent: + # -- SPIRE agent image + image: ghcr.io/spiffe/spire-agent:1.6.3@sha256:8eef9857bf223181ecef10d9bbcd2f7838f3689e9bd2445bede35066a732e823 + # -- SPIRE agent service account + serviceAccount: + create: true + name: spire-agent + # -- SPIRE agent annotations + annotations: {} + # -- SPIRE agent labels + labels: {} + # -- SPIRE Workload Attestor kubelet verification. + skipKubeletVerification: true + # -- SPIRE agent tolerations configuration + # ref: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/ + tolerations: [] + # -- SPIRE agent affinity configuration + affinity: {} + # -- SPIRE agent nodeSelector configuration + # ref: ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#nodeselector + nodeSelector: {} + # -- Security context to be added to spire agent pods. + # SecurityContext holds pod-level security attributes and common container settings. + # ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod + podSecurityContext: {} + # -- Security context to be added to spire agent containers. + # SecurityContext holds pod-level security attributes and common container settings. + # ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container + securityContext: {} + server: + # -- SPIRE server image + image: ghcr.io/spiffe/spire-server:1.6.3@sha256:f4bc49fb0bd1d817a6c46204cc7ce943c73fb0a5496a78e0e4dc20c9a816ad7f + # -- SPIRE server service account + serviceAccount: + create: true + name: spire-server + # -- SPIRE server init containers + initContainers: [] + # -- SPIRE server annotations + annotations: {} + # -- SPIRE server labels + labels: {} + # SPIRE server service configuration + service: + # -- Service type for the SPIRE server service + type: ClusterIP + # -- Annotations to be added to the SPIRE server service + annotations: {} + # -- Labels to be added to the SPIRE server service + labels: {} + # -- SPIRE server affinity configuration + affinity: {} + # -- SPIRE server nodeSelector configuration + # ref: ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#nodeselector + nodeSelector: {} + # -- SPIRE server tolerations configuration + # ref: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/ + tolerations: [] + # SPIRE server datastorage configuration + dataStorage: + # -- Enable SPIRE server data storage + enabled: true + # -- Size of the SPIRE server data storage + size: 1Gi + # -- Access mode of the SPIRE server data storage + accessMode: ReadWriteOnce + # -- StorageClass of the SPIRE server data storage + storageClass: null + # SPIRE CA configuration + ca: + # -- SPIRE CA key type + # AWS requires the use of RSA. EC cryptography is not supported + keyType: "rsa-4096" + # -- SPIRE CA Subject + subject: + country: "US" + organization: "SPIRE" + commonName: "Cilium SPIRE CA" + # -- SPIRE server address used by Cilium Operator + # + # If k8s Service DNS along with port number is used (e.g. ..svc(.*): format), + # Cilium Operator will resolve its address by looking up the clusterIP from Service resource. + # + # Example values: 10.0.0.1:8081, spire-server.cilium-spire.svc:8081 + serverAddress: ~ + # -- SPIFFE trust domain to use for fetching certificates + trustDomain: spiffe.cilium + # -- SPIRE socket path where the SPIRE delegated api agent is listening + adminSocketPath: /run/spire/sockets/admin.sock + # -- SPIRE socket path where the SPIRE workload agent is listening. + # Applies to both the Cilium Agent and Operator + agentSocketPath: /run/spire/sockets/agent/agent.sock + # -- SPIRE connection timeout + connectionTimeout: 30s diff --git a/packages/system/cilium/charts/cilium/values.yaml.tmpl b/packages/system/cilium/charts/cilium/values.yaml.tmpl new file mode 100644 index 00000000..f1d9a819 --- /dev/null +++ b/packages/system/cilium/charts/cilium/values.yaml.tmpl @@ -0,0 +1,3221 @@ + +# upgradeCompatibility helps users upgrading to ensure that the configMap for +# Cilium will not change critical values to ensure continued operation +# This is flag is not required for new installations. +# For example: 1.7, 1.8, 1.9 +# upgradeCompatibility: '1.8' + +debug: + # -- Enable debug logging + enabled: false + # -- Configure verbosity levels for debug logging + # This option is used to enable debug messages for operations related to such + # sub-system such as (e.g. kvstore, envoy, datapath or policy), and flow is + # for enabling debug messages emitted per request, message and connection. + # + # Applicable values: + # - flow + # - kvstore + # - envoy + # - datapath + # - policy + verbose: ~ + +rbac: + # -- Enable creation of Resource-Based Access Control configuration. + create: true + +# -- Configure image pull secrets for pulling container images +imagePullSecrets: +# - name: "image-pull-secret" + +# -- (string) Kubernetes config path +# @default -- `"~/.kube/config"` +kubeConfigPath: "" +# -- (string) Kubernetes service host +k8sServiceHost: "" +# -- (string) Kubernetes service port +k8sServicePort: "" + +# -- Configure the client side rate limit for the agent and operator +# +# If the amount of requests to the Kubernetes API server exceeds the configured +# rate limit, the agent and operator will start to throttle requests by delaying +# them until there is budget or the request times out. +k8sClientRateLimit: + # -- The sustained request rate in requests per second. + qps: 5 + # -- The burst request rate in requests per second. + # The rate limiter will allow short bursts with a higher rate. + burst: 10 + +cluster: + # -- Name of the cluster. Only required for Cluster Mesh and mutual authentication with SPIRE. + name: default + # -- (int) Unique ID of the cluster. Must be unique across all connected + # clusters and in the range of 1 to 255. Only required for Cluster Mesh, + # may be 0 if Cluster Mesh is not used. + id: 0 + +# -- Define serviceAccount names for components. +# @default -- Component's fully qualified name. +serviceAccounts: + cilium: + create: true + name: cilium + automount: true + annotations: {} + nodeinit: + create: true + # -- Enabled is temporary until https://github.com/cilium/cilium-cli/issues/1396 is implemented. + # Cilium CLI doesn't create the SAs for node-init, thus the workaround. Helm is not affected by + # this issue. Name and automount can be configured, if enabled is set to true. + # Otherwise, they are ignored. Enabled can be removed once the issue is fixed. + # Cilium-nodeinit DS must also be fixed. + enabled: false + name: cilium-nodeinit + automount: true + annotations: {} + envoy: + create: true + name: cilium-envoy + automount: true + annotations: {} + etcd: + create: true + name: cilium-etcd-operator + automount: true + annotations: {} + operator: + create: true + name: cilium-operator + automount: true + annotations: {} + preflight: + create: true + name: cilium-pre-flight + automount: true + annotations: {} + relay: + create: true + name: hubble-relay + automount: false + annotations: {} + ui: + create: true + name: hubble-ui + automount: true + annotations: {} + clustermeshApiserver: + create: true + name: clustermesh-apiserver + automount: true + annotations: {} + # -- Clustermeshcertgen is used if clustermesh.apiserver.tls.auto.method=cronJob + clustermeshcertgen: + create: true + name: clustermesh-apiserver-generate-certs + automount: true + annotations: {} + # -- Hubblecertgen is used if hubble.tls.auto.method=cronJob + hubblecertgen: + create: true + name: hubble-generate-certs + automount: true + annotations: {} + +# -- Configure termination grace period for cilium-agent DaemonSet. +terminationGracePeriodSeconds: 1 + +# -- Install the cilium agent resources. +agent: true + +# -- Agent container name. +name: cilium + +# -- Roll out cilium agent pods automatically when configmap is updated. +rollOutCiliumPods: false + +# -- Agent container image. +image: + override: ~ + repository: "${CILIUM_REPO}" + tag: "${CILIUM_VERSION}" + pullPolicy: "${PULL_POLICY}" + # cilium-digest + digest: ${CILIUM_DIGEST} + useDigest: ${USE_DIGESTS} + +# -- Affinity for cilium-agent. +affinity: + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - topologyKey: kubernetes.io/hostname + labelSelector: + matchLabels: + k8s-app: cilium + +# -- Node selector for cilium-agent. +nodeSelector: + kubernetes.io/os: linux + +# -- Node tolerations for agent scheduling to nodes with taints +# ref: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/ +tolerations: +- operator: Exists + # - key: "key" + # operator: "Equal|Exists" + # value: "value" + # effect: "NoSchedule|PreferNoSchedule|NoExecute(1.6 only)" + +# -- The priority class to use for cilium-agent. +priorityClassName: "" + +# -- DNS policy for Cilium agent pods. +# Ref: https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-s-dns-policy +dnsPolicy: "" + +# -- Additional containers added to the cilium DaemonSet. +extraContainers: [] + +# -- Additional agent container arguments. +extraArgs: [] + +# -- Additional agent container environment variables. +extraEnv: [] + +# -- Additional agent hostPath mounts. +extraHostPathMounts: [] + # - name: host-mnt-data + # mountPath: /host/mnt/data + # hostPath: /mnt/data + # hostPathType: Directory + # readOnly: true + # mountPropagation: HostToContainer + +# -- Additional agent volumes. +extraVolumes: [] + +# -- Additional agent volumeMounts. +extraVolumeMounts: [] + +# -- extraConfig allows you to specify additional configuration parameters to be +# included in the cilium-config configmap. +extraConfig: {} +# my-config-a: "1234" +# my-config-b: |- +# test 1 +# test 2 +# test 3 + +# -- Security Context for cilium-agent pods. +podSecurityContext: {} + +# -- Annotations to be added to agent pods +podAnnotations: {} + +# -- Labels to be added to agent pods +podLabels: {} + +# -- Agent resource limits & requests +# ref: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ +resources: {} + # limits: + # cpu: 4000m + # memory: 4Gi + # requests: + # cpu: 100m + # memory: 512Mi + +# -- resources & limits for the agent init containers +initResources: {} + +securityContext: + # -- User to run the pod with + # runAsUser: 0 + # -- Run the pod with elevated privileges + privileged: false + # -- SELinux options for the `cilium-agent` and init containers + seLinuxOptions: + level: 's0' + # Running with spc_t since we have removed the privileged mode. + # Users can change it to a different type as long as they have the + # type available on the system. + type: 'spc_t' + capabilities: + # -- Capabilities for the `cilium-agent` container + ciliumAgent: + # Use to set socket permission + - CHOWN + # Used to terminate envoy child process + - KILL + # Used since cilium modifies routing tables, etc... + - NET_ADMIN + # Used since cilium creates raw sockets, etc... + - NET_RAW + # Used since cilium monitor uses mmap + - IPC_LOCK + # Used in iptables. Consider removing once we are iptables-free + - SYS_MODULE + # We need it for now but might not need it for >= 5.11 specially + # for the 'SYS_RESOURCE'. + # In >= 5.8 there's already BPF and PERMON capabilities + - SYS_ADMIN + # Could be an alternative for the SYS_ADMIN for the RLIMIT_NPROC + - SYS_RESOURCE + # Both PERFMON and BPF requires kernel 5.8, container runtime + # cri-o >= v1.22.0 or containerd >= v1.5.0. + # If available, SYS_ADMIN can be removed. + #- PERFMON + #- BPF + # Allow discretionary access control (e.g. required for package installation) + - DAC_OVERRIDE + # Allow to set Access Control Lists (ACLs) on arbitrary files (e.g. required for package installation) + - FOWNER + # Allow to execute program that changes GID (e.g. required for package installation) + - SETGID + # Allow to execute program that changes UID (e.g. required for package installation) + - SETUID + # -- Capabilities for the `mount-cgroup` init container + mountCgroup: + # Only used for 'mount' cgroup + - SYS_ADMIN + # Used for nsenter + - SYS_CHROOT + - SYS_PTRACE + # -- capabilities for the `apply-sysctl-overwrites` init container + applySysctlOverwrites: + # Required in order to access host's /etc/sysctl.d dir + - SYS_ADMIN + # Used for nsenter + - SYS_CHROOT + - SYS_PTRACE + # -- Capabilities for the `clean-cilium-state` init container + cleanCiliumState: + # Most of the capabilities here are the same ones used in the + # cilium-agent's container because this container can be used to + # uninstall all Cilium resources, and therefore it is likely that + # will need the same capabilities. + # Used since cilium modifies routing tables, etc... + - NET_ADMIN + # Used in iptables. Consider removing once we are iptables-free + - SYS_MODULE + # We need it for now but might not need it for >= 5.11 specially + # for the 'SYS_RESOURCE'. + # In >= 5.8 there's already BPF and PERMON capabilities + - SYS_ADMIN + # Could be an alternative for the SYS_ADMIN for the RLIMIT_NPROC + - SYS_RESOURCE + # Both PERFMON and BPF requires kernel 5.8, container runtime + # cri-o >= v1.22.0 or containerd >= v1.5.0. + # If available, SYS_ADMIN can be removed. + #- PERFMON + #- BPF + +# -- Cilium agent update strategy +updateStrategy: + type: RollingUpdate + rollingUpdate: + maxUnavailable: 2 + +# Configuration Values for cilium-agent + +aksbyocni: + # -- Enable AKS BYOCNI integration. + # Note that this is incompatible with AKS clusters not created in BYOCNI mode: + # use Azure integration (`azure.enabled`) instead. + enabled: false + +# -- Enable installation of PodCIDR routes between worker +# nodes if worker nodes share a common L2 network segment. +autoDirectNodeRoutes: false + +# -- Annotate k8s node upon initialization with Cilium's metadata. +annotateK8sNode: false + +azure: + # -- Enable Azure integration. + # Note that this is incompatible with AKS clusters created in BYOCNI mode: use + # AKS BYOCNI integration (`aksbyocni.enabled`) instead. + enabled: false + # usePrimaryAddress: false + # resourceGroup: group1 + # subscriptionID: 00000000-0000-0000-0000-000000000000 + # tenantID: 00000000-0000-0000-0000-000000000000 + # clientID: 00000000-0000-0000-0000-000000000000 + # clientSecret: 00000000-0000-0000-0000-000000000000 + # userAssignedIdentityID: 00000000-0000-0000-0000-000000000000 + +alibabacloud: + # -- Enable AlibabaCloud ENI integration + enabled: false + +# -- Enable bandwidth manager to optimize TCP and UDP workloads and allow +# for rate-limiting traffic from individual Pods with EDT (Earliest Departure +# Time) through the "kubernetes.io/egress-bandwidth" Pod annotation. +bandwidthManager: + # -- Enable bandwidth manager infrastructure (also prerequirement for BBR) + enabled: false + # -- Activate BBR TCP congestion control for Pods + bbr: false + +# -- Configure standalone NAT46/NAT64 gateway +nat46x64Gateway: + # -- Enable RFC8215-prefixed translation + enabled: false + +# -- EnableHighScaleIPcache enables the special ipcache mode for high scale +# clusters. The ipcache content will be reduced to the strict minimum and +# traffic will be encapsulated to carry security identities. +highScaleIPcache: + # -- Enable the high scale mode for the ipcache. + enabled: false + +# -- Configure L2 announcements +l2announcements: + # -- Enable L2 announcements + enabled: false + # -- If a lease is not renewed for X duration, the current leader is considered dead, a new leader is picked + # leaseDuration: 15s + # -- The interval at which the leader will renew the lease + # leaseRenewDeadline: 5s + # -- The timeout between retries if renewal fails + # leaseRetryPeriod: 2s + +# -- Configure L2 pod announcements +l2podAnnouncements: + # -- Enable L2 pod announcements + enabled: false + # -- Interface used for sending Gratuitous ARP pod announcements + interface: "eth0" + +# -- Configure BGP +bgp: + # -- Enable BGP support inside Cilium; embeds a new ConfigMap for BGP inside + # cilium-agent and cilium-operator + enabled: false + announce: + # -- Enable allocation and announcement of service LoadBalancer IPs + loadbalancerIP: false + # -- Enable announcement of node pod CIDR + podCIDR: false + +# -- This feature set enables virtual BGP routers to be created via +# CiliumBGPPeeringPolicy CRDs. +bgpControlPlane: + # -- Enables the BGP control plane. + enabled: false + +pmtuDiscovery: + # -- Enable path MTU discovery to send ICMP fragmentation-needed replies to + # the client. + enabled: false + +bpf: + autoMount: + # -- Enable automatic mount of BPF filesystem + # When `autoMount` is enabled, the BPF filesystem is mounted at + # `bpf.root` path on the underlying host and inside the cilium agent pod. + # If users disable `autoMount`, it's expected that users have mounted + # bpffs filesystem at the specified `bpf.root` volume, and then the + # volume will be mounted inside the cilium agent pod at the same path. + enabled: true + # -- Configure the mount point for the BPF filesystem + root: /sys/fs/bpf + + # -- Enables pre-allocation of eBPF map values. This increases + # memory usage but can reduce latency. + preallocateMaps: false + + # -- (int) Configure the maximum number of entries in auth map. + # @default -- `524288` + authMapMax: ~ + + # -- (int) Configure the maximum number of entries in the TCP connection tracking + # table. + # @default -- `524288` + ctTcpMax: ~ + + # -- (int) Configure the maximum number of entries for the non-TCP connection + # tracking table. + # @default -- `262144` + ctAnyMax: ~ + + # -- Configure the maximum number of service entries in the + # load balancer maps. + lbMapMax: 65536 + + # -- (int) Configure the maximum number of entries for the NAT table. + # @default -- `524288` + natMax: ~ + + # -- (int) Configure the maximum number of entries for the neighbor table. + # @default -- `524288` + neighMax: ~ + + # -- Configure the maximum number of entries in endpoint policy map (per endpoint). + policyMapMax: 16384 + + # -- (float64) Configure auto-sizing for all BPF maps based on available memory. + # ref: https://docs.cilium.io/en/stable/network/ebpf/maps/ + # @default -- `0.0025` + mapDynamicSizeRatio: ~ + + # -- Configure the level of aggregation for monitor notifications. + # Valid options are none, low, medium, maximum. + monitorAggregation: medium + + # -- Configure the typical time between monitor notifications for + # active connections. + monitorInterval: "5s" + + # -- Configure which TCP flags trigger notifications when seen for the + # first time in a connection. + monitorFlags: "all" + + # -- Allow cluster external access to ClusterIP services. + lbExternalClusterIP: false + + # -- (bool) Enable native IP masquerade support in eBPF + # @default -- `false` + masquerade: ~ + + # -- (bool) Configure whether direct routing mode should route traffic via + # host stack (true) or directly and more efficiently out of BPF (false) if + # the kernel supports it. The latter has the implication that it will also + # bypass netfilter in the host namespace. + # @default -- `false` + hostLegacyRouting: ~ + + # -- (bool) Configure the eBPF-based TPROXY to reduce reliance on iptables rules + # for implementing Layer 7 policy. + # @default -- `false` + tproxy: ~ + + # -- (list) Configure explicitly allowed VLAN id's for bpf logic bypass. + # [0] will allow all VLAN id's without any filtering. + # @default -- `[]` + vlanBypass: ~ + +# -- Enable BPF clock source probing for more efficient tick retrieval. +bpfClockProbe: false + +# -- Clean all eBPF datapath state from the initContainer of the cilium-agent +# DaemonSet. +# +# WARNING: Use with care! +cleanBpfState: false + +# -- Clean all local Cilium state from the initContainer of the cilium-agent +# DaemonSet. Implies cleanBpfState: true. +# +# WARNING: Use with care! +cleanState: false + +# -- Wait for KUBE-PROXY-CANARY iptables rule to appear in "wait-for-kube-proxy" +# init container before launching cilium-agent. +# More context can be found in the commit message of below PR +# https://github.com/cilium/cilium/pull/20123 +waitForKubeProxy: false + +cni: + # -- Install the CNI configuration and binary files into the filesystem. + install: true + + # -- Remove the CNI configuration and binary files on agent shutdown. Enable this + # if you're removing Cilium from the cluster. Disable this to prevent the CNI + # configuration file from being removed during agent upgrade, which can cause + # nodes to go unmanageable. + uninstall: false + + # -- Configure chaining on top of other CNI plugins. Possible values: + # - none + # - aws-cni + # - flannel + # - generic-veth + # - portmap + chainingMode: ~ + + # -- A CNI network name in to which the Cilium plugin should be added as a chained plugin. + # This will cause the agent to watch for a CNI network with this network name. When it is + # found, this will be used as the basis for Cilium's CNI configuration file. If this is + # set, it assumes a chaining mode of generic-veth. As a special case, a chaining mode + # of aws-cni implies a chainingTarget of aws-cni. + chainingTarget: ~ + + # -- Make Cilium take ownership over the `/etc/cni/net.d` directory on the + # node, renaming all non-Cilium CNI configurations to `*.cilium_bak`. + # This ensures no Pods can be scheduled using other CNI plugins during Cilium + # agent downtime. + exclusive: true + + # -- Configure the log file for CNI logging with retention policy of 7 days. + # Disable CNI file logging by setting this field to empty explicitly. + logFile: /var/run/cilium/cilium-cni.log + + # -- Skip writing of the CNI configuration. This can be used if + # writing of the CNI configuration is performed by external automation. + customConf: false + + # -- Configure the path to the CNI configuration directory on the host. + confPath: /etc/cni/net.d + + # -- Configure the path to the CNI binary directory on the host. + binPath: /opt/cni/bin + + # -- Specify the path to a CNI config to read from on agent start. + # This can be useful if you want to manage your CNI + # configuration outside of a Kubernetes environment. This parameter is + # mutually exclusive with the 'cni.configMap' parameter. The agent will + # write this to 05-cilium.conflist on startup. + # readCniConf: /host/etc/cni/net.d/05-sample.conflist.input + + # -- When defined, configMap will mount the provided value as ConfigMap and + # interpret the cniConf variable as CNI configuration file and write it + # when the agent starts up + # configMap: cni-configuration + + # -- Configure the key in the CNI ConfigMap to read the contents of + # the CNI configuration from. + configMapKey: cni-config + + # -- Configure the path to where to mount the ConfigMap inside the agent pod. + confFileMountPath: /tmp/cni-configuration + + # -- Configure the path to where the CNI configuration directory is mounted + # inside the agent pod. + hostConfDirMountPath: /host/etc/cni/net.d + +# -- (string) Configure how frequently garbage collection should occur for the datapath +# connection tracking table. +# @default -- `"0s"` +conntrackGCInterval: "" + +# -- (string) Configure the maximum frequency for the garbage collection of the +# connection tracking table. Only affects the automatic computation for the frequency +# and has no effect when 'conntrackGCInterval' is set. This can be set to more frequently +# clean up unused identities created from ToFQDN policies. +conntrackGCMaxInterval: "" + +# -- Configure container runtime specific integration. +# Deprecated in favor of bpf.autoMount.enabled. To be removed in 1.15. +containerRuntime: + # -- Enables specific integrations for container runtimes. + # Supported values: + # - crio + # - none + integration: none + +# -- (string) Configure timeout in which Cilium will exit if CRDs are not available +# @default -- `"5m"` +crdWaitTimeout: "" + +# -- Tail call hooks for custom eBPF programs. +customCalls: + # -- Enable tail call hooks for custom eBPF programs. + enabled: false + +daemon: + # -- Configure where Cilium runtime state should be stored. + runPath: "/var/run/cilium" + + # -- Configure a custom list of possible configuration override sources + # The default is "config-map:cilium-config,cilium-node-config". For supported + # values, see the help text for the build-config subcommand. + # Note that this value should be a comma-separated string. + configSources: ~ + + # -- allowedConfigOverrides is a list of config-map keys that can be overridden. + # That is to say, if this value is set, config sources (excepting the first one) can + # only override keys in this list. + # + # This takes precedence over blockedConfigOverrides. + # + # By default, all keys may be overridden. To disable overrides, set this to "none" or + # change the configSources variable. + allowedConfigOverrides: ~ + + # -- blockedConfigOverrides is a list of config-map keys that may not be overridden. + # In other words, if any of these keys appear in a configuration source excepting the + # first one, they will be ignored + # + # This is ignored if allowedConfigOverrides is set. + # + # By default, all keys may be overridden. + blockedConfigOverrides: ~ + +# -- Specify which network interfaces can run the eBPF datapath. This means +# that a packet sent from a pod to a destination outside the cluster will be +# masqueraded (to an output device IPv4 address), if the output device runs the +# program. When not specified, probing will automatically detect devices. +# devices: "" + +# -- Enables experimental support for the detection of new and removed datapath +# devices. When devices change the eBPF datapath is reloaded and services updated. +# If "devices" is set then only those devices, or devices matching a wildcard will +# be considered. +enableRuntimeDeviceDetection: false + +# -- Chains to ignore when installing feeder rules. +# disableIptablesFeederRules: "" + +# -- Limit iptables-based egress masquerading to interface selector. +# egressMasqueradeInterfaces: "" + +# -- Whether to enable CNP status updates. +enableCnpStatusUpdates: false + +# -- Configures the use of the KVStore to optimize Kubernetes event handling by +# mirroring it into the KVstore for reduced overhead in large clusters. +enableK8sEventHandover: false + +# -- Enable setting identity mark for local traffic. +# enableIdentityMark: true + +# -- Enable Kubernetes EndpointSlice feature in Cilium if the cluster supports it. +# enableK8sEndpointSlice: true + +# -- Enable CiliumEndpointSlice feature. +enableCiliumEndpointSlice: false + +envoyConfig: + # -- Enable CiliumEnvoyConfig CRD + # CiliumEnvoyConfig CRD can also be implicitly enabled by other options. + enabled: false + + # -- SecretsNamespace is the namespace in which envoy SDS will retrieve secrets from. + secretsNamespace: + # -- Create secrets namespace for CiliumEnvoyConfig CRDs. + create: true + + # -- The name of the secret namespace to which Cilium agents are given read access. + name: cilium-secrets + +ingressController: + # -- Enable cilium ingress controller + # This will automatically set enable-envoy-config as well. + enabled: false + + # -- Set cilium ingress controller to be the default ingress controller + # This will let cilium ingress controller route entries without ingress class set + default: false + + # -- Default ingress load balancer mode + # Supported values: shared, dedicated + # For granular control, use the following annotations on the ingress resource + # ingress.cilium.io/loadbalancer-mode: shared|dedicated, + loadbalancerMode: dedicated + + # -- Enforce https for host having matching TLS host in Ingress. + # Incoming traffic to http listener will return 308 http error code with respective location in header. + enforceHttps: true + + # -- IngressLBAnnotations are the annotation prefixes, which are used to filter annotations to propagate + # from Ingress to the Load Balancer service + ingressLBAnnotationPrefixes: ['service.beta.kubernetes.io', 'service.kubernetes.io', 'cloud.google.com'] + + # -- Default secret namespace for ingresses without .spec.tls[].secretName set. + defaultSecretNamespace: + + # -- Default secret name for ingresses without .spec.tls[].secretName set. + defaultSecretName: + + # -- SecretsNamespace is the namespace in which envoy SDS will retrieve TLS secrets from. + secretsNamespace: + # -- Create secrets namespace for Ingress. + create: true + + # -- Name of Ingress secret namespace. + name: cilium-secrets + + # -- Enable secret sync, which will make sure all TLS secrets used by Ingress are synced to secretsNamespace.name. + # If disabled, TLS secrets must be maintained externally. + sync: true + + # -- Load-balancer service in shared mode. + # This is a single load-balancer service for all Ingress resources. + service: + # -- Service name + name: cilium-ingress + # -- Labels to be added for the shared LB service + labels: {} + # -- Annotations to be added for the shared LB service + annotations: {} + # -- Service type for the shared LB service + type: LoadBalancer + # -- Configure a specific nodePort for insecure HTTP traffic on the shared LB service + insecureNodePort: ~ + # -- Configure a specific nodePort for secure HTTPS traffic on the shared LB service + secureNodePort : ~ + # -- Configure a specific loadBalancerClass on the shared LB service (requires Kubernetes 1.24+) + loadBalancerClass: ~ + # -- Configure a specific loadBalancerIP on the shared LB service + loadBalancerIP : ~ + # -- Configure if node port allocation is required for LB service + # ref: https://kubernetes.io/docs/concepts/services-networking/service/#load-balancer-nodeport-allocation + allocateLoadBalancerNodePorts: ~ + +gatewayAPI: + # -- Enable support for Gateway API in cilium + # This will automatically set enable-envoy-config as well. + enabled: false + + # -- SecretsNamespace is the namespace in which envoy SDS will retrieve TLS secrets from. + secretsNamespace: + # -- Create secrets namespace for Gateway API. + create: true + + # -- Name of Gateway API secret namespace. + name: cilium-secrets + + # -- Enable secret sync, which will make sure all TLS secrets used by Ingress are synced to secretsNamespace.name. + # If disabled, TLS secrets must be maintained externally. + sync: true + +# -- Enables the fallback compatibility solution for when the xt_socket kernel +# module is missing and it is needed for the datapath L7 redirection to work +# properly. See documentation for details on when this can be disabled: +# https://docs.cilium.io/en/stable/operations/system_requirements/#linux-kernel. +enableXTSocketFallback: true + +encryption: + # -- Enable transparent network encryption. + enabled: false + + # -- Encryption method. Can be either ipsec or wireguard. + type: ipsec + + # -- Enable encryption for pure node to node traffic. + # This option is only effective when encryption.type is set to "wireguard". + nodeEncryption: false + + ipsec: + # -- Name of the key file inside the Kubernetes secret configured via secretName. + keyFile: "" + + # -- Path to mount the secret inside the Cilium pod. + mountPath: "" + + # -- Name of the Kubernetes secret containing the encryption keys. + secretName: "" + + # -- The interface to use for encrypted traffic. + interface: "" + + # -- Enable the key watcher. If disabled, a restart of the agent will be + # necessary on key rotations. + keyWatcher: true + + # -- Maximum duration of the IPsec key rotation. The previous key will be + # removed after that delay. + keyRotationDuration: "5m" + + wireguard: + # -- Enables the fallback to the user-space implementation. + userspaceFallback: false + + # -- Deprecated in favor of encryption.ipsec.keyFile. To be removed in 1.15. + # Name of the key file inside the Kubernetes secret configured via secretName. + # This option is only effective when encryption.type is set to ipsec. + keyFile: keys + + # -- Deprecated in favor of encryption.ipsec.mountPath. To be removed in 1.15. + # Path to mount the secret inside the Cilium pod. + # This option is only effective when encryption.type is set to ipsec. + mountPath: /etc/ipsec + + # -- Deprecated in favor of encryption.ipsec.secretName. To be removed in 1.15. + # Name of the Kubernetes secret containing the encryption keys. + # This option is only effective when encryption.type is set to ipsec. + secretName: cilium-ipsec-keys + + # -- Deprecated in favor of encryption.ipsec.interface. To be removed in 1.15. + # The interface to use for encrypted traffic. + # This option is only effective when encryption.type is set to ipsec. + interface: "" + +endpointHealthChecking: + # -- Enable connectivity health checking between virtual endpoints. + enabled: true + +# -- Enable endpoint status. +# Status can be: policy, health, controllers, log and / or state. For 2 or more options use a space. +endpointStatus: + enabled: false + status: "" + +endpointRoutes: + # -- Enable use of per endpoint routes instead of routing via + # the cilium_host interface. + enabled: false + +k8sNetworkPolicy: + # -- Enable support for K8s NetworkPolicy + enabled: true + +eni: + # -- Enable Elastic Network Interface (ENI) integration. + enabled: false + # -- Update ENI Adapter limits from the EC2 API + updateEC2AdapterLimitViaAPI: true + # -- Release IPs not used from the ENI + awsReleaseExcessIPs: false + # -- Enable ENI prefix delegation + awsEnablePrefixDelegation: false + # -- EC2 API endpoint to use + ec2APIEndpoint: "" + # -- Tags to apply to the newly created ENIs + eniTags: {} + # -- Interval for garbage collection of unattached ENIs. Set to "0s" to disable. + # @default -- `"5m"` + gcInterval: "" + # -- Additional tags attached to ENIs created by Cilium. + # Dangling ENIs with this tag will be garbage collected + # @default -- `{"io.cilium/cilium-managed":"true,"io.cilium/cluster-name":""}` + gcTags: {} + # -- If using IAM role for Service Accounts will not try to + # inject identity values from cilium-aws kubernetes secret. + # Adds annotation to service account if managed by Helm. + # See https://github.com/aws/amazon-eks-pod-identity-webhook + iamRole: "" + # -- Filter via subnet IDs which will dictate which subnets are going to be used to create new ENIs + # Important note: This requires that each instance has an ENI with a matching subnet attached + # when Cilium is deployed. If you only want to control subnets for ENIs attached by Cilium, + # use the CNI configuration file settings (cni.customConf) instead. + subnetIDsFilter: [] + # -- Filter via tags (k=v) which will dictate which subnets are going to be used to create new ENIs + # Important note: This requires that each instance has an ENI with a matching subnet attached + # when Cilium is deployed. If you only want to control subnets for ENIs attached by Cilium, + # use the CNI configuration file settings (cni.customConf) instead. + subnetTagsFilter: [] + # -- Filter via AWS EC2 Instance tags (k=v) which will dictate which AWS EC2 Instances + # are going to be used to create new ENIs + instanceTagsFilter: [] + +externalIPs: + # -- Enable ExternalIPs service support. + enabled: false + +# fragmentTracking enables IPv4 fragment tracking support in the datapath. +# fragmentTracking: true + +gke: + # -- Enable Google Kubernetes Engine integration + enabled: false + +# -- Enable connectivity health checking. +healthChecking: true + +# -- TCP port for the agent health API. This is not the port for cilium-health. +healthPort: 9879 + +# -- Configure the host firewall. +hostFirewall: + # -- Enables the enforcement of host policies in the eBPF datapath. + enabled: false + +hostPort: + # -- Enable hostPort service support. + enabled: false + +# -- Configure socket LB +socketLB: + # -- Enable socket LB + enabled: false + + # -- Disable socket lb for non-root ns. This is used to enable Istio routing rules. + # hostNamespaceOnly: false + +# -- Configure certificate generation for Hubble integration. +# If hubble.tls.auto.method=cronJob, these values are used +# for the Kubernetes CronJob which will be scheduled regularly to +# (re)generate any certificates not provided manually. +certgen: + image: + override: ~ + repository: "${CERTGEN_REPO}" + tag: "${CERTGEN_VERSION}" + digest: "${CERTGEN_DIGEST}" + useDigest: true + pullPolicy: "${PULL_POLICY}" + # -- Seconds after which the completed job pod will be deleted + ttlSecondsAfterFinished: 1800 + # -- Labels to be added to hubble-certgen pods + podLabels: {} + # -- Annotations to be added to the hubble-certgen initial Job and CronJob + annotations: + job: {} + cronJob: {} + # -- Node tolerations for pod assignment on nodes with taints + # ref: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/ + tolerations: [] + + # -- Additional certgen volumes. + extraVolumes: [] + + # -- Additional certgen volumeMounts. + extraVolumeMounts: [] + +hubble: + # -- Enable Hubble (true by default). + enabled: true + + # -- Buffer size of the channel Hubble uses to receive monitor events. If this + # value is not set, the queue size is set to the default monitor queue size. + # eventQueueSize: "" + + # -- Number of recent flows for Hubble to cache. Defaults to 4095. + # Possible values are: + # 1, 3, 7, 15, 31, 63, 127, 255, 511, 1023, + # 2047, 4095, 8191, 16383, 32767, 65535 + # eventBufferCapacity: "4095" + + # -- Hubble metrics configuration. + # See https://docs.cilium.io/en/stable/observability/metrics/#hubble-metrics + # for more comprehensive documentation about Hubble metrics. + metrics: + # -- Configures the list of metrics to collect. If empty or null, metrics + # are disabled. + # Example: + # + # enabled: + # - dns:query;ignoreAAAA + # - drop + # - tcp + # - flow + # - icmp + # - http + # + # You can specify the list of metrics from the helm CLI: + # + # --set metrics.enabled="{dns:query;ignoreAAAA,drop,tcp,flow,icmp,http}" + # + enabled: ~ + # -- Enables exporting hubble metrics in OpenMetrics format. + enableOpenMetrics: false + # -- Configure the port the hubble metric server listens on. + port: 9965 + # -- Annotations to be added to hubble-metrics service. + serviceAnnotations: {} + serviceMonitor: + # -- Create ServiceMonitor resources for Prometheus Operator. + # This requires the prometheus CRDs to be available. + # ref: https://github.com/prometheus-operator/prometheus-operator/blob/main/example/prometheus-operator-crd/monitoring.coreos.com_servicemonitors.yaml) + enabled: false + # -- Labels to add to ServiceMonitor hubble + labels: {} + # -- Annotations to add to ServiceMonitor hubble + annotations: {} + # -- Interval for scrape metrics. + interval: "10s" + # -- Relabeling configs for the ServiceMonitor hubble + relabelings: + - sourceLabels: + - __meta_kubernetes_pod_node_name + targetLabel: node + replacement: ${1} + # -- Metrics relabeling configs for the ServiceMonitor hubble + metricRelabelings: ~ + # -- Grafana dashboards for hubble + # grafana can import dashboards based on the label and value + # ref: https://github.com/grafana/helm-charts/tree/main/charts/grafana#sidecar-for-dashboards + dashboards: + enabled: false + label: grafana_dashboard + namespace: ~ + labelValue: "1" + annotations: {} + + # -- Unix domain socket path to listen to when Hubble is enabled. + socketPath: /var/run/cilium/hubble.sock + + # -- An additional address for Hubble to listen to. + # Set this field ":4244" if you are enabling Hubble Relay, as it assumes that + # Hubble is listening on port 4244. + listenAddress: ":4244" + # -- Whether Hubble should prefer to announce IPv6 or IPv4 addresses if both are available. + preferIpv6: false + # -- (bool) Skip Hubble events with unknown cgroup ids + # @default -- `true` + skipUnknownCGroupIDs: ~ + + peerService: + # -- Service Port for the Peer service. + # If not set, it is dynamically assigned to port 443 if TLS is enabled and to + # port 80 if not. + # servicePort: 80 + # -- Target Port for the Peer service, must match the hubble.listenAddress' + # port. + targetPort: 4244 + # -- The cluster domain to use to query the Hubble Peer service. It should + # be the local cluster. + clusterDomain: cluster.local + # -- TLS configuration for Hubble + tls: + # -- Enable mutual TLS for listenAddress. Setting this value to false is + # highly discouraged as the Hubble API provides access to potentially + # sensitive network flow metadata and is exposed on the host network. + enabled: true + # -- Configure automatic TLS certificates generation. + auto: + # -- Auto-generate certificates. + # When set to true, automatically generate a CA and certificates to + # enable mTLS between Hubble server and Hubble Relay instances. If set to + # false, the certs for Hubble server need to be provided by setting + # appropriate values below. + enabled: true + # -- Set the method to auto-generate certificates. Supported values: + # - helm: This method uses Helm to generate all certificates. + # - cronJob: This method uses a Kubernetes CronJob the generate any + # certificates not provided by the user at installation + # time. + # - certmanager: This method use cert-manager to generate & rotate certificates. + method: helm + # -- Generated certificates validity duration in days. + certValidityDuration: 1095 + # -- Schedule for certificates regeneration (regardless of their expiration date). + # Only used if method is "cronJob". If nil, then no recurring job will be created. + # Instead, only the one-shot job is deployed to generate the certificates at + # installation time. + # + # Defaults to midnight of the first day of every fourth month. For syntax, see + # https://kubernetes.io/docs/concepts/workloads/controllers/cron-jobs/#schedule-syntax + schedule: "0 0 1 */4 *" + + # [Example] + # certManagerIssuerRef: + # group: cert-manager.io + # kind: ClusterIssuer + # name: ca-issuer + # -- certmanager issuer used when hubble.tls.auto.method=certmanager. + certManagerIssuerRef: {} + + # -- base64 encoded PEM values for the Hubble server certificate and private key + server: + cert: "" + key: "" + # -- Extra DNS names added to certificate when it's auto generated + extraDnsNames: [] + # -- Extra IP addresses added to certificate when it's auto generated + extraIpAddresses: [] + + relay: + # -- Enable Hubble Relay (requires hubble.enabled=true) + enabled: false + + # -- Roll out Hubble Relay pods automatically when configmap is updated. + rollOutPods: false + + # -- Hubble-relay container image. + image: + override: ~ + repository: "${HUBBLE_RELAY_REPO}" + tag: "${CILIUM_VERSION}" + # hubble-relay-digest + digest: ${HUBBLE_RELAY_DIGEST} + useDigest: ${USE_DIGESTS} + pullPolicy: "${PULL_POLICY}" + + # -- Specifies the resources for the hubble-relay pods + resources: {} + + # -- Number of replicas run for the hubble-relay deployment. + replicas: 1 + + # -- Affinity for hubble-replay + affinity: + podAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - topologyKey: kubernetes.io/hostname + labelSelector: + matchLabels: + k8s-app: cilium + + # -- Pod topology spread constraints for hubble-relay + topologySpreadConstraints: [] + # - maxSkew: 1 + # topologyKey: topology.kubernetes.io/zone + # whenUnsatisfiable: DoNotSchedule + + # -- Node labels for pod assignment + # ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#nodeselector + nodeSelector: + kubernetes.io/os: linux + + # -- Node tolerations for pod assignment on nodes with taints + # ref: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/ + tolerations: [] + + # -- Additional hubble-relay environment variables. + extraEnv: [] + + # -- Annotations to be added to hubble-relay pods + podAnnotations: {} + + # -- Labels to be added to hubble-relay pods + podLabels: {} + + # PodDisruptionBudget settings + podDisruptionBudget: + # -- enable PodDisruptionBudget + # ref: https://kubernetes.io/docs/concepts/workloads/pods/disruptions/ + enabled: false + # -- Minimum number/percentage of pods that should remain scheduled. + # When it's set, maxUnavailable must be disabled by `maxUnavailable: null` + minAvailable: null + # -- Maximum number/percentage of pods that may be made unavailable + maxUnavailable: 1 + + # -- The priority class to use for hubble-relay + priorityClassName: "" + + # -- Configure termination grace period for hubble relay Deployment. + terminationGracePeriodSeconds: 1 + + # -- hubble-relay update strategy + updateStrategy: + type: RollingUpdate + rollingUpdate: + maxUnavailable: 1 + + # -- Additional hubble-relay volumes. + extraVolumes: [] + + # -- Additional hubble-relay volumeMounts. + extraVolumeMounts: [] + + # -- hubble-relay pod security context + podSecurityContext: + fsGroup: 65532 + + # -- hubble-relay container security context + securityContext: + # readOnlyRootFilesystem: true + runAsNonRoot: true + runAsUser: 65532 + runAsGroup: 65532 + capabilities: + drop: + - ALL + + # -- hubble-relay service configuration. + service: + # --- The type of service used for Hubble Relay access, either ClusterIP or NodePort. + type: ClusterIP + # --- The port to use when the service type is set to NodePort. + nodePort: 31234 + + # -- Host to listen to. Specify an empty string to bind to all the interfaces. + listenHost: "" + + # -- Port to listen to. + listenPort: "4245" + + # -- TLS configuration for Hubble Relay + tls: + # -- base64 encoded PEM values for the hubble-relay client certificate and private key + # This keypair is presented to Hubble server instances for mTLS + # authentication and is required when hubble.tls.enabled is true. + # These values need to be set manually if hubble.tls.auto.enabled is false. + client: + cert: "" + key: "" + # -- base64 encoded PEM values for the hubble-relay server certificate and private key + server: + # When set to true, enable TLS on for Hubble Relay server + # (ie: for clients connecting to the Hubble Relay API). + enabled: false + # When set to true enforces mutual TLS between Hubble Relay server and its clients. + # False allow non-mutual TLS connections. + # This option has no effect when TLS is disabled. + mtls: false + # These values need to be set manually if hubble.tls.auto.enabled is false. + cert: "" + key: "" + # -- extra DNS names added to certificate when its auto gen + extraDnsNames: [] + # -- extra IP addresses added to certificate when its auto gen + extraIpAddresses: [] + + # -- Dial timeout to connect to the local hubble instance to receive peer information (e.g. "30s"). + dialTimeout: ~ + + # -- Backoff duration to retry connecting to the local hubble instance in case of failure (e.g. "30s"). + retryTimeout: ~ + + # -- Max number of flows that can be buffered for sorting before being sent to the + # client (per request) (e.g. 100). + sortBufferLenMax: ~ + + # -- When the per-request flows sort buffer is not full, a flow is drained every + # time this timeout is reached (only affects requests in follow-mode) (e.g. "1s"). + sortBufferDrainTimeout: ~ + + # -- Port to use for the k8s service backed by hubble-relay pods. + # If not set, it is dynamically assigned to port 443 if TLS is enabled and to + # port 80 if not. + # servicePort: 80 + + # -- Enable prometheus metrics for hubble-relay on the configured port at + # /metrics + prometheus: + enabled: false + port: 9966 + serviceMonitor: + # -- Enable service monitors. + # This requires the prometheus CRDs to be available (see https://github.com/prometheus-operator/prometheus-operator/blob/main/example/prometheus-operator-crd/monitoring.coreos.com_servicemonitors.yaml) + enabled: false + # -- Labels to add to ServiceMonitor hubble-relay + labels: {} + # -- Annotations to add to ServiceMonitor hubble-relay + annotations: {} + # -- Interval for scrape metrics. + interval: "10s" + # -- Specify the Kubernetes namespace where Prometheus expects to find + # service monitors configured. + # namespace: "" + # -- Relabeling configs for the ServiceMonitor hubble-relay + relabelings: ~ + # -- Metrics relabeling configs for the ServiceMonitor hubble-relay + metricRelabelings: ~ + + gops: + # -- Enable gops for hubble-relay + enabled: true + # -- Configure gops listen port for hubble-relay + port: 9893 + + pprof: + # -- Enable pprof for hubble-relay + enabled: false + # -- Configure pprof listen address for hubble-relay + address: localhost + # -- Configure pprof listen port for hubble-relay + port: 6062 + + ui: + # -- Whether to enable the Hubble UI. + enabled: false + + standalone: + # -- When true, it will allow installing the Hubble UI only, without checking dependencies. + # It is useful if a cluster already has cilium and Hubble relay installed and you just + # want Hubble UI to be deployed. + # When installed via helm, installing UI should be done via `helm upgrade` and when installed via the cilium cli, then `cilium hubble enable --ui` + enabled: false + + tls: + # -- When deploying Hubble UI in standalone, with tls enabled for Hubble relay, it is required + # to provide a volume for mounting the client certificates. + certsVolume: {} + # projected: + # defaultMode: 0400 + # sources: + # - secret: + # name: hubble-ui-client-certs + # items: + # - key: tls.crt + # path: client.crt + # - key: tls.key + # path: client.key + # - key: ca.crt + # path: hubble-relay-ca.crt + + # -- Roll out Hubble-ui pods automatically when configmap is updated. + rollOutPods: false + + tls: + # -- base64 encoded PEM values used to connect to hubble-relay + # This keypair is presented to Hubble Relay instances for mTLS + # authentication and is required when hubble.relay.tls.server.enabled is true. + # These values need to be set manually if hubble.tls.auto.enabled is false. + client: + cert: "" + key: "" + + backend: + # -- Hubble-ui backend image. + image: + override: ~ + repository: "${HUBBLE_UI_BACKEND_REPO}" + tag: "${HUBBLE_UI_BACKEND_VERSION}" + digest: "${HUBBLE_UI_BACKEND_DIGEST}" + useDigest: true + pullPolicy: "${PULL_POLICY}" + + # -- Hubble-ui backend security context. + securityContext: {} + + # -- Additional hubble-ui backend environment variables. + extraEnv: [] + + # -- Additional hubble-ui backend volumes. + extraVolumes: [] + + # -- Additional hubble-ui backend volumeMounts. + extraVolumeMounts: [] + + # -- Resource requests and limits for the 'backend' container of the 'hubble-ui' deployment. + resources: {} + # limits: + # cpu: 1000m + # memory: 1024M + # requests: + # cpu: 100m + # memory: 64Mi + + frontend: + # -- Hubble-ui frontend image. + image: + override: ~ + repository: "${HUBBLE_UI_FRONTEND_REPO}" + tag: "${HUBBLE_UI_FRONTEND_VERSION}" + digest: "${HUBBLE_UI_FRONTEND_DIGEST}" + useDigest: true + pullPolicy: "${PULL_POLICY}" + + # -- Hubble-ui frontend security context. + securityContext: {} + + # -- Additional hubble-ui frontend environment variables. + extraEnv: [] + + # -- Additional hubble-ui frontend volumes. + extraVolumes: [] + + # -- Additional hubble-ui frontend volumeMounts. + extraVolumeMounts: [] + + # -- Resource requests and limits for the 'frontend' container of the 'hubble-ui' deployment. + resources: {} + # limits: + # cpu: 1000m + # memory: 1024M + # requests: + # cpu: 100m + # memory: 64Mi + server: + # -- Controls server listener for ipv6 + ipv6: + enabled: true + + # -- The number of replicas of Hubble UI to deploy. + replicas: 1 + + # -- Annotations to be added to hubble-ui pods + podAnnotations: {} + + # -- Labels to be added to hubble-ui pods + podLabels: {} + + # PodDisruptionBudget settings + podDisruptionBudget: + # -- enable PodDisruptionBudget + # ref: https://kubernetes.io/docs/concepts/workloads/pods/disruptions/ + enabled: false + # -- Minimum number/percentage of pods that should remain scheduled. + # When it's set, maxUnavailable must be disabled by `maxUnavailable: null` + minAvailable: null + # -- Maximum number/percentage of pods that may be made unavailable + maxUnavailable: 1 + + # -- Affinity for hubble-ui + affinity: {} + + # -- Pod topology spread constraints for hubble-ui + topologySpreadConstraints: [] + # - maxSkew: 1 + # topologyKey: topology.kubernetes.io/zone + # whenUnsatisfiable: DoNotSchedule + + # -- Node labels for pod assignment + # ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#nodeselector + nodeSelector: + kubernetes.io/os: linux + + # -- Node tolerations for pod assignment on nodes with taints + # ref: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/ + tolerations: [] + + # -- The priority class to use for hubble-ui + priorityClassName: "" + + # -- hubble-ui update strategy. + updateStrategy: + type: RollingUpdate + rollingUpdate: + maxUnavailable: 1 + + # -- Security context to be added to Hubble UI pods + securityContext: + runAsUser: 1001 + runAsGroup: 1001 + fsGroup: 1001 + + # -- hubble-ui service configuration. + service: + # -- Annotations to be added for the Hubble UI service + annotations: {} + # --- The type of service used for Hubble UI access, either ClusterIP or NodePort. + type: ClusterIP + # --- The port to use when the service type is set to NodePort. + nodePort: 31235 + + # -- Defines base url prefix for all hubble-ui http requests. + # It needs to be changed in case if ingress for hubble-ui is configured under some sub-path. + # Trailing `/` is required for custom path, ex. `/service-map/` + baseUrl: "/" + + # -- hubble-ui ingress configuration. + ingress: + enabled: false + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + className: "" + hosts: + - chart-example.local + labels: {} + tls: [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + +# -- Method to use for identity allocation (`crd` or `kvstore`). +identityAllocationMode: "crd" + +# -- (string) Time to wait before using new identity on endpoint identity change. +# @default -- `"5s"` +identityChangeGracePeriod: "" + +# -- Install Iptables rules to skip netfilter connection tracking on all pod +# traffic. This option is only effective when Cilium is running in direct +# routing and full KPR mode. Moreover, this option cannot be enabled when Cilium +# is running in a managed Kubernetes environment or in a chained CNI setup. +installNoConntrackIptablesRules: false + +ipam: + # -- Configure IP Address Management mode. + # ref: https://docs.cilium.io/en/stable/network/concepts/ipam/ + mode: "cluster-pool" + # -- Maximum rate at which the CiliumNode custom resource is updated. + ciliumNodeUpdateRate: "15s" + operator: + # -- IPv4 CIDR list range to delegate to individual nodes for IPAM. + clusterPoolIPv4PodCIDRList: ["10.0.0.0/8"] + # -- IPv4 CIDR mask size to delegate to individual nodes for IPAM. + clusterPoolIPv4MaskSize: 24 + # -- IPv6 CIDR list range to delegate to individual nodes for IPAM. + clusterPoolIPv6PodCIDRList: ["fd00::/104"] + # -- IPv6 CIDR mask size to delegate to individual nodes for IPAM. + clusterPoolIPv6MaskSize: 120 + # -- IP pools to auto-create in multi-pool IPAM mode. + autoCreateCiliumPodIPPools: {} + # default: + # ipv4: + # cidrs: + # - 10.10.0.0/8 + # maskSize: 24 + # other: + # ipv6: + # cidrs: + # - fd00:100::/80 + # maskSize: 96 + # -- The maximum burst size when rate limiting access to external APIs. + # Also known as the token bucket capacity. + # @default -- `20` + externalAPILimitBurstSize: ~ + # -- The maximum queries per second when rate limiting access to + # external APIs. Also known as the bucket refill rate, which is used to + # refill the bucket up to the burst size capacity. + # @default -- `4.0` + externalAPILimitQPS: ~ + +# -- Configure the eBPF-based ip-masq-agent +ipMasqAgent: + enabled: false +# the config of nonMasqueradeCIDRs +# config: + # nonMasqueradeCIDRs: [] + # masqLinkLocal: false + # masqLinkLocalIPv6: false + +# iptablesLockTimeout defines the iptables "--wait" option when invoked from Cilium. +# iptablesLockTimeout: "5s" + +ipv4: + # -- Enable IPv4 support. + enabled: true + +ipv6: + # -- Enable IPv6 support. + enabled: false + +# -- Configure Kubernetes specific configuration +k8s: {} + # -- requireIPv4PodCIDR enables waiting for Kubernetes to provide the PodCIDR + # range via the Kubernetes node resource + # requireIPv4PodCIDR: false + + # -- requireIPv6PodCIDR enables waiting for Kubernetes to provide the PodCIDR + # range via the Kubernetes node resource + # requireIPv6PodCIDR: false + +# -- Keep the deprecated selector labels when deploying Cilium DaemonSet. +keepDeprecatedLabels: false + +# -- Keep the deprecated probes when deploying Cilium DaemonSet +keepDeprecatedProbes: false + +startupProbe: + # -- failure threshold of startup probe. + # 105 x 2s translates to the old behaviour of the readiness probe (120s delay + 30 x 3s) + failureThreshold: 105 + # -- interval between checks of the startup probe + periodSeconds: 2 +livenessProbe: + # -- failure threshold of liveness probe + failureThreshold: 10 + # -- interval between checks of the liveness probe + periodSeconds: 30 +readinessProbe: + # -- failure threshold of readiness probe + failureThreshold: 3 + # -- interval between checks of the readiness probe + periodSeconds: 30 + +# -- Configure the kube-proxy replacement in Cilium BPF datapath +# Valid options are "true", "false", "disabled" (deprecated), "partial" (deprecated), "strict" (deprecated). +# ref: https://docs.cilium.io/en/stable/network/kubernetes/kubeproxy-free/ +#kubeProxyReplacement: "false" + +# -- healthz server bind address for the kube-proxy replacement. +# To enable set the value to '0.0.0.0:10256' for all ipv4 +# addresses and this '[::]:10256' for all ipv6 addresses. +# By default it is disabled. +kubeProxyReplacementHealthzBindAddr: "" + +l2NeighDiscovery: + # -- Enable L2 neighbor discovery in the agent + enabled: true + # -- Override the agent's default neighbor resolution refresh period. + refreshPeriod: "30s" + +# -- Enable Layer 7 network policy. +l7Proxy: true + +# -- Enable Local Redirect Policy. +localRedirectPolicy: false + +# To include or exclude matched resources from cilium identity evaluation +# labels: "" + +# logOptions allows you to define logging options. eg: +# logOptions: +# format: json + +# -- Enables periodic logging of system load +logSystemLoad: false + +# -- Configure maglev consistent hashing +maglev: {} + # -- tableSize is the size (parameter M) for the backend table of one + # service entry + # tableSize: + + # -- hashSeed is the cluster-wide base64 encoded seed for the hashing + # hashSeed: + +# -- Enables masquerading of IPv4 traffic leaving the node from endpoints. +enableIPv4Masquerade: true + +# -- Enables IPv6 BIG TCP support which increases maximum IPv6 GSO/GRO limits for nodes and pods +enableIPv6BIGTCP: false + +# -- Enables IPv4 BIG TCP support which increases maximum IPv4 GSO/GRO limits for nodes and pods +enableIPv4BIGTCP: false + +# -- Enables masquerading of IPv6 traffic leaving the node from endpoints. +enableIPv6Masquerade: true + +# -- Enables egress gateway to redirect and SNAT the traffic that leaves the +# cluster. +egressGateway: + enabled: false + # -- Install egress gateway IP rules and routes in order to properly steer + # egress gateway traffic to the correct ENI interface + installRoutes: false + # -- Time between triggers of egress gateway state reconciliations + reconciliationTriggerInterval: 1s + # -- Maximum number of entries in egress gateway policy map + # maxPolicyEntries: 16384 + +vtep: +# -- Enables VXLAN Tunnel Endpoint (VTEP) Integration (beta) to allow +# Cilium-managed pods to talk to third party VTEP devices over Cilium tunnel. + enabled: false + +# -- A space separated list of VTEP device endpoint IPs, for example "1.1.1.1 1.1.2.1" + endpoint: "" +# -- A space separated list of VTEP device CIDRs, for example "1.1.1.0/24 1.1.2.0/24" + cidr: "" +# -- VTEP CIDRs Mask that applies to all VTEP CIDRs, for example "255.255.255.0" + mask: "" +# -- A space separated list of VTEP device MAC addresses (VTEP MAC), for example "x:x:x:x:x:x y:y:y:y:y:y:y" + mac: "" + +# -- (string) Allows to explicitly specify the IPv4 CIDR for native routing. +# When specified, Cilium assumes networking for this CIDR is preconfigured and +# hands traffic destined for that range to the Linux network stack without +# applying any SNAT. +# Generally speaking, specifying a native routing CIDR implies that Cilium can +# depend on the underlying networking stack to route packets to their +# destination. To offer a concrete example, if Cilium is configured to use +# direct routing and the Kubernetes CIDR is included in the native routing CIDR, +# the user must configure the routes to reach pods, either manually or by +# setting the auto-direct-node-routes flag. +ipv4NativeRoutingCIDR: "" + +# -- (string) Allows to explicitly specify the IPv6 CIDR for native routing. +# When specified, Cilium assumes networking for this CIDR is preconfigured and +# hands traffic destined for that range to the Linux network stack without +# applying any SNAT. +# Generally speaking, specifying a native routing CIDR implies that Cilium can +# depend on the underlying networking stack to route packets to their +# destination. To offer a concrete example, if Cilium is configured to use +# direct routing and the Kubernetes CIDR is included in the native routing CIDR, +# the user must configure the routes to reach pods, either manually or by +# setting the auto-direct-node-routes flag. +ipv6NativeRoutingCIDR: "" + +# -- cilium-monitor sidecar. +monitor: + # -- Enable the cilium-monitor sidecar. + enabled: false + +# -- Configure service load balancing +loadBalancer: + # -- standalone enables the standalone L4LB which does not connect to + # kube-apiserver. + # standalone: false + + # -- algorithm is the name of the load balancing algorithm for backend + # selection e.g. random or maglev + # algorithm: random + + # -- mode is the operation mode of load balancing for remote backends + # e.g. snat, dsr, hybrid + # mode: snat + + # -- acceleration is the option to accelerate service handling via XDP + # e.g. native, disabled + # acceleration: disabled + + # -- dsrDispatch configures whether IP option or IPIP encapsulation is + # used to pass a service IP and port to remote backend + # dsrDispatch: opt + + # -- serviceTopology enables K8s Topology Aware Hints -based service + # endpoints filtering + # serviceTopology: false + + # -- L7 LoadBalancer + l7: + # -- Enable L7 service load balancing via envoy proxy. + # The request to a k8s service, which has specific annotation e.g. service.cilium.io/lb-l7, + # will be forwarded to the local backend proxy to be load balanced to the service endpoints. + # Please refer to docs for supported annotations for more configuration. + # + # Applicable values: + # - envoy: Enable L7 load balancing via envoy proxy. This will automatically set enable-envoy-config as well. + # - disabled: Disable L7 load balancing by way of service annotation. + backend: disabled + # -- List of ports from service to be automatically redirected to above backend. + # Any service exposing one of these ports will be automatically redirected. + # Fine-grained control can be achieved by using the service annotation. + ports: [] + # -- Default LB algorithm + # The default LB algorithm to be used for services, which can be overridden by the + # service annotation (e.g. service.cilium.io/lb-l7-algorithm) + # Applicable values: round_robin, least_request, random + algorithm: round_robin + +# -- Configure N-S k8s service loadbalancing +nodePort: + # -- Enable the Cilium NodePort service implementation. + enabled: false + + # -- Port range to use for NodePort services. + # range: "30000,32767" + + # -- Set to true to prevent applications binding to service ports. + bindProtection: true + + # -- Append NodePort range to ip_local_reserved_ports if clash with ephemeral + # ports is detected. + autoProtectPortRange: true + + # -- Enable healthcheck nodePort server for NodePort services + enableHealthCheck: true + +# policyAuditMode: false + +# -- The agent can be put into one of the three policy enforcement modes: +# default, always and never. +# ref: https://docs.cilium.io/en/stable/security/policy/intro/#policy-enforcement-modes +policyEnforcementMode: "default" + +pprof: + # -- Enable pprof for cilium-agent + enabled: false + # -- Configure pprof listen address for cilium-agent + address: localhost + # -- Configure pprof listen port for cilium-agent + port: 6060 + +# -- Configure prometheus metrics on the configured port at /metrics +prometheus: + enabled: false + port: 9962 + serviceMonitor: + # -- Enable service monitors. + # This requires the prometheus CRDs to be available (see https://github.com/prometheus-operator/prometheus-operator/blob/main/example/prometheus-operator-crd/monitoring.coreos.com_servicemonitors.yaml) + enabled: false + # -- Labels to add to ServiceMonitor cilium-agent + labels: {} + # -- Annotations to add to ServiceMonitor cilium-agent + annotations: {} + # -- Interval for scrape metrics. + interval: "10s" + # -- Specify the Kubernetes namespace where Prometheus expects to find + # service monitors configured. + # namespace: "" + # -- Relabeling configs for the ServiceMonitor cilium-agent + relabelings: + - sourceLabels: + - __meta_kubernetes_pod_node_name + targetLabel: node + replacement: ${1} + # -- Metrics relabeling configs for the ServiceMonitor cilium-agent + metricRelabelings: ~ + # -- Set to `true` and helm will not check for monitoring.coreos.com/v1 CRDs before deploying + trustCRDsExist: false + + # -- Metrics that should be enabled or disabled from the default metric list. + # The list is expected to be separated by a space. (+metric_foo to enable + # metric_foo , -metric_bar to disable metric_bar). + # ref: https://docs.cilium.io/en/stable/observability/metrics/ + metrics: ~ + +# -- Grafana dashboards for cilium-agent +# grafana can import dashboards based on the label and value +# ref: https://github.com/grafana/helm-charts/tree/main/charts/grafana#sidecar-for-dashboards +dashboards: + enabled: false + label: grafana_dashboard + namespace: ~ + labelValue: "1" + annotations: {} + +# -- Configure Istio proxy options. +proxy: + + prometheus: + # -- Deprecated in favor of envoy.prometheus.enabled + enabled: true + # -- Deprecated in favor of envoy.prometheus.port + port: ~ + # -- Regular expression matching compatible Istio sidecar istio-proxy + # container image names + sidecarImageRegex: "cilium/istio_proxy" + +# Configure Cilium Envoy options. +envoy: + # -- Enable Envoy Proxy in standalone DaemonSet. + enabled: false + + log: + # -- The format string to use for laying out the log message metadata of Envoy. + format: "[%Y-%m-%d %T.%e][%t][%l][%n] [%g:%#] %v" + # -- Path to a separate Envoy log file, if any. Defaults to /dev/stdout. + path: "" + + # -- Time in seconds after which a TCP connection attempt times out + connectTimeoutSeconds: 2 + # -- ProxyMaxRequestsPerConnection specifies the max_requests_per_connection setting for Envoy + maxRequestsPerConnection: 0 + # -- Set Envoy HTTP option max_connection_duration seconds. Default 0 (disable) + maxConnectionDurationSeconds: 0 + # -- Set Envoy upstream HTTP idle connection timeout seconds. + # Does not apply to connections with pending requests. Default 60s + idleTimeoutDurationSeconds: 60 + + # -- Envoy container image. + image: + override: ~ + repository: "quay.io/cilium/cilium-envoy" + tag: "v1.26.6-ad82c7c56e88989992fd25d8d67747de865c823b" + pullPolicy: "${PULL_POLICY}" + digest: "sha256:992998398dadfff7117bfa9fdb7c9474fefab7f0237263f7c8114e106c67baca" + useDigest: true + + # -- Additional containers added to the cilium Envoy DaemonSet. + extraContainers: [] + + # -- Additional envoy container arguments. + extraArgs: [] + + # -- Additional envoy container environment variables. + extraEnv: [] + + # -- Additional envoy hostPath mounts. + extraHostPathMounts: [] + # - name: host-mnt-data + # mountPath: /host/mnt/data + # hostPath: /mnt/data + # hostPathType: Directory + # readOnly: true + # mountPropagation: HostToContainer + + # -- Additional envoy volumes. + extraVolumes: [] + + # -- Additional envoy volumeMounts. + extraVolumeMounts: [] + + # -- Configure termination grace period for cilium-envoy DaemonSet. + terminationGracePeriodSeconds: 1 + + # -- TCP port for the health API. + healthPort: 9878 + + # -- cilium-envoy update strategy + # ref: https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/#updating-a-daemonset + updateStrategy: + type: RollingUpdate + rollingUpdate: + maxUnavailable: 2 + # -- Roll out cilium envoy pods automatically when configmap is updated. + rollOutPods: false + + # -- Security Context for cilium-envoy pods. + podSecurityContext: {} + + # -- Annotations to be added to envoy pods + podAnnotations: {} + + # -- Labels to be added to envoy pods + podLabels: {} + + # -- Envoy resource limits & requests + # ref: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + resources: {} + # limits: + # cpu: 4000m + # memory: 4Gi + # requests: + # cpu: 100m + # memory: 512Mi + + startupProbe: + # -- failure threshold of startup probe. + # 105 x 2s translates to the old behaviour of the readiness probe (120s delay + 30 x 3s) + failureThreshold: 105 + # -- interval between checks of the startup probe + periodSeconds: 2 + livenessProbe: + # -- failure threshold of liveness probe + failureThreshold: 10 + # -- interval between checks of the liveness probe + periodSeconds: 30 + readinessProbe: + # -- failure threshold of readiness probe + failureThreshold: 3 + # -- interval between checks of the readiness probe + periodSeconds: 30 + + securityContext: + # -- User to run the pod with + # runAsUser: 0 + # -- Run the pod with elevated privileges + privileged: false + # -- SELinux options for the `cilium-envoy` container + seLinuxOptions: + level: 's0' + # Running with spc_t since we have removed the privileged mode. + # Users can change it to a different type as long as they have the + # type available on the system. + type: 'spc_t' + capabilities: + # -- Capabilities for the `cilium-envoy` container + envoy: + # Used since cilium proxy uses setting IPPROTO_IP/IP_TRANSPARENT + - NET_ADMIN + # We need it for now but might not need it for >= 5.11 specially + # for the 'SYS_RESOURCE'. + # In >= 5.8 there's already BPF and PERMON capabilities + - SYS_ADMIN + # Both PERFMON and BPF requires kernel 5.8, container runtime + # cri-o >= v1.22.0 or containerd >= v1.5.0. + # If available, SYS_ADMIN can be removed. + #- PERFMON + #- BPF + + # -- Affinity for cilium-envoy. + affinity: + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - topologyKey: kubernetes.io/hostname + labelSelector: + matchLabels: + k8s-app: cilium-envoy + + # -- Node selector for cilium-envoy. + nodeSelector: + kubernetes.io/os: linux + + # -- Node tolerations for envoy scheduling to nodes with taints + # ref: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/ + tolerations: + - operator: Exists + # - key: "key" + # operator: "Equal|Exists" + # value: "value" + # effect: "NoSchedule|PreferNoSchedule|NoExecute(1.6 only)" + + # -- The priority class to use for cilium-envoy. + priorityClassName: ~ + + # -- DNS policy for Cilium envoy pods. + # Ref: https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-s-dns-policy + dnsPolicy: ~ + + prometheus: + # -- Enable prometheus metrics for cilium-envoy + enabled: true + serviceMonitor: + # -- Enable service monitors. + # This requires the prometheus CRDs to be available (see https://github.com/prometheus-operator/prometheus-operator/blob/main/example/prometheus-operator-crd/monitoring.coreos.com_servicemonitors.yaml) + enabled: false + # -- Labels to add to ServiceMonitor cilium-envoy + labels: {} + # -- Annotations to add to ServiceMonitor cilium-envoy + annotations: {} + # -- Interval for scrape metrics. + interval: "10s" + # -- Specify the Kubernetes namespace where Prometheus expects to find + # service monitors configured. + # namespace: "" + # -- Relabeling configs for the ServiceMonitor cilium-envoy + relabelings: + - sourceLabels: + - __meta_kubernetes_pod_node_name + targetLabel: node + replacement: ${1} + # -- Metrics relabeling configs for the ServiceMonitor cilium-envoy + metricRelabelings: ~ + # -- Serve prometheus metrics for cilium-envoy on the configured port + port: "9964" + +# -- Enable use of the remote node identity. +# ref: https://docs.cilium.io/en/v1.7/install/upgrade/#configmap-remote-node-identity +remoteNodeIdentity: true + +# -- Enable resource quotas for priority classes used in the cluster. +resourceQuotas: + enabled: false + cilium: + hard: + # 5k nodes * 2 DaemonSets (Cilium and cilium node init) + pods: "10k" + operator: + hard: + # 15 "clusterwide" Cilium Operator pods for HA + pods: "15" + +# Need to document default +################## +#sessionAffinity: false + +# -- Do not run Cilium agent when running with clean mode. Useful to completely +# uninstall Cilium as it will stop Cilium from starting and create artifacts +# in the node. +sleepAfterInit: false + +# -- Enable check of service source ranges (currently, only for LoadBalancer). +svcSourceRangeCheck: true + +# -- Synchronize Kubernetes nodes to kvstore and perform CNP GC. +synchronizeK8sNodes: true + +# -- Configure TLS configuration in the agent. +tls: + # -- This configures how the Cilium agent loads the secrets used TLS-aware CiliumNetworkPolicies + # (namely the secrets referenced by terminatingTLS and originatingTLS). + # Possible values: + # - local + # - k8s + secretsBackend: local + + # -- Base64 encoded PEM values for the CA certificate and private key. + # This can be used as common CA to generate certificates used by hubble and clustermesh components. + # It is neither required nor used when cert-manager is used to generate the certificates. + ca: + # -- Optional CA cert. If it is provided, it will be used by cilium to + # generate all other certificates. Otherwise, an ephemeral CA is generated. + cert: "" + + # -- Optional CA private key. If it is provided, it will be used by cilium to + # generate all other certificates. Otherwise, an ephemeral CA is generated. + key: "" + + # -- Generated certificates validity duration in days. This will be used for auto generated CA. + certValidityDuration: 1095 + + # -- Configure the CA trust bundle used for the validation of the certificates + # leveraged by hubble and clustermesh. When enabled, it overrides the content of the + # 'ca.crt' field of the respective certificates, allowing for CA rotation with no down-time. + caBundle: + # -- Enable the use of the CA trust bundle. + enabled: false + + # -- Name of the ConfigMap containing the CA trust bundle. + name: cilium-root-ca.crt + + # -- Entry of the ConfigMap containing the CA trust bundle. + key: ca.crt + + # -- Use a Secret instead of a ConfigMap. + useSecret: false + + # If uncommented, creates the ConfigMap and fills it with the specified content. + # Otherwise, the ConfigMap is assumed to be already present in .Release.Namespace. + # + # content: | + # -----BEGIN CERTIFICATE----- + # ... + # -----END CERTIFICATE----- + # -----BEGIN CERTIFICATE----- + # ... + # -----END CERTIFICATE----- + +# -- Configure the encapsulation configuration for communication between nodes. +# Deprecated in favor of tunnelProtocol and routingMode. To be removed in 1.15. +# Possible values: +# - disabled +# - vxlan +# - geneve +# @default -- `"vxlan"` +tunnel: "" + +# -- Tunneling protocol to use in tunneling mode and for ad-hoc tunnels. +# Possible values: +# - "" +# - vxlan +# - geneve +# @default -- `"vxlan"` +tunnelProtocol: "" + +# -- Enable native-routing mode or tunneling mode. +# Possible values: +# - "" +# - native +# - tunnel +# @default -- `"tunnel"` +routingMode: "" + +# -- Configure VXLAN and Geneve tunnel port. +# @default -- Port 8472 for VXLAN, Port 6081 for Geneve +tunnelPort: 0 + +# -- Configure the underlying network MTU to overwrite auto-detected MTU. +MTU: 0 + +# -- Disable the usage of CiliumEndpoint CRD. +disableEndpointCRD: false + +wellKnownIdentities: + # -- Enable the use of well-known identities. + enabled: false + +etcd: + # -- Enable etcd mode for the agent. + enabled: false + + # -- cilium-etcd-operator image. + image: + override: ~ + repository: "${CILIUM_ETCD_OPERATOR_REPO}" + tag: "${CILIUM_ETCD_OPERATOR_VERSION}" + digest: "${CILIUM_ETCD_OPERATOR_DIGEST}" + useDigest: true + pullPolicy: "${PULL_POLICY}" + + # -- The priority class to use for cilium-etcd-operator + priorityClassName: "" + + # -- Additional cilium-etcd-operator container arguments. + extraArgs: [] + + # -- Additional cilium-etcd-operator volumes. + extraVolumes: [] + + # -- Additional cilium-etcd-operator volumeMounts. + extraVolumeMounts: [] + + # -- Node tolerations for cilium-etcd-operator scheduling to nodes with taints + # ref: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/ + tolerations: + - operator: Exists + # - key: "key" + # operator: "Equal|Exists" + # value: "value" + # effect: "NoSchedule|PreferNoSchedule|NoExecute(1.6 only)" + + # -- Pod topology spread constraints for cilium-etcd-operator + topologySpreadConstraints: [] + # - maxSkew: 1 + # topologyKey: topology.kubernetes.io/zone + # whenUnsatisfiable: DoNotSchedule + + # -- Node labels for cilium-etcd-operator pod assignment + # ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#nodeselector + nodeSelector: + kubernetes.io/os: linux + + # -- Security context to be added to cilium-etcd-operator pods + podSecurityContext: {} + + # -- Annotations to be added to cilium-etcd-operator pods + podAnnotations: {} + + # -- Labels to be added to cilium-etcd-operator pods + podLabels: {} + + # PodDisruptionBudget settings + podDisruptionBudget: + # -- enable PodDisruptionBudget + # ref: https://kubernetes.io/docs/concepts/workloads/pods/disruptions/ + enabled: false + # -- Minimum number/percentage of pods that should remain scheduled. + # When it's set, maxUnavailable must be disabled by `maxUnavailable: null` + minAvailable: null + # -- Maximum number/percentage of pods that may be made unavailable + maxUnavailable: 1 + + # -- cilium-etcd-operator resource limits & requests + # ref: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + resources: {} + # limits: + # cpu: 4000m + # memory: 4Gi + # requests: + # cpu: 100m + # memory: 512Mi + + # -- Security context to be added to cilium-etcd-operator pods + securityContext: {} + # runAsUser: 0 + + # -- cilium-etcd-operator update strategy + updateStrategy: + type: RollingUpdate + rollingUpdate: + maxSurge: 1 + maxUnavailable: 1 + + # -- If etcd is behind a k8s service set this option to true so that Cilium + # does the service translation automatically without requiring a DNS to be + # running. + k8sService: false + + # -- Cluster domain for cilium-etcd-operator. + clusterDomain: cluster.local + + # -- List of etcd endpoints (not needed when using managed=true). + endpoints: + - https://CHANGE-ME:2379 + + # -- Enable use of TLS/SSL for connectivity to etcd. (auto-enabled if + # managed=true) + ssl: false + +operator: + # -- Enable the cilium-operator component (required). + enabled: true + + # -- Roll out cilium-operator pods automatically when configmap is updated. + rollOutPods: false + + # -- cilium-operator image. + image: + override: ~ + repository: "${CILIUM_OPERATOR_BASE_REPO}" + tag: "${CILIUM_VERSION}" + # operator-generic-digest + genericDigest: ${OPERATOR_GENERIC_DIGEST} + # operator-azure-digest + azureDigest: ${OPERATOR_AZURE_DIGEST} + # operator-aws-digest + awsDigest: ${OPERATOR_AWS_DIGEST} + # operator-alibabacloud-digest + alibabacloudDigest: ${OPERATOR_ALIBABACLOUD_DIGEST} + useDigest: ${USE_DIGESTS} + pullPolicy: "${PULL_POLICY}" + suffix: "${CILIUM_OPERATOR_SUFFIX}" + + # -- Number of replicas to run for the cilium-operator deployment + replicas: 2 + + # -- The priority class to use for cilium-operator + priorityClassName: "" + + # -- DNS policy for Cilium operator pods. + # Ref: https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-s-dns-policy + dnsPolicy: "" + + # -- cilium-operator update strategy + updateStrategy: + type: RollingUpdate + rollingUpdate: + maxSurge: 25% + maxUnavailable: 50% + + # -- Affinity for cilium-operator + affinity: + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - topologyKey: kubernetes.io/hostname + labelSelector: + matchLabels: + io.cilium/app: operator + + # -- Pod topology spread constraints for cilium-operator + topologySpreadConstraints: [] + # - maxSkew: 1 + # topologyKey: topology.kubernetes.io/zone + # whenUnsatisfiable: DoNotSchedule + + # -- Node labels for cilium-operator pod assignment + # ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#nodeselector + nodeSelector: + kubernetes.io/os: linux + + # -- Node tolerations for cilium-operator scheduling to nodes with taints + # ref: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/ + tolerations: + - operator: Exists + # - key: "key" + # operator: "Equal|Exists" + # value: "value" + # effect: "NoSchedule|PreferNoSchedule|NoExecute(1.6 only)" + + # -- Additional cilium-operator container arguments. + extraArgs: [] + + # -- Additional cilium-operator environment variables. + extraEnv: [] + + # -- Additional cilium-operator hostPath mounts. + extraHostPathMounts: [] + # - name: host-mnt-data + # mountPath: /host/mnt/data + # hostPath: /mnt/data + # hostPathType: Directory + # readOnly: true + # mountPropagation: HostToContainer + + # -- Additional cilium-operator volumes. + extraVolumes: [] + + # -- Additional cilium-operator volumeMounts. + extraVolumeMounts: [] + + # -- Security context to be added to cilium-operator pods + podSecurityContext: {} + + # -- Annotations to be added to cilium-operator pods + podAnnotations: {} + + # -- Labels to be added to cilium-operator pods + podLabels: {} + + # PodDisruptionBudget settings + podDisruptionBudget: + # -- enable PodDisruptionBudget + # ref: https://kubernetes.io/docs/concepts/workloads/pods/disruptions/ + enabled: false + # -- Minimum number/percentage of pods that should remain scheduled. + # When it's set, maxUnavailable must be disabled by `maxUnavailable: null` + minAvailable: null + # -- Maximum number/percentage of pods that may be made unavailable + maxUnavailable: 1 + + # -- cilium-operator resource limits & requests + # ref: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + resources: {} + # limits: + # cpu: 1000m + # memory: 1Gi + # requests: + # cpu: 100m + # memory: 128Mi + + # -- Security context to be added to cilium-operator pods + securityContext: {} + # runAsUser: 0 + + # -- Interval for endpoint garbage collection. + endpointGCInterval: "5m0s" + + # -- Interval for cilium node garbage collection. + nodeGCInterval: "5m0s" + + # -- Skip CNP node status clean up at operator startup. + skipCNPStatusStartupClean: false + + # -- Interval for identity garbage collection. + identityGCInterval: "15m0s" + + # -- Timeout for identity heartbeats. + identityHeartbeatTimeout: "30m0s" + + pprof: + # -- Enable pprof for cilium-operator + enabled: false + # -- Configure pprof listen address for cilium-operator + address: localhost + # -- Configure pprof listen port for cilium-operator + port: 6061 + + # -- Enable prometheus metrics for cilium-operator on the configured port at + # /metrics + prometheus: + enabled: false + port: 9963 + serviceMonitor: + # -- Enable service monitors. + # This requires the prometheus CRDs to be available (see https://github.com/prometheus-operator/prometheus-operator/blob/main/example/prometheus-operator-crd/monitoring.coreos.com_servicemonitors.yaml) + enabled: false + # -- Labels to add to ServiceMonitor cilium-operator + labels: {} + # -- Annotations to add to ServiceMonitor cilium-operator + annotations: {} + # -- Interval for scrape metrics. + interval: "10s" + # -- Relabeling configs for the ServiceMonitor cilium-operator + relabelings: ~ + # -- Metrics relabeling configs for the ServiceMonitor cilium-operator + metricRelabelings: ~ + + # -- Grafana dashboards for cilium-operator + # grafana can import dashboards based on the label and value + # ref: https://github.com/grafana/helm-charts/tree/main/charts/grafana#sidecar-for-dashboards + dashboards: + enabled: false + label: grafana_dashboard + namespace: ~ + labelValue: "1" + annotations: {} + + # -- Skip CRDs creation for cilium-operator + skipCRDCreation: false + + # -- Remove Cilium node taint from Kubernetes nodes that have a healthy Cilium + # pod running. + removeNodeTaints: true + + # -- Taint nodes where Cilium is scheduled but not running. This prevents pods + # from being scheduled to nodes where Cilium is not the default CNI provider. + # @default -- same as removeNodeTaints + setNodeTaints: ~ + + # -- Set Node condition NetworkUnavailable to 'false' with the reason + # 'CiliumIsUp' for nodes that have a healthy Cilium pod. + setNodeNetworkStatus: true + + unmanagedPodWatcher: + # -- Restart any pod that are not managed by Cilium. + restart: true + # -- Interval, in seconds, to check if there are any pods that are not + # managed by Cilium. + intervalSeconds: 15 + +nodeinit: + # -- Enable the node initialization DaemonSet + enabled: false + + # -- node-init image. + image: + override: ~ + repository: "${CILIUM_NODEINIT_REPO}" + tag: "${CILIUM_NODEINIT_VERSION}" + pullPolicy: "${PULL_POLICY}" + + # -- The priority class to use for the nodeinit pod. + priorityClassName: "" + + # -- node-init update strategy + updateStrategy: + type: RollingUpdate + + # -- Additional nodeinit environment variables. + extraEnv: [] + + # -- Additional nodeinit volumes. + extraVolumes: [] + + # -- Additional nodeinit volumeMounts. + extraVolumeMounts: [] + + # -- Affinity for cilium-nodeinit + affinity: {} + + # -- Node labels for nodeinit pod assignment + # ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#nodeselector + nodeSelector: + kubernetes.io/os: linux + + # -- Node tolerations for nodeinit scheduling to nodes with taints + # ref: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/ + tolerations: + - operator: Exists + # - key: "key" + # operator: "Equal|Exists" + # value: "value" + # effect: "NoSchedule|PreferNoSchedule|NoExecute(1.6 only)" + + # -- Annotations to be added to node-init pods. + podAnnotations: {} + + # -- Labels to be added to node-init pods. + podLabels: {} + + # -- nodeinit resource limits & requests + # ref: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + resources: + requests: + cpu: 100m + memory: 100Mi + + # -- Security context to be added to nodeinit pods. + securityContext: + privileged: false + seLinuxOptions: + level: 's0' + # Running with spc_t since we have removed the privileged mode. + # Users can change it to a different type as long as they have the + # type available on the system. + type: 'spc_t' + capabilities: + add: + # Used in iptables. Consider removing once we are iptables-free + - SYS_MODULE + # Used for nsenter + - NET_ADMIN + - SYS_ADMIN + - SYS_CHROOT + - SYS_PTRACE + + # -- bootstrapFile is the location of the file where the bootstrap timestamp is + # written by the node-init DaemonSet + bootstrapFile: "/tmp/cilium-bootstrap.d/cilium-bootstrap-time" + + # -- startup offers way to customize startup nodeinit script (pre and post position) + startup: + preScript: "" + postScript: "" + # -- prestop offers way to customize prestop nodeinit script (pre and post position) + prestop: + preScript: "" + postScript: "" + +preflight: + # -- Enable Cilium pre-flight resources (required for upgrade) + enabled: false + + # -- Cilium pre-flight image. + image: + override: ~ + repository: "${CILIUM_REPO}" + tag: "${CILIUM_VERSION}" + # cilium-digest + digest: ${CILIUM_DIGEST} + useDigest: ${USE_DIGESTS} + pullPolicy: "${PULL_POLICY}" + + # -- The priority class to use for the preflight pod. + priorityClassName: "" + + # -- preflight update strategy + updateStrategy: + type: RollingUpdate + + # -- Additional preflight environment variables. + extraEnv: [] + + # -- Additional preflight volumes. + extraVolumes: [] + + # -- Additional preflight volumeMounts. + extraVolumeMounts: [] + + # -- Affinity for cilium-preflight + affinity: + podAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - topologyKey: kubernetes.io/hostname + labelSelector: + matchLabels: + k8s-app: cilium + + # -- Node labels for preflight pod assignment + # ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#nodeselector + nodeSelector: + kubernetes.io/os: linux + + # -- Node tolerations for preflight scheduling to nodes with taints + # ref: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/ + tolerations: + - key: node.kubernetes.io/not-ready + effect: NoSchedule + - key: node-role.kubernetes.io/master + effect: NoSchedule + - key: node-role.kubernetes.io/control-plane + effect: NoSchedule + - key: node.cloudprovider.kubernetes.io/uninitialized + effect: NoSchedule + value: "true" + - key: CriticalAddonsOnly + operator: "Exists" + # - key: "key" + # operator: "Equal|Exists" + # value: "value" + # effect: "NoSchedule|PreferNoSchedule|NoExecute(1.6 only)" + + # -- Security context to be added to preflight pods. + podSecurityContext: {} + + # -- Annotations to be added to preflight pods + podAnnotations: {} + + # -- Labels to be added to the preflight pod. + podLabels: {} + + # PodDisruptionBudget settings + podDisruptionBudget: + # -- enable PodDisruptionBudget + # ref: https://kubernetes.io/docs/concepts/workloads/pods/disruptions/ + enabled: false + # -- Minimum number/percentage of pods that should remain scheduled. + # When it's set, maxUnavailable must be disabled by `maxUnavailable: null` + minAvailable: null + # -- Maximum number/percentage of pods that may be made unavailable + maxUnavailable: 1 + + # -- preflight resource limits & requests + # ref: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + resources: {} + # limits: + # cpu: 4000m + # memory: 4Gi + # requests: + # cpu: 100m + # memory: 512Mi + + # -- Security context to be added to preflight pods + securityContext: {} + # runAsUser: 0 + + # -- Path to write the `--tofqdns-pre-cache` file to. + tofqdnsPreCache: "" + + # -- Configure termination grace period for preflight Deployment and DaemonSet. + terminationGracePeriodSeconds: 1 + + # -- By default we should always validate the installed CNPs before upgrading + # Cilium. This will make sure the user will have the policies deployed in the + # cluster with the right schema. + validateCNPs: true + +# -- Explicitly enable or disable priority class. +# .Capabilities.KubeVersion is unsettable in `helm template` calls, +# it depends on k8s libraries version that Helm was compiled against. +# This option allows to explicitly disable setting the priority class, which +# is useful for rendering charts for gke clusters in advance. +enableCriticalPriorityClass: true + +# disableEnvoyVersionCheck removes the check for Envoy, which can be useful +# on AArch64 as the images do not currently ship a version of Envoy. +#disableEnvoyVersionCheck: false + +clustermesh: + # -- Deploy clustermesh-apiserver for clustermesh + useAPIServer: false + + # -- Clustermesh explicit configuration. + config: + # -- Enable the Clustermesh explicit configuration. + enabled: false + # -- Default dns domain for the Clustermesh API servers + # This is used in the case cluster addresses are not provided + # and IPs are used. + domain: mesh.cilium.io + # -- List of clusters to be peered in the mesh. + clusters: [] + # clusters: + # # -- Name of the cluster + # - name: cluster1 + # # -- Address of the cluster, use this if you created DNS records for + # # the cluster Clustermesh API server. + # address: cluster1.mesh.cilium.io + # # -- Port of the cluster Clustermesh API server. + # port: 2379 + # # -- IPs of the cluster Clustermesh API server, use multiple ones when + # # you have multiple IPs to access the Clustermesh API server. + # ips: + # - 172.18.255.201 + # # -- base64 encoded PEM values for the cluster client certificate, private key and certificate authority. + # # These fields can (and should) be omitted in case the CA is shared across clusters. In that case, the + # # "remote" private key and certificate available in the local cluster are automatically used instead. + # tls: + # cert: "" + # key: "" + # caCert: "" + + apiserver: + # -- Clustermesh API server image. + image: + override: ~ + repository: "${CLUSTERMESH_APISERVER_REPO}" + tag: "${CILIUM_VERSION}" + # clustermesh-apiserver-digest + digest: ${CLUSTERMESH_APISERVER_DIGEST} + useDigest: ${USE_DIGESTS} + pullPolicy: "${PULL_POLICY}" + + etcd: + # -- Clustermesh API server etcd image. + image: + override: ~ + repository: "${ETCD_REPO}" + tag: "${ETCD_VERSION}" + digest: "${ETCD_DIGEST}" + useDigest: true + pullPolicy: "${PULL_POLICY}" + + # -- Specifies the resources for etcd container in the apiserver + resources: {} + # requests: + # cpu: 200m + # memory: 256Mi + # limits: + # cpu: 1000m + # memory: 256Mi + + # -- Security context to be added to clustermesh-apiserver etcd containers + securityContext: {} + + init: + # -- Specifies the resources for etcd init container in the apiserver + resources: {} + # requests: + # cpu: 100m + # memory: 100Mi + # limits: + # cpu: 100m + # memory: 100Mi + + kvstoremesh: + # -- Enable KVStoreMesh. KVStoreMesh caches the information retrieved + # from the remote clusters in the local etcd instance. + enabled: false + + # -- KVStoreMesh image. + image: + override: ~ + repository: "${KVSTOREMESH_REPO}" + tag: "${CILIUM_VERSION}" + # kvstoremesh-digest + digest: ${KVSTOREMESH_DIGEST} + useDigest: ${USE_DIGESTS} + pullPolicy: "${PULL_POLICY}" + + # -- Additional KVStoreMesh arguments. + extraArgs: [] + + # -- Additional KVStoreMesh environment variables. + extraEnv: [] + + # -- Resource requests and limits for the KVStoreMesh container + resources: {} + # requests: + # cpu: 100m + # memory: 64Mi + # limits: + # cpu: 1000m + # memory: 1024M + + # -- Additional KVStoreMesh volumeMounts. + extraVolumeMounts: [] + + # -- KVStoreMesh Security context + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + + service: + # -- The type of service used for apiserver access. + type: NodePort + # -- Optional port to use as the node port for apiserver access. + # + # WARNING: make sure to configure a different NodePort in each cluster if + # kube-proxy replacement is enabled, as Cilium is currently affected by a known + # bug (#24692) when NodePorts are handled by the KPR implementation. If a service + # with the same NodePort exists both in the local and the remote cluster, all + # traffic originating from inside the cluster and targeting the corresponding + # NodePort will be redirected to a local backend, regardless of whether the + # destination node belongs to the local or the remote cluster. + nodePort: 32379 + # -- Optional loadBalancer IP address to use with type LoadBalancer. + # loadBalancerIP: + + # -- Annotations for the clustermesh-apiserver + # For GKE LoadBalancer, use annotation cloud.google.com/load-balancer-type: "Internal" + # For EKS LoadBalancer, use annotation service.beta.kubernetes.io/aws-load-balancer-internal: 0.0.0.0/0 + annotations: {} + + # -- The externalTrafficPolicy of service used for apiserver access. + externalTrafficPolicy: + + # -- The internalTrafficPolicy of service used for apiserver access. + internalTrafficPolicy: + + # -- Number of replicas run for the clustermesh-apiserver deployment. + replicas: 1 + + # -- Additional clustermesh-apiserver arguments. + extraArgs: [] + + # -- Additional clustermesh-apiserver environment variables. + extraEnv: [] + + # -- Additional clustermesh-apiserver volumes. + extraVolumes: [] + + # -- Additional clustermesh-apiserver volumeMounts. + extraVolumeMounts: [] + + # -- Security context to be added to clustermesh-apiserver containers + securityContext: {} + + # -- Security context to be added to clustermesh-apiserver pods + podSecurityContext: {} + + # -- Annotations to be added to clustermesh-apiserver pods + podAnnotations: {} + + # -- Labels to be added to clustermesh-apiserver pods + podLabels: {} + + # PodDisruptionBudget settings + podDisruptionBudget: + # -- enable PodDisruptionBudget + # ref: https://kubernetes.io/docs/concepts/workloads/pods/disruptions/ + enabled: false + # -- Minimum number/percentage of pods that should remain scheduled. + # When it's set, maxUnavailable must be disabled by `maxUnavailable: null` + minAvailable: null + # -- Maximum number/percentage of pods that may be made unavailable + maxUnavailable: 1 + + # -- Resource requests and limits for the clustermesh-apiserver container of the clustermesh-apiserver deployment, such as + # resources: + # limits: + # cpu: 1000m + # memory: 1024M + # requests: + # cpu: 100m + # memory: 64Mi + # -- Resource requests and limits for the clustermesh-apiserver + resources: {} + # requests: + # cpu: 100m + # memory: 64Mi + # limits: + # cpu: 1000m + # memory: 1024M + + # -- Affinity for clustermesh.apiserver + affinity: + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - topologyKey: kubernetes.io/hostname + labelSelector: + matchLabels: + k8s-app: clustermesh-apiserver + + # -- Pod topology spread constraints for clustermesh-apiserver + topologySpreadConstraints: [] + # - maxSkew: 1 + # topologyKey: topology.kubernetes.io/zone + # whenUnsatisfiable: DoNotSchedule + + # -- Node labels for pod assignment + # ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#nodeselector + nodeSelector: + kubernetes.io/os: linux + + # -- Node tolerations for pod assignment on nodes with taints + # ref: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/ + tolerations: [] + + # -- clustermesh-apiserver update strategy + updateStrategy: + type: RollingUpdate + rollingUpdate: + maxUnavailable: 1 + + # -- The priority class to use for clustermesh-apiserver + priorityClassName: "" + + tls: + # -- Configure the clustermesh authentication mode. + # Supported values: + # - legacy: All clusters access remote clustermesh instances with the same + # username (i.e., remote). The "remote" certificate must be + # generated with CN=remote if provided manually. + # - migration: Intermediate mode required to upgrade from legacy to cluster + # (and vice versa) with no disruption. Specifically, it enables + # the creation of the per-cluster usernames, while still using + # the common one for authentication. The "remote" certificate must + # be generated with CN=remote if provided manually (same as legacy). + # - cluster: Each cluster accesses remote etcd instances with a username + # depending on the local cluster name (i.e., remote-). + # The "remote" certificate must be generated with CN=remote- + # if provided manually. Cluster mode is meaningful only when the same + # CA is shared across all clusters part of the mesh. + authMode: legacy + + # -- Configure automatic TLS certificates generation. + # A Kubernetes CronJob is used the generate any + # certificates not provided by the user at installation + # time. + auto: + # -- When set to true, automatically generate a CA and certificates to + # enable mTLS between clustermesh-apiserver and external workload instances. + # If set to false, the certs to be provided by setting appropriate values below. + enabled: true + # Sets the method to auto-generate certificates. Supported values: + # - helm: This method uses Helm to generate all certificates. + # - cronJob: This method uses a Kubernetes CronJob the generate any + # certificates not provided by the user at installation + # time. + # - certmanager: This method use cert-manager to generate & rotate certificates. + method: helm + # -- Generated certificates validity duration in days. + certValidityDuration: 1095 + # -- Schedule for certificates regeneration (regardless of their expiration date). + # Only used if method is "cronJob". If nil, then no recurring job will be created. + # Instead, only the one-shot job is deployed to generate the certificates at + # installation time. + # + # Due to the out-of-band distribution of client certs to external workloads the + # CA is (re)regenerated only if it is not provided as a helm value and the k8s + # secret is manually deleted. + # + # Defaults to none. Commented syntax gives midnight of the first day of every + # fourth month. For syntax, see + # https://kubernetes.io/docs/concepts/workloads/controllers/cron-jobs/#schedule-syntax + # schedule: "0 0 1 */4 *" + + # [Example] + # certManagerIssuerRef: + # group: cert-manager.io + # kind: ClusterIssuer + # name: ca-issuer + # -- certmanager issuer used when clustermesh.apiserver.tls.auto.method=certmanager. + certManagerIssuerRef: {} + # -- Deprecated in favor of tls.ca. To be removed in 1.15. + # base64 encoded PEM values for the ExternalWorkload CA certificate and private key. + ca: + # -- Deprecated in favor of tls.ca.cert. To be removed in 1.15. + # Optional CA cert. If it is provided, it will be used by the 'cronJob' method to + # generate all other certificates. Otherwise, an ephemeral CA is generated. + cert: "" + # -- Deprecated in favor of tls.ca.key. To be removed in 1.15. + # Optional CA private key. If it is provided, it will be used by the 'cronJob' method to + # generate all other certificates. Otherwise, an ephemeral CA is generated. + key: "" + # -- base64 encoded PEM values for the clustermesh-apiserver server certificate and private key. + # Used if 'auto' is not enabled. + server: + cert: "" + key: "" + # -- Extra DNS names added to certificate when it's auto generated + extraDnsNames: [] + # -- Extra IP addresses added to certificate when it's auto generated + extraIpAddresses: [] + # -- base64 encoded PEM values for the clustermesh-apiserver admin certificate and private key. + # Used if 'auto' is not enabled. + admin: + cert: "" + key: "" + # -- base64 encoded PEM values for the clustermesh-apiserver client certificate and private key. + # Used if 'auto' is not enabled. + client: + cert: "" + key: "" + # -- base64 encoded PEM values for the clustermesh-apiserver remote cluster certificate and private key. + # Used if 'auto' is not enabled. + remote: + cert: "" + key: "" + + # clustermesh-apiserver Prometheus metrics configuration + metrics: + # -- Enables exporting apiserver metrics in OpenMetrics format. + enabled: true + # -- Configure the port the apiserver metric server listens on. + port: 9962 + + kvstoremesh: + # -- Enables exporting KVStoreMesh metrics in OpenMetrics format. + enabled: true + # -- Configure the port the KVStoreMesh metric server listens on. + port: 9964 + + etcd: + # -- Enables exporting etcd metrics in OpenMetrics format. + enabled: false + # -- Set level of detail for etcd metrics; specify 'extensive' to include server side gRPC histogram metrics. + mode: basic + # -- Configure the port the etcd metric server listens on. + port: 9963 + + serviceMonitor: + # -- Enable service monitor. + # This requires the prometheus CRDs to be available (see https://github.com/prometheus-operator/prometheus-operator/blob/main/example/prometheus-operator-crd/monitoring.coreos.com_servicemonitors.yaml) + enabled: false + # -- Labels to add to ServiceMonitor clustermesh-apiserver + labels: {} + # -- Annotations to add to ServiceMonitor clustermesh-apiserver + annotations: {} + # -- Specify the Kubernetes namespace where Prometheus expects to find + # service monitors configured. + # namespace: "" + + # -- Interval for scrape metrics (apiserver metrics) + interval: "10s" + # -- Relabeling configs for the ServiceMonitor clustermesh-apiserver (apiserver metrics) + relabelings: ~ + # -- Metrics relabeling configs for the ServiceMonitor clustermesh-apiserver (apiserver metrics) + metricRelabelings: ~ + + kvstoremesh: + # -- Interval for scrape metrics (KVStoreMesh metrics) + interval: "10s" + # -- Relabeling configs for the ServiceMonitor clustermesh-apiserver (KVStoreMesh metrics) + relabelings: ~ + # -- Metrics relabeling configs for the ServiceMonitor clustermesh-apiserver (KVStoreMesh metrics) + metricRelabelings: ~ + + etcd: + # -- Interval for scrape metrics (etcd metrics) + interval: "10s" + # -- Relabeling configs for the ServiceMonitor clustermesh-apiserver (etcd metrics) + relabelings: ~ + # -- Metrics relabeling configs for the ServiceMonitor clustermesh-apiserver (etcd metrics) + metricRelabelings: ~ + +# -- Configure external workloads support +externalWorkloads: + # -- Enable support for external workloads, such as VMs (false by default). + enabled: false + +# -- Configure cgroup related configuration +cgroup: + autoMount: + # -- Enable auto mount of cgroup2 filesystem. + # When `autoMount` is enabled, cgroup2 filesystem is mounted at + # `cgroup.hostRoot` path on the underlying host and inside the cilium agent pod. + # If users disable `autoMount`, it's expected that users have mounted + # cgroup2 filesystem at the specified `cgroup.hostRoot` volume, and then the + # volume will be mounted inside the cilium agent pod at the same path. + enabled: true + # -- Init Container Cgroup Automount resource limits & requests + resources: {} + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + # -- Configure cgroup root where cgroup2 filesystem is mounted on the host (see also: `cgroup.autoMount`) + hostRoot: /run/cilium/cgroupv2 + +# -- Configure whether to enable auto detect of terminating state for endpoints +# in order to support graceful termination. +enableK8sTerminatingEndpoint: true + +# -- Configure whether to unload DNS policy rules on graceful shutdown +# dnsPolicyUnloadOnShutdown: false + +# -- Configure the key of the taint indicating that Cilium is not ready on the node. +# When set to a value starting with `ignore-taint.cluster-autoscaler.kubernetes.io/`, the Cluster Autoscaler will ignore the taint on its decisions, allowing the cluster to scale up. +agentNotReadyTaintKey: "node.cilium.io/agent-not-ready" + +dnsProxy: + # -- DNS response code for rejecting DNS requests, available options are '[nameError refused]'. + dnsRejectResponseCode: refused + # -- Allow the DNS proxy to compress responses to endpoints that are larger than 512 Bytes or the EDNS0 option, if present. + enableDnsCompression: true + # -- Maximum number of IPs to maintain per FQDN name for each endpoint. + endpointMaxIpPerHostname: 50 + # -- Time during which idle but previously active connections with expired DNS lookups are still considered alive. + idleConnectionGracePeriod: 0s + # -- Maximum number of IPs to retain for expired DNS lookups with still-active connections. + maxDeferredConnectionDeletes: 10000 + # -- The minimum time, in seconds, to use DNS data for toFQDNs policies. If + # the upstream DNS server returns a DNS record with a shorter TTL, Cilium + # overwrites the TTL with this value. Setting this value to zero means that + # Cilium will honor the TTLs returned by the upstream DNS server. + minTtl: 0 + # -- DNS cache data at this path is preloaded on agent startup. + preCache: "" + # -- Global port on which the in-agent DNS proxy should listen. Default 0 is a OS-assigned port. + proxyPort: 0 + # -- The maximum time the DNS proxy holds an allowed DNS response before sending it along. Responses are sent as soon as the datapath is updated with the new IP information. + proxyResponseMaxDelay: 100ms + +# -- SCTP Configuration Values +sctp: + # -- Enable SCTP support. NOTE: Currently, SCTP support does not support rewriting ports or multihoming. + enabled: false + +# Configuration for types of authentication for Cilium (beta) +authentication: + # -- Enable authentication processing and garbage collection. + # Note that if disabled, policy enforcement will still block requests that require authentication. + # But the resulting authentication requests for these requests will not be processed, therefore the requests not be allowed. + enabled: true + # -- Buffer size of the channel Cilium uses to receive authentication events from the signal map. + queueSize: 1024 + # -- Buffer size of the channel Cilium uses to receive certificate expiration events from auth handlers. + rotatedIdentitiesQueueSize: 1024 + # -- Interval for garbage collection of auth map entries. + gcInterval: "5m0s" + # Configuration for Cilium's service-to-service mutual authentication using TLS handshakes. + # Note that this is not full mTLS support without also enabling encryption of some form. + # Current encryption options are Wireguard or IPSec, configured in encryption block above. + mutual: + # -- Port on the agent where mutual authentication handshakes between agents will be performed + port: 4250 + # Settings for SPIRE + spire: + # -- Enable SPIRE integration (beta) + enabled: false + # Settings to control the SPIRE installation and configuration + install: + # -- Enable SPIRE installation. + # This will only take effect only if authentication.mutual.spire.enabled is true + enabled: true + # -- SPIRE namespace to install into + namespace: cilium-spire + # SPIRE agent configuration + agent: + # -- SPIRE agent image + image: ghcr.io/spiffe/spire-agent:1.6.3@sha256:8eef9857bf223181ecef10d9bbcd2f7838f3689e9bd2445bede35066a732e823 + # -- SPIRE agent service account + serviceAccount: + create: true + name: spire-agent + # -- SPIRE agent annotations + annotations: {} + # -- SPIRE agent labels + labels: {} + # -- SPIRE Workload Attestor kubelet verification. + skipKubeletVerification: true + # -- SPIRE agent tolerations configuration + # ref: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/ + tolerations: [] + # -- SPIRE agent affinity configuration + affinity: {} + # -- SPIRE agent nodeSelector configuration + # ref: ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#nodeselector + nodeSelector: {} + # -- Security context to be added to spire agent pods. + # SecurityContext holds pod-level security attributes and common container settings. + # ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod + podSecurityContext: {} + # -- Security context to be added to spire agent containers. + # SecurityContext holds pod-level security attributes and common container settings. + # ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container + securityContext: {} + server: + # -- SPIRE server image + image: ghcr.io/spiffe/spire-server:1.6.3@sha256:f4bc49fb0bd1d817a6c46204cc7ce943c73fb0a5496a78e0e4dc20c9a816ad7f + # -- SPIRE server service account + serviceAccount: + create: true + name: spire-server + # -- SPIRE server init containers + initContainers: [] + # -- SPIRE server annotations + annotations: {} + # -- SPIRE server labels + labels: {} + # SPIRE server service configuration + service: + # -- Service type for the SPIRE server service + type: ClusterIP + # -- Annotations to be added to the SPIRE server service + annotations: {} + # -- Labels to be added to the SPIRE server service + labels: {} + # -- SPIRE server affinity configuration + affinity: {} + # -- SPIRE server nodeSelector configuration + # ref: ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#nodeselector + nodeSelector: {} + # -- SPIRE server tolerations configuration + # ref: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/ + tolerations: [] + # SPIRE server datastorage configuration + dataStorage: + # -- Enable SPIRE server data storage + enabled: true + # -- Size of the SPIRE server data storage + size: 1Gi + # -- Access mode of the SPIRE server data storage + accessMode: ReadWriteOnce + # -- StorageClass of the SPIRE server data storage + storageClass: null + # SPIRE CA configuration + ca: + # -- SPIRE CA key type + # AWS requires the use of RSA. EC cryptography is not supported + keyType: "rsa-4096" + # -- SPIRE CA Subject + subject: + country: "US" + organization: "SPIRE" + commonName: "Cilium SPIRE CA" + # -- SPIRE server address used by Cilium Operator + # + # If k8s Service DNS along with port number is used (e.g. ..svc(.*): format), + # Cilium Operator will resolve its address by looking up the clusterIP from Service resource. + # + # Example values: 10.0.0.1:8081, spire-server.cilium-spire.svc:8081 + serverAddress: ~ + # -- SPIFFE trust domain to use for fetching certificates + trustDomain: spiffe.cilium + # -- SPIRE socket path where the SPIRE delegated api agent is listening + adminSocketPath: /run/spire/sockets/admin.sock + # -- SPIRE socket path where the SPIRE workload agent is listening. + # Applies to both the Cilium Agent and Operator + agentSocketPath: /run/spire/sockets/agent/agent.sock + # -- SPIRE connection timeout + connectionTimeout: 30s diff --git a/packages/system/cilium/patches/fix-cgroups.patch b/packages/system/cilium/patches/fix-cgroups.patch new file mode 100644 index 00000000..db4fabfe --- /dev/null +++ b/packages/system/cilium/patches/fix-cgroups.patch @@ -0,0 +1,21 @@ +diff --git a/apps/cilium/charts/cilium/templates/cilium-agent/daemonset.yaml b/apps/cilium/charts/cilium/templates/cilium-agent/daemonset.yaml +index a608b69..1b5c622 100644 +--- a/apps/cilium/charts/cilium/templates/cilium-agent/daemonset.yaml ++++ b/apps/cilium/charts/cilium/templates/cilium-agent/daemonset.yaml +@@ -105,9 +105,13 @@ spec: + - "true" + {{- else }} + command: +- - cilium-agent +- args: +- - --config-dir=/tmp/cilium/config-map ++ # Workaround: https://github.com/cilium/cilium/pull/27561 ++ - /bin/sh ++ - -c ++ - | ++ rm -rf /run/cilium/cgroupv2 ++ ln -sf /sys/fs/cgroup /run/cilium/cgroupv2 ++ exec cilium-agent --config-dir=/tmp/cilium/config-map + {{- with .Values.extraArgs }} + {{- toYaml . | trim | nindent 8 }} + {{- end }} diff --git a/packages/system/cilium/templates/cni.yaml b/packages/system/cilium/templates/cni.yaml new file mode 100644 index 00000000..4cde9b51 --- /dev/null +++ b/packages/system/cilium/templates/cni.yaml @@ -0,0 +1,29 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: cni-configuration + namespace: cozy-cilium +data: + cni-config: |- + { + "name": "generic-veth", + "cniVersion": "0.3.1", + "plugins": [ + { + "type": "kube-ovn", + "server_socket": "/run/openvswitch/kube-ovn-daemon.sock", + "ipam": { + "type": "kube-ovn", + "server_socket": "/run/openvswitch/kube-ovn-daemon.sock" + } + }, + { + "type": "portmap", + "snat": true, + "capabilities": {"portMappings": true} + }, + { + "type": "cilium-cni" + } + ] + } diff --git a/packages/system/cilium/values.yaml b/packages/system/cilium/values.yaml new file mode 100644 index 00000000..2c054039 --- /dev/null +++ b/packages/system/cilium/values.yaml @@ -0,0 +1,27 @@ +cilium: + hubble: + enabled: false + externalIPs: + enabled: true + tunnel: disabled + autoDirectNodeRoutes: false + kubeProxyReplacement: strict + bpf: + masquerade: true + loadBalancer: + algorithm: maglev + cgroup: + autoMount: + enabled: false + hostRoot: /sys/fs/cgroup + ipam: + mode: "kubernetes" + k8sServiceHost: localhost + k8sServicePort: 7445 + + cni: + chainingMode: generic-veth + customConf: true + configMap: cni-configuration + routingMode: native + enableIPv4Masquerade: false diff --git a/packages/system/dashboard/.helmignore b/packages/system/dashboard/.helmignore new file mode 100644 index 00000000..43b1c5aa --- /dev/null +++ b/packages/system/dashboard/.helmignore @@ -0,0 +1,3 @@ +hack +.gitkeep +images/*/* diff --git a/packages/system/dashboard/Chart.yaml b/packages/system/dashboard/Chart.yaml new file mode 100644 index 00000000..ecc25562 --- /dev/null +++ b/packages/system/dashboard/Chart.yaml @@ -0,0 +1,2 @@ +name: cozy-dashboard +version: 1.0.0 diff --git a/packages/system/dashboard/Makefile b/packages/system/dashboard/Makefile new file mode 100644 index 00000000..8e67094d --- /dev/null +++ b/packages/system/dashboard/Makefile @@ -0,0 +1,57 @@ +NAME=dashboard +NAMESPACE=cozy-dashboard +PUSH := 1 +LOAD := 0 +REPOSITORY := ghcr.io/aenix-io/cozystack +TAG := v0.0.1 + +show: + helm template --dry-run=server -n $(NAMESPACE) $(NAME) . + +apply: + helm upgrade -i -n $(NAMESPACE) $(NAME) . + +diff: + helm diff upgrade --allow-unreleased --normalize-manifests -n $(NAMESPACE) $(NAME) . + +update: update-chart update-dockerfiles +image: image-dashboard image-kubeapps-apis + +update-chart: + rm -rf charts + helm repo add bitnami https://charts.bitnami.com/bitnami + helm repo update bitnami + helm pull bitnami/kubeapps --untar --untardir charts + rm -rf charts/kubeapps/charts/postgresql/ + ln -s ../../images charts/kubeapps/images + +update-dockerfiles: + tag=$$(git ls-remote --tags --sort="v:refname" https://github.com/vmware-tanzu/kubeapps | awk -F'[/^]' 'END{print $$3}') && \ + wget https://github.com/vmware-tanzu/kubeapps/raw/$${tag}/cmd/kubeapps-apis/Dockerfile -O images/kubeapps-apis/Dockerfile && \ + patch images/kubeapps-apis/Dockerfile < images/kubeapps-apis/dockerfile.diff && \ + node_image=$$(wget -O- https://github.com/vmware-tanzu/kubeapps/raw/main/dashboard/Dockerfile | awk '/FROM bitnami\/node/ {print $$2}') && \ + sed -i "s|FROM .* AS build|FROM $${node_image} AS build|" images/dashboard/Dockerfile && \ + version=$$(echo "$$tag" | sed 's/^v//') && \ + sed -i "s/ARG VERSION=.*/ARG VERSION=$${version}/" images/dashboard/Dockerfile + +image-dashboard: + docker buildx build images/dashboard \ + --provenance false \ + --tag $(REPOSITORY)/dashboard:$(TAG) \ + --cache-from type=registry,ref=$(REPOSITORY)/dashboard:$(TAG) \ + --cache-to type=inline \ + --metadata-file images/dashboard.json \ + --push=$(PUSH) \ + --load=$(LOAD) + echo "$(REPOSITORY)/dashboard:$(TAG)" > images/dashboard.tag + +image-kubeapps-apis: + docker buildx build images/kubeapps-apis \ + --provenance false \ + --tag $(REPOSITORY)/kubeapps-apis:$(TAG) \ + --cache-from type=registry,ref=$(REPOSITORY)/kubeapps-apis:$(TAG) \ + --cache-to type=inline \ + --metadata-file images/kubeapps-apis.json \ + --push=$(PUSH) \ + --load=$(LOAD) + echo "$(REPOSITORY)/kubeapps-apis:$(TAG)" > images/kubeapps-apis.tag diff --git a/packages/system/dashboard/charts/kubeapps/.helmignore b/packages/system/dashboard/charts/kubeapps/.helmignore new file mode 100644 index 00000000..8f27905b --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/.helmignore @@ -0,0 +1,24 @@ +# Copyright 2021-2022 the Kubeapps contributors. +# SPDX-License-Identifier: Apache-2.0 + +# 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 +*~ +# Various IDEs +.project +.idea/ +*.tmproj diff --git a/packages/system/dashboard/charts/kubeapps/Chart.lock b/packages/system/dashboard/charts/kubeapps/Chart.lock new file mode 100644 index 00000000..958a3640 --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/Chart.lock @@ -0,0 +1,12 @@ +dependencies: +- name: redis + repository: oci://registry-1.docker.io/bitnamicharts + version: 18.4.0 +- name: postgresql + repository: oci://registry-1.docker.io/bitnamicharts + version: 13.2.14 +- name: common + repository: oci://registry-1.docker.io/bitnamicharts + version: 2.13.3 +digest: sha256:7bede05a463745ea72d332aaaf406d84e335d8af09dce403736f4e4e14c3554d +generated: "2023-11-21T18:18:20.024990735Z" diff --git a/packages/system/dashboard/charts/kubeapps/Chart.yaml b/packages/system/dashboard/charts/kubeapps/Chart.yaml new file mode 100644 index 00000000..01f84f1f --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/Chart.yaml @@ -0,0 +1,54 @@ +annotations: + category: Infrastructure + images: | + - name: kubeapps-apis + image: docker.io/bitnami/kubeapps-apis:2.9.0-debian-11-r13 + - name: kubeapps-apprepository-controller + image: docker.io/bitnami/kubeapps-apprepository-controller:2.9.0-debian-11-r12 + - name: kubeapps-asset-syncer + image: docker.io/bitnami/kubeapps-asset-syncer:2.9.0-debian-11-r13 + - name: kubeapps-oci-catalog + image: docker.io/bitnami/kubeapps-oci-catalog:2.9.0-debian-11-r6 + - name: kubeapps-pinniped-proxy + image: docker.io/bitnami/kubeapps-pinniped-proxy:2.9.0-debian-11-r10 + - name: kubeapps-dashboard + image: docker.io/bitnami/kubeapps-dashboard:2.9.0-debian-11-r16 + - name: nginx + image: docker.io/bitnami/nginx:1.25.3-debian-11-r1 + - name: oauth2-proxy + image: docker.io/bitnami/oauth2-proxy:7.5.1-debian-11-r11 + licenses: Apache-2.0 +apiVersion: v2 +appVersion: 2.9.0 +dependencies: +- condition: packaging.flux.enabled + name: redis + repository: oci://registry-1.docker.io/bitnamicharts + version: 18.x.x +- condition: packaging.helm.enabled + name: postgresql + repository: oci://registry-1.docker.io/bitnamicharts + version: 13.x.x +- name: common + repository: oci://registry-1.docker.io/bitnamicharts + tags: + - bitnami-common + version: 2.x.x +description: Kubeapps is a web-based UI for launching and managing applications on + Kubernetes. It allows users to deploy trusted applications and operators to control + users access to the cluster. +home: https://bitnami.com +icon: https://bitnami.com/assets/stacks/kubeapps/img/kubeapps-stack-220x234.png +keywords: +- helm +- dashboard +- service catalog +- deployment +kubeVersion: '>=1.21.0-0' +maintainers: +- name: VMware, Inc. + url: https://github.com/bitnami/charts +name: kubeapps +sources: +- https://github.com/bitnami/charts/tree/main/bitnami/kubeapps +version: 14.1.2 diff --git a/packages/system/dashboard/charts/kubeapps/README.md b/packages/system/dashboard/charts/kubeapps/README.md new file mode 100644 index 00000000..cc93bc9e --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/README.md @@ -0,0 +1,1148 @@ + + +# Bitnami package for Kubeapps + +Kubeapps is a web-based UI for launching and managing applications on Kubernetes. It allows users to deploy trusted applications and operators to control users access to the cluster. + +[Overview of Kubeapps](https://github.com/vmware-tanzu/kubeapps) + +## TL;DR + +```console +helm install my-release oci://registry-1.docker.io/bitnamicharts/kubeapps --namespace kubeapps --create-namespace +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. +> Check out the [getting started](https://github.com/vmware-tanzu/kubeapps/blob/main/site/content/docs/latest/tutorials/getting-started.md) to start deploying apps with Kubeapps. + +Looking to use Kubeapps in production? Try [VMware Tanzu Application Catalog](https://bitnami.com/enterprise), the enterprise edition of Bitnami Application Catalog. + +## Introduction + +This chart bootstraps a [Kubeapps](https://kubeapps.dev) deployment on a [Kubernetes](https://kubernetes.io) cluster using the [Helm](https://helm.sh) package manager. + +With Kubeapps you can: + +- Customize deployments through an intuitive, form-based user interface +- Inspect, upgrade and delete applications installed in the cluster +- Browse and deploy [Helm](https://github.com/helm/helm) charts from public or private chart repositories (including [VMware Marketplace™](https://marketplace.cloud.vmware.com) and [Bitnami Application Catalog](https://bitnami.com/application-catalog)) +- Browse and deploy [Kubernetes Operators](https://operatorhub.io/) +- Secure authentication to Kubeapps using a [standalone OAuth2/OIDC provider](https://github.com/vmware-tanzu/kubeapps/blob/main/site/content/docs/latest/tutorials/using-an-OIDC-provider.md) or [using Pinniped](https://github.com/vmware-tanzu/kubeapps/blob/main/site/content/docs/latest/howto/OIDC/using-an-OIDC-provider-with-pinniped.md) +- Secure authorization based on Kubernetes [Role-Based Access Control](https://github.com/vmware-tanzu/kubeapps/blob/main/site/content/docs/latest/howto/access-control.md) + +**_Note:_** Kubeapps 2.0 and onwards supports Helm 3 only. While only the Helm 3 API is supported, in most cases, charts made for Helm 2 will still work. + +It also packages the [Bitnami PostgreSQL chart](https://github.com/bitnami/charts/tree/main/bitnami/postgresql), which is required for bootstrapping a deployment for the database requirements of the Kubeapps application. + +## Prerequisites + +- Kubernetes 1.23+ +- Helm 3.8.0+ +- Administrative access to the cluster to create Custom Resource Definitions (CRDs) +- PV provisioner support in the underlying infrastructure (required for PostgreSQL database) + +## Installing the Chart + +To install the chart with the release name `my-release`: + +```console +helm install my-release oci://REGISTRY_NAME/REPOSITORY_NAME/kubeapps --namespace kubeapps --create-namespace +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. + +The command deploys Kubeapps on the Kubernetes cluster in the `kubeapps` namespace. The [Parameters](#parameters) section lists the parameters that can be configured during installation. + +> **Caveat**: Only one Kubeapps installation is supported per namespace + +Once you have installed Kubeapps follow the [Getting Started Guide](https://github.com/vmware-tanzu/kubeapps/blob/main/site/content/docs/latest/tutorials/getting-started.md) for additional information on how to access and use Kubeapps. + +## Parameters + +### Global parameters + +| Name | Description | Value | +| ------------------------- | ----------------------------------------------- | ----- | +| `global.imageRegistry` | Global Docker image registry | `""` | +| `global.imagePullSecrets` | Global Docker registry secret names as an array | `[]` | +| `global.storageClass` | Global StorageClass for Persistent Volume(s) | `""` | + +### Common parameters + +| Name | Description | Value | +| ------------------------ | --------------------------------------------------------------------------------------- | -------------- | +| `kubeVersion` | Override Kubernetes version | `""` | +| `nameOverride` | String to partially override common.names.fullname | `""` | +| `fullnameOverride` | String to fully override common.names.fullname | `""` | +| `commonLabels` | Labels to add to all deployed objects | `{}` | +| `commonAnnotations` | Annotations to add to all deployed objects | `{}` | +| `extraDeploy` | Array of extra objects to deploy with the release | `[]` | +| `enableIPv6` | Enable IPv6 configuration | `false` | +| `diagnosticMode.enabled` | Enable diagnostic mode (all probes will be disabled and the command will be overridden) | `false` | +| `diagnosticMode.command` | Command to override all containers in the deployment | `["sleep"]` | +| `diagnosticMode.args` | Args to override all containers in the deployment | `["infinity"]` | + +### Traffic Exposure Parameters + +| Name | Description | Value | +| -------------------------- | -------------------------------------------------------------------------------------------------------------------------------- | ------------------------ | +| `ingress.enabled` | Enable ingress record generation for Kubeapps | `false` | +| `ingress.apiVersion` | Force Ingress API version (automatically detected if not set) | `""` | +| `ingress.hostname` | Default host for the ingress record | `kubeapps.local` | +| `ingress.path` | Default path for the ingress record | `/` | +| `ingress.pathType` | Ingress path type | `ImplementationSpecific` | +| `ingress.annotations` | Additional annotations for the Ingress resource. To enable certificate autogeneration, place here your cert-manager annotations. | `{}` | +| `ingress.tls` | Enable TLS configuration for the host defined at `ingress.hostname` parameter | `false` | +| `ingress.selfSigned` | Create a TLS secret for this ingress record using self-signed certificates generated by Helm | `false` | +| `ingress.extraHosts` | An array with additional hostname(s) to be covered with the ingress record | `[]` | +| `ingress.extraPaths` | An array with additional arbitrary paths that may need to be added to the ingress under the main host | `[]` | +| `ingress.extraTls` | TLS configuration for additional hostname(s) to be covered with this ingress record | `[]` | +| `ingress.secrets` | Custom TLS certificates as secrets | `[]` | +| `ingress.ingressClassName` | IngressClass that will be be used to implement the Ingress (Kubernetes 1.18+) | `""` | +| `ingress.extraRules` | Additional rules to be covered with this ingress record | `[]` | + +### Kubeapps packaging options + +| Name | Description | Value | +| -------------------------- | ---------------------------------------------------------- | ------- | +| `packaging.helm.enabled` | Enable the standard Helm packaging. | `true` | +| `packaging.carvel.enabled` | Enable support for the Carvel (kapp-controller) packaging. | `false` | +| `packaging.flux.enabled` | Enable support for Flux (v2) packaging. | `false` | + +### Frontend parameters + +| Name | Description | Value | +| ------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------- | ----------------------- | +| `frontend.image.registry` | NGINX image registry | `REGISTRY_NAME` | +| `frontend.image.repository` | NGINX image repository | `REPOSITORY_NAME/nginx` | +| `frontend.image.digest` | NGINX image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag | `""` | +| `frontend.image.pullPolicy` | NGINX image pull policy | `IfNotPresent` | +| `frontend.image.pullSecrets` | NGINX image pull secrets | `[]` | +| `frontend.image.debug` | Enable image debug mode | `false` | +| `frontend.proxypassAccessTokenAsBearer` | Use access_token as the Bearer when talking to the k8s api server | `false` | +| `frontend.proxypassExtraSetHeader` | Set an additional proxy header for all requests proxied via NGINX | `""` | +| `frontend.largeClientHeaderBuffers` | Set large_client_header_buffers in NGINX config | `4 32k` | +| `frontend.replicaCount` | Number of frontend replicas to deploy | `2` | +| `frontend.updateStrategy.type` | Frontend deployment strategy type. | `RollingUpdate` | +| `frontend.resources.limits.cpu` | The CPU limits for the NGINX container | `250m` | +| `frontend.resources.limits.memory` | The memory limits for the NGINX container | `128Mi` | +| `frontend.resources.requests.cpu` | The requested CPU for the NGINX container | `25m` | +| `frontend.resources.requests.memory` | The requested memory for the NGINX container | `32Mi` | +| `frontend.extraEnvVars` | Array with extra environment variables to add to the NGINX container | `[]` | +| `frontend.extraEnvVarsCM` | Name of existing ConfigMap containing extra env vars for the NGINX container | `""` | +| `frontend.extraEnvVarsSecret` | Name of existing Secret containing extra env vars for the NGINX container | `""` | +| `frontend.containerPorts.http` | NGINX HTTP container port | `8080` | +| `frontend.podSecurityContext.enabled` | Enabled frontend pods' Security Context | `true` | +| `frontend.podSecurityContext.fsGroup` | Set frontend pod's Security Context fsGroup | `1001` | +| `frontend.containerSecurityContext.enabled` | Enabled containers' Security Context | `true` | +| `frontend.containerSecurityContext.runAsUser` | Set containers' Security Context runAsUser | `1001` | +| `frontend.containerSecurityContext.runAsNonRoot` | Set container's Security Context runAsNonRoot | `true` | +| `frontend.containerSecurityContext.privileged` | Set container's Security Context privileged | `false` | +| `frontend.containerSecurityContext.readOnlyRootFilesystem` | Set container's Security Context readOnlyRootFilesystem | `false` | +| `frontend.containerSecurityContext.allowPrivilegeEscalation` | Set container's Security Context allowPrivilegeEscalation | `false` | +| `frontend.containerSecurityContext.capabilities.drop` | List of capabilities to be dropped | `["ALL"]` | +| `frontend.containerSecurityContext.seccompProfile.type` | Set container's Security Context seccomp profile | `RuntimeDefault` | +| `frontend.livenessProbe.enabled` | Enable livenessProbe | `true` | +| `frontend.livenessProbe.initialDelaySeconds` | Initial delay seconds for livenessProbe | `60` | +| `frontend.livenessProbe.periodSeconds` | Period seconds for livenessProbe | `10` | +| `frontend.livenessProbe.timeoutSeconds` | Timeout seconds for livenessProbe | `5` | +| `frontend.livenessProbe.failureThreshold` | Failure threshold for livenessProbe | `6` | +| `frontend.livenessProbe.successThreshold` | Success threshold for livenessProbe | `1` | +| `frontend.readinessProbe.enabled` | Enable readinessProbe | `true` | +| `frontend.readinessProbe.initialDelaySeconds` | Initial delay seconds for readinessProbe | `0` | +| `frontend.readinessProbe.periodSeconds` | Period seconds for readinessProbe | `10` | +| `frontend.readinessProbe.timeoutSeconds` | Timeout seconds for readinessProbe | `5` | +| `frontend.readinessProbe.failureThreshold` | Failure threshold for readinessProbe | `6` | +| `frontend.readinessProbe.successThreshold` | Success threshold for readinessProbe | `1` | +| `frontend.startupProbe.enabled` | Enable startupProbe | `false` | +| `frontend.startupProbe.initialDelaySeconds` | Initial delay seconds for startupProbe | `0` | +| `frontend.startupProbe.periodSeconds` | Period seconds for startupProbe | `10` | +| `frontend.startupProbe.timeoutSeconds` | Timeout seconds for startupProbe | `5` | +| `frontend.startupProbe.failureThreshold` | Failure threshold for startupProbe | `6` | +| `frontend.startupProbe.successThreshold` | Success threshold for startupProbe | `1` | +| `frontend.customLivenessProbe` | Custom livenessProbe that overrides the default one | `{}` | +| `frontend.customReadinessProbe` | Custom readinessProbe that overrides the default one | `{}` | +| `frontend.customStartupProbe` | Custom startupProbe that overrides the default one | `{}` | +| `frontend.lifecycleHooks` | Custom lifecycle hooks for frontend containers | `{}` | +| `frontend.command` | Override default container command (useful when using custom images) | `[]` | +| `frontend.args` | Override default container args (useful when using custom images) | `[]` | +| `frontend.podLabels` | Extra labels for frontend pods | `{}` | +| `frontend.podAnnotations` | Annotations for frontend pods | `{}` | +| `frontend.podAffinityPreset` | Pod affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` | `""` | +| `frontend.podAntiAffinityPreset` | Pod anti-affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` | `soft` | +| `frontend.nodeAffinityPreset.type` | Node affinity preset type. Ignored if `affinity` is set. Allowed values: `soft` or `hard` | `""` | +| `frontend.nodeAffinityPreset.key` | Node label key to match. Ignored if `affinity` is set | `""` | +| `frontend.nodeAffinityPreset.values` | Node label values to match. Ignored if `affinity` is set | `[]` | +| `frontend.affinity` | Affinity for pod assignment | `{}` | +| `frontend.nodeSelector` | Node labels for pod assignment | `{}` | +| `frontend.tolerations` | Tolerations for pod assignment | `[]` | +| `frontend.priorityClassName` | Priority class name for frontend pods | `""` | +| `frontend.schedulerName` | Name of the k8s scheduler (other than default) | `""` | +| `frontend.topologySpreadConstraints` | Topology Spread Constraints for pod assignment | `[]` | +| `frontend.hostAliases` | Custom host aliases for frontend pods | `[]` | +| `frontend.extraVolumes` | Optionally specify extra list of additional volumes for frontend pods | `[]` | +| `frontend.extraVolumeMounts` | Optionally specify extra list of additional volumeMounts for frontend container(s) | `[]` | +| `frontend.sidecars` | Add additional sidecar containers to the frontend pod | `[]` | +| `frontend.initContainers` | Add additional init containers to the frontend pods | `[]` | +| `frontend.service.type` | Frontend service type | `ClusterIP` | +| `frontend.service.ports.http` | Frontend service HTTP port | `80` | +| `frontend.service.nodePorts.http` | Node port for HTTP | `""` | +| `frontend.service.clusterIP` | Frontend service Cluster IP | `""` | +| `frontend.service.loadBalancerIP` | Frontend service Load Balancer IP | `""` | +| `frontend.service.loadBalancerSourceRanges` | Frontend service Load Balancer sources | `[]` | +| `frontend.service.externalTrafficPolicy` | Frontend service external traffic policy | `Cluster` | +| `frontend.service.extraPorts` | Extra ports to expose (normally used with the `sidecar` value) | `[]` | +| `frontend.service.annotations` | Additional custom annotations for frontend service | `{}` | +| `frontend.service.sessionAffinity` | Session Affinity for Kubernetes service, can be "None" or "ClientIP" | `None` | +| `frontend.service.sessionAffinityConfig` | Additional settings for the sessionAffinity | `{}` | + +### Dashboard parameters + +| Name | Description | Value | +| ------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- | ------------------------------------ | +| `dashboard.enabled` | Specifies whether Kubeapps Dashboard should be deployed or not | `true` | +| `dashboard.image.registry` | Dashboard image registry | `REGISTRY_NAME` | +| `dashboard.image.repository` | Dashboard image repository | `REPOSITORY_NAME/kubeapps-dashboard` | +| `dashboard.image.digest` | Dashboard image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag | `""` | +| `dashboard.image.pullPolicy` | Dashboard image pull policy | `IfNotPresent` | +| `dashboard.image.pullSecrets` | Dashboard image pull secrets | `[]` | +| `dashboard.image.debug` | Enable image debug mode | `false` | +| `dashboard.customStyle` | Custom CSS injected to the Dashboard to customize Kubeapps look and feel | `""` | +| `dashboard.customAppViews` | Package names to signal a custom app view | `[]` | +| `dashboard.customComponents` | Custom Form components injected into the BasicDeploymentForm | `""` | +| `dashboard.remoteComponentsUrl` | Remote URL that can be used to load custom components vs loading from the local filesystem | `""` | +| `dashboard.skipAvailablePackageDetails` | Skip the package details view and go straight to the installation view of the latest version | `false` | +| `dashboard.customLocale` | Custom translations injected to the Dashboard to customize the strings used in Kubeapps | `""` | +| `dashboard.defaultTheme` | Default theme used in the Dashboard if the user has not selected any theme yet. | `""` | +| `dashboard.replicaCount` | Number of Dashboard replicas to deploy | `2` | +| `dashboard.createNamespaceLabels` | Labels added to newly created namespaces | `{}` | +| `dashboard.updateStrategy.type` | Dashboard deployment strategy type. | `RollingUpdate` | +| `dashboard.extraEnvVars` | Array with extra environment variables to add to the Dashboard container | `[]` | +| `dashboard.extraEnvVarsCM` | Name of existing ConfigMap containing extra env vars for the Dashboard container | `""` | +| `dashboard.extraEnvVarsSecret` | Name of existing Secret containing extra env vars for the Dashboard container | `""` | +| `dashboard.containerPorts.http` | Dashboard HTTP container port | `8080` | +| `dashboard.resources.limits.cpu` | The CPU limits for the Dashboard container | `250m` | +| `dashboard.resources.limits.memory` | The memory limits for the Dashboard container | `128Mi` | +| `dashboard.resources.requests.cpu` | The requested CPU for the Dashboard container | `25m` | +| `dashboard.resources.requests.memory` | The requested memory for the Dashboard container | `32Mi` | +| `dashboard.podSecurityContext.enabled` | Enabled Dashboard pods' Security Context | `true` | +| `dashboard.podSecurityContext.fsGroup` | Set Dashboard pod's Security Context fsGroup | `1001` | +| `dashboard.containerSecurityContext.enabled` | Enabled containers' Security Context | `true` | +| `dashboard.containerSecurityContext.runAsUser` | Set containers' Security Context runAsUser | `1001` | +| `dashboard.containerSecurityContext.runAsNonRoot` | Set container's Security Context runAsNonRoot | `true` | +| `dashboard.containerSecurityContext.privileged` | Set container's Security Context privileged | `false` | +| `dashboard.containerSecurityContext.readOnlyRootFilesystem` | Set container's Security Context readOnlyRootFilesystem | `false` | +| `dashboard.containerSecurityContext.allowPrivilegeEscalation` | Set container's Security Context allowPrivilegeEscalation | `false` | +| `dashboard.containerSecurityContext.capabilities.drop` | List of capabilities to be dropped | `["ALL"]` | +| `dashboard.containerSecurityContext.seccompProfile.type` | Set container's Security Context seccomp profile | `RuntimeDefault` | +| `dashboard.livenessProbe.enabled` | Enable livenessProbe | `true` | +| `dashboard.livenessProbe.initialDelaySeconds` | Initial delay seconds for livenessProbe | `60` | +| `dashboard.livenessProbe.periodSeconds` | Period seconds for livenessProbe | `10` | +| `dashboard.livenessProbe.timeoutSeconds` | Timeout seconds for livenessProbe | `5` | +| `dashboard.livenessProbe.failureThreshold` | Failure threshold for livenessProbe | `6` | +| `dashboard.livenessProbe.successThreshold` | Success threshold for livenessProbe | `1` | +| `dashboard.readinessProbe.enabled` | Enable readinessProbe | `true` | +| `dashboard.readinessProbe.initialDelaySeconds` | Initial delay seconds for readinessProbe | `0` | +| `dashboard.readinessProbe.periodSeconds` | Period seconds for readinessProbe | `10` | +| `dashboard.readinessProbe.timeoutSeconds` | Timeout seconds for readinessProbe | `5` | +| `dashboard.readinessProbe.failureThreshold` | Failure threshold for readinessProbe | `6` | +| `dashboard.readinessProbe.successThreshold` | Success threshold for readinessProbe | `1` | +| `dashboard.startupProbe.enabled` | Enable startupProbe | `true` | +| `dashboard.startupProbe.initialDelaySeconds` | Initial delay seconds for startupProbe | `0` | +| `dashboard.startupProbe.periodSeconds` | Period seconds for startupProbe | `10` | +| `dashboard.startupProbe.timeoutSeconds` | Timeout seconds for startupProbe | `5` | +| `dashboard.startupProbe.failureThreshold` | Failure threshold for startupProbe | `6` | +| `dashboard.startupProbe.successThreshold` | Success threshold for startupProbe | `1` | +| `dashboard.customLivenessProbe` | Custom livenessProbe that overrides the default one | `{}` | +| `dashboard.customReadinessProbe` | Custom readinessProbe that overrides the default one | `{}` | +| `dashboard.customStartupProbe` | Custom startupProbe that overrides the default one | `{}` | +| `dashboard.lifecycleHooks` | Custom lifecycle hooks for Dashboard containers | `{}` | +| `dashboard.command` | Override default container command (useful when using custom images) | `[]` | +| `dashboard.args` | Override default container args (useful when using custom images) | `[]` | +| `dashboard.podLabels` | Extra labels for Dashboard pods | `{}` | +| `dashboard.podAnnotations` | Annotations for Dashboard pods | `{}` | +| `dashboard.podAffinityPreset` | Pod affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` | `""` | +| `dashboard.podAntiAffinityPreset` | Pod anti-affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` | `soft` | +| `dashboard.nodeAffinityPreset.type` | Node affinity preset type. Ignored if `affinity` is set. Allowed values: `soft` or `hard` | `""` | +| `dashboard.nodeAffinityPreset.key` | Node label key to match. Ignored if `affinity` is set | `""` | +| `dashboard.nodeAffinityPreset.values` | Node label values to match. Ignored if `affinity` is set | `[]` | +| `dashboard.affinity` | Affinity for pod assignment | `{}` | +| `dashboard.nodeSelector` | Node labels for pod assignment | `{}` | +| `dashboard.tolerations` | Tolerations for pod assignment | `[]` | +| `dashboard.priorityClassName` | Priority class name for Dashboard pods | `""` | +| `dashboard.schedulerName` | Name of the k8s scheduler (other than default) | `""` | +| `dashboard.topologySpreadConstraints` | Topology Spread Constraints for pod assignment | `[]` | +| `dashboard.hostAliases` | Custom host aliases for Dashboard pods | `[]` | +| `dashboard.extraVolumes` | Optionally specify extra list of additional volumes for Dashboard pods | `[]` | +| `dashboard.extraVolumeMounts` | Optionally specify extra list of additional volumeMounts for Dashboard container(s) | `[]` | +| `dashboard.sidecars` | Add additional sidecar containers to the Dashboard pod | `[]` | +| `dashboard.initContainers` | Add additional init containers to the Dashboard pods | `[]` | +| `dashboard.service.ports.http` | Dashboard service HTTP port | `8080` | +| `dashboard.service.annotations` | Additional custom annotations for Dashboard service | `{}` | + +### AppRepository Controller parameters + +| Name | Description | Value | +| ----------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------- | +| `apprepository.image.registry` | Kubeapps AppRepository Controller image registry | `REGISTRY_NAME` | +| `apprepository.image.repository` | Kubeapps AppRepository Controller image repository | `REPOSITORY_NAME/kubeapps-apprepository-controller` | +| `apprepository.image.digest` | Kubeapps AppRepository Controller image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag | `""` | +| `apprepository.image.pullPolicy` | Kubeapps AppRepository Controller image pull policy | `IfNotPresent` | +| `apprepository.image.pullSecrets` | Kubeapps AppRepository Controller image pull secrets | `[]` | +| `apprepository.syncImage.registry` | Kubeapps Asset Syncer image registry | `REGISTRY_NAME` | +| `apprepository.syncImage.repository` | Kubeapps Asset Syncer image repository | `REPOSITORY_NAME/kubeapps-asset-syncer` | +| `apprepository.syncImage.digest` | Kubeapps Asset Syncer image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag | `""` | +| `apprepository.syncImage.pullPolicy` | Kubeapps Asset Syncer image pull policy | `IfNotPresent` | +| `apprepository.syncImage.pullSecrets` | Kubeapps Asset Syncer image pull secrets | `[]` | +| `apprepository.globalReposNamespaceSuffix` | Suffix for the namespace of global repos in the Helm plugin. Defaults to empty for backwards compatibility. Ignored if kubeappsapis.pluginConfig.helm.packages.v1alpha1.globalPackagingNamespace is set. | `""` | +| `apprepository.initialRepos` | Initial chart repositories to configure | `[]` | +| `apprepository.customAnnotations` | Custom annotations be added to each AppRepository-generated CronJob, Job and Pod | `{}` | +| `apprepository.customLabels` | Custom labels be added to each AppRepository-generated CronJob, Job and Pod | `{}` | +| `apprepository.initialReposProxy.enabled` | Enables the proxy | `false` | +| `apprepository.initialReposProxy.httpProxy` | URL for the http proxy | `""` | +| `apprepository.initialReposProxy.httpsProxy` | URL for the https proxy | `""` | +| `apprepository.initialReposProxy.noProxy` | URL to exclude from using the proxy | `""` | +| `apprepository.crontab` | Default schedule for syncing App repositories (defaults to every 10 minutes) | `""` | +| `apprepository.watchAllNamespaces` | Watch all namespaces to support separate AppRepositories per namespace | `true` | +| `apprepository.extraFlags` | Additional command line flags for AppRepository Controller | `[]` | +| `apprepository.replicaCount` | Number of AppRepository Controller replicas to deploy | `1` | +| `apprepository.updateStrategy.type` | AppRepository Controller deployment strategy type. | `RollingUpdate` | +| `apprepository.resources.limits.cpu` | The CPU limits for the AppRepository Controller container | `250m` | +| `apprepository.resources.limits.memory` | The memory limits for the AppRepository Controller container | `128Mi` | +| `apprepository.resources.requests.cpu` | The requested CPU for the AppRepository Controller container | `25m` | +| `apprepository.resources.requests.memory` | The requested memory for the AppRepository Controller container | `32Mi` | +| `apprepository.podSecurityContext.enabled` | Enabled AppRepository Controller pods' Security Context | `true` | +| `apprepository.podSecurityContext.fsGroup` | Set AppRepository Controller pod's Security Context fsGroup | `1001` | +| `apprepository.containerSecurityContext.enabled` | Enabled containers' Security Context | `true` | +| `apprepository.containerSecurityContext.runAsUser` | Set containers' Security Context runAsUser | `1001` | +| `apprepository.containerSecurityContext.runAsNonRoot` | Set container's Security Context runAsNonRoot | `true` | +| `apprepository.containerSecurityContext.privileged` | Set container's Security Context privileged | `false` | +| `apprepository.containerSecurityContext.readOnlyRootFilesystem` | Set container's Security Context readOnlyRootFilesystem | `false` | +| `apprepository.containerSecurityContext.allowPrivilegeEscalation` | Set container's Security Context allowPrivilegeEscalation | `false` | +| `apprepository.containerSecurityContext.capabilities.drop` | List of capabilities to be dropped | `["ALL"]` | +| `apprepository.containerSecurityContext.seccompProfile.type` | Set container's Security Context seccomp profile | `RuntimeDefault` | +| `apprepository.lifecycleHooks` | Custom lifecycle hooks for AppRepository Controller containers | `{}` | +| `apprepository.command` | Override default container command (useful when using custom images) | `[]` | +| `apprepository.args` | Override default container args (useful when using custom images) | `[]` | +| `apprepository.extraEnvVars` | Array with extra environment variables to add to AppRepository Controller pod(s) | `[]` | +| `apprepository.extraEnvVarsCM` | Name of existing ConfigMap containing extra env vars for AppRepository Controller pod(s) | `""` | +| `apprepository.extraEnvVarsSecret` | Name of existing Secret containing extra env vars for AppRepository Controller pod(s) | `""` | +| `apprepository.extraVolumes` | Optionally specify extra list of additional volumes for the AppRepository Controller pod(s) | `[]` | +| `apprepository.extraVolumeMounts` | Optionally specify extra list of additional volumeMounts for the AppRepository Controller container(s) | `[]` | +| `apprepository.podLabels` | Extra labels for AppRepository Controller pods | `{}` | +| `apprepository.podAnnotations` | Annotations for AppRepository Controller pods | `{}` | +| `apprepository.podAffinityPreset` | Pod affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` | `""` | +| `apprepository.podAntiAffinityPreset` | Pod anti-affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` | `soft` | +| `apprepository.nodeAffinityPreset.type` | Node affinity preset type. Ignored if `affinity` is set. Allowed values: `soft` or `hard` | `""` | +| `apprepository.nodeAffinityPreset.key` | Node label key to match. Ignored if `affinity` is set | `""` | +| `apprepository.nodeAffinityPreset.values` | Node label values to match. Ignored if `affinity` is set | `[]` | +| `apprepository.affinity` | Affinity for pod assignment | `{}` | +| `apprepository.nodeSelector` | Node labels for pod assignment | `{}` | +| `apprepository.tolerations` | Tolerations for pod assignment | `[]` | +| `apprepository.priorityClassName` | Priority class name for AppRepository Controller pods | `""` | +| `apprepository.schedulerName` | Name of the k8s scheduler (other than default) | `""` | +| `apprepository.topologySpreadConstraints` | Topology Spread Constraints for pod assignment | `[]` | +| `apprepository.hostAliases` | Custom host aliases for AppRepository Controller pods | `[]` | +| `apprepository.sidecars` | Add additional sidecar containers to the AppRepository Controller pod(s) | `[]` | +| `apprepository.initContainers` | Add additional init containers to the AppRepository Controller pod(s) | `[]` | +| `apprepository.serviceAccount.create` | Specifies whether a ServiceAccount should be created | `true` | +| `apprepository.serviceAccount.name` | Name of the service account to use. If not set and create is true, a name is generated using the fullname template. | `""` | +| `apprepository.serviceAccount.automountServiceAccountToken` | Automount service account token for the server service account | `true` | +| `apprepository.serviceAccount.annotations` | Annotations for service account. Evaluated as a template. Only used if `create` is `true`. | `{}` | + +### Auth Proxy parameters + +| Name | Description | Value | +| ------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- | ------------------------------ | +| `authProxy.enabled` | Specifies whether Kubeapps should configure OAuth login/logout | `false` | +| `authProxy.image.registry` | OAuth2 Proxy image registry | `REGISTRY_NAME` | +| `authProxy.image.repository` | OAuth2 Proxy image repository | `REPOSITORY_NAME/oauth2-proxy` | +| `authProxy.image.digest` | OAuth2 Proxy image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag | `""` | +| `authProxy.image.pullPolicy` | OAuth2 Proxy image pull policy | `IfNotPresent` | +| `authProxy.image.pullSecrets` | OAuth2 Proxy image pull secrets | `[]` | +| `authProxy.external` | Use an external Auth Proxy instead of deploying its own one | `false` | +| `authProxy.oauthLoginURI` | OAuth Login URI to which the Kubeapps frontend redirects for authn | `/oauth2/start` | +| `authProxy.oauthLogoutURI` | OAuth Logout URI to which the Kubeapps frontend redirects for authn | `/oauth2/sign_out` | +| `authProxy.skipKubeappsLoginPage` | Skip the Kubeapps login page when using OIDC and directly redirect to the IdP | `false` | +| `authProxy.provider` | OAuth provider | `""` | +| `authProxy.clientID` | OAuth Client ID | `""` | +| `authProxy.clientSecret` | OAuth Client secret | `""` | +| `authProxy.cookieSecret` | Secret used by oauth2-proxy to encrypt any credentials | `""` | +| `authProxy.existingOauth2Secret` | Name of an existing secret containing the OAuth client secrets, it should contain the keys clientID, clientSecret, and cookieSecret | `""` | +| `authProxy.cookieRefresh` | Duration after which to refresh the cookie | `2m` | +| `authProxy.scope` | OAuth scope specification | `openid email groups` | +| `authProxy.emailDomain` | Allowed email domains | `*` | +| `authProxy.extraFlags` | Additional command line flags for oauth2-proxy | `[]` | +| `authProxy.lifecycleHooks` | for the Auth Proxy container(s) to automate configuration before or after startup | `{}` | +| `authProxy.command` | Override default container command (useful when using custom images) | `[]` | +| `authProxy.args` | Override default container args (useful when using custom images) | `[]` | +| `authProxy.extraEnvVars` | Array with extra environment variables to add to the Auth Proxy container | `[]` | +| `authProxy.extraEnvVarsCM` | Name of existing ConfigMap containing extra env vars for Auth Proxy containers(s) | `""` | +| `authProxy.extraEnvVarsSecret` | Name of existing Secret containing extra env vars for Auth Proxy containers(s) | `""` | +| `authProxy.extraVolumeMounts` | Optionally specify extra list of additional volumeMounts for the Auth Proxy container(s) | `[]` | +| `authProxy.containerPorts.proxy` | Auth Proxy HTTP container port | `3000` | +| `authProxy.containerSecurityContext.enabled` | Enabled containers' Security Context | `true` | +| `authProxy.containerSecurityContext.runAsUser` | Set containers' Security Context runAsUser | `1001` | +| `authProxy.containerSecurityContext.runAsNonRoot` | Set container's Security Context runAsNonRoot | `true` | +| `authProxy.containerSecurityContext.privileged` | Set container's Security Context privileged | `false` | +| `authProxy.containerSecurityContext.readOnlyRootFilesystem` | Set container's Security Context readOnlyRootFilesystem | `false` | +| `authProxy.containerSecurityContext.allowPrivilegeEscalation` | Set container's Security Context allowPrivilegeEscalation | `false` | +| `authProxy.containerSecurityContext.capabilities.drop` | List of capabilities to be dropped | `["ALL"]` | +| `authProxy.containerSecurityContext.seccompProfile.type` | Set container's Security Context seccomp profile | `RuntimeDefault` | +| `authProxy.resources.limits.cpu` | The CPU limits for the OAuth2 Proxy container | `250m` | +| `authProxy.resources.limits.memory` | The memory limits for the OAuth2 Proxy container | `128Mi` | +| `authProxy.resources.requests.cpu` | The requested CPU for the OAuth2 Proxy container | `25m` | +| `authProxy.resources.requests.memory` | The requested memory for the OAuth2 Proxy container | `32Mi` | + +### Pinniped Proxy parameters + +| Name | Description | Value | +| ----------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- | ----------------------------------------- | +| `pinnipedProxy.enabled` | Specifies whether Kubeapps should configure Pinniped Proxy | `false` | +| `pinnipedProxy.image.registry` | Pinniped Proxy image registry | `REGISTRY_NAME` | +| `pinnipedProxy.image.repository` | Pinniped Proxy image repository | `REPOSITORY_NAME/kubeapps-pinniped-proxy` | +| `pinnipedProxy.image.digest` | Pinniped Proxy image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag | `""` | +| `pinnipedProxy.image.pullPolicy` | Pinniped Proxy image pull policy | `IfNotPresent` | +| `pinnipedProxy.image.pullSecrets` | Pinniped Proxy image pull secrets | `[]` | +| `pinnipedProxy.defaultPinnipedNamespace` | Namespace in which pinniped concierge is installed | `pinniped-concierge` | +| `pinnipedProxy.defaultAuthenticatorType` | Authenticator type | `JWTAuthenticator` | +| `pinnipedProxy.defaultAuthenticatorName` | Authenticator name | `jwt-authenticator` | +| `pinnipedProxy.defaultPinnipedAPISuffix` | API suffix | `pinniped.dev` | +| `pinnipedProxy.tls.existingSecret` | TLS secret with which to proxy requests | `""` | +| `pinnipedProxy.tls.caCertificate` | TLS CA cert config map which clients of pinniped proxy should use with TLS requests | `""` | +| `pinnipedProxy.lifecycleHooks` | For the Pinniped Proxy container(s) to automate configuration before or after startup | `{}` | +| `pinnipedProxy.command` | Override default container command (useful when using custom images) | `[]` | +| `pinnipedProxy.args` | Override default container args (useful when using custom images) | `[]` | +| `pinnipedProxy.extraEnvVars` | Array with extra environment variables to add to Pinniped Proxy container(s) | `[]` | +| `pinnipedProxy.extraEnvVarsCM` | Name of existing ConfigMap containing extra env vars for Pinniped Proxy container(s) | `""` | +| `pinnipedProxy.extraEnvVarsSecret` | Name of existing Secret containing extra env vars for Pinniped Proxy container(s) | `""` | +| `pinnipedProxy.extraVolumeMounts` | Optionally specify extra list of additional volumeMounts for the Pinniped Proxy container(s) | `[]` | +| `pinnipedProxy.containerPorts.pinnipedProxy` | Pinniped Proxy container port | `3333` | +| `pinnipedProxy.containerSecurityContext.enabled` | Enabled containers' Security Context | `true` | +| `pinnipedProxy.containerSecurityContext.runAsUser` | Set containers' Security Context runAsUser | `1001` | +| `pinnipedProxy.containerSecurityContext.runAsNonRoot` | Set container's Security Context runAsNonRoot | `true` | +| `pinnipedProxy.containerSecurityContext.privileged` | Set container's Security Context privileged | `false` | +| `pinnipedProxy.containerSecurityContext.readOnlyRootFilesystem` | Set container's Security Context readOnlyRootFilesystem | `false` | +| `pinnipedProxy.containerSecurityContext.allowPrivilegeEscalation` | Set container's Security Context allowPrivilegeEscalation | `false` | +| `pinnipedProxy.containerSecurityContext.capabilities.drop` | List of capabilities to be dropped | `["ALL"]` | +| `pinnipedProxy.containerSecurityContext.seccompProfile.type` | Set container's Security Context seccomp profile | `RuntimeDefault` | +| `pinnipedProxy.resources.limits.cpu` | The CPU limits for the Pinniped Proxy container | `250m` | +| `pinnipedProxy.resources.limits.memory` | The memory limits for the Pinniped Proxy container | `128Mi` | +| `pinnipedProxy.resources.requests.cpu` | The requested CPU for the Pinniped Proxy container | `25m` | +| `pinnipedProxy.resources.requests.memory` | The requested memory for the Pinniped Proxy container | `32Mi` | +| `pinnipedProxy.service.ports.pinnipedProxy` | Pinniped Proxy service port | `3333` | +| `pinnipedProxy.service.annotations` | Additional custom annotations for Pinniped Proxy service | `{}` | + +### Other Parameters + +| Name | Description | Value | +| ------------- | --------------------------------------------------------- | ------ | +| `clusters` | List of clusters that Kubeapps can target for deployments | `[]` | +| `rbac.create` | Specifies whether RBAC resources should be created | `true` | + +### Feature flags + +| Name | Description | Value | +| --------------------------------------- | ---------------------------------------------------------------------------------------------------------- | ------- | +| `featureFlags.apiOnly.enabled` | Enable ingress for API operations only. Access to "/" will not be possible, so Dashboard will be unusable. | `false` | +| `featureFlags.apiOnly.grpc.annotations` | Specific annotations for the GRPC ingress in API-only mode | `{}` | +| `featureFlags.operators` | Enable support for Operators in Kubeapps | `false` | +| `featureFlags.schemaEditor.enabled` | Enable a visual editor for customizing the package schemas | `false` | + +### Database Parameters + +| Name | Description | Value | +| ---------------------------------------- | ---------------------------------------------------------------------------- | ------------ | +| `postgresql.enabled` | Deploy a PostgreSQL server to satisfy the applications database requirements | `true` | +| `postgresql.auth.username` | Username for PostgreSQL server | `postgres` | +| `postgresql.auth.postgresPassword` | Password for 'postgres' user | `""` | +| `postgresql.auth.database` | Name for a custom database to create | `assets` | +| `postgresql.auth.existingSecret` | Name of existing secret to use for PostgreSQL credentials | `""` | +| `postgresql.primary.persistence.enabled` | Enable PostgreSQL Primary data persistence using PVC | `false` | +| `postgresql.architecture` | PostgreSQL architecture (`standalone` or `replication`) | `standalone` | +| `postgresql.securityContext.enabled` | Enabled PostgreSQL replicas pods' Security Context | `false` | +| `postgresql.resources.limits` | The resources limits for the PostgreSQL container | `{}` | +| `postgresql.resources.requests.cpu` | The requested CPU for the PostgreSQL container | `250m` | +| `postgresql.resources.requests.memory` | The requested memory for the PostgreSQL container | `256Mi` | + +### kubeappsapis parameters + +| Name | Description | Value | +| ----------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------- | +| `kubeappsapis.enabledPlugins` | Manually override which plugins are enabled for the Kubeapps-APIs service | `[]` | +| `kubeappsapis.pluginConfig.core.packages.v1alpha1.versionsInSummary.major` | Number of major versions to display in the summary | `3` | +| `kubeappsapis.pluginConfig.core.packages.v1alpha1.versionsInSummary.minor` | Number of minor versions to display in the summary | `3` | +| `kubeappsapis.pluginConfig.core.packages.v1alpha1.versionsInSummary.patch` | Number of patch versions to display in the summary | `3` | +| `kubeappsapis.pluginConfig.core.packages.v1alpha1.timeoutSeconds` | Value to wait for Kubernetes commands to complete | `300` | +| `kubeappsapis.pluginConfig.helm.packages.v1alpha1.globalPackagingNamespace` | Custom global packaging namespace. Using this value will override the current "kubeapps release namespace + suffix" pattern and will create a new namespace if not exists. | `""` | +| `kubeappsapis.pluginConfig.kappController.packages.v1alpha1.defaultUpgradePolicy` | Default upgrade policy generating version constraints | `none` | +| `kubeappsapis.pluginConfig.kappController.packages.v1alpha1.defaultPrereleasesVersionSelection` | Default policy for allowing prereleases containing one of the identifiers | `nil` | +| `kubeappsapis.pluginConfig.kappController.packages.v1alpha1.defaultAllowDowngrades` | Default policy for allowing applications to be downgraded to previous versions | `false` | +| `kubeappsapis.pluginConfig.kappController.packages.v1alpha1.globalPackagingNamespace` | Default global packaging namespace | `kapp-controller-packaging-global` | +| `kubeappsapis.pluginConfig.flux.packages.v1alpha1.defaultUpgradePolicy` | Default upgrade policy generating version constraints | `none` | +| `kubeappsapis.pluginConfig.flux.packages.v1alpha1.noCrossNamespaceRefs` | Enable this flag to disallow cross-namespace references, useful when running Flux on multi-tenant clusters | `false` | +| `kubeappsapis.pluginConfig.resources.packages.v1alpha1.trustedNamespaces.headerName` | Optional header name for trusted namespaces | `""` | +| `kubeappsapis.pluginConfig.resources.packages.v1alpha1.trustedNamespaces.headerPattern` | Optional header pattern for trusted namespaces | `""` | +| `kubeappsapis.image.registry` | Kubeapps-APIs image registry | `REGISTRY_NAME` | +| `kubeappsapis.image.repository` | Kubeapps-APIs image repository | `REPOSITORY_NAME/kubeapps-apis` | +| `kubeappsapis.image.digest` | Kubeapps-APIs image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag | `""` | +| `kubeappsapis.image.pullPolicy` | Kubeapps-APIs image pull policy | `IfNotPresent` | +| `kubeappsapis.image.pullSecrets` | Kubeapps-APIs image pull secrets | `[]` | +| `kubeappsapis.replicaCount` | Number of frontend replicas to deploy | `2` | +| `kubeappsapis.updateStrategy.type` | KubeappsAPIs deployment strategy type. | `RollingUpdate` | +| `kubeappsapis.extraFlags` | Additional command line flags for KubeappsAPIs | `[]` | +| `kubeappsapis.qps` | KubeappsAPIs Kubernetes API client QPS limit | `50.0` | +| `kubeappsapis.burst` | KubeappsAPIs Kubernetes API client Burst limit | `100` | +| `kubeappsapis.terminationGracePeriodSeconds` | The grace time period for sig term | `300` | +| `kubeappsapis.extraEnvVars` | Array with extra environment variables to add to the KubeappsAPIs container | `[]` | +| `kubeappsapis.extraEnvVarsCM` | Name of existing ConfigMap containing extra env vars for the KubeappsAPIs container | `""` | +| `kubeappsapis.extraEnvVarsSecret` | Name of existing Secret containing extra env vars for the KubeappsAPIs container | `""` | +| `kubeappsapis.containerPorts.http` | KubeappsAPIs HTTP container port | `50051` | +| `kubeappsapis.resources.limits.cpu` | The CPU limits for the KubeappsAPIs container | `250m` | +| `kubeappsapis.resources.limits.memory` | The memory limits for the KubeappsAPIs container | `256Mi` | +| `kubeappsapis.resources.requests.cpu` | The requested CPU for the KubeappsAPIs container | `25m` | +| `kubeappsapis.resources.requests.memory` | The requested memory for the KubeappsAPIs container | `32Mi` | +| `kubeappsapis.podSecurityContext.enabled` | Enabled KubeappsAPIs pods' Security Context | `true` | +| `kubeappsapis.podSecurityContext.fsGroup` | Set KubeappsAPIs pod's Security Context fsGroup | `1001` | +| `kubeappsapis.containerSecurityContext.enabled` | Enabled containers' Security Context | `true` | +| `kubeappsapis.containerSecurityContext.runAsUser` | Set containers' Security Context runAsUser | `1001` | +| `kubeappsapis.containerSecurityContext.runAsNonRoot` | Set container's Security Context runAsNonRoot | `true` | +| `kubeappsapis.containerSecurityContext.privileged` | Set container's Security Context privileged | `false` | +| `kubeappsapis.containerSecurityContext.readOnlyRootFilesystem` | Set container's Security Context readOnlyRootFilesystem | `false` | +| `kubeappsapis.containerSecurityContext.allowPrivilegeEscalation` | Set container's Security Context allowPrivilegeEscalation | `false` | +| `kubeappsapis.containerSecurityContext.capabilities.drop` | List of capabilities to be dropped | `["ALL"]` | +| `kubeappsapis.containerSecurityContext.seccompProfile.type` | Set container's Security Context seccomp profile | `RuntimeDefault` | +| `kubeappsapis.livenessProbe.enabled` | Enable livenessProbe | `true` | +| `kubeappsapis.livenessProbe.initialDelaySeconds` | Initial delay seconds for livenessProbe | `60` | +| `kubeappsapis.livenessProbe.periodSeconds` | Period seconds for livenessProbe | `10` | +| `kubeappsapis.livenessProbe.timeoutSeconds` | Timeout seconds for livenessProbe | `5` | +| `kubeappsapis.livenessProbe.failureThreshold` | Failure threshold for livenessProbe | `6` | +| `kubeappsapis.livenessProbe.successThreshold` | Success threshold for livenessProbe | `1` | +| `kubeappsapis.readinessProbe.enabled` | Enable readinessProbe | `true` | +| `kubeappsapis.readinessProbe.initialDelaySeconds` | Initial delay seconds for readinessProbe | `0` | +| `kubeappsapis.readinessProbe.periodSeconds` | Period seconds for readinessProbe | `10` | +| `kubeappsapis.readinessProbe.timeoutSeconds` | Timeout seconds for readinessProbe | `5` | +| `kubeappsapis.readinessProbe.failureThreshold` | Failure threshold for readinessProbe | `6` | +| `kubeappsapis.readinessProbe.successThreshold` | Success threshold for readinessProbe | `1` | +| `kubeappsapis.startupProbe.enabled` | Enable startupProbe | `false` | +| `kubeappsapis.startupProbe.initialDelaySeconds` | Initial delay seconds for startupProbe | `0` | +| `kubeappsapis.startupProbe.periodSeconds` | Period seconds for startupProbe | `10` | +| `kubeappsapis.startupProbe.timeoutSeconds` | Timeout seconds for startupProbe | `5` | +| `kubeappsapis.startupProbe.failureThreshold` | Failure threshold for startupProbe | `6` | +| `kubeappsapis.startupProbe.successThreshold` | Success threshold for startupProbe | `1` | +| `kubeappsapis.customLivenessProbe` | Custom livenessProbe that overrides the default one | `{}` | +| `kubeappsapis.customReadinessProbe` | Custom readinessProbe that overrides the default one | `{}` | +| `kubeappsapis.customStartupProbe` | Custom startupProbe that overrides the default one | `{}` | +| `kubeappsapis.lifecycleHooks` | Custom lifecycle hooks for KubeappsAPIs containers | `{}` | +| `kubeappsapis.command` | Override default container command (useful when using custom images) | `[]` | +| `kubeappsapis.args` | Override default container args (useful when using custom images) | `[]` | +| `kubeappsapis.extraVolumes` | Optionally specify extra list of additional volumes for the KubeappsAPIs pod(s) | `[]` | +| `kubeappsapis.extraVolumeMounts` | Optionally specify extra list of additional volumeMounts for the KubeappsAPIs container(s) | `[]` | +| `kubeappsapis.podLabels` | Extra labels for KubeappsAPIs pods | `{}` | +| `kubeappsapis.podAnnotations` | Annotations for KubeappsAPIs pods | `{}` | +| `kubeappsapis.podAffinityPreset` | Pod affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` | `""` | +| `kubeappsapis.podAntiAffinityPreset` | Pod anti-affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` | `soft` | +| `kubeappsapis.nodeAffinityPreset.type` | Node affinity preset type. Ignored if `affinity` is set. Allowed values: `soft` or `hard` | `""` | +| `kubeappsapis.nodeAffinityPreset.key` | Node label key to match. Ignored if `affinity` is set | `""` | +| `kubeappsapis.nodeAffinityPreset.values` | Node label values to match. Ignored if `affinity` is set | `[]` | +| `kubeappsapis.affinity` | Affinity for pod assignment | `{}` | +| `kubeappsapis.nodeSelector` | Node labels for pod assignment | `{}` | +| `kubeappsapis.tolerations` | Tolerations for pod assignment | `[]` | +| `kubeappsapis.priorityClassName` | Priority class name for KubeappsAPIs pods | `""` | +| `kubeappsapis.schedulerName` | Name of the k8s scheduler (other than default) | `""` | +| `kubeappsapis.topologySpreadConstraints` | Topology Spread Constraints for pod assignment | `[]` | +| `kubeappsapis.hostAliases` | Custom host aliases for KubeappsAPIs pods | `[]` | +| `kubeappsapis.sidecars` | Add additional sidecar containers to the KubeappsAPIs pod(s) | `[]` | +| `kubeappsapis.initContainers` | Add additional init containers to the KubeappsAPIs pod(s) | `[]` | +| `kubeappsapis.service.ports.http` | KubeappsAPIs service HTTP port | `8080` | +| `kubeappsapis.service.annotations` | Additional custom annotations for KubeappsAPIs service | `{}` | +| `kubeappsapis.serviceAccount.create` | Specifies whether a ServiceAccount should be created | `true` | +| `kubeappsapis.serviceAccount.name` | Name of the service account to use. If not set and create is true, a name is generated using the fullname template. | `""` | +| `kubeappsapis.serviceAccount.automountServiceAccountToken` | Automount service account token for the server service account | `true` | +| `kubeappsapis.serviceAccount.annotations` | Annotations for service account. Evaluated as a template. Only used if `create` is `true`. | `{}` | + +### OCI Catalog chart configuration + +| Name | Description | Value | +| -------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- | -------------------------------------- | +| `ociCatalog.enabled` | Enable the OCI catalog gRPC service for cataloging | `false` | +| `ociCatalog.image.registry` | OCI Catalog image registry | `REGISTRY_NAME` | +| `ociCatalog.image.repository` | OCI Catalog image repository | `REPOSITORY_NAME/kubeapps-oci-catalog` | +| `ociCatalog.image.digest` | OCI Catalog image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag | `""` | +| `ociCatalog.image.pullPolicy` | OCI Catalog image pull policy | `IfNotPresent` | +| `ociCatalog.image.pullSecrets` | OCI Catalog image pull secrets | `[]` | +| `ociCatalog.image.debug` | Enable image debug mode | `false` | +| `ociCatalog.extraFlags` | Additional command line flags for OCI Catalog | `[]` | +| `ociCatalog.extraEnvVars` | Array with extra environment variables to add to the oci-catalog container | `[]` | +| `ociCatalog.extraEnvVarsCM` | Name of existing ConfigMap containing extra env vars for the OCI Catalog container | `""` | +| `ociCatalog.extraEnvVarsSecret` | Name of existing Secret containing extra env vars for the OCI Catalog container | `""` | +| `ociCatalog.containerPorts.grpc` | OCI Catalog gRPC container port | `50061` | +| `ociCatalog.resources.limits.cpu` | The CPU limits for the OCI Catalog container | `250m` | +| `ociCatalog.resources.limits.memory` | The memory limits for the OCI Catalog container | `256Mi` | +| `ociCatalog.resources.requests.cpu` | The requested CPU for the OCI Catalog container | `25m` | +| `ociCatalog.resources.requests.memory` | The requested memory for the OCI Catalog container | `32Mi` | +| `ociCatalog.containerSecurityContext.enabled` | Enabled containers' Security Context | `true` | +| `ociCatalog.containerSecurityContext.runAsUser` | Set containers' Security Context runAsUser | `1001` | +| `ociCatalog.containerSecurityContext.runAsNonRoot` | Set container's Security Context runAsNonRoot | `true` | +| `ociCatalog.containerSecurityContext.privileged` | Set container's Security Context privileged | `false` | +| `ociCatalog.containerSecurityContext.readOnlyRootFilesystem` | Set container's Security Context readOnlyRootFilesystem | `false` | +| `ociCatalog.containerSecurityContext.allowPrivilegeEscalation` | Set container's Security Context allowPrivilegeEscalation | `false` | +| `ociCatalog.containerSecurityContext.capabilities.drop` | List of capabilities to be dropped | `["ALL"]` | +| `ociCatalog.containerSecurityContext.seccompProfile.type` | Set container's Security Context seccomp profile | `RuntimeDefault` | +| `ociCatalog.livenessProbe.enabled` | Enable livenessProbe | `true` | +| `ociCatalog.livenessProbe.initialDelaySeconds` | Initial delay seconds for livenessProbe | `60` | +| `ociCatalog.livenessProbe.periodSeconds` | Period seconds for livenessProbe | `10` | +| `ociCatalog.livenessProbe.timeoutSeconds` | Timeout seconds for livenessProbe | `5` | +| `ociCatalog.livenessProbe.failureThreshold` | Failure threshold for livenessProbe | `6` | +| `ociCatalog.livenessProbe.successThreshold` | Success threshold for livenessProbe | `1` | +| `ociCatalog.readinessProbe.enabled` | Enable readinessProbe | `true` | +| `ociCatalog.readinessProbe.initialDelaySeconds` | Initial delay seconds for readinessProbe | `0` | +| `ociCatalog.readinessProbe.periodSeconds` | Period seconds for readinessProbe | `10` | +| `ociCatalog.readinessProbe.timeoutSeconds` | Timeout seconds for readinessProbe | `5` | +| `ociCatalog.readinessProbe.failureThreshold` | Failure threshold for readinessProbe | `6` | +| `ociCatalog.readinessProbe.successThreshold` | Success threshold for readinessProbe | `1` | +| `ociCatalog.startupProbe.enabled` | Enable startupProbe | `false` | +| `ociCatalog.startupProbe.initialDelaySeconds` | Initial delay seconds for startupProbe | `0` | +| `ociCatalog.startupProbe.periodSeconds` | Period seconds for startupProbe | `10` | +| `ociCatalog.startupProbe.timeoutSeconds` | Timeout seconds for startupProbe | `5` | +| `ociCatalog.startupProbe.failureThreshold` | Failure threshold for startupProbe | `6` | +| `ociCatalog.startupProbe.successThreshold` | Success threshold for startupProbe | `1` | +| `ociCatalog.customLivenessProbe` | Custom livenessProbe that overrides the default one | `{}` | +| `ociCatalog.customReadinessProbe` | Custom readinessProbe that overrides the default one | `{}` | +| `ociCatalog.customStartupProbe` | Custom startupProbe that overrides the default one | `{}` | +| `ociCatalog.lifecycleHooks` | Custom lifecycle hooks for OCI Catalog containers | `{}` | +| `ociCatalog.command` | Override default container command (useful when using custom images) | `[]` | +| `ociCatalog.args` | Override default container args (useful when using custom images) | `[]` | +| `ociCatalog.extraVolumes` | Optionally specify extra list of additional volumes for the OCI Catalog pod(s) | `[]` | +| `ociCatalog.extraVolumeMounts` | Optionally specify extra list of additional volumeMounts for the OCI Catalog container(s) | `[]` | + +### Redis® chart configuration + +| Name | Description | Value | +| ----------------------------------- | ---------------------------------------------------------------- | -------------------------------------------------------- | +| `redis.auth.enabled` | Enable password authentication | `true` | +| `redis.auth.password` | Redis® password | `""` | +| `redis.auth.existingSecret` | The name of an existing secret with Redis® credentials | `""` | +| `redis.architecture` | Redis(R) architecture (`standalone` or `replication`) | `standalone` | +| `redis.master.extraFlags` | Array with additional command line flags for Redis® master | `["--maxmemory 200mb","--maxmemory-policy allkeys-lru"]` | +| `redis.master.disableCommands` | Array with commands to deactivate on Redis® | `[]` | +| `redis.master.persistence.enabled` | Enable Redis® master data persistence using PVC | `false` | +| `redis.replica.replicaCount` | Number of Redis® replicas to deploy | `1` | +| `redis.replica.extraFlags` | Array with additional command line flags for Redis® replicas | `["--maxmemory 200mb","--maxmemory-policy allkeys-lru"]` | +| `redis.replica.disableCommands` | Array with commands to deactivate on Redis® | `[]` | +| `redis.replica.persistence.enabled` | Enable Redis® replica data persistence using PVC | `false` | + +```console +helm install kubeapps --namespace kubeapps \ + --set ingress.enabled=true \ + oci://REGISTRY_NAME/REPOSITORY_NAME/kubeapps +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. + +The above command enables an Ingress Rule to expose Kubeapps. + +Alternatively, a YAML file that specifies the values for parameters can be provided while installing the chart. For example, + +```console +helm install kubeapps --namespace kubeapps -f custom-values.yaml oci://REGISTRY_NAME/REPOSITORY_NAME/kubeapps +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. + +## Configuration and installation details + +### Configuring Initial Repositories + +By default, Kubeapps will track the [Bitnami Application Catalog](https://github.com/bitnami/charts). To change these defaults, override with your desired parameters the `apprepository.initialRepos` object present in the [values.yaml](https://github.com/bitnami/charts/tree/main/bitnami/kubeapps/values.yaml) file. + +### Enabling Operators + +Since v1.9.0 (and by default since v2.0), Kubeapps supports deploying and managing Operators within its dashboard. More information about how to enable and use this feature can be found in [this guide](https://github.com/vmware-tanzu/kubeapps/blob/main/site/content/docs/latest/tutorials/operators.md). + +### Exposing Externally + +> **Note**: The Kubeapps frontend sets up a proxy to the Kubernetes API service which means that when exposing the Kubeapps service to a network external to the Kubernetes cluster (perhaps on an internal or public network), the Kubernetes API will also be exposed for authenticated requests from that network. It is highly recommended that you [use an OAuth2/OIDC provider with Kubeapps](https://github.com/vmware-tanzu/kubeapps/blob/main/site/content/docs/latest/tutorials/using-an-OIDC-provider.md) to ensure that your authentication proxy is exposed rather than the Kubeapps frontend. This ensures that only the configured users trusted by your Identity Provider will be able to reach the Kubeapps frontend and therefore the Kubernetes API. Kubernetes service token authentication should only be used for users for demonstration purposes only, not production environments. + +#### LoadBalancer Service + +The simplest way to expose the Kubeapps Dashboard is to assign a LoadBalancer type to the Kubeapps frontend Service. For example, you can use the following parameter: `frontend.service.type=LoadBalancer` + +Wait for your cluster to assign a LoadBalancer IP or Hostname to the `kubeapps` Service and access it on that address: + +```console +kubectl get services --namespace kubeapps --watch +``` + +#### Ingress + +This chart provides support for Ingress resources. If you have an ingress controller installed on your cluster, such as [nginx-ingress-controller](https://github.com/bitnami/charts/tree/main/bitnami/nginx-ingress-controller) or [contour](https://github.com/bitnami/charts/tree/main/bitnami/contour) you can utilize the ingress controller to serve your application. + +To enable ingress integration, please set `ingress.enabled` to `true` + +##### Hosts + +Most likely you will only want to have one hostname that maps to this Kubeapps installation (use the `ingress.hostname` parameter to set the hostname), however, it is possible to have more than one host. To facilitate this, the `ingress.extraHosts` object is an array. + +##### Annotations + +For annotations, please see [this document](https://github.com/kubernetes/ingress-nginx/blob/main/docs/user-guide/nginx-configuration/annotations.md). Not all annotations are supported by all ingress controllers, but this document does a good job of indicating which annotation is supported by many popular ingress controllers. Annotations can be set using `ingress.annotations`. + +##### TLS + +This chart will facilitate the creation of TLS secrets for use with the ingress controller, however, this is not required. There are four common use cases: + +- Helm generates/manages certificate secrets based on the parameters. +- The user generates/manages certificates separately. +- Helm creates self-signed certificates and generates/manages certificate secrets. +- An additional tool (like [cert-manager](https://github.com/jetstack/cert-manager/)) manages the secrets for the application. + +In the first two cases, it is needed a certificate and a key. We would expect them to look like this: + +- certificate files should look like (and there can be more than one certificate if there is a certificate chain) + + ```console + -----BEGIN CERTIFICATE----- + MIID6TCCAtGgAwIBAgIJAIaCwivkeB5EMA0GCSqGSIb3DQEBCwUAMFYxCzAJBgNV + ... + jScrvkiBO65F46KioCL9h5tDvomdU1aqpI/CBzhvZn1c0ZTf87tGQR8NK7v7 + -----END CERTIFICATE----- + ``` + +- keys should look like: + + ```console + -----BEGIN RSA PRIVATE KEY----- + MIIEogIBAAKCAQEAvLYcyu8f3skuRyUgeeNpeDvYBCDcgq+LsWap6zbX5f8oLqp4 + ... + wrj2wDbCDCFmfqnSJ+dKI3vFLlEz44sAV8jX/kd4Y6ZTQhlLbYc= + -----END RSA PRIVATE KEY----- + ``` + +- If you are going to use Helm to manage the certificates based on the parameters, please copy these values into the `certificate` and `key` values for a given `ingress.secrets` entry. +- In case you are going to manage TLS secrets separately, please know that you must use a TLS secret with name _INGRESS_HOSTNAME-tls_ (where _INGRESS_HOSTNAME_ is a placeholder to be replaced with the hostname you set using the `ingress.hostname` parameter). +- To use self-signed certificates created by Helm, set both `ingress.tls` and `ingress.selfSigned` to `true`. +- If your cluster has a [cert-manager](https://github.com/jetstack/cert-manager) add-on to automate the management and issuance of TLS certificates, set `ingress.certManager` boolean to true to enable the corresponding annotations for cert-manager. + +## Upgrading Kubeapps + +You can upgrade Kubeapps from the Kubeapps web interface. Select the namespace in which Kubeapps is installed (`kubeapps` if you followed the instructions in this guide) and click on the "Upgrade" button. Select the new version and confirm. + +You can also use the Helm CLI to upgrade Kubeapps, first ensure you have updated your local chart repository cache: + +```console +helm repo update +``` + +Now upgrade Kubeapps: + +```console +export RELEASE_NAME=kubeapps +helm upgrade $RELEASE_NAME oci://REGISTRY_NAME/REPOSITORY_NAME/kubeapps +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. + +If you find issues upgrading Kubeapps, check the [troubleshooting](#error-while-upgrading-the-chart) section. + +### To 14.0.0 + +This major updates the PostgreSQL subchart to its newest major, 13.0.0. [Here](https://github.com/bitnami/charts/tree/master/bitnami/postgresql#to-1300) you can find more information about the changes introduced in that version. + +### To 13.0.0 + +This major updates the Redis® subchart to its newest major, 18.0.0. [Here](https://github.com/bitnami/charts/tree/main/bitnami/redis#to-1800) you can find more information about the changes introduced in that version. + +NOTE: Due to an error in our release process, Redis®' chart versions higher or equal than 17.15.4 already use Redis® 7.2 by default. + +### To 12.0.0 + +This major updates the PostgreSQL subchart to its newest major, 12.0.0. [Here](https://github.com/bitnami/charts/tree/master/bitnami/postgresql#to-1200) you can find more information about the changes introduced in that version. + +## Uninstalling the Chart + +To uninstall/delete the `kubeapps` deployment: + +```console +helm uninstall -n kubeapps kubeapps + +# Optional: Only if there are no more instances of Kubeapps +$ kubectl delete crd apprepositories.kubeapps.com +``` + +The first command removes most of the Kubernetes components associated with the chart and deletes the release. After that, if there are no more instances of Kubeapps in the cluster you can manually delete the `apprepositories.kubeapps.com` CRD used by Kubeapps that is shared for the entire cluster. + +> **NOTE**: If you delete the CRD for `apprepositories.kubeapps.com` it will delete the repositories for **all** the installed instances of `kubeapps`. This will break existing installations of `kubeapps` if they exist. + +If you have dedicated a namespace only for Kubeapps you can completely clean the remaining completed/failed jobs or any stale resources by deleting the namespace + +```console +kubectl delete namespace kubeapps +``` + +## FAQ + +- [How to install Kubeapps for demo purposes?](#how-to-install-kubeapps-for-demo-purposes) +- [How to install Kubeapps in production scenarios?](#how-to-install-kubeapps-in-production-scenarios) +- [How to use Kubeapps?](#how-to-use-kubeapps) +- [How to configure Kubeapps with Ingress](#how-to-configure-kubeapps-with-ingress) + - [Serving Kubeapps in a subpath](#serving-kubeapps-in-a-subpath) +- [Can Kubeapps install apps into more than one cluster?](#can-kubeapps-install-apps-into-more-than-one-cluster) +- [Can Kubeapps be installed without Internet connection?](#can-kubeapps-be-installed-without-internet-connection) +- [Does Kubeapps support private repositories?](#does-kubeapps-support-private-repositories) +- [Is there any API documentation?](#is-there-any-api-documentation) +- [Why can't I configure global private repositories?](#why-cant-i-configure-global-private-repositories) +- [Does Kubeapps support Operators?](#does-kubeapps-support-operators) +- [Slow response when listing namespaces?](#slow-response-when-listing-namespaces) +- [More questions?](#more-questions) + +### How to install Kubeapps for demo purposes? + +Install Kubeapps for exclusively **demo purposes** by simply following the [getting started](https://github.com/vmware-tanzu/kubeapps/blob/main/site/content/docs/latest/tutorials/getting-started.md) docs. + +### How to install Kubeapps in production scenarios? + +For any user-facing installation, you should [configure an OAuth2/OIDC provider](https://github.com/vmware-tanzu/kubeapps/blob/main/site/content/docs/latest/tutorials/using-an-OIDC-provider.md) to enable secure user authentication with Kubeapps and the cluster. +Please also refer to the [Access Control](https://github.com/vmware-tanzu/kubeapps/blob/main/site/content/docs/latest/howto/access-control.md) documentation to configure fine-grained access control for users. + +### How to use Kubeapps? + +Have a look at the [dashboard documentation](https://github.com/vmware-tanzu/kubeapps/blob/main/site/content/docs/latest/howto/dashboard.md) for knowing how to use the Kubeapps dashboard: deploying applications, listing and removing the applications running in your cluster and adding new repositories. + +### How to configure Kubeapps with Ingress + +The example below will match the URL `http://example.com` to the Kubeapps dashboard. For further configuration, please refer to your specific Ingress configuration docs (e.g., [NGINX](https://github.com/kubernetes/ingress-nginx) or [HAProxy](https://github.com/haproxytech/kubernetes-ingress)). + +```console +helm install kubeapps oci://REGISTRY_NAME/REPOSITORY_NAME/kubeapps \ + --namespace kubeapps \ + --set ingress.enabled=true \ + --set ingress.hostname=example.com \ + --set ingress.annotations."kubernetes\.io/ingress\.class"=nginx # or your preferred ingress controller +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. + +If you are using LDAP via Dex with OIDC or you are getting an error message like `upstream sent too big header while reading response header from upstream` it means the cookie size is too big and can't be processed by the Ingress Controller. +You can work around this problem by setting the following Nginx ingress annotations (look for similar annotations in your preferred Ingress Controller): + +```text + # rest of the helm install ... command + --set ingress.annotations."nginx\.ingress\.kubernetes\.io/proxy-read-timeout"=600 + --set ingress.annotations."nginx\.ingress\.kubernetes\.io/proxy-buffer-size"=8k + --set ingress.annotations."nginx\.ingress\.kubernetes\.io/proxy-buffers"=4 +``` + +#### Serving Kubeapps in a subpath + +You may want to serve Kubeapps with a subpath, for instance `http://example.com/subpath`, you have to set the proper Ingress configuration. If you are using the ingress configuration provided by the Kubeapps chart, you will have to set the `ingress.hostname` and `path` parameters: + +```console +helm install kubeapps oci://REGISTRY_NAME/REPOSITORY_NAME/kubeapps \ + --namespace kubeapps \ + --set ingress.enabled=true \ + --set ingress.hostname=example.com \ + --set ingress.path=/subpath \ + --set ingress.annotations."kubernetes\.io/ingress\.class"=nginx # or your preferred ingress controller +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. + +Besides, if you are using the OAuth2/OIDC login (more information at the [using an OIDC provider documentation](https://github.com/vmware-tanzu/kubeapps/blob/main/site/content/docs/latest/tutorials/using-an-OIDC-provider.md)), you will need, also, to configure the different URLs: + +```console +helm install kubeapps oci://REGISTRY_NAME/REPOSITORY_NAME/kubeapps \ + --namespace kubeapps \ + # ... other OIDC and ingress flags + --set authProxy.oauthLoginURI="/subpath/oauth2/login" \ + --set authProxy.oauthLogoutURI="/subpath/oauth2/logout" \ + --set authProxy.extraFlags="{,--proxy-prefix=/subpath/oauth2}" +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. + +### Can Kubeapps install apps into more than one cluster? + +Yes! Kubeapps 2.0+ supports multicluster environments. Have a look at the [Kubeapps dashboard documentation](https://github.com/vmware-tanzu/kubeapps/blob/main/site/content/docs/latest/howto/deploying-to-multiple-clusters.md) to know more. + +### Can Kubeapps be installed without Internet connection? + +Yes! Follow the [offline installation documentation](https://github.com/vmware-tanzu/kubeapps/blob/main/site/content/docs/latest/howto/offline-installation.md) to discover how to perform an installation in an air-gapped scenario. + +### Does Kubeapps support private repositories? + +Of course! Have a look at the [private package repositories documentation](https://github.com/vmware-tanzu/kubeapps/blob/main/site/content/docs/latest/howto/private-app-repository.md) to learn how to configure a private repository in Kubeapps. + +### Is there any API documentation? + +Yes! But it is not definitive and is still subject to change. Check out the [latest API online documentation](https://app.swaggerhub.com/apis/vmware-tanzu/Kubeapps) or download the Kubeapps [OpenAPI Specification yaml file](https://github.com/vmware-tanzu/kubeapps/blob/main/dashboard/public/openapi.yaml) from the repository. + +### Why can't I configure global private repositories? + +You can, but you will need to configure the `imagePullSecrets` manually. + +Kubeapps does not allow you to add `imagePullSecrets` to an AppRepository that is available to the whole cluster because it would require that Kubeapps copies those secrets to the target namespace when a user deploys an app. + +If you create a global AppRepository but the images are on a private registry requiring `imagePullSecrets`, the best way to configure that is to ensure your [Kubernetes nodes are configured with the required `imagePullSecrets`](https://kubernetes.io/docs/concepts/containers/images/#configuring-nodes-to-authenticate-to-a-private-registry) - this allows all users (of those nodes) to use those images in their deployments without ever requiring access to the secrets. + +You could alternatively ensure that the `imagePullSecret` is available in all namespaces in which you want people to deploy, but this unnecessarily compromises the secret. + +### Does Kubeapps support Operators? + +Yes! You can get started by following the [operators documentation](https://github.com/vmware-tanzu/kubeapps/blob/main/site/content/docs/latest/tutorials/operators.md). + +### Slow response when listing namespaces + +Kubeapps uses the currently logged-in user credential to retrieve the list of all namespaces. If the user does not have permission to list namespaces, the backend will try again with its own service account. It will list all the namespaces and then will iterate through each namespace to check if the user has permissions to get secrets for each one. +This can lead to a slow response if the number of namespaces on the cluster is large. + +To reduce this response time, you can increase the number of checks that Kubeapps will perform in parallel (per connection) setting the value: `kubeappsapis.burst=` and `kubeappsapis.QPS=`. + +### More questions? + +Feel free to [open an issue](https://github.com/vmware-tanzu/kubeapps/issues/new) if you have any questions! + +## Troubleshooting + +### Upgrading to chart version 8.0.0 + +This major release renames several values in this chart and adds missing features, in order to get aligned with the rest of the assets in the Bitnami charts repository. + +Additionally, it updates both the [PostgreSQL](https://github.com/bitnami/charts/tree/main/bitnami/postgresql) and the [Redis](https://github.com/bitnami/charts/tree/main/bitnami/redis) subcharts to their latest major versions, 11.0.0 and 16.0.0 respectively, where similar changes have been also performed. +Check [PostgreSQL Upgrading Notes](https://docs.bitnami.com/kubernetes/infrastructure/postgresql/administration/upgrade/#to-1100) and [Redis Upgrading Notes](https://github.com/bitnami/charts/tree/main/bitnami/redis#to-1600) for more information. + +The following values have been renamed: + +- `frontend.service.port` renamed as `frontend.service.ports.http`. +- `frontend.service.nodePort` renamed as `frontend.service.nodePorts.http`. +- `frontend.containerPort` renamed as `frontend.containerPorts.http`. +- `dashboard.service.port` renamed as `dashboard.service.ports.http`. +- `dashboard.containerPort` renamed as `dashboard.containerPorts.http`. +- `apprepository.service.port` renamed as `apprepository.service.ports.http`. +- `apprepository.containerPort` renamed as `apprepository.containerPorts.http`. +- `kubeops.service.port` renamed as `kubeops.service.ports.http`. +- `kubeops.containerPort` renamed as `kubeops.containerPorts.http`. +- `assetsvc.service.port` renamed as `assetsvc.service.ports.http`. +- `assetsvc.containerPort` renamed as `assetsvc.containerPorts.http`. +- `authProxy.containerPort` renamed as `authProxy.containerPorts.proxy`. +- `authProxy.additionalFlags` renamed as `authProxy.extraFlags`, +- Pinniped Proxy service no longer uses `pinnipedProxy.containerPort`. Use `pinnipedProxy.service.ports.pinnipedProxy` to change the service port. +- `pinnipedProxy.containerPort` renamed as `pinnipedProxy.containerPorts.pinnipedProxy`. +- `postgresql.replication.enabled` has been removed. Use `postgresql.architecture` instead. +- `postgresql.postgresqlDatabase` renamed as `postgresql.auth.database`. +- `postgresql.postgresqlPassword` renamed as `postgresql.auth.password`. +- `postgresql.existingSecret` renamed as `postgresql.auth.existingSecret`. +- `redis.redisPassword` renamed as `redis.auth.password`. +- `redis.existingSecret` renamed as `redis.auth.existingSecret`. + +Note also that if you have an existing Postgresql secret that is used for Kubeapps, you will need to update the key from `postgresql-password` to `postgres-password`. + +### Nginx Ipv6 error + +When starting the application with the `--set enableIPv6=true` option, the Nginx server present in the services `kubeapps` and `kubeapps-internal-dashboard` may fail with the following: + +```console +nginx: [emerg] socket() [::]:8080 failed (97: Address family not supported by protocol) +``` + +This usually means that your cluster is not compatible with IPv6. To deactivate it, install kubeapps with the flag: `--set enableIPv6=false`. + +### Forbidden error while installing the Chart + +If during installation you run into an error similar to: + +```console +Error: release kubeapps failed: clusterroles.rbac.authorization.k8s.io "kubeapps-apprepository-controller" is forbidden: attempt to grant extra privileges: [{[get] [batch] [cronjobs] [] []... +``` + +Or: + +```console +Error: namespaces "kubeapps" is forbidden: User "system:serviceaccount:kube-system:default" cannot get namespaces in the namespace "kubeapps" +``` + +It is possible, though uncommon, that your cluster does not have Role-Based Access Control (RBAC) enabled. To check if your cluster has RBAC you can run the following command: + +```console +kubectl api-versions +``` + +If the above command does not include entries for `rbac.authorization.k8s.io` you should perform the chart installation by setting `rbac.create=false`: + +```console +helm install --name kubeapps --namespace kubeapps oci://REGISTRY_NAME/REPOSITORY_NAME/kubeapps --set rbac.create=false +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. + +### Error while upgrading the Chart + +It is possible that when upgrading Kubeapps an error appears. That can be caused by a breaking change in the new chart or because the current chart installation is in an inconsistent state. If you find issues upgrading Kubeapps you can follow these steps: + +> Note: These steps assume that you have installed Kubeapps in the namespace `kubeapps` using the name `kubeapps`. If that is not the case replace the command with your namespace and/or name. +> Note: If you are upgrading from 2.3.1 see the [following section](#upgrading-to-231). +> Note: If you are upgrading from 1.X to 2.X see the [following section](#upgrading-to-20). + +1. (Optional) Backup your personal repositories (if you have any): + + ```console + kubectl get apprepository -A -o yaml > .yaml + ``` + +2. Delete Kubeapps: + + ```console + helm del --purge kubeapps + ``` + +3. (Optional) Delete the App Repositories CRD: + + > **Warning**: Do not run this step if you have more than one Kubeapps installation in your cluster. + + ```console + kubectl delete crd apprepositories.kubeapps.com + ``` + +4. (Optional) Clean the Kubeapps namespace: + + > **Warning**: Do not run this step if you have workloads other than Kubeapps in the `kubeapps` namespace. + + ```console + kubectl delete namespace kubeapps + ``` + +5. Install the latest version of Kubeapps (using any custom modifications you need): + + ```console + helm repo update + helm install --name kubeapps --namespace kubeapps oci://REGISTRY_NAME/REPOSITORY_NAME/kubeapps + ``` + + > Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. + +6. (Optional) Restore any repositories you backed up in the first step: + + ```console + kubectl apply -f .yaml + ``` + +After that you should be able to access the new version of Kubeapps. If the above doesn't work for you or you run into any other issues please open an [issue](https://github.com/vmware-tanzu/kubeapps/issues/new). + +### Upgrading to chart version 7.0.0 + +In this release, no breaking changes were included in Kubeapps (version 2.3.2). However, the chart adopted the standardizations included in the rest of the charts in the Bitnami catalog. + +Most of these standardizations simply add new parameters that allow to add more customizations such as adding custom env. variables, volumes or sidecar containers. That said, some of them include breaking changes: + +- Chart labels were adapted to follow the [Helm charts standard labels](https://helm.sh/docs/chart_best_practices/labels/#standard-labels). +- `securityContext.*` parameters are deprecated in favor of `XXX.podSecurityContext.*` and `XXX.containerSecurityContext.*`, where _XXX_ is placeholder you need to replace with the actual component(s). For instance, to modify the container security context for "kubeops" use `kubeops.podSecurityContext` and `kubeops.containerSecurityContext` parameters. + +### Upgrading to 2.3.1 + +Kubeapps 2.3.1 (Chart version 6.0.0) introduces some breaking changes. Helm-specific functionality has been removed in order to support other installation methods (like using YAML manifests, [`kapp`](https://carvel.dev/kapp) or [`kustomize`](https://kustomize.io/)). Because of that, there are some steps required before upgrading from a previous version: + +1. Kubeapps will no longer create a database secret for you automatically but rather will rely on the default behavior of the PostgreSQL chart. If you try to upgrade Kubeapps and you installed it without setting a password, you will get the following error: + + ```console + Error: UPGRADE FAILED: template: kubeapps/templates/NOTES.txt:73:4: executing "kubeapps/templates/NOTES.txt" at : error calling include: template: kubeapps/charts/common/templates/_errors.tpl:18:48: executing "common.errors.upgrade.passwords.empty" at : error calling fail: + PASSWORDS ERROR: you must provide your current passwords when upgrade the release + 'postgresql.postgresqlPassword' must not be empty, please add '--set postgresql.postgresqlPassword=$POSTGRESQL_PASSWORD' to the command. To get the current value: + ``` + + The error gives you generic instructions for retrieving the PostgreSQL password, but if you have installed a Kubeapps version prior to 2.3.1, the name of the secret will differ. Run the following command: + + ```console + export POSTGRESQL_PASSWORD=$(kubectl get secret --namespace "kubeapps" kubeapps-db -o jsonpath="{.data.postgresql-password}" | base64 -d) + ``` + + > NOTE: Replace the namespace in the command with the namespace in which you have deployed Kubeapps. + + Make sure that you have stored the password in the variable `$POSTGRESQL_PASSWORD` before continuing with the next issue. + +2. The chart `initialRepos` are no longer installed using [Helm hooks](https://helm.sh/docs/topics/charts_hooks/), which caused these repos not to be handled by Helm after the first installation. Now they will be tracked for every update. However, if you do not delete the existing ones, it will fail to update with: + +```console +Error: UPGRADE FAILED: rendered manifests contain a resource that already exists. Unable to continue with update: AppRepository "bitnami" in namespace "kubeapps" exists and cannot be imported into the current release: invalid ownership metadata; annotation validation error: missing key "meta.helm.sh/release-name": must be set to "kubeapps"; annotation validation error: missing key "meta.helm.sh/release-namespace": must be set to "kubeapps" +``` + +To bypass this issue, you will need to before delete all the initialRepos from the chart values (only the `bitnami` repo by default): + +```console +kubectl delete apprepositories.kubeapps.com -n kubeapps bitnami +``` + +> NOTE: Replace the namespace in the command with the namespace in which you have deployed Kubeapps. + +After that, you will be able to upgrade Kubeapps to 2.3.1 using the existing database secret: + +> **WARNING**: Make sure that the variable `$POSTGRESQL_PASSWORD` is properly populated. Setting a wrong (or empty) password will corrupt the release. + +```console +helm upgrade kubeapps oci://REGISTRY_NAME/REPOSITORY_NAME/kubeapps -n kubeapps --set postgresql.postgresqlPassword=$POSTGRESQL_PASSWORD +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. + +### Upgrading to 2.0.1 (Chart 5.0.0) + +[On November 13, 2020, Helm 2 support was formally finished](https://github.com/helm/charts#status-of-the-project), this major version is the result of the required changes applied to the Helm Chart to be able to incorporate the different features added in Helm 3 and to be consistent with the Helm project itself regarding the Helm 2 EOL. + +#### What changes were introduced in this major version? + +- Previous versions of this Helm Chart use `apiVersion: v1` (installable by both Helm 2 and 3), this Helm Chart was updated to `apiVersion: v2` (installable by Helm 3 only). [Here](https://helm.sh/docs/topics/charts/#the-apiversion-field) you can find more information about the `apiVersion` field. +- Move dependency information from the _requirements.yaml_ to the _Chart.yaml_ +- After running `helm dependency update`, a _Chart.lock_ file is generated containing the same structure used in the previous _requirements.lock_ +- The different fields present in the _Chart.yaml_ file has been ordered alphabetically in a homogeneous way for all the Bitnami Helm Charts +- In the case of PostgreSQL subchart, apart from the same changes that are described in this section, there are also other major changes due to the _master/slave_ nomenclature was replaced by _primary/readReplica_. [Here](https://github.com/bitnami/charts/pull/4385) you can find more information about the changes introduced. + +#### Considerations when upgrading to this version + +- If you want to upgrade to this version using Helm 2, this scenario is not supported as this version does not support Helm 2 anymore +- If you installed the previous version with Helm 2 and wants to upgrade to this version with Helm 3, please refer to the [official Helm documentation](https://helm.sh/docs/topics/v2_v3_migration/#migration-use-cases) about migrating from Helm 2 to 3 +- If you want to upgrade to this version from a previous one installed with Helm 3, you should not face any issues related to the new `apiVersion`. Due to the PostgreSQL major version bump, it is necessary to remove the existing statefulsets: + +> Note: The command below assumes that Kubeapps has been deployed in the kubeapps namespace using "kubeapps" as release name, if that is not the case, adapt the command accordingly. + +```console +kubectl delete statefulset -n kubeapps kubeapps-postgresql-master kubeapps-postgresql-slave +``` + +#### Useful links + +- +- +- + +### Upgrading to 2.0 + +Kubeapps 2.0 (Chart version 4.0.0) introduces some breaking changes: + +- Helm 2 is no longer supported. If you are still using some Helm 2 charts, [migrate them with the available tools](https://helm.sh/docs/topics/v2_v3_migration/). Note that some charts (but not all of them) may require to be migrated to the [new Chart specification (v2)](https://helm.sh/docs/topics/charts/#the-apiversion-field). If you are facing any issue managing this migration and Kubeapps, please open a new issue! +- MongoDB® is no longer supported. Since 2.0, the only database supported is PostgreSQL. +- PostgreSQL chart dependency has been upgraded to a new major version. + +Due to the last point, it is necessary to run a command before upgrading to Kubeapps 2.0: + +> Note: The command below assumes that Kubeapps has been deployed in the kubeapps namespace using "kubeapps" as release name, if that is not the case, adapt the command accordingly. + +```console +kubectl delete statefulset -n kubeapps kubeapps-postgresql-master kubeapps-postgresql-slave +``` + +After that, you should be able to upgrade Kubeapps as always and the database will be repopulated. + +## License + +Copyright © 2023 VMware, Inc. + +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 + + + +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. \ No newline at end of file diff --git a/packages/system/dashboard/charts/kubeapps/charts/common/.helmignore b/packages/system/dashboard/charts/kubeapps/charts/common/.helmignore new file mode 100644 index 00000000..50af0317 --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/charts/common/.helmignore @@ -0,0 +1,22 @@ +# 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 +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/packages/system/dashboard/charts/kubeapps/charts/common/Chart.yaml b/packages/system/dashboard/charts/kubeapps/charts/common/Chart.yaml new file mode 100644 index 00000000..40cd22d7 --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/charts/common/Chart.yaml @@ -0,0 +1,23 @@ +annotations: + category: Infrastructure + licenses: Apache-2.0 +apiVersion: v2 +appVersion: 2.13.3 +description: A Library Helm Chart for grouping common logic between bitnami charts. + This chart is not deployable by itself. +home: https://bitnami.com +icon: https://bitnami.com/downloads/logos/bitnami-mark.png +keywords: +- common +- helper +- template +- function +- bitnami +maintainers: +- name: VMware, Inc. + url: https://github.com/bitnami/charts +name: common +sources: +- https://github.com/bitnami/charts +type: library +version: 2.13.3 diff --git a/packages/system/dashboard/charts/kubeapps/charts/common/README.md b/packages/system/dashboard/charts/kubeapps/charts/common/README.md new file mode 100644 index 00000000..80da4cc2 --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/charts/common/README.md @@ -0,0 +1,235 @@ +# Bitnami Common Library Chart + +A [Helm Library Chart](https://helm.sh/docs/topics/library_charts/#helm) for grouping common logic between Bitnami charts. + +## TL;DR + +```yaml +dependencies: + - name: common + version: 2.x.x + repository: oci://registry-1.docker.io/bitnamicharts +``` + +```console +helm dependency update +``` + +```yaml +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "common.names.fullname" . }} +data: + myvalue: "Hello World" +``` + +## Introduction + +This chart provides a common template helpers which can be used to develop new charts using [Helm](https://helm.sh) package manager. + +Bitnami charts can be used with [Kubeapps](https://kubeapps.dev/) for deployment and management of Helm Charts in clusters. + +Looking to use our applications in production? Try [VMware Application Catalog](https://bitnami.com/enterprise), the enterprise edition of Bitnami Application Catalog. + +## Prerequisites + +- Kubernetes 1.23+ +- Helm 3.8.0+ + +## Parameters + +## Special input schemas + +### ImageRoot + +```yaml +registry: + type: string + description: Docker registry where the image is located + example: docker.io + +repository: + type: string + description: Repository and image name + example: bitnami/nginx + +tag: + type: string + description: image tag + example: 1.16.1-debian-10-r63 + +pullPolicy: + type: string + description: Specify a imagePullPolicy. Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent' + +pullSecrets: + type: array + items: + type: string + description: Optionally specify an array of imagePullSecrets (evaluated as templates). + +debug: + type: boolean + description: Set to true if you would like to see extra information on logs + example: false + +## An instance would be: +# registry: docker.io +# repository: bitnami/nginx +# tag: 1.16.1-debian-10-r63 +# pullPolicy: IfNotPresent +# debug: false +``` + +### Persistence + +```yaml +enabled: + type: boolean + description: Whether enable persistence. + example: true + +storageClass: + type: string + description: Ghost data Persistent Volume Storage Class, If set to "-", storageClassName: "" which disables dynamic provisioning. + example: "-" + +accessMode: + type: string + description: Access mode for the Persistent Volume Storage. + example: ReadWriteOnce + +size: + type: string + description: Size the Persistent Volume Storage. + example: 8Gi + +path: + type: string + description: Path to be persisted. + example: /bitnami + +## An instance would be: +# enabled: true +# storageClass: "-" +# accessMode: ReadWriteOnce +# size: 8Gi +# path: /bitnami +``` + +### ExistingSecret + +```yaml +name: + type: string + description: Name of the existing secret. + example: mySecret +keyMapping: + description: Mapping between the expected key name and the name of the key in the existing secret. + type: object + +## An instance would be: +# name: mySecret +# keyMapping: +# password: myPasswordKey +``` + +#### Example of use + +When we store sensitive data for a deployment in a secret, some times we want to give to users the possibility of using theirs existing secrets. + +```yaml +# templates/secret.yaml +--- +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "common.names.fullname" . }} + labels: + app: {{ include "common.names.fullname" . }} +type: Opaque +data: + password: {{ .Values.password | b64enc | quote }} + +# templates/dpl.yaml +--- +... + env: + - name: PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "common.secrets.name" (dict "existingSecret" .Values.existingSecret "context" $) }} + key: {{ include "common.secrets.key" (dict "existingSecret" .Values.existingSecret "key" "password") }} +... + +# values.yaml +--- +name: mySecret +keyMapping: + password: myPasswordKey +``` + +### ValidateValue + +#### NOTES.txt + +```console +{{- $validateValueConf00 := (dict "valueKey" "path.to.value00" "secret" "secretName" "field" "password-00") -}} +{{- $validateValueConf01 := (dict "valueKey" "path.to.value01" "secret" "secretName" "field" "password-01") -}} + +{{ include "common.validations.values.multiple.empty" (dict "required" (list $validateValueConf00 $validateValueConf01) "context" $) }} +``` + +If we force those values to be empty we will see some alerts + +```console +helm install test mychart --set path.to.value00="",path.to.value01="" + 'path.to.value00' must not be empty, please add '--set path.to.value00=$PASSWORD_00' to the command. To get the current value: + + export PASSWORD_00=$(kubectl get secret --namespace default secretName -o jsonpath="{.data.password-00}" | base64 -d) + + 'path.to.value01' must not be empty, please add '--set path.to.value01=$PASSWORD_01' to the command. To get the current value: + + export PASSWORD_01=$(kubectl get secret --namespace default secretName -o jsonpath="{.data.password-01}" | base64 -d) +``` + +## Upgrading + +### To 1.0.0 + +[On November 13, 2020, Helm v2 support was formally finished](https://github.com/helm/charts#status-of-the-project), this major version is the result of the required changes applied to the Helm Chart to be able to incorporate the different features added in Helm v3 and to be consistent with the Helm project itself regarding the Helm v2 EOL. + +#### What changes were introduced in this major version? + +- Previous versions of this Helm Chart use `apiVersion: v1` (installable by both Helm 2 and 3), this Helm Chart was updated to `apiVersion: v2` (installable by Helm 3 only). [Here](https://helm.sh/docs/topics/charts/#the-apiversion-field) you can find more information about the `apiVersion` field. +- Use `type: library`. [Here](https://v3.helm.sh/docs/faq/#library-chart-support) you can find more information. +- The different fields present in the *Chart.yaml* file has been ordered alphabetically in a homogeneous way for all the Bitnami Helm Charts + +#### Considerations when upgrading to this version + +- If you want to upgrade to this version from a previous one installed with Helm v3, you shouldn't face any issues +- If you want to upgrade to this version using Helm v2, this scenario is not supported as this version doesn't support Helm v2 anymore +- If you installed the previous version with Helm v2 and wants to upgrade to this version with Helm v3, please refer to the [official Helm documentation](https://helm.sh/docs/topics/v2_v3_migration/#migration-use-cases) about migrating from Helm v2 to v3 + +#### Useful links + +- +- +- + +## License + +Copyright © 2023 VMware, Inc. + +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 + + + +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/packages/system/dashboard/charts/kubeapps/charts/common/templates/_affinities.tpl b/packages/system/dashboard/charts/kubeapps/charts/common/templates/_affinities.tpl new file mode 100644 index 00000000..e85b1df4 --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/charts/common/templates/_affinities.tpl @@ -0,0 +1,139 @@ +{{/* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Return a soft nodeAffinity definition +{{ include "common.affinities.nodes.soft" (dict "key" "FOO" "values" (list "BAR" "BAZ")) -}} +*/}} +{{- define "common.affinities.nodes.soft" -}} +preferredDuringSchedulingIgnoredDuringExecution: + - preference: + matchExpressions: + - key: {{ .key }} + operator: In + values: + {{- range .values }} + - {{ . | quote }} + {{- end }} + weight: 1 +{{- end -}} + +{{/* +Return a hard nodeAffinity definition +{{ include "common.affinities.nodes.hard" (dict "key" "FOO" "values" (list "BAR" "BAZ")) -}} +*/}} +{{- define "common.affinities.nodes.hard" -}} +requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: {{ .key }} + operator: In + values: + {{- range .values }} + - {{ . | quote }} + {{- end }} +{{- end -}} + +{{/* +Return a nodeAffinity definition +{{ include "common.affinities.nodes" (dict "type" "soft" "key" "FOO" "values" (list "BAR" "BAZ")) -}} +*/}} +{{- define "common.affinities.nodes" -}} + {{- if eq .type "soft" }} + {{- include "common.affinities.nodes.soft" . -}} + {{- else if eq .type "hard" }} + {{- include "common.affinities.nodes.hard" . -}} + {{- end -}} +{{- end -}} + +{{/* +Return a topologyKey definition +{{ include "common.affinities.topologyKey" (dict "topologyKey" "BAR") -}} +*/}} +{{- define "common.affinities.topologyKey" -}} +{{ .topologyKey | default "kubernetes.io/hostname" -}} +{{- end -}} + +{{/* +Return a soft podAffinity/podAntiAffinity definition +{{ include "common.affinities.pods.soft" (dict "component" "FOO" "customLabels" .Values.podLabels "extraMatchLabels" .Values.extraMatchLabels "topologyKey" "BAR" "extraPodAffinityTerms" .Values.extraPodAffinityTerms "context" $) -}} +*/}} +{{- define "common.affinities.pods.soft" -}} +{{- $component := default "" .component -}} +{{- $customLabels := default (dict) .customLabels -}} +{{- $extraMatchLabels := default (dict) .extraMatchLabels -}} +{{- $extraPodAffinityTerms := default (list) .extraPodAffinityTerms -}} +preferredDuringSchedulingIgnoredDuringExecution: + - podAffinityTerm: + labelSelector: + matchLabels: {{- (include "common.labels.matchLabels" ( dict "customLabels" $customLabels "context" .context )) | nindent 10 }} + {{- if not (empty $component) }} + {{ printf "app.kubernetes.io/component: %s" $component }} + {{- end }} + {{- range $key, $value := $extraMatchLabels }} + {{ $key }}: {{ $value | quote }} + {{- end }} + topologyKey: {{ include "common.affinities.topologyKey" (dict "topologyKey" .topologyKey) }} + weight: 1 + {{- range $extraPodAffinityTerms }} + - podAffinityTerm: + labelSelector: + matchLabels: {{- (include "common.labels.matchLabels" ( dict "customLabels" $customLabels "context" $.context )) | nindent 10 }} + {{- if not (empty $component) }} + {{ printf "app.kubernetes.io/component: %s" $component }} + {{- end }} + {{- range $key, $value := .extraMatchLabels }} + {{ $key }}: {{ $value | quote }} + {{- end }} + topologyKey: {{ include "common.affinities.topologyKey" (dict "topologyKey" .topologyKey) }} + weight: {{ .weight | default 1 -}} + {{- end -}} +{{- end -}} + +{{/* +Return a hard podAffinity/podAntiAffinity definition +{{ include "common.affinities.pods.hard" (dict "component" "FOO" "customLabels" .Values.podLabels "extraMatchLabels" .Values.extraMatchLabels "topologyKey" "BAR" "extraPodAffinityTerms" .Values.extraPodAffinityTerms "context" $) -}} +*/}} +{{- define "common.affinities.pods.hard" -}} +{{- $component := default "" .component -}} +{{- $customLabels := default (dict) .customLabels -}} +{{- $extraMatchLabels := default (dict) .extraMatchLabels -}} +{{- $extraPodAffinityTerms := default (list) .extraPodAffinityTerms -}} +requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchLabels: {{- (include "common.labels.matchLabels" ( dict "customLabels" $customLabels "context" .context )) | nindent 8 }} + {{- if not (empty $component) }} + {{ printf "app.kubernetes.io/component: %s" $component }} + {{- end }} + {{- range $key, $value := $extraMatchLabels }} + {{ $key }}: {{ $value | quote }} + {{- end }} + topologyKey: {{ include "common.affinities.topologyKey" (dict "topologyKey" .topologyKey) }} + {{- range $extraPodAffinityTerms }} + - labelSelector: + matchLabels: {{- (include "common.labels.matchLabels" ( dict "customLabels" $customLabels "context" $.context )) | nindent 8 }} + {{- if not (empty $component) }} + {{ printf "app.kubernetes.io/component: %s" $component }} + {{- end }} + {{- range $key, $value := .extraMatchLabels }} + {{ $key }}: {{ $value | quote }} + {{- end }} + topologyKey: {{ include "common.affinities.topologyKey" (dict "topologyKey" .topologyKey) }} + {{- end -}} +{{- end -}} + +{{/* +Return a podAffinity/podAntiAffinity definition +{{ include "common.affinities.pods" (dict "type" "soft" "key" "FOO" "values" (list "BAR" "BAZ")) -}} +*/}} +{{- define "common.affinities.pods" -}} + {{- if eq .type "soft" }} + {{- include "common.affinities.pods.soft" . -}} + {{- else if eq .type "hard" }} + {{- include "common.affinities.pods.hard" . -}} + {{- end -}} +{{- end -}} diff --git a/packages/system/dashboard/charts/kubeapps/charts/common/templates/_capabilities.tpl b/packages/system/dashboard/charts/kubeapps/charts/common/templates/_capabilities.tpl new file mode 100644 index 00000000..115674af --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/charts/common/templates/_capabilities.tpl @@ -0,0 +1,229 @@ +{{/* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Return the target Kubernetes version +*/}} +{{- define "common.capabilities.kubeVersion" -}} +{{- if .Values.global }} + {{- if .Values.global.kubeVersion }} + {{- .Values.global.kubeVersion -}} + {{- else }} + {{- default .Capabilities.KubeVersion.Version .Values.kubeVersion -}} + {{- end -}} +{{- else }} +{{- default .Capabilities.KubeVersion.Version .Values.kubeVersion -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for poddisruptionbudget. +*/}} +{{- define "common.capabilities.policy.apiVersion" -}} +{{- if semverCompare "<1.21-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "policy/v1beta1" -}} +{{- else -}} +{{- print "policy/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for networkpolicy. +*/}} +{{- define "common.capabilities.networkPolicy.apiVersion" -}} +{{- if semverCompare "<1.7-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "extensions/v1beta1" -}} +{{- else -}} +{{- print "networking.k8s.io/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for cronjob. +*/}} +{{- define "common.capabilities.cronjob.apiVersion" -}} +{{- if semverCompare "<1.21-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "batch/v1beta1" -}} +{{- else -}} +{{- print "batch/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for daemonset. +*/}} +{{- define "common.capabilities.daemonset.apiVersion" -}} +{{- if semverCompare "<1.14-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "extensions/v1beta1" -}} +{{- else -}} +{{- print "apps/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for deployment. +*/}} +{{- define "common.capabilities.deployment.apiVersion" -}} +{{- if semverCompare "<1.14-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "extensions/v1beta1" -}} +{{- else -}} +{{- print "apps/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for statefulset. +*/}} +{{- define "common.capabilities.statefulset.apiVersion" -}} +{{- if semverCompare "<1.14-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "apps/v1beta1" -}} +{{- else -}} +{{- print "apps/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for ingress. +*/}} +{{- define "common.capabilities.ingress.apiVersion" -}} +{{- if .Values.ingress -}} +{{- if .Values.ingress.apiVersion -}} +{{- .Values.ingress.apiVersion -}} +{{- else if semverCompare "<1.14-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "extensions/v1beta1" -}} +{{- else if semverCompare "<1.19-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "networking.k8s.io/v1beta1" -}} +{{- else -}} +{{- print "networking.k8s.io/v1" -}} +{{- end }} +{{- else if semverCompare "<1.14-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "extensions/v1beta1" -}} +{{- else if semverCompare "<1.19-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "networking.k8s.io/v1beta1" -}} +{{- else -}} +{{- print "networking.k8s.io/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for RBAC resources. +*/}} +{{- define "common.capabilities.rbac.apiVersion" -}} +{{- if semverCompare "<1.17-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "rbac.authorization.k8s.io/v1beta1" -}} +{{- else -}} +{{- print "rbac.authorization.k8s.io/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for CRDs. +*/}} +{{- define "common.capabilities.crd.apiVersion" -}} +{{- if semverCompare "<1.19-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "apiextensions.k8s.io/v1beta1" -}} +{{- else -}} +{{- print "apiextensions.k8s.io/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for APIService. +*/}} +{{- define "common.capabilities.apiService.apiVersion" -}} +{{- if semverCompare "<1.10-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "apiregistration.k8s.io/v1beta1" -}} +{{- else -}} +{{- print "apiregistration.k8s.io/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for Horizontal Pod Autoscaler. +*/}} +{{- define "common.capabilities.hpa.apiVersion" -}} +{{- if semverCompare "<1.23-0" (include "common.capabilities.kubeVersion" .context) -}} +{{- if .beta2 -}} +{{- print "autoscaling/v2beta2" -}} +{{- else -}} +{{- print "autoscaling/v2beta1" -}} +{{- end -}} +{{- else -}} +{{- print "autoscaling/v2" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for Vertical Pod Autoscaler. +*/}} +{{- define "common.capabilities.vpa.apiVersion" -}} +{{- if semverCompare "<1.23-0" (include "common.capabilities.kubeVersion" .context) -}} +{{- if .beta2 -}} +{{- print "autoscaling/v2beta2" -}} +{{- else -}} +{{- print "autoscaling/v2beta1" -}} +{{- end -}} +{{- else -}} +{{- print "autoscaling/v2" -}} +{{- end -}} +{{- end -}} + +{{/* +Returns true if PodSecurityPolicy is supported +*/}} +{{- define "common.capabilities.psp.supported" -}} +{{- if semverCompare "<1.25-0" (include "common.capabilities.kubeVersion" .) -}} + {{- true -}} +{{- end -}} +{{- end -}} + +{{/* +Returns true if AdmissionConfiguration is supported +*/}} +{{- define "common.capabilities.admissionConfiguration.supported" -}} +{{- if semverCompare ">=1.23-0" (include "common.capabilities.kubeVersion" .) -}} + {{- true -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for AdmissionConfiguration. +*/}} +{{- define "common.capabilities.admissionConfiguration.apiVersion" -}} +{{- if semverCompare "<1.23-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "apiserver.config.k8s.io/v1alpha1" -}} +{{- else if semverCompare "<1.25-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "apiserver.config.k8s.io/v1beta1" -}} +{{- else -}} +{{- print "apiserver.config.k8s.io/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for PodSecurityConfiguration. +*/}} +{{- define "common.capabilities.podSecurityConfiguration.apiVersion" -}} +{{- if semverCompare "<1.23-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "pod-security.admission.config.k8s.io/v1alpha1" -}} +{{- else if semverCompare "<1.25-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "pod-security.admission.config.k8s.io/v1beta1" -}} +{{- else -}} +{{- print "pod-security.admission.config.k8s.io/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Returns true if the used Helm version is 3.3+. +A way to check the used Helm version was not introduced until version 3.3.0 with .Capabilities.HelmVersion, which contains an additional "{}}" structure. +This check is introduced as a regexMatch instead of {{ if .Capabilities.HelmVersion }} because checking for the key HelmVersion in <3.3 results in a "interface not found" error. +**To be removed when the catalog's minimun Helm version is 3.3** +*/}} +{{- define "common.capabilities.supportsHelmVersion" -}} +{{- if regexMatch "{(v[0-9])*[^}]*}}$" (.Capabilities | toString ) }} + {{- true -}} +{{- end -}} +{{- end -}} diff --git a/packages/system/dashboard/charts/kubeapps/charts/common/templates/_errors.tpl b/packages/system/dashboard/charts/kubeapps/charts/common/templates/_errors.tpl new file mode 100644 index 00000000..07ded6f6 --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/charts/common/templates/_errors.tpl @@ -0,0 +1,28 @@ +{{/* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Through error when upgrading using empty passwords values that must not be empty. + +Usage: +{{- $validationError00 := include "common.validations.values.single.empty" (dict "valueKey" "path.to.password00" "secret" "secretName" "field" "password-00") -}} +{{- $validationError01 := include "common.validations.values.single.empty" (dict "valueKey" "path.to.password01" "secret" "secretName" "field" "password-01") -}} +{{ include "common.errors.upgrade.passwords.empty" (dict "validationErrors" (list $validationError00 $validationError01) "context" $) }} + +Required password params: + - validationErrors - String - Required. List of validation strings to be return, if it is empty it won't throw error. + - context - Context - Required. Parent context. +*/}} +{{- define "common.errors.upgrade.passwords.empty" -}} + {{- $validationErrors := join "" .validationErrors -}} + {{- if and $validationErrors .context.Release.IsUpgrade -}} + {{- $errorString := "\nPASSWORDS ERROR: You must provide your current passwords when upgrading the release." -}} + {{- $errorString = print $errorString "\n Note that even after reinstallation, old credentials may be needed as they may be kept in persistent volume claims." -}} + {{- $errorString = print $errorString "\n Further information can be obtained at https://docs.bitnami.com/general/how-to/troubleshoot-helm-chart-issues/#credential-errors-while-upgrading-chart-releases" -}} + {{- $errorString = print $errorString "\n%s" -}} + {{- printf $errorString $validationErrors | fail -}} + {{- end -}} +{{- end -}} diff --git a/packages/system/dashboard/charts/kubeapps/charts/common/templates/_images.tpl b/packages/system/dashboard/charts/kubeapps/charts/common/templates/_images.tpl new file mode 100644 index 00000000..1bcb779d --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/charts/common/templates/_images.tpl @@ -0,0 +1,117 @@ +{{/* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Return the proper image name +{{ include "common.images.image" ( dict "imageRoot" .Values.path.to.the.image "global" .Values.global ) }} +*/}} +{{- define "common.images.image" -}} +{{- $registryName := .imageRoot.registry -}} +{{- $repositoryName := .imageRoot.repository -}} +{{- $separator := ":" -}} +{{- $termination := .imageRoot.tag | toString -}} +{{- if .global }} + {{- if .global.imageRegistry }} + {{- $registryName = .global.imageRegistry -}} + {{- end -}} +{{- end -}} +{{- if .imageRoot.digest }} + {{- $separator = "@" -}} + {{- $termination = .imageRoot.digest | toString -}} +{{- end -}} +{{- if $registryName }} + {{- printf "%s/%s%s%s" $registryName $repositoryName $separator $termination -}} +{{- else -}} + {{- printf "%s%s%s" $repositoryName $separator $termination -}} +{{- end -}} +{{- end -}} + +{{/* +Return the proper Docker Image Registry Secret Names (deprecated: use common.images.renderPullSecrets instead) +{{ include "common.images.pullSecrets" ( dict "images" (list .Values.path.to.the.image1, .Values.path.to.the.image2) "global" .Values.global) }} +*/}} +{{- define "common.images.pullSecrets" -}} + {{- $pullSecrets := list }} + + {{- if .global }} + {{- range .global.imagePullSecrets -}} + {{- if kindIs "map" . -}} + {{- $pullSecrets = append $pullSecrets .name -}} + {{- else -}} + {{- $pullSecrets = append $pullSecrets . -}} + {{- end }} + {{- end -}} + {{- end -}} + + {{- range .images -}} + {{- range .pullSecrets -}} + {{- if kindIs "map" . -}} + {{- $pullSecrets = append $pullSecrets .name -}} + {{- else -}} + {{- $pullSecrets = append $pullSecrets . -}} + {{- end -}} + {{- end -}} + {{- end -}} + + {{- if (not (empty $pullSecrets)) }} +imagePullSecrets: + {{- range $pullSecrets | uniq }} + - name: {{ . }} + {{- end }} + {{- end }} +{{- end -}} + +{{/* +Return the proper Docker Image Registry Secret Names evaluating values as templates +{{ include "common.images.renderPullSecrets" ( dict "images" (list .Values.path.to.the.image1, .Values.path.to.the.image2) "context" $) }} +*/}} +{{- define "common.images.renderPullSecrets" -}} + {{- $pullSecrets := list }} + {{- $context := .context }} + + {{- if $context.Values.global }} + {{- range $context.Values.global.imagePullSecrets -}} + {{- if kindIs "map" . -}} + {{- $pullSecrets = append $pullSecrets (include "common.tplvalues.render" (dict "value" .name "context" $context)) -}} + {{- else -}} + {{- $pullSecrets = append $pullSecrets (include "common.tplvalues.render" (dict "value" . "context" $context)) -}} + {{- end -}} + {{- end -}} + {{- end -}} + + {{- range .images -}} + {{- range .pullSecrets -}} + {{- if kindIs "map" . -}} + {{- $pullSecrets = append $pullSecrets (include "common.tplvalues.render" (dict "value" .name "context" $context)) -}} + {{- else -}} + {{- $pullSecrets = append $pullSecrets (include "common.tplvalues.render" (dict "value" . "context" $context)) -}} + {{- end -}} + {{- end -}} + {{- end -}} + + {{- if (not (empty $pullSecrets)) }} +imagePullSecrets: + {{- range $pullSecrets | uniq }} + - name: {{ . }} + {{- end }} + {{- end }} +{{- end -}} + +{{/* +Return the proper image version (ingores image revision/prerelease info & fallbacks to chart appVersion) +{{ include "common.images.version" ( dict "imageRoot" .Values.path.to.the.image "chart" .Chart ) }} +*/}} +{{- define "common.images.version" -}} +{{- $imageTag := .imageRoot.tag | toString -}} +{{/* regexp from https://github.com/Masterminds/semver/blob/23f51de38a0866c5ef0bfc42b3f735c73107b700/version.go#L41-L44 */}} +{{- if regexMatch `^([0-9]+)(\.[0-9]+)?(\.[0-9]+)?(-([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?(\+([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?$` $imageTag -}} + {{- $version := semver $imageTag -}} + {{- printf "%d.%d.%d" $version.Major $version.Minor $version.Patch -}} +{{- else -}} + {{- print .chart.AppVersion -}} +{{- end -}} +{{- end -}} + diff --git a/packages/system/dashboard/charts/kubeapps/charts/common/templates/_ingress.tpl b/packages/system/dashboard/charts/kubeapps/charts/common/templates/_ingress.tpl new file mode 100644 index 00000000..efa5b85c --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/charts/common/templates/_ingress.tpl @@ -0,0 +1,73 @@ +{{/* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Generate backend entry that is compatible with all Kubernetes API versions. + +Usage: +{{ include "common.ingress.backend" (dict "serviceName" "backendName" "servicePort" "backendPort" "context" $) }} + +Params: + - serviceName - String. Name of an existing service backend + - servicePort - String/Int. Port name (or number) of the service. It will be translated to different yaml depending if it is a string or an integer. + - context - Dict - Required. The context for the template evaluation. +*/}} +{{- define "common.ingress.backend" -}} +{{- $apiVersion := (include "common.capabilities.ingress.apiVersion" .context) -}} +{{- if or (eq $apiVersion "extensions/v1beta1") (eq $apiVersion "networking.k8s.io/v1beta1") -}} +serviceName: {{ .serviceName }} +servicePort: {{ .servicePort }} +{{- else -}} +service: + name: {{ .serviceName }} + port: + {{- if typeIs "string" .servicePort }} + name: {{ .servicePort }} + {{- else if or (typeIs "int" .servicePort) (typeIs "float64" .servicePort) }} + number: {{ .servicePort | int }} + {{- end }} +{{- end -}} +{{- end -}} + +{{/* +Print "true" if the API pathType field is supported +Usage: +{{ include "common.ingress.supportsPathType" . }} +*/}} +{{- define "common.ingress.supportsPathType" -}} +{{- if (semverCompare "<1.18-0" (include "common.capabilities.kubeVersion" .)) -}} +{{- print "false" -}} +{{- else -}} +{{- print "true" -}} +{{- end -}} +{{- end -}} + +{{/* +Returns true if the ingressClassname field is supported +Usage: +{{ include "common.ingress.supportsIngressClassname" . }} +*/}} +{{- define "common.ingress.supportsIngressClassname" -}} +{{- if semverCompare "<1.18-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "false" -}} +{{- else -}} +{{- print "true" -}} +{{- end -}} +{{- end -}} + +{{/* +Return true if cert-manager required annotations for TLS signed +certificates are set in the Ingress annotations +Ref: https://cert-manager.io/docs/usage/ingress/#supported-annotations +Usage: +{{ include "common.ingress.certManagerRequest" ( dict "annotations" .Values.path.to.the.ingress.annotations ) }} +*/}} +{{- define "common.ingress.certManagerRequest" -}} +{{ if or (hasKey .annotations "cert-manager.io/cluster-issuer") (hasKey .annotations "cert-manager.io/issuer") (hasKey .annotations "kubernetes.io/tls-acme") }} + {{- true -}} +{{- end -}} +{{- end -}} diff --git a/packages/system/dashboard/charts/kubeapps/charts/common/templates/_labels.tpl b/packages/system/dashboard/charts/kubeapps/charts/common/templates/_labels.tpl new file mode 100644 index 00000000..d90a6cdc --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/charts/common/templates/_labels.tpl @@ -0,0 +1,46 @@ +{{/* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Kubernetes standard labels +{{ include "common.labels.standard" (dict "customLabels" .Values.commonLabels "context" $) -}} +*/}} +{{- define "common.labels.standard" -}} +{{- if and (hasKey . "customLabels") (hasKey . "context") -}} +{{- $default := dict "app.kubernetes.io/name" (include "common.names.name" .context) "helm.sh/chart" (include "common.names.chart" .context) "app.kubernetes.io/instance" .context.Release.Name "app.kubernetes.io/managed-by" .context.Release.Service -}} +{{- with .context.Chart.AppVersion -}} +{{- $_ := set $default "app.kubernetes.io/version" . -}} +{{- end -}} +{{ template "common.tplvalues.merge" (dict "values" (list .customLabels $default) "context" .context) }} +{{- else -}} +app.kubernetes.io/name: {{ include "common.names.name" . }} +helm.sh/chart: {{ include "common.names.chart" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- with .Chart.AppVersion }} +app.kubernetes.io/version: {{ . | quote }} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Labels used on immutable fields such as deploy.spec.selector.matchLabels or svc.spec.selector +{{ include "common.labels.matchLabels" (dict "customLabels" .Values.podLabels "context" $) -}} + +We don't want to loop over custom labels appending them to the selector +since it's very likely that it will break deployments, services, etc. +However, it's important to overwrite the standard labels if the user +overwrote them on metadata.labels fields. +*/}} +{{- define "common.labels.matchLabels" -}} +{{- if and (hasKey . "customLabels") (hasKey . "context") -}} +{{ merge (pick (include "common.tplvalues.render" (dict "value" .customLabels "context" .context) | fromYaml) "app.kubernetes.io/name" "app.kubernetes.io/instance") (dict "app.kubernetes.io/name" (include "common.names.name" .context) "app.kubernetes.io/instance" .context.Release.Name ) | toYaml }} +{{- else -}} +app.kubernetes.io/name: {{ include "common.names.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end -}} +{{- end -}} diff --git a/packages/system/dashboard/charts/kubeapps/charts/common/templates/_names.tpl b/packages/system/dashboard/charts/kubeapps/charts/common/templates/_names.tpl new file mode 100644 index 00000000..a222924f --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/charts/common/templates/_names.tpl @@ -0,0 +1,71 @@ +{{/* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "common.names.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "common.names.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | 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 "common.names.fullname" -}} +{{- if .Values.fullnameOverride -}} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- if contains $name .Release.Name -}} +{{- .Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Create a default fully qualified dependency 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. +Usage: +{{ include "common.names.dependency.fullname" (dict "chartName" "dependency-chart-name" "chartValues" .Values.dependency-chart "context" $) }} +*/}} +{{- define "common.names.dependency.fullname" -}} +{{- if .chartValues.fullnameOverride -}} +{{- .chartValues.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .chartName .chartValues.nameOverride -}} +{{- if contains $name .context.Release.Name -}} +{{- .context.Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" .context.Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Allow the release namespace to be overridden for multi-namespace deployments in combined charts. +*/}} +{{- define "common.names.namespace" -}} +{{- default .Release.Namespace .Values.namespaceOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a fully qualified app name adding the installation's namespace. +*/}} +{{- define "common.names.fullname.namespace" -}} +{{- printf "%s-%s" (include "common.names.fullname" .) (include "common.names.namespace" .) | trunc 63 | trimSuffix "-" -}} +{{- end -}} diff --git a/packages/system/dashboard/charts/kubeapps/charts/common/templates/_secrets.tpl b/packages/system/dashboard/charts/kubeapps/charts/common/templates/_secrets.tpl new file mode 100644 index 00000000..a193c46b --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/charts/common/templates/_secrets.tpl @@ -0,0 +1,172 @@ +{{/* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Generate secret name. + +Usage: +{{ include "common.secrets.name" (dict "existingSecret" .Values.path.to.the.existingSecret "defaultNameSuffix" "mySuffix" "context" $) }} + +Params: + - existingSecret - ExistingSecret/String - Optional. The path to the existing secrets in the values.yaml given by the user + to be used instead of the default one. Allows for it to be of type String (just the secret name) for backwards compatibility. + +info: https://github.com/bitnami/charts/tree/main/bitnami/common#existingsecret + - defaultNameSuffix - String - Optional. It is used only if we have several secrets in the same deployment. + - context - Dict - Required. The context for the template evaluation. +*/}} +{{- define "common.secrets.name" -}} +{{- $name := (include "common.names.fullname" .context) -}} + +{{- if .defaultNameSuffix -}} +{{- $name = printf "%s-%s" $name .defaultNameSuffix | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{- with .existingSecret -}} +{{- if not (typeIs "string" .) -}} +{{- with .name -}} +{{- $name = . -}} +{{- end -}} +{{- else -}} +{{- $name = . -}} +{{- end -}} +{{- end -}} + +{{- printf "%s" $name -}} +{{- end -}} + +{{/* +Generate secret key. + +Usage: +{{ include "common.secrets.key" (dict "existingSecret" .Values.path.to.the.existingSecret "key" "keyName") }} + +Params: + - existingSecret - ExistingSecret/String - Optional. The path to the existing secrets in the values.yaml given by the user + to be used instead of the default one. Allows for it to be of type String (just the secret name) for backwards compatibility. + +info: https://github.com/bitnami/charts/tree/main/bitnami/common#existingsecret + - key - String - Required. Name of the key in the secret. +*/}} +{{- define "common.secrets.key" -}} +{{- $key := .key -}} + +{{- if .existingSecret -}} + {{- if not (typeIs "string" .existingSecret) -}} + {{- if .existingSecret.keyMapping -}} + {{- $key = index .existingSecret.keyMapping $.key -}} + {{- end -}} + {{- end }} +{{- end -}} + +{{- printf "%s" $key -}} +{{- end -}} + +{{/* +Generate secret password or retrieve one if already created. + +Usage: +{{ include "common.secrets.passwords.manage" (dict "secret" "secret-name" "key" "keyName" "providedValues" (list "path.to.password1" "path.to.password2") "length" 10 "strong" false "chartName" "chartName" "context" $) }} + +Params: + - secret - String - Required - Name of the 'Secret' resource where the password is stored. + - key - String - Required - Name of the key in the secret. + - providedValues - List - Required - The path to the validating value in the values.yaml, e.g: "mysql.password". Will pick first parameter with a defined value. + - length - int - Optional - Length of the generated random password. + - strong - Boolean - Optional - Whether to add symbols to the generated random password. + - chartName - String - Optional - Name of the chart used when said chart is deployed as a subchart. + - context - Context - Required - Parent context. + - failOnNew - Boolean - Optional - Default to true. If set to false, skip errors adding new keys to existing secrets. +The order in which this function returns a secret password: + 1. Already existing 'Secret' resource + (If a 'Secret' resource is found under the name provided to the 'secret' parameter to this function and that 'Secret' resource contains a key with the name passed as the 'key' parameter to this function then the value of this existing secret password will be returned) + 2. Password provided via the values.yaml + (If one of the keys passed to the 'providedValues' parameter to this function is a valid path to a key in the values.yaml and has a value, the value of the first key with a value will be returned) + 3. Randomly generated secret password + (A new random secret password with the length specified in the 'length' parameter will be generated and returned) + +*/}} +{{- define "common.secrets.passwords.manage" -}} + +{{- $password := "" }} +{{- $subchart := "" }} +{{- $failOnNew := default true .failOnNew }} +{{- $chartName := default "" .chartName }} +{{- $passwordLength := default 10 .length }} +{{- $providedPasswordKey := include "common.utils.getKeyFromList" (dict "keys" .providedValues "context" $.context) }} +{{- $providedPasswordValue := include "common.utils.getValueFromKey" (dict "key" $providedPasswordKey "context" $.context) }} +{{- $secretData := (lookup "v1" "Secret" (include "common.names.namespace" .context) .secret).data }} +{{- if $secretData }} + {{- if hasKey $secretData .key }} + {{- $password = index $secretData .key | quote }} + {{- else if $failOnNew }} + {{- printf "\nPASSWORDS ERROR: The secret \"%s\" does not contain the key \"%s\"\n" .secret .key | fail -}} + {{- end -}} +{{- else if $providedPasswordValue }} + {{- $password = $providedPasswordValue | toString | b64enc | quote }} +{{- else }} + + {{- if .context.Values.enabled }} + {{- $subchart = $chartName }} + {{- end -}} + + {{- $requiredPassword := dict "valueKey" $providedPasswordKey "secret" .secret "field" .key "subchart" $subchart "context" $.context -}} + {{- $requiredPasswordError := include "common.validations.values.single.empty" $requiredPassword -}} + {{- $passwordValidationErrors := list $requiredPasswordError -}} + {{- include "common.errors.upgrade.passwords.empty" (dict "validationErrors" $passwordValidationErrors "context" $.context) -}} + + {{- if .strong }} + {{- $subStr := list (lower (randAlpha 1)) (randNumeric 1) (upper (randAlpha 1)) | join "_" }} + {{- $password = randAscii $passwordLength }} + {{- $password = regexReplaceAllLiteral "\\W" $password "@" | substr 5 $passwordLength }} + {{- $password = printf "%s%s" $subStr $password | toString | shuffle | b64enc | quote }} + {{- else }} + {{- $password = randAlphaNum $passwordLength | b64enc | quote }} + {{- end }} +{{- end -}} +{{- printf "%s" $password -}} +{{- end -}} + +{{/* +Reuses the value from an existing secret, otherwise sets its value to a default value. + +Usage: +{{ include "common.secrets.lookup" (dict "secret" "secret-name" "key" "keyName" "defaultValue" .Values.myValue "context" $) }} + +Params: + - secret - String - Required - Name of the 'Secret' resource where the password is stored. + - key - String - Required - Name of the key in the secret. + - defaultValue - String - Required - The path to the validating value in the values.yaml, e.g: "mysql.password". Will pick first parameter with a defined value. + - context - Context - Required - Parent context. + +*/}} +{{- define "common.secrets.lookup" -}} +{{- $value := "" -}} +{{- $secretData := (lookup "v1" "Secret" (include "common.names.namespace" .context) .secret).data -}} +{{- if and $secretData (hasKey $secretData .key) -}} + {{- $value = index $secretData .key -}} +{{- else if .defaultValue -}} + {{- $value = .defaultValue | toString | b64enc -}} +{{- end -}} +{{- if $value -}} +{{- printf "%s" $value -}} +{{- end -}} +{{- end -}} + +{{/* +Returns whether a previous generated secret already exists + +Usage: +{{ include "common.secrets.exists" (dict "secret" "secret-name" "context" $) }} + +Params: + - secret - String - Required - Name of the 'Secret' resource where the password is stored. + - context - Context - Required - Parent context. +*/}} +{{- define "common.secrets.exists" -}} +{{- $secret := (lookup "v1" "Secret" (include "common.names.namespace" .context) .secret) }} +{{- if $secret }} + {{- true -}} +{{- end -}} +{{- end -}} diff --git a/packages/system/dashboard/charts/kubeapps/charts/common/templates/_storage.tpl b/packages/system/dashboard/charts/kubeapps/charts/common/templates/_storage.tpl new file mode 100644 index 00000000..16405a0f --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/charts/common/templates/_storage.tpl @@ -0,0 +1,28 @@ +{{/* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Return the proper Storage Class +{{ include "common.storage.class" ( dict "persistence" .Values.path.to.the.persistence "global" $) }} +*/}} +{{- define "common.storage.class" -}} + +{{- $storageClass := .persistence.storageClass -}} +{{- if .global -}} + {{- if .global.storageClass -}} + {{- $storageClass = .global.storageClass -}} + {{- end -}} +{{- end -}} + +{{- if $storageClass -}} + {{- if (eq "-" $storageClass) -}} + {{- printf "storageClassName: \"\"" -}} + {{- else }} + {{- printf "storageClassName: %s" $storageClass -}} + {{- end -}} +{{- end -}} + +{{- end -}} diff --git a/packages/system/dashboard/charts/kubeapps/charts/common/templates/_tplvalues.tpl b/packages/system/dashboard/charts/kubeapps/charts/common/templates/_tplvalues.tpl new file mode 100644 index 00000000..a8ed7637 --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/charts/common/templates/_tplvalues.tpl @@ -0,0 +1,38 @@ +{{/* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Renders a value that contains template perhaps with scope if the scope is present. +Usage: +{{ include "common.tplvalues.render" ( dict "value" .Values.path.to.the.Value "context" $ ) }} +{{ include "common.tplvalues.render" ( dict "value" .Values.path.to.the.Value "context" $ "scope" $app ) }} +*/}} +{{- define "common.tplvalues.render" -}} +{{- $value := typeIs "string" .value | ternary .value (.value | toYaml) }} +{{- if contains "{{" (toJson .value) }} + {{- if .scope }} + {{- tpl (cat "{{- with $.RelativeScope -}}" $value "{{- end }}") (merge (dict "RelativeScope" .scope) .context) }} + {{- else }} + {{- tpl $value .context }} + {{- end }} +{{- else }} + {{- $value }} +{{- end }} +{{- end -}} + +{{/* +Merge a list of values that contains template after rendering them. +Merge precedence is consistent with http://masterminds.github.io/sprig/dicts.html#merge-mustmerge +Usage: +{{ include "common.tplvalues.merge" ( dict "values" (list .Values.path.to.the.Value1 .Values.path.to.the.Value2) "context" $ ) }} +*/}} +{{- define "common.tplvalues.merge" -}} +{{- $dst := dict -}} +{{- range .values -}} +{{- $dst = include "common.tplvalues.render" (dict "value" . "context" $.context "scope" $.scope) | fromYaml | merge $dst -}} +{{- end -}} +{{ $dst | toYaml }} +{{- end -}} diff --git a/packages/system/dashboard/charts/kubeapps/charts/common/templates/_utils.tpl b/packages/system/dashboard/charts/kubeapps/charts/common/templates/_utils.tpl new file mode 100644 index 00000000..bfbddf05 --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/charts/common/templates/_utils.tpl @@ -0,0 +1,77 @@ +{{/* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Print instructions to get a secret value. +Usage: +{{ include "common.utils.secret.getvalue" (dict "secret" "secret-name" "field" "secret-value-field" "context" $) }} +*/}} +{{- define "common.utils.secret.getvalue" -}} +{{- $varname := include "common.utils.fieldToEnvVar" . -}} +export {{ $varname }}=$(kubectl get secret --namespace {{ include "common.names.namespace" .context | quote }} {{ .secret }} -o jsonpath="{.data.{{ .field }}}" | base64 -d) +{{- end -}} + +{{/* +Build env var name given a field +Usage: +{{ include "common.utils.fieldToEnvVar" dict "field" "my-password" }} +*/}} +{{- define "common.utils.fieldToEnvVar" -}} + {{- $fieldNameSplit := splitList "-" .field -}} + {{- $upperCaseFieldNameSplit := list -}} + + {{- range $fieldNameSplit -}} + {{- $upperCaseFieldNameSplit = append $upperCaseFieldNameSplit ( upper . ) -}} + {{- end -}} + + {{ join "_" $upperCaseFieldNameSplit }} +{{- end -}} + +{{/* +Gets a value from .Values given +Usage: +{{ include "common.utils.getValueFromKey" (dict "key" "path.to.key" "context" $) }} +*/}} +{{- define "common.utils.getValueFromKey" -}} +{{- $splitKey := splitList "." .key -}} +{{- $value := "" -}} +{{- $latestObj := $.context.Values -}} +{{- range $splitKey -}} + {{- if not $latestObj -}} + {{- printf "please review the entire path of '%s' exists in values" $.key | fail -}} + {{- end -}} + {{- $value = ( index $latestObj . ) -}} + {{- $latestObj = $value -}} +{{- end -}} +{{- printf "%v" (default "" $value) -}} +{{- end -}} + +{{/* +Returns first .Values key with a defined value or first of the list if all non-defined +Usage: +{{ include "common.utils.getKeyFromList" (dict "keys" (list "path.to.key1" "path.to.key2") "context" $) }} +*/}} +{{- define "common.utils.getKeyFromList" -}} +{{- $key := first .keys -}} +{{- $reverseKeys := reverse .keys }} +{{- range $reverseKeys }} + {{- $value := include "common.utils.getValueFromKey" (dict "key" . "context" $.context ) }} + {{- if $value -}} + {{- $key = . }} + {{- end -}} +{{- end -}} +{{- printf "%s" $key -}} +{{- end -}} + +{{/* +Checksum a template at "path" containing a *single* resource (ConfigMap,Secret) for use in pod annotations, excluding the metadata (see #18376). +Usage: +{{ include "common.utils.checksumTemplate" (dict "path" "/configmap.yaml" "context" $) }} +*/}} +{{- define "common.utils.checksumTemplate" -}} +{{- $obj := include (print .context.Template.BasePath .path) .context | fromYaml -}} +{{ omit $obj "apiVersion" "kind" "metadata" | toYaml | sha256sum }} +{{- end -}} diff --git a/packages/system/dashboard/charts/kubeapps/charts/common/templates/_warnings.tpl b/packages/system/dashboard/charts/kubeapps/charts/common/templates/_warnings.tpl new file mode 100644 index 00000000..66dffc1f --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/charts/common/templates/_warnings.tpl @@ -0,0 +1,19 @@ +{{/* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Warning about using rolling tag. +Usage: +{{ include "common.warnings.rollingTag" .Values.path.to.the.imageRoot }} +*/}} +{{- define "common.warnings.rollingTag" -}} + +{{- if and (contains "bitnami/" .repository) (not (.tag | toString | regexFind "-r\\d+$|sha256:")) }} +WARNING: Rolling tag detected ({{ .repository }}:{{ .tag }}), please note that it is strongly recommended to avoid using rolling tags in a production environment. ++info https://docs.bitnami.com/containers/how-to/understand-rolling-tags-containers/ +{{- end }} + +{{- end -}} diff --git a/packages/system/dashboard/charts/kubeapps/charts/common/templates/validations/_cassandra.tpl b/packages/system/dashboard/charts/kubeapps/charts/common/templates/validations/_cassandra.tpl new file mode 100644 index 00000000..eda9aada --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/charts/common/templates/validations/_cassandra.tpl @@ -0,0 +1,77 @@ +{{/* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Validate Cassandra required passwords are not empty. + +Usage: +{{ include "common.validations.values.cassandra.passwords" (dict "secret" "secretName" "subchart" false "context" $) }} +Params: + - secret - String - Required. Name of the secret where Cassandra values are stored, e.g: "cassandra-passwords-secret" + - subchart - Boolean - Optional. Whether Cassandra is used as subchart or not. Default: false +*/}} +{{- define "common.validations.values.cassandra.passwords" -}} + {{- $existingSecret := include "common.cassandra.values.existingSecret" . -}} + {{- $enabled := include "common.cassandra.values.enabled" . -}} + {{- $dbUserPrefix := include "common.cassandra.values.key.dbUser" . -}} + {{- $valueKeyPassword := printf "%s.password" $dbUserPrefix -}} + + {{- if and (or (not $existingSecret) (eq $existingSecret "\"\"")) (eq $enabled "true") -}} + {{- $requiredPasswords := list -}} + + {{- $requiredPassword := dict "valueKey" $valueKeyPassword "secret" .secret "field" "cassandra-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredPassword -}} + + {{- include "common.validations.values.multiple.empty" (dict "required" $requiredPasswords "context" .context) -}} + + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for existingSecret. + +Usage: +{{ include "common.cassandra.values.existingSecret" (dict "context" $) }} +Params: + - subchart - Boolean - Optional. Whether Cassandra is used as subchart or not. Default: false +*/}} +{{- define "common.cassandra.values.existingSecret" -}} + {{- if .subchart -}} + {{- .context.Values.cassandra.dbUser.existingSecret | quote -}} + {{- else -}} + {{- .context.Values.dbUser.existingSecret | quote -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled cassandra. + +Usage: +{{ include "common.cassandra.values.enabled" (dict "context" $) }} +*/}} +{{- define "common.cassandra.values.enabled" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.cassandra.enabled -}} + {{- else -}} + {{- printf "%v" (not .context.Values.enabled) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for the key dbUser + +Usage: +{{ include "common.cassandra.values.key.dbUser" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether Cassandra is used as subchart or not. Default: false +*/}} +{{- define "common.cassandra.values.key.dbUser" -}} + {{- if .subchart -}} + cassandra.dbUser + {{- else -}} + dbUser + {{- end -}} +{{- end -}} diff --git a/packages/system/dashboard/charts/kubeapps/charts/common/templates/validations/_mariadb.tpl b/packages/system/dashboard/charts/kubeapps/charts/common/templates/validations/_mariadb.tpl new file mode 100644 index 00000000..17d83a2f --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/charts/common/templates/validations/_mariadb.tpl @@ -0,0 +1,108 @@ +{{/* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Validate MariaDB required passwords are not empty. + +Usage: +{{ include "common.validations.values.mariadb.passwords" (dict "secret" "secretName" "subchart" false "context" $) }} +Params: + - secret - String - Required. Name of the secret where MariaDB values are stored, e.g: "mysql-passwords-secret" + - subchart - Boolean - Optional. Whether MariaDB is used as subchart or not. Default: false +*/}} +{{- define "common.validations.values.mariadb.passwords" -}} + {{- $existingSecret := include "common.mariadb.values.auth.existingSecret" . -}} + {{- $enabled := include "common.mariadb.values.enabled" . -}} + {{- $architecture := include "common.mariadb.values.architecture" . -}} + {{- $authPrefix := include "common.mariadb.values.key.auth" . -}} + {{- $valueKeyRootPassword := printf "%s.rootPassword" $authPrefix -}} + {{- $valueKeyUsername := printf "%s.username" $authPrefix -}} + {{- $valueKeyPassword := printf "%s.password" $authPrefix -}} + {{- $valueKeyReplicationPassword := printf "%s.replicationPassword" $authPrefix -}} + + {{- if and (or (not $existingSecret) (eq $existingSecret "\"\"")) (eq $enabled "true") -}} + {{- $requiredPasswords := list -}} + + {{- $requiredRootPassword := dict "valueKey" $valueKeyRootPassword "secret" .secret "field" "mariadb-root-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredRootPassword -}} + + {{- $valueUsername := include "common.utils.getValueFromKey" (dict "key" $valueKeyUsername "context" .context) }} + {{- if not (empty $valueUsername) -}} + {{- $requiredPassword := dict "valueKey" $valueKeyPassword "secret" .secret "field" "mariadb-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredPassword -}} + {{- end -}} + + {{- if (eq $architecture "replication") -}} + {{- $requiredReplicationPassword := dict "valueKey" $valueKeyReplicationPassword "secret" .secret "field" "mariadb-replication-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredReplicationPassword -}} + {{- end -}} + + {{- include "common.validations.values.multiple.empty" (dict "required" $requiredPasswords "context" .context) -}} + + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for existingSecret. + +Usage: +{{ include "common.mariadb.values.auth.existingSecret" (dict "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MariaDB is used as subchart or not. Default: false +*/}} +{{- define "common.mariadb.values.auth.existingSecret" -}} + {{- if .subchart -}} + {{- .context.Values.mariadb.auth.existingSecret | quote -}} + {{- else -}} + {{- .context.Values.auth.existingSecret | quote -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled mariadb. + +Usage: +{{ include "common.mariadb.values.enabled" (dict "context" $) }} +*/}} +{{- define "common.mariadb.values.enabled" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.mariadb.enabled -}} + {{- else -}} + {{- printf "%v" (not .context.Values.enabled) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for architecture + +Usage: +{{ include "common.mariadb.values.architecture" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MariaDB is used as subchart or not. Default: false +*/}} +{{- define "common.mariadb.values.architecture" -}} + {{- if .subchart -}} + {{- .context.Values.mariadb.architecture -}} + {{- else -}} + {{- .context.Values.architecture -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for the key auth + +Usage: +{{ include "common.mariadb.values.key.auth" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MariaDB is used as subchart or not. Default: false +*/}} +{{- define "common.mariadb.values.key.auth" -}} + {{- if .subchart -}} + mariadb.auth + {{- else -}} + auth + {{- end -}} +{{- end -}} diff --git a/packages/system/dashboard/charts/kubeapps/charts/common/templates/validations/_mongodb.tpl b/packages/system/dashboard/charts/kubeapps/charts/common/templates/validations/_mongodb.tpl new file mode 100644 index 00000000..bbb445b8 --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/charts/common/templates/validations/_mongodb.tpl @@ -0,0 +1,113 @@ +{{/* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Validate MongoDB® required passwords are not empty. + +Usage: +{{ include "common.validations.values.mongodb.passwords" (dict "secret" "secretName" "subchart" false "context" $) }} +Params: + - secret - String - Required. Name of the secret where MongoDB® values are stored, e.g: "mongodb-passwords-secret" + - subchart - Boolean - Optional. Whether MongoDB® is used as subchart or not. Default: false +*/}} +{{- define "common.validations.values.mongodb.passwords" -}} + {{- $existingSecret := include "common.mongodb.values.auth.existingSecret" . -}} + {{- $enabled := include "common.mongodb.values.enabled" . -}} + {{- $authPrefix := include "common.mongodb.values.key.auth" . -}} + {{- $architecture := include "common.mongodb.values.architecture" . -}} + {{- $valueKeyRootPassword := printf "%s.rootPassword" $authPrefix -}} + {{- $valueKeyUsername := printf "%s.username" $authPrefix -}} + {{- $valueKeyDatabase := printf "%s.database" $authPrefix -}} + {{- $valueKeyPassword := printf "%s.password" $authPrefix -}} + {{- $valueKeyReplicaSetKey := printf "%s.replicaSetKey" $authPrefix -}} + {{- $valueKeyAuthEnabled := printf "%s.enabled" $authPrefix -}} + + {{- $authEnabled := include "common.utils.getValueFromKey" (dict "key" $valueKeyAuthEnabled "context" .context) -}} + + {{- if and (or (not $existingSecret) (eq $existingSecret "\"\"")) (eq $enabled "true") (eq $authEnabled "true") -}} + {{- $requiredPasswords := list -}} + + {{- $requiredRootPassword := dict "valueKey" $valueKeyRootPassword "secret" .secret "field" "mongodb-root-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredRootPassword -}} + + {{- $valueUsername := include "common.utils.getValueFromKey" (dict "key" $valueKeyUsername "context" .context) }} + {{- $valueDatabase := include "common.utils.getValueFromKey" (dict "key" $valueKeyDatabase "context" .context) }} + {{- if and $valueUsername $valueDatabase -}} + {{- $requiredPassword := dict "valueKey" $valueKeyPassword "secret" .secret "field" "mongodb-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredPassword -}} + {{- end -}} + + {{- if (eq $architecture "replicaset") -}} + {{- $requiredReplicaSetKey := dict "valueKey" $valueKeyReplicaSetKey "secret" .secret "field" "mongodb-replica-set-key" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredReplicaSetKey -}} + {{- end -}} + + {{- include "common.validations.values.multiple.empty" (dict "required" $requiredPasswords "context" .context) -}} + + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for existingSecret. + +Usage: +{{ include "common.mongodb.values.auth.existingSecret" (dict "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MongoDb is used as subchart or not. Default: false +*/}} +{{- define "common.mongodb.values.auth.existingSecret" -}} + {{- if .subchart -}} + {{- .context.Values.mongodb.auth.existingSecret | quote -}} + {{- else -}} + {{- .context.Values.auth.existingSecret | quote -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled mongodb. + +Usage: +{{ include "common.mongodb.values.enabled" (dict "context" $) }} +*/}} +{{- define "common.mongodb.values.enabled" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.mongodb.enabled -}} + {{- else -}} + {{- printf "%v" (not .context.Values.enabled) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for the key auth + +Usage: +{{ include "common.mongodb.values.key.auth" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MongoDB® is used as subchart or not. Default: false +*/}} +{{- define "common.mongodb.values.key.auth" -}} + {{- if .subchart -}} + mongodb.auth + {{- else -}} + auth + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for architecture + +Usage: +{{ include "common.mongodb.values.architecture" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MongoDB® is used as subchart or not. Default: false +*/}} +{{- define "common.mongodb.values.architecture" -}} + {{- if .subchart -}} + {{- .context.Values.mongodb.architecture -}} + {{- else -}} + {{- .context.Values.architecture -}} + {{- end -}} +{{- end -}} diff --git a/packages/system/dashboard/charts/kubeapps/charts/common/templates/validations/_mysql.tpl b/packages/system/dashboard/charts/kubeapps/charts/common/templates/validations/_mysql.tpl new file mode 100644 index 00000000..ca3953f8 --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/charts/common/templates/validations/_mysql.tpl @@ -0,0 +1,108 @@ +{{/* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Validate MySQL required passwords are not empty. + +Usage: +{{ include "common.validations.values.mysql.passwords" (dict "secret" "secretName" "subchart" false "context" $) }} +Params: + - secret - String - Required. Name of the secret where MySQL values are stored, e.g: "mysql-passwords-secret" + - subchart - Boolean - Optional. Whether MySQL is used as subchart or not. Default: false +*/}} +{{- define "common.validations.values.mysql.passwords" -}} + {{- $existingSecret := include "common.mysql.values.auth.existingSecret" . -}} + {{- $enabled := include "common.mysql.values.enabled" . -}} + {{- $architecture := include "common.mysql.values.architecture" . -}} + {{- $authPrefix := include "common.mysql.values.key.auth" . -}} + {{- $valueKeyRootPassword := printf "%s.rootPassword" $authPrefix -}} + {{- $valueKeyUsername := printf "%s.username" $authPrefix -}} + {{- $valueKeyPassword := printf "%s.password" $authPrefix -}} + {{- $valueKeyReplicationPassword := printf "%s.replicationPassword" $authPrefix -}} + + {{- if and (or (not $existingSecret) (eq $existingSecret "\"\"")) (eq $enabled "true") -}} + {{- $requiredPasswords := list -}} + + {{- $requiredRootPassword := dict "valueKey" $valueKeyRootPassword "secret" .secret "field" "mysql-root-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredRootPassword -}} + + {{- $valueUsername := include "common.utils.getValueFromKey" (dict "key" $valueKeyUsername "context" .context) }} + {{- if not (empty $valueUsername) -}} + {{- $requiredPassword := dict "valueKey" $valueKeyPassword "secret" .secret "field" "mysql-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredPassword -}} + {{- end -}} + + {{- if (eq $architecture "replication") -}} + {{- $requiredReplicationPassword := dict "valueKey" $valueKeyReplicationPassword "secret" .secret "field" "mysql-replication-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredReplicationPassword -}} + {{- end -}} + + {{- include "common.validations.values.multiple.empty" (dict "required" $requiredPasswords "context" .context) -}} + + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for existingSecret. + +Usage: +{{ include "common.mysql.values.auth.existingSecret" (dict "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MySQL is used as subchart or not. Default: false +*/}} +{{- define "common.mysql.values.auth.existingSecret" -}} + {{- if .subchart -}} + {{- .context.Values.mysql.auth.existingSecret | quote -}} + {{- else -}} + {{- .context.Values.auth.existingSecret | quote -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled mysql. + +Usage: +{{ include "common.mysql.values.enabled" (dict "context" $) }} +*/}} +{{- define "common.mysql.values.enabled" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.mysql.enabled -}} + {{- else -}} + {{- printf "%v" (not .context.Values.enabled) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for architecture + +Usage: +{{ include "common.mysql.values.architecture" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MySQL is used as subchart or not. Default: false +*/}} +{{- define "common.mysql.values.architecture" -}} + {{- if .subchart -}} + {{- .context.Values.mysql.architecture -}} + {{- else -}} + {{- .context.Values.architecture -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for the key auth + +Usage: +{{ include "common.mysql.values.key.auth" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MySQL is used as subchart or not. Default: false +*/}} +{{- define "common.mysql.values.key.auth" -}} + {{- if .subchart -}} + mysql.auth + {{- else -}} + auth + {{- end -}} +{{- end -}} diff --git a/packages/system/dashboard/charts/kubeapps/charts/common/templates/validations/_postgresql.tpl b/packages/system/dashboard/charts/kubeapps/charts/common/templates/validations/_postgresql.tpl new file mode 100644 index 00000000..8c9aa570 --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/charts/common/templates/validations/_postgresql.tpl @@ -0,0 +1,134 @@ +{{/* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Validate PostgreSQL required passwords are not empty. + +Usage: +{{ include "common.validations.values.postgresql.passwords" (dict "secret" "secretName" "subchart" false "context" $) }} +Params: + - secret - String - Required. Name of the secret where postgresql values are stored, e.g: "postgresql-passwords-secret" + - subchart - Boolean - Optional. Whether postgresql is used as subchart or not. Default: false +*/}} +{{- define "common.validations.values.postgresql.passwords" -}} + {{- $existingSecret := include "common.postgresql.values.existingSecret" . -}} + {{- $enabled := include "common.postgresql.values.enabled" . -}} + {{- $valueKeyPostgresqlPassword := include "common.postgresql.values.key.postgressPassword" . -}} + {{- $valueKeyPostgresqlReplicationEnabled := include "common.postgresql.values.key.replicationPassword" . -}} + {{- if and (or (not $existingSecret) (eq $existingSecret "\"\"")) (eq $enabled "true") -}} + {{- $requiredPasswords := list -}} + {{- $requiredPostgresqlPassword := dict "valueKey" $valueKeyPostgresqlPassword "secret" .secret "field" "postgresql-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredPostgresqlPassword -}} + + {{- $enabledReplication := include "common.postgresql.values.enabled.replication" . -}} + {{- if (eq $enabledReplication "true") -}} + {{- $requiredPostgresqlReplicationPassword := dict "valueKey" $valueKeyPostgresqlReplicationEnabled "secret" .secret "field" "postgresql-replication-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredPostgresqlReplicationPassword -}} + {{- end -}} + + {{- include "common.validations.values.multiple.empty" (dict "required" $requiredPasswords "context" .context) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to decide whether evaluate global values. + +Usage: +{{ include "common.postgresql.values.use.global" (dict "key" "key-of-global" "context" $) }} +Params: + - key - String - Required. Field to be evaluated within global, e.g: "existingSecret" +*/}} +{{- define "common.postgresql.values.use.global" -}} + {{- if .context.Values.global -}} + {{- if .context.Values.global.postgresql -}} + {{- index .context.Values.global.postgresql .key | quote -}} + {{- end -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for existingSecret. + +Usage: +{{ include "common.postgresql.values.existingSecret" (dict "context" $) }} +*/}} +{{- define "common.postgresql.values.existingSecret" -}} + {{- $globalValue := include "common.postgresql.values.use.global" (dict "key" "existingSecret" "context" .context) -}} + + {{- if .subchart -}} + {{- default (.context.Values.postgresql.existingSecret | quote) $globalValue -}} + {{- else -}} + {{- default (.context.Values.existingSecret | quote) $globalValue -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled postgresql. + +Usage: +{{ include "common.postgresql.values.enabled" (dict "context" $) }} +*/}} +{{- define "common.postgresql.values.enabled" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.postgresql.enabled -}} + {{- else -}} + {{- printf "%v" (not .context.Values.enabled) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for the key postgressPassword. + +Usage: +{{ include "common.postgresql.values.key.postgressPassword" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether postgresql is used as subchart or not. Default: false +*/}} +{{- define "common.postgresql.values.key.postgressPassword" -}} + {{- $globalValue := include "common.postgresql.values.use.global" (dict "key" "postgresqlUsername" "context" .context) -}} + + {{- if not $globalValue -}} + {{- if .subchart -}} + postgresql.postgresqlPassword + {{- else -}} + postgresqlPassword + {{- end -}} + {{- else -}} + global.postgresql.postgresqlPassword + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled.replication. + +Usage: +{{ include "common.postgresql.values.enabled.replication" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether postgresql is used as subchart or not. Default: false +*/}} +{{- define "common.postgresql.values.enabled.replication" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.postgresql.replication.enabled -}} + {{- else -}} + {{- printf "%v" .context.Values.replication.enabled -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for the key replication.password. + +Usage: +{{ include "common.postgresql.values.key.replicationPassword" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether postgresql is used as subchart or not. Default: false +*/}} +{{- define "common.postgresql.values.key.replicationPassword" -}} + {{- if .subchart -}} + postgresql.replication.password + {{- else -}} + replication.password + {{- end -}} +{{- end -}} diff --git a/packages/system/dashboard/charts/kubeapps/charts/common/templates/validations/_redis.tpl b/packages/system/dashboard/charts/kubeapps/charts/common/templates/validations/_redis.tpl new file mode 100644 index 00000000..fc0d208d --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/charts/common/templates/validations/_redis.tpl @@ -0,0 +1,81 @@ +{{/* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + + +{{/* vim: set filetype=mustache: */}} +{{/* +Validate Redis® required passwords are not empty. + +Usage: +{{ include "common.validations.values.redis.passwords" (dict "secret" "secretName" "subchart" false "context" $) }} +Params: + - secret - String - Required. Name of the secret where redis values are stored, e.g: "redis-passwords-secret" + - subchart - Boolean - Optional. Whether redis is used as subchart or not. Default: false +*/}} +{{- define "common.validations.values.redis.passwords" -}} + {{- $enabled := include "common.redis.values.enabled" . -}} + {{- $valueKeyPrefix := include "common.redis.values.keys.prefix" . -}} + {{- $standarizedVersion := include "common.redis.values.standarized.version" . }} + + {{- $existingSecret := ternary (printf "%s%s" $valueKeyPrefix "auth.existingSecret") (printf "%s%s" $valueKeyPrefix "existingSecret") (eq $standarizedVersion "true") }} + {{- $existingSecretValue := include "common.utils.getValueFromKey" (dict "key" $existingSecret "context" .context) }} + + {{- $valueKeyRedisPassword := ternary (printf "%s%s" $valueKeyPrefix "auth.password") (printf "%s%s" $valueKeyPrefix "password") (eq $standarizedVersion "true") }} + {{- $valueKeyRedisUseAuth := ternary (printf "%s%s" $valueKeyPrefix "auth.enabled") (printf "%s%s" $valueKeyPrefix "usePassword") (eq $standarizedVersion "true") }} + + {{- if and (or (not $existingSecret) (eq $existingSecret "\"\"")) (eq $enabled "true") -}} + {{- $requiredPasswords := list -}} + + {{- $useAuth := include "common.utils.getValueFromKey" (dict "key" $valueKeyRedisUseAuth "context" .context) -}} + {{- if eq $useAuth "true" -}} + {{- $requiredRedisPassword := dict "valueKey" $valueKeyRedisPassword "secret" .secret "field" "redis-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredRedisPassword -}} + {{- end -}} + + {{- include "common.validations.values.multiple.empty" (dict "required" $requiredPasswords "context" .context) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled redis. + +Usage: +{{ include "common.redis.values.enabled" (dict "context" $) }} +*/}} +{{- define "common.redis.values.enabled" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.redis.enabled -}} + {{- else -}} + {{- printf "%v" (not .context.Values.enabled) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right prefix path for the values + +Usage: +{{ include "common.redis.values.key.prefix" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether redis is used as subchart or not. Default: false +*/}} +{{- define "common.redis.values.keys.prefix" -}} + {{- if .subchart -}}redis.{{- else -}}{{- end -}} +{{- end -}} + +{{/* +Checks whether the redis chart's includes the standarizations (version >= 14) + +Usage: +{{ include "common.redis.values.standarized.version" (dict "context" $) }} +*/}} +{{- define "common.redis.values.standarized.version" -}} + + {{- $standarizedAuth := printf "%s%s" (include "common.redis.values.keys.prefix" .) "auth" -}} + {{- $standarizedAuthValues := include "common.utils.getValueFromKey" (dict "key" $standarizedAuth "context" .context) }} + + {{- if $standarizedAuthValues -}} + {{- true -}} + {{- end -}} +{{- end -}} diff --git a/packages/system/dashboard/charts/kubeapps/charts/common/templates/validations/_validations.tpl b/packages/system/dashboard/charts/kubeapps/charts/common/templates/validations/_validations.tpl new file mode 100644 index 00000000..31ceda87 --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/charts/common/templates/validations/_validations.tpl @@ -0,0 +1,51 @@ +{{/* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Validate values must not be empty. + +Usage: +{{- $validateValueConf00 := (dict "valueKey" "path.to.value" "secret" "secretName" "field" "password-00") -}} +{{- $validateValueConf01 := (dict "valueKey" "path.to.value" "secret" "secretName" "field" "password-01") -}} +{{ include "common.validations.values.empty" (dict "required" (list $validateValueConf00 $validateValueConf01) "context" $) }} + +Validate value params: + - valueKey - String - Required. The path to the validating value in the values.yaml, e.g: "mysql.password" + - secret - String - Optional. Name of the secret where the validating value is generated/stored, e.g: "mysql-passwords-secret" + - field - String - Optional. Name of the field in the secret data, e.g: "mysql-password" +*/}} +{{- define "common.validations.values.multiple.empty" -}} + {{- range .required -}} + {{- include "common.validations.values.single.empty" (dict "valueKey" .valueKey "secret" .secret "field" .field "context" $.context) -}} + {{- end -}} +{{- end -}} + +{{/* +Validate a value must not be empty. + +Usage: +{{ include "common.validations.value.empty" (dict "valueKey" "mariadb.password" "secret" "secretName" "field" "my-password" "subchart" "subchart" "context" $) }} + +Validate value params: + - valueKey - String - Required. The path to the validating value in the values.yaml, e.g: "mysql.password" + - secret - String - Optional. Name of the secret where the validating value is generated/stored, e.g: "mysql-passwords-secret" + - field - String - Optional. Name of the field in the secret data, e.g: "mysql-password" + - subchart - String - Optional - Name of the subchart that the validated password is part of. +*/}} +{{- define "common.validations.values.single.empty" -}} + {{- $value := include "common.utils.getValueFromKey" (dict "key" .valueKey "context" .context) }} + {{- $subchart := ternary "" (printf "%s." .subchart) (empty .subchart) }} + + {{- if not $value -}} + {{- $varname := "my-value" -}} + {{- $getCurrentValue := "" -}} + {{- if and .secret .field -}} + {{- $varname = include "common.utils.fieldToEnvVar" . -}} + {{- $getCurrentValue = printf " To get the current value:\n\n %s\n" (include "common.utils.secret.getvalue" .) -}} + {{- end -}} + {{- printf "\n '%s' must not be empty, please add '--set %s%s=$%s' to the command.%s" .valueKey $subchart .valueKey $varname $getCurrentValue -}} + {{- end -}} +{{- end -}} diff --git a/packages/system/dashboard/charts/kubeapps/charts/common/values.yaml b/packages/system/dashboard/charts/kubeapps/charts/common/values.yaml new file mode 100644 index 00000000..9abe0e15 --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/charts/common/values.yaml @@ -0,0 +1,8 @@ +# Copyright VMware, Inc. +# SPDX-License-Identifier: APACHE-2.0 + +## bitnami/common +## It is required by CI/CD tools and processes. +## @skip exampleValue +## +exampleValue: common-chart diff --git a/packages/system/dashboard/charts/kubeapps/charts/redis/.helmignore b/packages/system/dashboard/charts/kubeapps/charts/redis/.helmignore new file mode 100644 index 00000000..f0c13194 --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/charts/redis/.helmignore @@ -0,0 +1,21 @@ +# 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 +*~ +# Various IDEs +.project +.idea/ +*.tmproj diff --git a/packages/system/dashboard/charts/kubeapps/charts/redis/Chart.lock b/packages/system/dashboard/charts/kubeapps/charts/redis/Chart.lock new file mode 100644 index 00000000..694a2da7 --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/charts/redis/Chart.lock @@ -0,0 +1,6 @@ +dependencies: +- name: common + repository: oci://registry-1.docker.io/bitnamicharts + version: 2.13.3 +digest: sha256:9a971689db0c66ea95ac2e911c05014c2b96c6077c991131ff84f2982f88fb83 +generated: "2023-10-19T12:32:36.790999138Z" diff --git a/packages/system/dashboard/charts/kubeapps/charts/redis/Chart.yaml b/packages/system/dashboard/charts/kubeapps/charts/redis/Chart.yaml new file mode 100644 index 00000000..0aa1bc3c --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/charts/redis/Chart.yaml @@ -0,0 +1,36 @@ +annotations: + category: Database + images: | + - name: os-shell + image: docker.io/bitnami/os-shell:11-debian-11-r91 + - name: redis-exporter + image: docker.io/bitnami/redis-exporter:1.55.0-debian-11-r2 + - name: redis-sentinel + image: docker.io/bitnami/redis-sentinel:7.2.3-debian-11-r1 + - name: redis + image: docker.io/bitnami/redis:7.2.3-debian-11-r1 + licenses: Apache-2.0 +apiVersion: v2 +appVersion: 7.2.3 +dependencies: +- name: common + repository: oci://registry-1.docker.io/bitnamicharts + tags: + - bitnami-common + version: 2.x.x +description: Redis(R) is an open source, advanced key-value store. It is often referred + to as a data structure server since keys can contain strings, hashes, lists, sets + and sorted sets. +home: https://bitnami.com +icon: https://bitnami.com/assets/stacks/redis/img/redis-stack-220x234.png +keywords: +- redis +- keyvalue +- database +maintainers: +- name: VMware, Inc. + url: https://github.com/bitnami/charts +name: redis +sources: +- https://github.com/bitnami/charts/tree/main/bitnami/redis +version: 18.4.0 diff --git a/packages/system/dashboard/charts/kubeapps/charts/redis/README.md b/packages/system/dashboard/charts/kubeapps/charts/redis/README.md new file mode 100644 index 00000000..6305aaf8 --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/charts/redis/README.md @@ -0,0 +1,1019 @@ + + +# Bitnami package for Redis(R) + +Redis(R) is an open source, advanced key-value store. It is often referred to as a data structure server since keys can contain strings, hashes, lists, sets and sorted sets. + +[Overview of Redis®](http://redis.io) + +Disclaimer: Redis is a registered trademark of Redis Ltd. Any rights therein are reserved to Redis Ltd. Any use by Bitnami is for referential purposes only and does not indicate any sponsorship, endorsement, or affiliation between Redis Ltd. + +## TL;DR + +```console +helm install my-release oci://REGISTRY_NAME/REPOSITORY_NAME/redis +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. + +## Introduction + +This chart bootstraps a [Redis®](https://github.com/bitnami/containers/tree/main/bitnami/redis) deployment on a [Kubernetes](https://kubernetes.io) cluster using the [Helm](https://helm.sh) package manager. + +Bitnami charts can be used with [Kubeapps](https://kubeapps.dev/) for deployment and management of Helm Charts in clusters. + +### Choose between Redis® Helm Chart and Redis® Cluster Helm Chart + +You can choose any of the two Redis® Helm charts for deploying a Redis® cluster. + +1. [Redis® Helm Chart](https://github.com/bitnami/charts/tree/main/bitnami/redis) will deploy a master-replica cluster, with the [option](https://github.com/bitnami/charts/tree/main/bitnami/redis#redis-sentinel-configuration-parameters) of enabling using Redis® Sentinel. +2. [Redis® Cluster Helm Chart](https://github.com/bitnami/charts/tree/main/bitnami/redis-cluster) will deploy a Redis® Cluster topology with sharding. + +The main features of each chart are the following: + +| Redis® | Redis® Cluster | +|--------------------------------------------------------|------------------------------------------------------------------------| +| Supports multiple databases | Supports only one database. Better if you have a big dataset | +| Single write point (single master) | Multiple write points (multiple masters) | +| ![Redis® Topology](img/redis-topology.png) | ![Redis® Cluster Topology](img/redis-cluster-topology.png) | + +Looking to use Redisreg; in production? Try [VMware Tanzu Application Catalog](https://bitnami.com/enterprise), the enterprise edition of Bitnami Application Catalog. + +## Prerequisites + +- Kubernetes 1.23+ +- Helm 3.8.0+ +- PV provisioner support in the underlying infrastructure + +## Installing the Chart + +To install the chart with the release name `my-release`: + +```console +helm install my-release oci://REGISTRY_NAME/REPOSITORY_NAME/redis +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. + +The command deploys Redis® on the Kubernetes cluster in the default configuration. The [Parameters](#parameters) section lists the parameters that can be configured during installation. + +> **Tip**: List all releases using `helm list` + +## Uninstalling the Chart + +To uninstall/delete the `my-release` deployment: + +```console +helm delete my-release +``` + +The command removes all the Kubernetes components associated with the chart and deletes the release. + +## Parameters + +### Global parameters + +| Name | Description | Value | +| ------------------------- | ------------------------------------------------------ | ----- | +| `global.imageRegistry` | Global Docker image registry | `""` | +| `global.imagePullSecrets` | Global Docker registry secret names as an array | `[]` | +| `global.storageClass` | Global StorageClass for Persistent Volume(s) | `""` | +| `global.redis.password` | Global Redis® password (overrides `auth.password`) | `""` | + +### Common parameters + +| Name | Description | Value | +| ------------------------- | -------------------------------------------------------------------------------------------------------------- | --------------- | +| `kubeVersion` | Override Kubernetes version | `""` | +| `nameOverride` | String to partially override common.names.fullname | `""` | +| `fullnameOverride` | String to fully override common.names.fullname | `""` | +| `commonLabels` | Labels to add to all deployed objects | `{}` | +| `commonAnnotations` | Annotations to add to all deployed objects | `{}` | +| `secretAnnotations` | Annotations to add to secret | `{}` | +| `clusterDomain` | Kubernetes cluster domain name | `cluster.local` | +| `extraDeploy` | Array of extra objects to deploy with the release | `[]` | +| `useHostnames` | Use hostnames internally when announcing replication. If false, the hostname will be resolved to an IP address | `true` | +| `nameResolutionThreshold` | Failure threshold for internal hostnames resolution | `5` | +| `nameResolutionTimeout` | Timeout seconds between probes for internal hostnames resolution | `5` | +| `diagnosticMode.enabled` | Enable diagnostic mode (all probes will be disabled and the command will be overridden) | `false` | +| `diagnosticMode.command` | Command to override all containers in the deployment | `["sleep"]` | +| `diagnosticMode.args` | Args to override all containers in the deployment | `["infinity"]` | + +### Redis® Image parameters + +| Name | Description | Value | +| ------------------- | ---------------------------------------------------------------------------------------------------------- | ----------------------- | +| `image.registry` | Redis® image registry | `REGISTRY_NAME` | +| `image.repository` | Redis® image repository | `REPOSITORY_NAME/redis` | +| `image.digest` | Redis® image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag | `""` | +| `image.pullPolicy` | Redis® image pull policy | `IfNotPresent` | +| `image.pullSecrets` | Redis® image pull secrets | `[]` | +| `image.debug` | Enable image debug mode | `false` | + +### Redis® common configuration parameters + +| Name | Description | Value | +| -------------------------------- | ------------------------------------------------------------------------------------- | ------------- | +| `architecture` | Redis® architecture. Allowed values: `standalone` or `replication` | `replication` | +| `auth.enabled` | Enable password authentication | `true` | +| `auth.sentinel` | Enable password authentication on sentinels too | `true` | +| `auth.password` | Redis® password | `""` | +| `auth.existingSecret` | The name of an existing secret with Redis® credentials | `""` | +| `auth.existingSecretPasswordKey` | Password key to be retrieved from existing secret | `""` | +| `auth.usePasswordFiles` | Mount credentials as files instead of using an environment variable | `false` | +| `commonConfiguration` | Common configuration to be added into the ConfigMap | `""` | +| `existingConfigmap` | The name of an existing ConfigMap with your custom configuration for Redis® nodes | `""` | + +### Redis® master configuration parameters + +| Name | Description | Value | +| ---------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | ------------------------ | +| `master.count` | Number of Redis® master instances to deploy (experimental, requires additional configuration) | `1` | +| `master.configuration` | Configuration for Redis® master nodes | `""` | +| `master.disableCommands` | Array with Redis® commands to disable on master nodes | `["FLUSHDB","FLUSHALL"]` | +| `master.command` | Override default container command (useful when using custom images) | `[]` | +| `master.args` | Override default container args (useful when using custom images) | `[]` | +| `master.enableServiceLinks` | Whether information about services should be injected into pod's environment variable | `true` | +| `master.preExecCmds` | Additional commands to run prior to starting Redis® master | `[]` | +| `master.extraFlags` | Array with additional command line flags for Redis® master | `[]` | +| `master.extraEnvVars` | Array with extra environment variables to add to Redis® master nodes | `[]` | +| `master.extraEnvVarsCM` | Name of existing ConfigMap containing extra env vars for Redis® master nodes | `""` | +| `master.extraEnvVarsSecret` | Name of existing Secret containing extra env vars for Redis® master nodes | `""` | +| `master.containerPorts.redis` | Container port to open on Redis® master nodes | `6379` | +| `master.startupProbe.enabled` | Enable startupProbe on Redis® master nodes | `false` | +| `master.startupProbe.initialDelaySeconds` | Initial delay seconds for startupProbe | `20` | +| `master.startupProbe.periodSeconds` | Period seconds for startupProbe | `5` | +| `master.startupProbe.timeoutSeconds` | Timeout seconds for startupProbe | `5` | +| `master.startupProbe.failureThreshold` | Failure threshold for startupProbe | `5` | +| `master.startupProbe.successThreshold` | Success threshold for startupProbe | `1` | +| `master.livenessProbe.enabled` | Enable livenessProbe on Redis® master nodes | `true` | +| `master.livenessProbe.initialDelaySeconds` | Initial delay seconds for livenessProbe | `20` | +| `master.livenessProbe.periodSeconds` | Period seconds for livenessProbe | `5` | +| `master.livenessProbe.timeoutSeconds` | Timeout seconds for livenessProbe | `5` | +| `master.livenessProbe.failureThreshold` | Failure threshold for livenessProbe | `5` | +| `master.livenessProbe.successThreshold` | Success threshold for livenessProbe | `1` | +| `master.readinessProbe.enabled` | Enable readinessProbe on Redis® master nodes | `true` | +| `master.readinessProbe.initialDelaySeconds` | Initial delay seconds for readinessProbe | `20` | +| `master.readinessProbe.periodSeconds` | Period seconds for readinessProbe | `5` | +| `master.readinessProbe.timeoutSeconds` | Timeout seconds for readinessProbe | `1` | +| `master.readinessProbe.failureThreshold` | Failure threshold for readinessProbe | `5` | +| `master.readinessProbe.successThreshold` | Success threshold for readinessProbe | `1` | +| `master.customStartupProbe` | Custom startupProbe that overrides the default one | `{}` | +| `master.customLivenessProbe` | Custom livenessProbe that overrides the default one | `{}` | +| `master.customReadinessProbe` | Custom readinessProbe that overrides the default one | `{}` | +| `master.resources.limits` | The resources limits for the Redis® master containers | `{}` | +| `master.resources.requests` | The requested resources for the Redis® master containers | `{}` | +| `master.podSecurityContext.enabled` | Enabled Redis® master pods' Security Context | `true` | +| `master.podSecurityContext.fsGroup` | Set Redis® master pod's Security Context fsGroup | `1001` | +| `master.containerSecurityContext.enabled` | Enabled Redis® master containers' Security Context | `true` | +| `master.containerSecurityContext.runAsUser` | Set Redis® master containers' Security Context runAsUser | `1001` | +| `master.containerSecurityContext.runAsGroup` | Set Redis® master containers' Security Context runAsGroup | `0` | +| `master.containerSecurityContext.runAsNonRoot` | Set Redis® master containers' Security Context runAsNonRoot | `true` | +| `master.containerSecurityContext.allowPrivilegeEscalation` | Is it possible to escalate Redis® pod(s) privileges | `false` | +| `master.containerSecurityContext.seccompProfile.type` | Set Redis® master containers' Security Context seccompProfile | `RuntimeDefault` | +| `master.containerSecurityContext.capabilities.drop` | Set Redis® master containers' Security Context capabilities to drop | `["ALL"]` | +| `master.kind` | Use either Deployment, StatefulSet (default) or DaemonSet | `StatefulSet` | +| `master.schedulerName` | Alternate scheduler for Redis® master pods | `""` | +| `master.updateStrategy.type` | Redis® master statefulset strategy type | `RollingUpdate` | +| `master.minReadySeconds` | How many seconds a pod needs to be ready before killing the next, during update | `0` | +| `master.priorityClassName` | Redis® master pods' priorityClassName | `""` | +| `master.hostAliases` | Redis® master pods host aliases | `[]` | +| `master.podLabels` | Extra labels for Redis® master pods | `{}` | +| `master.podAnnotations` | Annotations for Redis® master pods | `{}` | +| `master.shareProcessNamespace` | Share a single process namespace between all of the containers in Redis® master pods | `false` | +| `master.podAffinityPreset` | Pod affinity preset. Ignored if `master.affinity` is set. Allowed values: `soft` or `hard` | `""` | +| `master.podAntiAffinityPreset` | Pod anti-affinity preset. Ignored if `master.affinity` is set. Allowed values: `soft` or `hard` | `soft` | +| `master.nodeAffinityPreset.type` | Node affinity preset type. Ignored if `master.affinity` is set. Allowed values: `soft` or `hard` | `""` | +| `master.nodeAffinityPreset.key` | Node label key to match. Ignored if `master.affinity` is set | `""` | +| `master.nodeAffinityPreset.values` | Node label values to match. Ignored if `master.affinity` is set | `[]` | +| `master.affinity` | Affinity for Redis® master pods assignment | `{}` | +| `master.nodeSelector` | Node labels for Redis® master pods assignment | `{}` | +| `master.tolerations` | Tolerations for Redis® master pods assignment | `[]` | +| `master.topologySpreadConstraints` | Spread Constraints for Redis® master pod assignment | `[]` | +| `master.dnsPolicy` | DNS Policy for Redis® master pod | `""` | +| `master.dnsConfig` | DNS Configuration for Redis® master pod | `{}` | +| `master.lifecycleHooks` | for the Redis® master container(s) to automate configuration before or after startup | `{}` | +| `master.extraVolumes` | Optionally specify extra list of additional volumes for the Redis® master pod(s) | `[]` | +| `master.extraVolumeMounts` | Optionally specify extra list of additional volumeMounts for the Redis® master container(s) | `[]` | +| `master.sidecars` | Add additional sidecar containers to the Redis® master pod(s) | `[]` | +| `master.initContainers` | Add additional init containers to the Redis® master pod(s) | `[]` | +| `master.persistence.enabled` | Enable persistence on Redis® master nodes using Persistent Volume Claims | `true` | +| `master.persistence.medium` | Provide a medium for `emptyDir` volumes. | `""` | +| `master.persistence.sizeLimit` | Set this to enable a size limit for `emptyDir` volumes. | `""` | +| `master.persistence.path` | The path the volume will be mounted at on Redis® master containers | `/data` | +| `master.persistence.subPath` | The subdirectory of the volume to mount on Redis® master containers | `""` | +| `master.persistence.subPathExpr` | Used to construct the subPath subdirectory of the volume to mount on Redis® master containers | `""` | +| `master.persistence.storageClass` | Persistent Volume storage class | `""` | +| `master.persistence.accessModes` | Persistent Volume access modes | `["ReadWriteOnce"]` | +| `master.persistence.size` | Persistent Volume size | `8Gi` | +| `master.persistence.annotations` | Additional custom annotations for the PVC | `{}` | +| `master.persistence.labels` | Additional custom labels for the PVC | `{}` | +| `master.persistence.selector` | Additional labels to match for the PVC | `{}` | +| `master.persistence.dataSource` | Custom PVC data source | `{}` | +| `master.persistence.existingClaim` | Use a existing PVC which must be created manually before bound | `""` | +| `master.persistentVolumeClaimRetentionPolicy.enabled` | Controls if and how PVCs are deleted during the lifecycle of a StatefulSet | `false` | +| `master.persistentVolumeClaimRetentionPolicy.whenScaled` | Volume retention behavior when the replica count of the StatefulSet is reduced | `Retain` | +| `master.persistentVolumeClaimRetentionPolicy.whenDeleted` | Volume retention behavior that applies when the StatefulSet is deleted | `Retain` | +| `master.service.type` | Redis® master service type | `ClusterIP` | +| `master.service.ports.redis` | Redis® master service port | `6379` | +| `master.service.nodePorts.redis` | Node port for Redis® master | `""` | +| `master.service.externalTrafficPolicy` | Redis® master service external traffic policy | `Cluster` | +| `master.service.extraPorts` | Extra ports to expose (normally used with the `sidecar` value) | `[]` | +| `master.service.internalTrafficPolicy` | Redis® master service internal traffic policy (requires Kubernetes v1.22 or greater to be usable) | `Cluster` | +| `master.service.clusterIP` | Redis® master service Cluster IP | `""` | +| `master.service.loadBalancerIP` | Redis® master service Load Balancer IP | `""` | +| `master.service.loadBalancerSourceRanges` | Redis® master service Load Balancer sources | `[]` | +| `master.service.externalIPs` | Redis® master service External IPs | `[]` | +| `master.service.annotations` | Additional custom annotations for Redis® master service | `{}` | +| `master.service.sessionAffinity` | Session Affinity for Kubernetes service, can be "None" or "ClientIP" | `None` | +| `master.service.sessionAffinityConfig` | Additional settings for the sessionAffinity | `{}` | +| `master.terminationGracePeriodSeconds` | Integer setting the termination grace period for the redis-master pods | `30` | +| `master.serviceAccount.create` | Specifies whether a ServiceAccount should be created | `false` | +| `master.serviceAccount.name` | The name of the ServiceAccount to use. | `""` | +| `master.serviceAccount.automountServiceAccountToken` | Whether to auto mount the service account token | `true` | +| `master.serviceAccount.annotations` | Additional custom annotations for the ServiceAccount | `{}` | + +### Redis® replicas configuration parameters + +| Name | Description | Value | +| ----------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- | ------------------------ | +| `replica.kind` | Use either DaemonSet or StatefulSet (default) | `StatefulSet` | +| `replica.replicaCount` | Number of Redis® replicas to deploy | `3` | +| `replica.configuration` | Configuration for Redis® replicas nodes | `""` | +| `replica.disableCommands` | Array with Redis® commands to disable on replicas nodes | `["FLUSHDB","FLUSHALL"]` | +| `replica.command` | Override default container command (useful when using custom images) | `[]` | +| `replica.args` | Override default container args (useful when using custom images) | `[]` | +| `replica.enableServiceLinks` | Whether information about services should be injected into pod's environment variable | `true` | +| `replica.preExecCmds` | Additional commands to run prior to starting Redis® replicas | `[]` | +| `replica.extraFlags` | Array with additional command line flags for Redis® replicas | `[]` | +| `replica.extraEnvVars` | Array with extra environment variables to add to Redis® replicas nodes | `[]` | +| `replica.extraEnvVarsCM` | Name of existing ConfigMap containing extra env vars for Redis® replicas nodes | `""` | +| `replica.extraEnvVarsSecret` | Name of existing Secret containing extra env vars for Redis® replicas nodes | `""` | +| `replica.externalMaster.enabled` | Use external master for bootstrapping | `false` | +| `replica.externalMaster.host` | External master host to bootstrap from | `""` | +| `replica.externalMaster.port` | Port for Redis service external master host | `6379` | +| `replica.containerPorts.redis` | Container port to open on Redis® replicas nodes | `6379` | +| `replica.startupProbe.enabled` | Enable startupProbe on Redis® replicas nodes | `true` | +| `replica.startupProbe.initialDelaySeconds` | Initial delay seconds for startupProbe | `10` | +| `replica.startupProbe.periodSeconds` | Period seconds for startupProbe | `10` | +| `replica.startupProbe.timeoutSeconds` | Timeout seconds for startupProbe | `5` | +| `replica.startupProbe.failureThreshold` | Failure threshold for startupProbe | `22` | +| `replica.startupProbe.successThreshold` | Success threshold for startupProbe | `1` | +| `replica.livenessProbe.enabled` | Enable livenessProbe on Redis® replicas nodes | `true` | +| `replica.livenessProbe.initialDelaySeconds` | Initial delay seconds for livenessProbe | `20` | +| `replica.livenessProbe.periodSeconds` | Period seconds for livenessProbe | `5` | +| `replica.livenessProbe.timeoutSeconds` | Timeout seconds for livenessProbe | `5` | +| `replica.livenessProbe.failureThreshold` | Failure threshold for livenessProbe | `5` | +| `replica.livenessProbe.successThreshold` | Success threshold for livenessProbe | `1` | +| `replica.readinessProbe.enabled` | Enable readinessProbe on Redis® replicas nodes | `true` | +| `replica.readinessProbe.initialDelaySeconds` | Initial delay seconds for readinessProbe | `20` | +| `replica.readinessProbe.periodSeconds` | Period seconds for readinessProbe | `5` | +| `replica.readinessProbe.timeoutSeconds` | Timeout seconds for readinessProbe | `1` | +| `replica.readinessProbe.failureThreshold` | Failure threshold for readinessProbe | `5` | +| `replica.readinessProbe.successThreshold` | Success threshold for readinessProbe | `1` | +| `replica.customStartupProbe` | Custom startupProbe that overrides the default one | `{}` | +| `replica.customLivenessProbe` | Custom livenessProbe that overrides the default one | `{}` | +| `replica.customReadinessProbe` | Custom readinessProbe that overrides the default one | `{}` | +| `replica.resources.limits` | The resources limits for the Redis® replicas containers | `{}` | +| `replica.resources.requests` | The requested resources for the Redis® replicas containers | `{}` | +| `replica.podSecurityContext.enabled` | Enabled Redis® replicas pods' Security Context | `true` | +| `replica.podSecurityContext.fsGroup` | Set Redis® replicas pod's Security Context fsGroup | `1001` | +| `replica.containerSecurityContext.enabled` | Enabled Redis® replicas containers' Security Context | `true` | +| `replica.containerSecurityContext.runAsUser` | Set Redis® replicas containers' Security Context runAsUser | `1001` | +| `replica.containerSecurityContext.runAsGroup` | Set Redis® replicas containers' Security Context runAsGroup | `0` | +| `replica.containerSecurityContext.runAsNonRoot` | Set Redis® replicas containers' Security Context runAsNonRoot | `true` | +| `replica.containerSecurityContext.allowPrivilegeEscalation` | Set Redis® replicas pod's Security Context allowPrivilegeEscalation | `false` | +| `replica.containerSecurityContext.seccompProfile.type` | Set Redis® replicas containers' Security Context seccompProfile | `RuntimeDefault` | +| `replica.containerSecurityContext.capabilities.drop` | Set Redis® replicas containers' Security Context capabilities to drop | `["ALL"]` | +| `replica.schedulerName` | Alternate scheduler for Redis® replicas pods | `""` | +| `replica.updateStrategy.type` | Redis® replicas statefulset strategy type | `RollingUpdate` | +| `replica.minReadySeconds` | How many seconds a pod needs to be ready before killing the next, during update | `0` | +| `replica.priorityClassName` | Redis® replicas pods' priorityClassName | `""` | +| `replica.podManagementPolicy` | podManagementPolicy to manage scaling operation of %%MAIN_CONTAINER_NAME%% pods | `""` | +| `replica.hostAliases` | Redis® replicas pods host aliases | `[]` | +| `replica.podLabels` | Extra labels for Redis® replicas pods | `{}` | +| `replica.podAnnotations` | Annotations for Redis® replicas pods | `{}` | +| `replica.shareProcessNamespace` | Share a single process namespace between all of the containers in Redis® replicas pods | `false` | +| `replica.podAffinityPreset` | Pod affinity preset. Ignored if `replica.affinity` is set. Allowed values: `soft` or `hard` | `""` | +| `replica.podAntiAffinityPreset` | Pod anti-affinity preset. Ignored if `replica.affinity` is set. Allowed values: `soft` or `hard` | `soft` | +| `replica.nodeAffinityPreset.type` | Node affinity preset type. Ignored if `replica.affinity` is set. Allowed values: `soft` or `hard` | `""` | +| `replica.nodeAffinityPreset.key` | Node label key to match. Ignored if `replica.affinity` is set | `""` | +| `replica.nodeAffinityPreset.values` | Node label values to match. Ignored if `replica.affinity` is set | `[]` | +| `replica.affinity` | Affinity for Redis® replicas pods assignment | `{}` | +| `replica.nodeSelector` | Node labels for Redis® replicas pods assignment | `{}` | +| `replica.tolerations` | Tolerations for Redis® replicas pods assignment | `[]` | +| `replica.topologySpreadConstraints` | Spread Constraints for Redis® replicas pod assignment | `[]` | +| `replica.dnsPolicy` | DNS Policy for Redis® replica pods | `""` | +| `replica.dnsConfig` | DNS Configuration for Redis® replica pods | `{}` | +| `replica.lifecycleHooks` | for the Redis® replica container(s) to automate configuration before or after startup | `{}` | +| `replica.extraVolumes` | Optionally specify extra list of additional volumes for the Redis® replicas pod(s) | `[]` | +| `replica.extraVolumeMounts` | Optionally specify extra list of additional volumeMounts for the Redis® replicas container(s) | `[]` | +| `replica.sidecars` | Add additional sidecar containers to the Redis® replicas pod(s) | `[]` | +| `replica.initContainers` | Add additional init containers to the Redis® replicas pod(s) | `[]` | +| `replica.persistence.enabled` | Enable persistence on Redis® replicas nodes using Persistent Volume Claims | `true` | +| `replica.persistence.medium` | Provide a medium for `emptyDir` volumes. | `""` | +| `replica.persistence.sizeLimit` | Set this to enable a size limit for `emptyDir` volumes. | `""` | +| `replica.persistence.path` | The path the volume will be mounted at on Redis® replicas containers | `/data` | +| `replica.persistence.subPath` | The subdirectory of the volume to mount on Redis® replicas containers | `""` | +| `replica.persistence.subPathExpr` | Used to construct the subPath subdirectory of the volume to mount on Redis® replicas containers | `""` | +| `replica.persistence.storageClass` | Persistent Volume storage class | `""` | +| `replica.persistence.accessModes` | Persistent Volume access modes | `["ReadWriteOnce"]` | +| `replica.persistence.size` | Persistent Volume size | `8Gi` | +| `replica.persistence.annotations` | Additional custom annotations for the PVC | `{}` | +| `replica.persistence.labels` | Additional custom labels for the PVC | `{}` | +| `replica.persistence.selector` | Additional labels to match for the PVC | `{}` | +| `replica.persistence.dataSource` | Custom PVC data source | `{}` | +| `replica.persistence.existingClaim` | Use a existing PVC which must be created manually before bound | `""` | +| `replica.persistentVolumeClaimRetentionPolicy.enabled` | Controls if and how PVCs are deleted during the lifecycle of a StatefulSet | `false` | +| `replica.persistentVolumeClaimRetentionPolicy.whenScaled` | Volume retention behavior when the replica count of the StatefulSet is reduced | `Retain` | +| `replica.persistentVolumeClaimRetentionPolicy.whenDeleted` | Volume retention behavior that applies when the StatefulSet is deleted | `Retain` | +| `replica.service.type` | Redis® replicas service type | `ClusterIP` | +| `replica.service.ports.redis` | Redis® replicas service port | `6379` | +| `replica.service.nodePorts.redis` | Node port for Redis® replicas | `""` | +| `replica.service.externalTrafficPolicy` | Redis® replicas service external traffic policy | `Cluster` | +| `replica.service.internalTrafficPolicy` | Redis® replicas service internal traffic policy (requires Kubernetes v1.22 or greater to be usable) | `Cluster` | +| `replica.service.extraPorts` | Extra ports to expose (normally used with the `sidecar` value) | `[]` | +| `replica.service.clusterIP` | Redis® replicas service Cluster IP | `""` | +| `replica.service.loadBalancerIP` | Redis® replicas service Load Balancer IP | `""` | +| `replica.service.loadBalancerSourceRanges` | Redis® replicas service Load Balancer sources | `[]` | +| `replica.service.annotations` | Additional custom annotations for Redis® replicas service | `{}` | +| `replica.service.sessionAffinity` | Session Affinity for Kubernetes service, can be "None" or "ClientIP" | `None` | +| `replica.service.sessionAffinityConfig` | Additional settings for the sessionAffinity | `{}` | +| `replica.terminationGracePeriodSeconds` | Integer setting the termination grace period for the redis-replicas pods | `30` | +| `replica.autoscaling.enabled` | Enable replica autoscaling settings | `false` | +| `replica.autoscaling.minReplicas` | Minimum replicas for the pod autoscaling | `1` | +| `replica.autoscaling.maxReplicas` | Maximum replicas for the pod autoscaling | `11` | +| `replica.autoscaling.targetCPU` | Percentage of CPU to consider when autoscaling | `""` | +| `replica.autoscaling.targetMemory` | Percentage of Memory to consider when autoscaling | `""` | +| `replica.serviceAccount.create` | Specifies whether a ServiceAccount should be created | `false` | +| `replica.serviceAccount.name` | The name of the ServiceAccount to use. | `""` | +| `replica.serviceAccount.automountServiceAccountToken` | Whether to auto mount the service account token | `true` | +| `replica.serviceAccount.annotations` | Additional custom annotations for the ServiceAccount | `{}` | + +### Redis® Sentinel configuration parameters + +| Name | Description | Value | +| ------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------- | +| `sentinel.enabled` | Use Redis® Sentinel on Redis® pods. | `false` | +| `sentinel.image.registry` | Redis® Sentinel image registry | `REGISTRY_NAME` | +| `sentinel.image.repository` | Redis® Sentinel image repository | `REPOSITORY_NAME/redis-sentinel` | +| `sentinel.image.digest` | Redis® Sentinel image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag | `""` | +| `sentinel.image.pullPolicy` | Redis® Sentinel image pull policy | `IfNotPresent` | +| `sentinel.image.pullSecrets` | Redis® Sentinel image pull secrets | `[]` | +| `sentinel.image.debug` | Enable image debug mode | `false` | +| `sentinel.annotations` | Additional custom annotations for Redis® Sentinel resource | `{}` | +| `sentinel.masterSet` | Master set name | `mymaster` | +| `sentinel.quorum` | Sentinel Quorum | `2` | +| `sentinel.getMasterTimeout` | Amount of time to allow before get_sentinel_master_info() times out. | `90` | +| `sentinel.automateClusterRecovery` | Automate cluster recovery in cases where the last replica is not considered a good replica and Sentinel won't automatically failover to it. | `false` | +| `sentinel.redisShutdownWaitFailover` | Whether the Redis® master container waits for the failover at shutdown (in addition to the Redis® Sentinel container). | `true` | +| `sentinel.downAfterMilliseconds` | Timeout for detecting a Redis® node is down | `60000` | +| `sentinel.failoverTimeout` | Timeout for performing a election failover | `180000` | +| `sentinel.parallelSyncs` | Number of replicas that can be reconfigured in parallel to use the new master after a failover | `1` | +| `sentinel.configuration` | Configuration for Redis® Sentinel nodes | `""` | +| `sentinel.command` | Override default container command (useful when using custom images) | `[]` | +| `sentinel.args` | Override default container args (useful when using custom images) | `[]` | +| `sentinel.enableServiceLinks` | Whether information about services should be injected into pod's environment variable | `true` | +| `sentinel.preExecCmds` | Additional commands to run prior to starting Redis® Sentinel | `[]` | +| `sentinel.extraEnvVars` | Array with extra environment variables to add to Redis® Sentinel nodes | `[]` | +| `sentinel.extraEnvVarsCM` | Name of existing ConfigMap containing extra env vars for Redis® Sentinel nodes | `""` | +| `sentinel.extraEnvVarsSecret` | Name of existing Secret containing extra env vars for Redis® Sentinel nodes | `""` | +| `sentinel.externalMaster.enabled` | Use external master for bootstrapping | `false` | +| `sentinel.externalMaster.host` | External master host to bootstrap from | `""` | +| `sentinel.externalMaster.port` | Port for Redis service external master host | `6379` | +| `sentinel.containerPorts.sentinel` | Container port to open on Redis® Sentinel nodes | `26379` | +| `sentinel.startupProbe.enabled` | Enable startupProbe on Redis® Sentinel nodes | `true` | +| `sentinel.startupProbe.initialDelaySeconds` | Initial delay seconds for startupProbe | `10` | +| `sentinel.startupProbe.periodSeconds` | Period seconds for startupProbe | `10` | +| `sentinel.startupProbe.timeoutSeconds` | Timeout seconds for startupProbe | `5` | +| `sentinel.startupProbe.failureThreshold` | Failure threshold for startupProbe | `22` | +| `sentinel.startupProbe.successThreshold` | Success threshold for startupProbe | `1` | +| `sentinel.livenessProbe.enabled` | Enable livenessProbe on Redis® Sentinel nodes | `true` | +| `sentinel.livenessProbe.initialDelaySeconds` | Initial delay seconds for livenessProbe | `20` | +| `sentinel.livenessProbe.periodSeconds` | Period seconds for livenessProbe | `10` | +| `sentinel.livenessProbe.timeoutSeconds` | Timeout seconds for livenessProbe | `5` | +| `sentinel.livenessProbe.failureThreshold` | Failure threshold for livenessProbe | `6` | +| `sentinel.livenessProbe.successThreshold` | Success threshold for livenessProbe | `1` | +| `sentinel.readinessProbe.enabled` | Enable readinessProbe on Redis® Sentinel nodes | `true` | +| `sentinel.readinessProbe.initialDelaySeconds` | Initial delay seconds for readinessProbe | `20` | +| `sentinel.readinessProbe.periodSeconds` | Period seconds for readinessProbe | `5` | +| `sentinel.readinessProbe.timeoutSeconds` | Timeout seconds for readinessProbe | `1` | +| `sentinel.readinessProbe.failureThreshold` | Failure threshold for readinessProbe | `6` | +| `sentinel.readinessProbe.successThreshold` | Success threshold for readinessProbe | `1` | +| `sentinel.customStartupProbe` | Custom startupProbe that overrides the default one | `{}` | +| `sentinel.customLivenessProbe` | Custom livenessProbe that overrides the default one | `{}` | +| `sentinel.customReadinessProbe` | Custom readinessProbe that overrides the default one | `{}` | +| `sentinel.persistence.enabled` | Enable persistence on Redis® sentinel nodes using Persistent Volume Claims (Experimental) | `false` | +| `sentinel.persistence.storageClass` | Persistent Volume storage class | `""` | +| `sentinel.persistence.accessModes` | Persistent Volume access modes | `["ReadWriteOnce"]` | +| `sentinel.persistence.size` | Persistent Volume size | `100Mi` | +| `sentinel.persistence.annotations` | Additional custom annotations for the PVC | `{}` | +| `sentinel.persistence.labels` | Additional custom labels for the PVC | `{}` | +| `sentinel.persistence.selector` | Additional labels to match for the PVC | `{}` | +| `sentinel.persistence.dataSource` | Custom PVC data source | `{}` | +| `sentinel.persistence.medium` | Provide a medium for `emptyDir` volumes. | `""` | +| `sentinel.persistence.sizeLimit` | Set this to enable a size limit for `emptyDir` volumes. | `""` | +| `sentinel.persistentVolumeClaimRetentionPolicy.enabled` | Controls if and how PVCs are deleted during the lifecycle of a StatefulSet | `false` | +| `sentinel.persistentVolumeClaimRetentionPolicy.whenScaled` | Volume retention behavior when the replica count of the StatefulSet is reduced | `Retain` | +| `sentinel.persistentVolumeClaimRetentionPolicy.whenDeleted` | Volume retention behavior that applies when the StatefulSet is deleted | `Retain` | +| `sentinel.resources.limits` | The resources limits for the Redis® Sentinel containers | `{}` | +| `sentinel.resources.requests` | The requested resources for the Redis® Sentinel containers | `{}` | +| `sentinel.containerSecurityContext.enabled` | Enabled Redis® Sentinel containers' Security Context | `true` | +| `sentinel.containerSecurityContext.runAsUser` | Set Redis® Sentinel containers' Security Context runAsUser | `1001` | +| `sentinel.containerSecurityContext.runAsGroup` | Set Redis® Sentinel containers' Security Context runAsGroup | `0` | +| `sentinel.containerSecurityContext.runAsNonRoot` | Set Redis® Sentinel containers' Security Context runAsNonRoot | `true` | +| `sentinel.containerSecurityContext.allowPrivilegeEscalation` | Set Redis® Sentinel containers' Security Context allowPrivilegeEscalation | `false` | +| `sentinel.containerSecurityContext.seccompProfile.type` | Set Redis® Sentinel containers' Security Context seccompProfile | `RuntimeDefault` | +| `sentinel.containerSecurityContext.capabilities.drop` | Set Redis® Sentinel containers' Security Context capabilities to drop | `["ALL"]` | +| `sentinel.lifecycleHooks` | for the Redis® sentinel container(s) to automate configuration before or after startup | `{}` | +| `sentinel.extraVolumes` | Optionally specify extra list of additional volumes for the Redis® Sentinel | `[]` | +| `sentinel.extraVolumeMounts` | Optionally specify extra list of additional volumeMounts for the Redis® Sentinel container(s) | `[]` | +| `sentinel.service.type` | Redis® Sentinel service type | `ClusterIP` | +| `sentinel.service.ports.redis` | Redis® service port for Redis® | `6379` | +| `sentinel.service.ports.sentinel` | Redis® service port for Redis® Sentinel | `26379` | +| `sentinel.service.nodePorts.redis` | Node port for Redis® | `""` | +| `sentinel.service.nodePorts.sentinel` | Node port for Sentinel | `""` | +| `sentinel.service.externalTrafficPolicy` | Redis® Sentinel service external traffic policy | `Cluster` | +| `sentinel.service.extraPorts` | Extra ports to expose (normally used with the `sidecar` value) | `[]` | +| `sentinel.service.clusterIP` | Redis® Sentinel service Cluster IP | `""` | +| `sentinel.service.loadBalancerIP` | Redis® Sentinel service Load Balancer IP | `""` | +| `sentinel.service.loadBalancerSourceRanges` | Redis® Sentinel service Load Balancer sources | `[]` | +| `sentinel.service.annotations` | Additional custom annotations for Redis® Sentinel service | `{}` | +| `sentinel.service.sessionAffinity` | Session Affinity for Kubernetes service, can be "None" or "ClientIP" | `None` | +| `sentinel.service.sessionAffinityConfig` | Additional settings for the sessionAffinity | `{}` | +| `sentinel.service.headless.annotations` | Annotations for the headless service. | `{}` | +| `sentinel.terminationGracePeriodSeconds` | Integer setting the termination grace period for the redis-node pods | `30` | + +### Other Parameters + +| Name | Description | Value | +| ----------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | ------- | +| `serviceBindings.enabled` | Create secret for service binding (Experimental) | `false` | +| `networkPolicy.enabled` | Enable creation of NetworkPolicy resources | `false` | +| `networkPolicy.allowExternal` | Don't require client label for connections | `true` | +| `networkPolicy.extraIngress` | Add extra ingress rules to the NetworkPolicy | `[]` | +| `networkPolicy.extraEgress` | Add extra egress rules to the NetworkPolicy | `[]` | +| `networkPolicy.ingressNSMatchLabels` | Labels to match to allow traffic from other namespaces | `{}` | +| `networkPolicy.ingressNSPodMatchLabels` | Pod labels to match to allow traffic from other namespaces | `{}` | +| `networkPolicy.metrics.allowExternal` | Don't require client label for connections for metrics endpoint | `true` | +| `networkPolicy.metrics.ingressNSMatchLabels` | Labels to match to allow traffic from other namespaces to metrics endpoint | `{}` | +| `networkPolicy.metrics.ingressNSPodMatchLabels` | Pod labels to match to allow traffic from other namespaces to metrics endpoint | `{}` | +| `podSecurityPolicy.create` | Whether to create a PodSecurityPolicy. WARNING: PodSecurityPolicy is deprecated in Kubernetes v1.21 or later, unavailable in v1.25 or later | `false` | +| `podSecurityPolicy.enabled` | Enable PodSecurityPolicy's RBAC rules | `false` | +| `rbac.create` | Specifies whether RBAC resources should be created | `false` | +| `rbac.rules` | Custom RBAC rules to set | `[]` | +| `serviceAccount.create` | Specifies whether a ServiceAccount should be created | `true` | +| `serviceAccount.name` | The name of the ServiceAccount to use. | `""` | +| `serviceAccount.automountServiceAccountToken` | Whether to auto mount the service account token | `true` | +| `serviceAccount.annotations` | Additional custom annotations for the ServiceAccount | `{}` | +| `pdb.create` | Specifies whether a PodDisruptionBudget should be created | `false` | +| `pdb.minAvailable` | Min number of pods that must still be available after the eviction | `1` | +| `pdb.maxUnavailable` | Max number of pods that can be unavailable after the eviction | `""` | +| `tls.enabled` | Enable TLS traffic | `false` | +| `tls.authClients` | Require clients to authenticate | `true` | +| `tls.autoGenerated` | Enable autogenerated certificates | `false` | +| `tls.existingSecret` | The name of the existing secret that contains the TLS certificates | `""` | +| `tls.certificatesSecret` | DEPRECATED. Use existingSecret instead. | `""` | +| `tls.certFilename` | Certificate filename | `""` | +| `tls.certKeyFilename` | Certificate Key filename | `""` | +| `tls.certCAFilename` | CA Certificate filename | `""` | +| `tls.dhParamsFilename` | File containing DH params (in order to support DH based ciphers) | `""` | + +### Metrics Parameters + +| Name | Description | Value | +| ----------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- | -------------------------------- | +| `metrics.enabled` | Start a sidecar prometheus exporter to expose Redis® metrics | `false` | +| `metrics.image.registry` | Redis® Exporter image registry | `REGISTRY_NAME` | +| `metrics.image.repository` | Redis® Exporter image repository | `REPOSITORY_NAME/redis-exporter` | +| `metrics.image.digest` | Redis® Exporter image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag | `""` | +| `metrics.image.pullPolicy` | Redis® Exporter image pull policy | `IfNotPresent` | +| `metrics.image.pullSecrets` | Redis® Exporter image pull secrets | `[]` | +| `metrics.startupProbe.enabled` | Enable startupProbe on Redis® replicas nodes | `false` | +| `metrics.startupProbe.initialDelaySeconds` | Initial delay seconds for startupProbe | `10` | +| `metrics.startupProbe.periodSeconds` | Period seconds for startupProbe | `10` | +| `metrics.startupProbe.timeoutSeconds` | Timeout seconds for startupProbe | `5` | +| `metrics.startupProbe.failureThreshold` | Failure threshold for startupProbe | `5` | +| `metrics.startupProbe.successThreshold` | Success threshold for startupProbe | `1` | +| `metrics.livenessProbe.enabled` | Enable livenessProbe on Redis® replicas nodes | `true` | +| `metrics.livenessProbe.initialDelaySeconds` | Initial delay seconds for livenessProbe | `10` | +| `metrics.livenessProbe.periodSeconds` | Period seconds for livenessProbe | `10` | +| `metrics.livenessProbe.timeoutSeconds` | Timeout seconds for livenessProbe | `5` | +| `metrics.livenessProbe.failureThreshold` | Failure threshold for livenessProbe | `5` | +| `metrics.livenessProbe.successThreshold` | Success threshold for livenessProbe | `1` | +| `metrics.readinessProbe.enabled` | Enable readinessProbe on Redis® replicas nodes | `true` | +| `metrics.readinessProbe.initialDelaySeconds` | Initial delay seconds for readinessProbe | `5` | +| `metrics.readinessProbe.periodSeconds` | Period seconds for readinessProbe | `10` | +| `metrics.readinessProbe.timeoutSeconds` | Timeout seconds for readinessProbe | `1` | +| `metrics.readinessProbe.failureThreshold` | Failure threshold for readinessProbe | `3` | +| `metrics.readinessProbe.successThreshold` | Success threshold for readinessProbe | `1` | +| `metrics.customStartupProbe` | Custom startupProbe that overrides the default one | `{}` | +| `metrics.customLivenessProbe` | Custom livenessProbe that overrides the default one | `{}` | +| `metrics.customReadinessProbe` | Custom readinessProbe that overrides the default one | `{}` | +| `metrics.command` | Override default metrics container init command (useful when using custom images) | `[]` | +| `metrics.redisTargetHost` | A way to specify an alternative Redis® hostname | `localhost` | +| `metrics.extraArgs` | Extra arguments for Redis® exporter, for example: | `{}` | +| `metrics.extraEnvVars` | Array with extra environment variables to add to Redis® exporter | `[]` | +| `metrics.containerSecurityContext.enabled` | Enabled Redis® exporter containers' Security Context | `true` | +| `metrics.containerSecurityContext.runAsUser` | Set Redis® exporter containers' Security Context runAsUser | `1001` | +| `metrics.containerSecurityContext.runAsGroup` | Set Redis® exporter containers' Security Context runAsGroup | `0` | +| `metrics.containerSecurityContext.runAsNonRoot` | Set Redis® exporter containers' Security Context runAsNonRoot | `true` | +| `metrics.containerSecurityContext.allowPrivilegeEscalation` | Set Redis® exporter containers' Security Context allowPrivilegeEscalation | `false` | +| `metrics.containerSecurityContext.seccompProfile.type` | Set Redis® exporter containers' Security Context seccompProfile | `RuntimeDefault` | +| `metrics.containerSecurityContext.capabilities.drop` | Set Redis® exporter containers' Security Context capabilities to drop | `["ALL"]` | +| `metrics.extraVolumes` | Optionally specify extra list of additional volumes for the Redis® metrics sidecar | `[]` | +| `metrics.extraVolumeMounts` | Optionally specify extra list of additional volumeMounts for the Redis® metrics sidecar | `[]` | +| `metrics.resources.limits` | The resources limits for the Redis® exporter container | `{}` | +| `metrics.resources.requests` | The requested resources for the Redis® exporter container | `{}` | +| `metrics.podLabels` | Extra labels for Redis® exporter pods | `{}` | +| `metrics.podAnnotations` | Annotations for Redis® exporter pods | `{}` | +| `metrics.service.type` | Redis® exporter service type | `ClusterIP` | +| `metrics.service.port` | Redis® exporter service port | `9121` | +| `metrics.service.externalTrafficPolicy` | Redis® exporter service external traffic policy | `Cluster` | +| `metrics.service.extraPorts` | Extra ports to expose (normally used with the `sidecar` value) | `[]` | +| `metrics.service.loadBalancerIP` | Redis® exporter service Load Balancer IP | `""` | +| `metrics.service.loadBalancerSourceRanges` | Redis® exporter service Load Balancer sources | `[]` | +| `metrics.service.annotations` | Additional custom annotations for Redis® exporter service | `{}` | +| `metrics.service.clusterIP` | Redis® exporter service Cluster IP | `""` | +| `metrics.serviceMonitor.enabled` | Create ServiceMonitor resource(s) for scraping metrics using PrometheusOperator | `false` | +| `metrics.serviceMonitor.namespace` | The namespace in which the ServiceMonitor will be created | `""` | +| `metrics.serviceMonitor.interval` | The interval at which metrics should be scraped | `30s` | +| `metrics.serviceMonitor.scrapeTimeout` | The timeout after which the scrape is ended | `""` | +| `metrics.serviceMonitor.relabellings` | Metrics RelabelConfigs to apply to samples before scraping. | `[]` | +| `metrics.serviceMonitor.metricRelabelings` | Metrics RelabelConfigs to apply to samples before ingestion. | `[]` | +| `metrics.serviceMonitor.honorLabels` | Specify honorLabels parameter to add the scrape endpoint | `false` | +| `metrics.serviceMonitor.additionalLabels` | Additional labels that can be used so ServiceMonitor resource(s) can be discovered by Prometheus | `{}` | +| `metrics.serviceMonitor.podTargetLabels` | Labels from the Kubernetes pod to be transferred to the created metrics | `[]` | +| `metrics.serviceMonitor.sampleLimit` | Limit of how many samples should be scraped from every Pod | `false` | +| `metrics.serviceMonitor.targetLimit` | Limit of how many targets should be scraped | `false` | +| `metrics.podMonitor.enabled` | Create PodMonitor resource(s) for scraping metrics using PrometheusOperator | `false` | +| `metrics.podMonitor.namespace` | The namespace in which the PodMonitor will be created | `""` | +| `metrics.podMonitor.interval` | The interval at which metrics should be scraped | `30s` | +| `metrics.podMonitor.scrapeTimeout` | The timeout after which the scrape is ended | `""` | +| `metrics.podMonitor.relabellings` | Metrics RelabelConfigs to apply to samples before scraping. | `[]` | +| `metrics.podMonitor.metricRelabelings` | Metrics RelabelConfigs to apply to samples before ingestion. | `[]` | +| `metrics.podMonitor.honorLabels` | Specify honorLabels parameter to add the scrape endpoint | `false` | +| `metrics.podMonitor.additionalLabels` | Additional labels that can be used so PodMonitor resource(s) can be discovered by Prometheus | `{}` | +| `metrics.podMonitor.podTargetLabels` | Labels from the Kubernetes pod to be transferred to the created metrics | `[]` | +| `metrics.podMonitor.sampleLimit` | Limit of how many samples should be scraped from every Pod | `false` | +| `metrics.podMonitor.targetLimit` | Limit of how many targets should be scraped | `false` | +| `metrics.prometheusRule.enabled` | Create a custom prometheusRule Resource for scraping metrics using PrometheusOperator | `false` | +| `metrics.prometheusRule.namespace` | The namespace in which the prometheusRule will be created | `""` | +| `metrics.prometheusRule.additionalLabels` | Additional labels for the prometheusRule | `{}` | +| `metrics.prometheusRule.rules` | Custom Prometheus rules | `[]` | + +### Init Container Parameters + +| Name | Description | Value | +| ------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------ | -------------------------- | +| `volumePermissions.enabled` | Enable init container that changes the owner/group of the PV mount point to `runAsUser:fsGroup` | `false` | +| `volumePermissions.image.registry` | OS Shell + Utility image registry | `REGISTRY_NAME` | +| `volumePermissions.image.repository` | OS Shell + Utility image repository | `REPOSITORY_NAME/os-shell` | +| `volumePermissions.image.digest` | OS Shell + Utility image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag | `""` | +| `volumePermissions.image.pullPolicy` | OS Shell + Utility image pull policy | `IfNotPresent` | +| `volumePermissions.image.pullSecrets` | OS Shell + Utility image pull secrets | `[]` | +| `volumePermissions.resources.limits` | The resources limits for the init container | `{}` | +| `volumePermissions.resources.requests` | The requested resources for the init container | `{}` | +| `volumePermissions.containerSecurityContext.runAsUser` | Set init container's Security Context runAsUser | `0` | +| `sysctl.enabled` | Enable init container to modify Kernel settings | `false` | +| `sysctl.image.registry` | OS Shell + Utility image registry | `REGISTRY_NAME` | +| `sysctl.image.repository` | OS Shell + Utility image repository | `REPOSITORY_NAME/os-shell` | +| `sysctl.image.digest` | OS Shell + Utility image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag | `""` | +| `sysctl.image.pullPolicy` | OS Shell + Utility image pull policy | `IfNotPresent` | +| `sysctl.image.pullSecrets` | OS Shell + Utility image pull secrets | `[]` | +| `sysctl.command` | Override default init-sysctl container command (useful when using custom images) | `[]` | +| `sysctl.mountHostSys` | Mount the host `/sys` folder to `/host-sys` | `false` | +| `sysctl.resources.limits` | The resources limits for the init container | `{}` | +| `sysctl.resources.requests` | The requested resources for the init container | `{}` | + +### useExternalDNS Parameters + +| Name | Description | Value | +| -------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------- | +| `useExternalDNS.enabled` | Enable various syntax that would enable external-dns to work. Note this requires a working installation of `external-dns` to be usable. | `false` | +| `useExternalDNS.additionalAnnotations` | Extra annotations to be utilized when `external-dns` is enabled. | `{}` | +| `useExternalDNS.annotationKey` | The annotation key utilized when `external-dns` is enabled. Setting this to `false` will disable annotations. | `external-dns.alpha.kubernetes.io/` | +| `useExternalDNS.suffix` | The DNS suffix utilized when `external-dns` is enabled. Note that we prepend the suffix with the full name of the release. | `""` | + +Specify each parameter using the `--set key=value[,key=value]` argument to `helm install`. For example, + +```console +helm install my-release \ + --set auth.password=secretpassword \ + oci://REGISTRY_NAME/REPOSITORY_NAME/redis +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. + +The above command sets the Redis® server password to `secretpassword`. + +> NOTE: Once this chart is deployed, it is not possible to change the application's access credentials, such as usernames or passwords, using Helm. To change these application credentials after deployment, delete any persistent volumes (PVs) used by the chart and re-deploy it, or use the application's built-in administrative tools if available. + +Alternatively, a YAML file that specifies the values for the parameters can be provided while installing the chart. For example, + +```console +helm install my-release -f values.yaml oci://REGISTRY_NAME/REPOSITORY_NAME/redis +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. +> **Tip**: You can use the default [values.yaml](values.yaml) + +## Configuration and installation details + +### [Rolling VS Immutable tags](https://docs.bitnami.com/containers/how-to/understand-rolling-tags-containers/) + +It is strongly recommended to use immutable tags in a production environment. This ensures your deployment does not change automatically if the same tag is updated with a different image. + +Bitnami will release a new chart updating its containers if a new version of the main container, significant changes, or critical vulnerabilities exist. + +### Use a different Redis® version + +To modify the application version used in this chart, specify a different version of the image using the `image.tag` parameter and/or a different repository using the `image.repository` parameter. Refer to the [chart documentation for more information on these parameters and how to use them with images from a private registry](https://docs.bitnami.com/kubernetes/infrastructure/redis/configuration/change-image-version/). + +### Bootstrapping with an External Cluster + +This chart is equipped with the ability to bring online a set of Pods that connect to an existing Redis deployment that lies outside of Kubernetes. This effectively creates a hybrid Redis Deployment where both Pods in Kubernetes and Instances such as Virtual Machines can partake in a single Redis Deployment. This is helpful in situations where one may be migrating Redis from Virtual Machines into Kubernetes, for example. To take advantage of this, use the following as an example configuration: + +```yaml +replica: + externalMaster: + enabled: true + host: external-redis-0.internal +sentinel: + externalMaster: + enabled: true + host: external-redis-0.internal +``` + +:warning: This is currently limited to clusters in which Sentinel and Redis run on the same node! :warning: + +Please also note that the external sentinel must be listening on port `26379`, and this is currently not configurable. + +Once the Kubernetes Redis Deployment is online and confirmed to be working with the existing cluster, the configuration can then be removed and the cluster will remain connected. + +### External DNS + +This chart is equipped to allow leveraging the ExternalDNS project. Doing so will enable ExternalDNS to publish the FQDN for each instance, in the format of `..`. +Example, when using the following configuration: + +```yaml +useExternalDNS: + enabled: true + suffix: prod.example.org + additionalAnnotations: + ttl: 10 +``` + +On a cluster where the name of the Helm release is `a`, the hostname of a Pod is generated as: `a-redis-node-0.a-redis.prod.example.org`. The IP of that FQDN will match that of the associated Pod. This modifies the following parameters of the Redis/Sentinel configuration using this new FQDN: + +- `replica-announce-ip` +- `known-sentinel` +- `known-replica` +- `announce-ip` + +:warning: This requires a working installation of `external-dns` to be fully functional. :warning: + +See the [official ExternalDNS documentation](https://github.com/kubernetes-sigs/external-dns) for additional configuration options. + +### Cluster topologies + +#### Default: Master-Replicas + +When installing the chart with `architecture=replication`, it will deploy a Redis® master StatefulSet and a Redis® replicas StatefulSet. The replicas will be read-replicas of the master. Two services will be exposed: + +- Redis® Master service: Points to the master, where read-write operations can be performed +- Redis® Replicas service: Points to the replicas, where only read operations are allowed by default. + +In case the master crashes, the replicas will wait until the master node is respawned again by the Kubernetes Controller Manager. + +#### Standalone + +When installing the chart with `architecture=standalone`, it will deploy a standalone Redis® StatefulSet. A single service will be exposed: + +- Redis® Master service: Points to the master, where read-write operations can be performed + +#### Master-Replicas with Sentinel + +When installing the chart with `architecture=replication` and `sentinel.enabled=true`, it will deploy a Redis® master StatefulSet (only one master allowed) and a Redis® replicas StatefulSet. In this case, the pods will contain an extra container with Redis® Sentinel. This container will form a cluster of Redis® Sentinel nodes, which will promote a new master in case the actual one fails. + +On graceful termination of the Redis® master pod, a failover of the master is initiated to promote a new master. The Redis® Sentinel container in this pod will wait for the failover to occur before terminating. If `sentinel.redisShutdownWaitFailover=true` is set (the default), the Redis® container will wait for the failover as well before terminating. This increases availability for reads during failover, but may cause stale reads until all clients have switched to the new master. + +In addition to this, only one service is exposed: + +- Redis® service: Exposes port 6379 for Redis® read-only operations and port 26379 for accessing Redis® Sentinel. + +For read-only operations, access the service using port 6379. For write operations, it's necessary to access the Redis® Sentinel cluster and query the current master using the command below (using redis-cli or similar): + +```console +SENTINEL get-master-addr-by-name +``` + +This command will return the address of the current master, which can be accessed from inside the cluster. + +In case the current master crashes, the Sentinel containers will elect a new master node. + +`master.count` greater than `1` is not designed for use when `sentinel.enabled=true`. + +### Multiple masters (experimental) + +When `master.count` is greater than `1`, special care must be taken to create a consistent setup. + +An example of use case is the creation of a redundant set of standalone masters or master-replicas per Kubernetes node where you must ensure: + +- No more than `1` master can be deployed per Kubernetes node +- Replicas and writers can only see the single master of their own Kubernetes node + +One way of achieving this is by setting `master.service.internalTrafficPolicy=Local` in combination with a `master.affinity.podAntiAffinity` spec to never schedule more than one master per Kubernetes node. + +It's recommended to only change `master.count` if you know what you are doing. +`master.count` greater than `1` is not designed for use when `sentinel.enabled=true`. + +### Using a password file + +To use a password file for Redis® you need to create a secret containing the password and then deploy the chart using that secret. + +Refer to the chart documentation for more information on [using a password file for Redis®](https://docs.bitnami.com/kubernetes/infrastructure/redis/administration/use-password-file/). + +### Securing traffic using TLS + +TLS support can be enabled in the chart by specifying the `tls.` parameters while creating a release. The following parameters should be configured to properly enable the TLS support in the chart: + +- `tls.enabled`: Enable TLS support. Defaults to `false` +- `tls.existingSecret`: Name of the secret that contains the certificates. No defaults. +- `tls.certFilename`: Certificate filename. No defaults. +- `tls.certKeyFilename`: Certificate key filename. No defaults. +- `tls.certCAFilename`: CA Certificate filename. No defaults. + +Refer to the chart documentation for more information on [creating the secret and a TLS deployment example](https://docs.bitnami.com/kubernetes/infrastructure/redis/administration/enable-tls/). + +### Metrics + +The chart optionally can start a metrics exporter for [prometheus](https://prometheus.io). The metrics endpoint (port 9121) is exposed in the service. Metrics can be scraped from within the cluster using something similar as the described in the [example Prometheus scrape configuration](https://github.com/prometheus/prometheus/blob/master/documentation/examples/prometheus-kubernetes.yml). If metrics are to be scraped from outside the cluster, the Kubernetes API proxy can be utilized to access the endpoint. + +If you have enabled TLS by specifying `tls.enabled=true` you also need to specify TLS option to the metrics exporter. You can do that via `metrics.extraArgs`. You can find the metrics exporter CLI flags for TLS [here](https://github.com/oliver006/redis_exporter#command-line-flags). For example: + +You can either specify `metrics.extraArgs.skip-tls-verification=true` to skip TLS verification or providing the following values under `metrics.extraArgs` for TLS client authentication: + +```console +tls-client-key-file +tls-client-cert-file +tls-ca-cert-file +``` + +### Host Kernel Settings + +Redis® may require some changes in the kernel of the host machine to work as expected, in particular increasing the `somaxconn` value and disabling transparent huge pages. + +Refer to the chart documentation for more information on [configuring host kernel settings with an example](https://docs.bitnami.com/kubernetes/infrastructure/redis/administration/configure-kernel-settings/). + +## Persistence + +By default, the chart mounts a [Persistent Volume](https://kubernetes.io/docs/concepts/storage/persistent-volumes/) at the `/data` path. The volume is created using dynamic volume provisioning. If a Persistent Volume Claim already exists, specify it during installation. + +### Existing PersistentVolumeClaim + +1. Create the PersistentVolume +2. Create the PersistentVolumeClaim +3. Install the chart + +```console +helm install my-release --set master.persistence.existingClaim=PVC_NAME oci://REGISTRY_NAME/REPOSITORY_NAME/redis +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. + +## Backup and restore + +Refer to the chart documentation for more information on [backing up and restoring Redis® deployments](https://docs.bitnami.com/kubernetes/infrastructure/redis/administration/backup-restore/). + +## NetworkPolicy + +To enable network policy for Redis®, 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 `true`. + +Refer to the chart documenation for more information on [enabling the network policy in Redis® deployments](https://docs.bitnami.com/kubernetes/infrastructure/redis/administration/enable-network-policy/). + +### Setting Pod's affinity + +This chart allows you to set your custom affinity using the `XXX.affinity` parameter(s). Find more information about Pod's affinity in the [Kubernetes documentation](https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity). + +As an alternative, you can use of the preset configurations for pod affinity, pod anti-affinity, and node affinity available at the [bitnami/common](https://github.com/bitnami/charts/tree/main/bitnami/common#affinities) chart. To do so, set the `XXX.podAffinityPreset`, `XXX.podAntiAffinityPreset`, or `XXX.nodeAffinityPreset` parameters. + +## Troubleshooting + +Find more information about how to deal with common errors related to Bitnami's Helm charts in [this troubleshooting guide](https://docs.bitnami.com/general/how-to/troubleshoot-helm-chart-issues). + +## Upgrading + +A major chart version change (like v1.2.3 -> v2.0.0) indicates that there is an incompatible breaking change needing manual actions. + +### RDB compatibility + +It's common to have RDB format changes across Redis® releases where we see backward compatibility but no forward compatibility. For example, v7.0 can load an RDB created by v6.2 , but the opposite is not true. +When that's the case, the rolling update can cause replicas to temporarily stop synchronizing while they are running a lower version than master. +For example, on a rolling update `master-0` and `replica-2` are updated first from version v6.2 to v7.0; `replica-0` and `replica-1` won't be able to start a full sync with `master-0` because they are still running v6.2 and can't support the RDB format from version 7.0 that master is now using. +This issue can be mitigated by splitting the upgrade into two stages: one for all replicas and another for any master. + +- Stage 1 (replicas only, as there's no master with an ordinal higher than 99): +`helm upgrade oci://REGISTRY_NAME/REPOSITORY_NAME/redis --set master.updateStrategy.rollingUpdate.partition=99` +- Stage 2 (anything else that is not up to date, in this case only master): +`helm upgrade oci://REGISTRY_NAME/REPOSITORY_NAME/redis` + +### To 18.0.0 + +This major version updates the Redis® docker image version used from `7.0` to `7.2`, the new stable version. There are no major changes in the chart, but we recommend checking the [Redis® 7.2 release notes](https://raw.githubusercontent.com/redis/redis/7.2/00-RELEASENOTES) before upgrading. + +NOTE: Due to an error in our release process, versions higher or equal than 17.15.4 already use 7.2 by default. + +### To 17.0.0 + +This major version updates the Redis® docker image version used from `6.2` to `7.0`, the new stable version. There are no major changes in the chart, but we recommend checking the [Redis® 7.0 release notes](https://raw.githubusercontent.com/redis/redis/7.0/00-RELEASENOTES) before upgrading. + +### To 16.0.0 + +This major release renames several values in this chart and adds missing features, in order to be inline with the rest of assets in the Bitnami charts repository. + +Affected values: + +- `master.service.port` renamed as `master.service.ports.redis`. +- `master.service.nodePort` renamed as `master.service.nodePorts.redis`. +- `replica.service.port` renamed as `replica.service.ports.redis`. +- `replica.service.nodePort` renamed as `replica.service.nodePorts.redis`. +- `sentinel.service.port` renamed as `sentinel.service.ports.redis`. +- `sentinel.service.sentinelPort` renamed as `sentinel.service.ports.sentinel`. +- `master.containerPort` renamed as `master.containerPorts.redis`. +- `replica.containerPort` renamed as `replica.containerPorts.redis`. +- `sentinel.containerPort` renamed as `sentinel.containerPorts.sentinel`. +- `master.spreadConstraints` renamed as `master.topologySpreadConstraints` +- `replica.spreadConstraints` renamed as `replica.topologySpreadConstraints` + +### To 15.0.0 + +The parameter to enable the usage of StaticIDs was removed. The behavior is to [always use StaticIDs](https://github.com/bitnami/charts/pull/7278). + +### To 14.8.0 + +The Redis® sentinel exporter was removed in this version because the upstream project was deprecated. The regular Redis® exporter is included in the sentinel scenario as usual. + +### To 14.0.0 + +- Several parameters were renamed or disappeared in favor of new ones on this major version: + - The term *slave* has been replaced by the term *replica*. Therefore, parameters prefixed with `slave` are now prefixed with `replicas`. + - Credentials parameter are reorganized under the `auth` parameter. + - `cluster.enabled` parameter is deprecated in favor of `architecture` parameter that accepts two values: `standalone` and `replication`. + - `securityContext.*` is deprecated in favor of `XXX.podSecurityContext` and `XXX.containerSecurityContext`. + - `sentinel.metrics.*` parameters are deprecated in favor of `metrics.sentinel.*` ones. +- New parameters to add custom command, environment variables, sidecars, init containers, etc. were added. +- Chart labels were adapted to follow the [Helm charts standard labels](https://helm.sh/docs/chart_best_practices/labels/#standard-labels). +- values.yaml metadata was adapted to follow the format supported by [Readme Generator for Helm](https://github.com/bitnami-labs/readme-generator-for-helm). + +Consequences: + +Backwards compatibility is not guaranteed. To upgrade to `14.0.0`, install a new release of the Redis® chart, and migrate the data from your previous release. You have 2 alternatives to do so: + +- Create a backup of the database, and restore it on the new release as explained in the [Backup and restore](#backup-and-restore) section. +- Reuse the PVC used to hold the master data on your previous release. To do so, use the `master.persistence.existingClaim` parameter. The following example assumes that the release name is `redis`: + +```console +helm install redis oci://REGISTRY_NAME/REPOSITORY_NAME/redis --set auth.password=[PASSWORD] --set master.persistence.existingClaim=[EXISTING_PVC] +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. + +| Note: you need to substitute the placeholder *[EXISTING_PVC]* with the name of the PVC used on your previous release, and *[PASSWORD]* with the password used in your previous release. + +### To 13.0.0 + +This major version updates the Redis® docker image version used from `6.0` to `6.2`, the new stable version. There are no major changes in the chart and there shouldn't be any breaking changes in it as `6.2` is basically a stricter superset of `6.0`. For more information, please refer to [Redis® 6.2 release notes](https://raw.githubusercontent.com/redis/redis/6.2/00-RELEASENOTES). + +### To 12.3.0 + +This version also introduces `bitnami/common`, a [library chart](https://helm.sh/docs/topics/library_charts/#helm) as a dependency. More documentation about this new utility could be found [here](https://github.com/bitnami/charts/tree/main/bitnami/common#bitnami-common-library-chart). Please, make sure that you have updated the chart dependencies before executing any upgrade. + +### To 12.0.0 + +[On November 13, 2020, Helm v2 support was formally finished](https://github.com/helm/charts#status-of-the-project), this major version is the result of the required changes applied to the Helm Chart to be able to incorporate the different features added in Helm v3 and to be consistent with the Helm project itself regarding the Helm v2 EOL. + +#### What changes were introduced in this major version? + +- Previous versions of this Helm Chart use `apiVersion: v1` (installable by both Helm 2 and 3), this Helm Chart was updated to `apiVersion: v2` (installable by Helm 3 only). [Here](https://helm.sh/docs/topics/charts/#the-apiversion-field) you can find more information about the `apiVersion` field. +- The different fields present in the *Chart.yaml* file has been ordered alphabetically in a homogeneous way for all the Bitnami Helm Charts + +#### Considerations when upgrading to this version + +- If you want to upgrade to this version from a previous one installed with Helm v3, you shouldn't face any issues +- If you want to upgrade to this version using Helm v2, this scenario is not supported as this version doesn't support Helm v2 anymore +- If you installed the previous version with Helm v2 and wants to upgrade to this version with Helm v3, please refer to the [official Helm documentation](https://helm.sh/docs/topics/v2_v3_migration/#migration-use-cases) about migrating from Helm v2 to v3 + +#### Useful links + +- +- +- + +### To 11.0.0 + +When using sentinel, a new statefulset called `-node` was introduced. This will break upgrading from a previous version where the statefulsets are called master and slave. Hence the PVC will not match the new naming and won't be reused. If you want to keep your data, you will need to perform a backup and then a restore the data in this new version. + +When deployed with sentinel enabled, only a group of nodes is deployed and the master/slave role is handled in the group. To avoid breaking the compatibility, the settings for this nodes are given through the `slave.xxxx` parameters in `values.yaml` + +### To 10.0.0 + +For releases with `usePassword: true`, the value `sentinel.usePassword` controls whether the password authentication also applies to the sentinel port. This defaults to `true` for a secure configuration, however it is possible to disable to account for the following cases: + +- Using a version of redis-sentinel prior to `5.0.1` where the authentication feature was introduced. +- Where redis clients need to be updated to support sentinel authentication. + +If using a master/slave topology, or with `usePassword: false`, no action is required. + +### To 9.0.0 + +The metrics exporter has been changed from a separate deployment to a sidecar container, due to the latest changes in the Redis® exporter code. Check the [official page](https://github.com/oliver006/redis_exporter/) for more information. The metrics container image was changed from oliver006/redis_exporter to bitnami/redis-exporter (Bitnami's maintained package of oliver006/redis_exporter). + +### To 8.0.18 + +For releases with `metrics.enabled: true` the default tag for the exporter image is now `v1.x.x`. This introduces many changes including metrics names. You'll want to use [this dashboard](https://github.com/oliver006/redis_exporter/blob/master/contrib/grafana_prometheus_redis_dashboard.json) now. Please see the [redis_exporter github page](https://github.com/oliver006/redis_exporter#upgrading-from-0x-to-1x) for more details. + +### To 7.0.0 + +This version causes a change in the Redis® Master StatefulSet definition, so the command helm upgrade would not work out of the box. As an alternative, one of the following could be done: + +- Recommended: Create a clone of the Redis® Master PVC (for example, using projects like [this one](https://github.com/edseymour/pvc-transfer)). Then launch a fresh release reusing this cloned PVC. + +```console +helm install my-release oci://REGISTRY_NAME/REPOSITORY_NAME/redis --set persistence.existingClaim= +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. + +- Alternative (not recommended, do at your own risk): `helm delete --purge` does not remove the PVC assigned to the Redis® Master StatefulSet. As a consequence, the following commands can be done to upgrade the release + +```console +helm delete --purge +helm install oci://REGISTRY_NAME/REPOSITORY_NAME/redis +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. + +Previous versions of the chart were not using persistence in the slaves, so this upgrade would add it to them. Another important change is that no values are inherited from master to slaves. For example, in 6.0.0 `slaves.readinessProbe.periodSeconds`, if empty, would be set to `master.readinessProbe.periodSeconds`. This approach lacked transparency and was difficult to maintain. From now on, all the slave parameters must be configured just as it is done with the masters. + +Some values have changed as well: + +- `master.port` and `slave.port` have been changed to `redisPort` (same value for both master and slaves) +- `master.securityContext` and `slave.securityContext` have been changed to `securityContext`(same values for both master and slaves) + +By default, the upgrade will not change the cluster topology. In case you want to use Redis® Sentinel, you must explicitly set `sentinel.enabled` to `true`. + +### To 6.0.0 + +Previous versions of the chart were using an init-container to change the permissions of the volumes. This was done in case the `securityContext` directive in the template was not enough for that (for example, with cephFS). In this new version of the chart, this container is disabled by default (which should not affect most of the deployments). If your installation still requires that init container, execute `helm upgrade` with the `--set volumePermissions.enabled=true`. + +### To 5.0.0 + +The default image in this release may be switched out for any image containing the `redis-server` +and `redis-cli` binaries. If `redis-server` is not the default image ENTRYPOINT, `master.command` +must be specified. + +#### Breaking changes + +- `master.args` and `slave.args` are removed. Use `master.command` or `slave.command` instead in order to override the image entrypoint, or `master.extraFlags` to pass additional flags to `redis-server`. +- `disableCommands` is now interpreted as an array of strings instead of a string of comma separated values. +- `master.persistence.path` now defaults to `/data`. + +### To 4.0.0 + +This version removes the `chart` label from the `spec.selector.matchLabels` +which is immutable since `StatefulSet apps/v1beta2`. It has been inadvertently +added, causing any subsequent upgrade to fail. See . + +It also fixes where a deployment `extensions/v1beta1` can not be upgraded if `spec.selector` is not explicitly set. + +Finally, it fixes by removing mutable labels in `spec.VolumeClaimTemplate.metadata.labels` so that it is upgradable. + +In order to upgrade, delete the Redis® StatefulSet before upgrading: + +```console +kubectl delete statefulsets.apps --cascade=false my-release-redis-master +``` + +And edit the Redis® slave (and metrics if enabled) deployment: + +```console +kubectl patch deployments my-release-redis-slave --type=json -p='[{"op": "remove", "path": "/spec/selector/matchLabels/chart"}]' +kubectl patch deployments my-release-redis-metrics --type=json -p='[{"op": "remove", "path": "/spec/selector/matchLabels/chart"}]' +``` + +## License + +Copyright © 2023 VMware, Inc. + +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 + + + +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. \ No newline at end of file diff --git a/packages/system/dashboard/charts/kubeapps/charts/redis/charts/common/.helmignore b/packages/system/dashboard/charts/kubeapps/charts/redis/charts/common/.helmignore new file mode 100644 index 00000000..50af0317 --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/charts/redis/charts/common/.helmignore @@ -0,0 +1,22 @@ +# 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 +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/packages/system/dashboard/charts/kubeapps/charts/redis/charts/common/Chart.yaml b/packages/system/dashboard/charts/kubeapps/charts/redis/charts/common/Chart.yaml new file mode 100644 index 00000000..40cd22d7 --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/charts/redis/charts/common/Chart.yaml @@ -0,0 +1,23 @@ +annotations: + category: Infrastructure + licenses: Apache-2.0 +apiVersion: v2 +appVersion: 2.13.3 +description: A Library Helm Chart for grouping common logic between bitnami charts. + This chart is not deployable by itself. +home: https://bitnami.com +icon: https://bitnami.com/downloads/logos/bitnami-mark.png +keywords: +- common +- helper +- template +- function +- bitnami +maintainers: +- name: VMware, Inc. + url: https://github.com/bitnami/charts +name: common +sources: +- https://github.com/bitnami/charts +type: library +version: 2.13.3 diff --git a/packages/system/dashboard/charts/kubeapps/charts/redis/charts/common/README.md b/packages/system/dashboard/charts/kubeapps/charts/redis/charts/common/README.md new file mode 100644 index 00000000..80da4cc2 --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/charts/redis/charts/common/README.md @@ -0,0 +1,235 @@ +# Bitnami Common Library Chart + +A [Helm Library Chart](https://helm.sh/docs/topics/library_charts/#helm) for grouping common logic between Bitnami charts. + +## TL;DR + +```yaml +dependencies: + - name: common + version: 2.x.x + repository: oci://registry-1.docker.io/bitnamicharts +``` + +```console +helm dependency update +``` + +```yaml +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "common.names.fullname" . }} +data: + myvalue: "Hello World" +``` + +## Introduction + +This chart provides a common template helpers which can be used to develop new charts using [Helm](https://helm.sh) package manager. + +Bitnami charts can be used with [Kubeapps](https://kubeapps.dev/) for deployment and management of Helm Charts in clusters. + +Looking to use our applications in production? Try [VMware Application Catalog](https://bitnami.com/enterprise), the enterprise edition of Bitnami Application Catalog. + +## Prerequisites + +- Kubernetes 1.23+ +- Helm 3.8.0+ + +## Parameters + +## Special input schemas + +### ImageRoot + +```yaml +registry: + type: string + description: Docker registry where the image is located + example: docker.io + +repository: + type: string + description: Repository and image name + example: bitnami/nginx + +tag: + type: string + description: image tag + example: 1.16.1-debian-10-r63 + +pullPolicy: + type: string + description: Specify a imagePullPolicy. Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent' + +pullSecrets: + type: array + items: + type: string + description: Optionally specify an array of imagePullSecrets (evaluated as templates). + +debug: + type: boolean + description: Set to true if you would like to see extra information on logs + example: false + +## An instance would be: +# registry: docker.io +# repository: bitnami/nginx +# tag: 1.16.1-debian-10-r63 +# pullPolicy: IfNotPresent +# debug: false +``` + +### Persistence + +```yaml +enabled: + type: boolean + description: Whether enable persistence. + example: true + +storageClass: + type: string + description: Ghost data Persistent Volume Storage Class, If set to "-", storageClassName: "" which disables dynamic provisioning. + example: "-" + +accessMode: + type: string + description: Access mode for the Persistent Volume Storage. + example: ReadWriteOnce + +size: + type: string + description: Size the Persistent Volume Storage. + example: 8Gi + +path: + type: string + description: Path to be persisted. + example: /bitnami + +## An instance would be: +# enabled: true +# storageClass: "-" +# accessMode: ReadWriteOnce +# size: 8Gi +# path: /bitnami +``` + +### ExistingSecret + +```yaml +name: + type: string + description: Name of the existing secret. + example: mySecret +keyMapping: + description: Mapping between the expected key name and the name of the key in the existing secret. + type: object + +## An instance would be: +# name: mySecret +# keyMapping: +# password: myPasswordKey +``` + +#### Example of use + +When we store sensitive data for a deployment in a secret, some times we want to give to users the possibility of using theirs existing secrets. + +```yaml +# templates/secret.yaml +--- +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "common.names.fullname" . }} + labels: + app: {{ include "common.names.fullname" . }} +type: Opaque +data: + password: {{ .Values.password | b64enc | quote }} + +# templates/dpl.yaml +--- +... + env: + - name: PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "common.secrets.name" (dict "existingSecret" .Values.existingSecret "context" $) }} + key: {{ include "common.secrets.key" (dict "existingSecret" .Values.existingSecret "key" "password") }} +... + +# values.yaml +--- +name: mySecret +keyMapping: + password: myPasswordKey +``` + +### ValidateValue + +#### NOTES.txt + +```console +{{- $validateValueConf00 := (dict "valueKey" "path.to.value00" "secret" "secretName" "field" "password-00") -}} +{{- $validateValueConf01 := (dict "valueKey" "path.to.value01" "secret" "secretName" "field" "password-01") -}} + +{{ include "common.validations.values.multiple.empty" (dict "required" (list $validateValueConf00 $validateValueConf01) "context" $) }} +``` + +If we force those values to be empty we will see some alerts + +```console +helm install test mychart --set path.to.value00="",path.to.value01="" + 'path.to.value00' must not be empty, please add '--set path.to.value00=$PASSWORD_00' to the command. To get the current value: + + export PASSWORD_00=$(kubectl get secret --namespace default secretName -o jsonpath="{.data.password-00}" | base64 -d) + + 'path.to.value01' must not be empty, please add '--set path.to.value01=$PASSWORD_01' to the command. To get the current value: + + export PASSWORD_01=$(kubectl get secret --namespace default secretName -o jsonpath="{.data.password-01}" | base64 -d) +``` + +## Upgrading + +### To 1.0.0 + +[On November 13, 2020, Helm v2 support was formally finished](https://github.com/helm/charts#status-of-the-project), this major version is the result of the required changes applied to the Helm Chart to be able to incorporate the different features added in Helm v3 and to be consistent with the Helm project itself regarding the Helm v2 EOL. + +#### What changes were introduced in this major version? + +- Previous versions of this Helm Chart use `apiVersion: v1` (installable by both Helm 2 and 3), this Helm Chart was updated to `apiVersion: v2` (installable by Helm 3 only). [Here](https://helm.sh/docs/topics/charts/#the-apiversion-field) you can find more information about the `apiVersion` field. +- Use `type: library`. [Here](https://v3.helm.sh/docs/faq/#library-chart-support) you can find more information. +- The different fields present in the *Chart.yaml* file has been ordered alphabetically in a homogeneous way for all the Bitnami Helm Charts + +#### Considerations when upgrading to this version + +- If you want to upgrade to this version from a previous one installed with Helm v3, you shouldn't face any issues +- If you want to upgrade to this version using Helm v2, this scenario is not supported as this version doesn't support Helm v2 anymore +- If you installed the previous version with Helm v2 and wants to upgrade to this version with Helm v3, please refer to the [official Helm documentation](https://helm.sh/docs/topics/v2_v3_migration/#migration-use-cases) about migrating from Helm v2 to v3 + +#### Useful links + +- +- +- + +## License + +Copyright © 2023 VMware, Inc. + +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 + + + +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/packages/system/dashboard/charts/kubeapps/charts/redis/charts/common/templates/_affinities.tpl b/packages/system/dashboard/charts/kubeapps/charts/redis/charts/common/templates/_affinities.tpl new file mode 100644 index 00000000..e85b1df4 --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/charts/redis/charts/common/templates/_affinities.tpl @@ -0,0 +1,139 @@ +{{/* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Return a soft nodeAffinity definition +{{ include "common.affinities.nodes.soft" (dict "key" "FOO" "values" (list "BAR" "BAZ")) -}} +*/}} +{{- define "common.affinities.nodes.soft" -}} +preferredDuringSchedulingIgnoredDuringExecution: + - preference: + matchExpressions: + - key: {{ .key }} + operator: In + values: + {{- range .values }} + - {{ . | quote }} + {{- end }} + weight: 1 +{{- end -}} + +{{/* +Return a hard nodeAffinity definition +{{ include "common.affinities.nodes.hard" (dict "key" "FOO" "values" (list "BAR" "BAZ")) -}} +*/}} +{{- define "common.affinities.nodes.hard" -}} +requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: {{ .key }} + operator: In + values: + {{- range .values }} + - {{ . | quote }} + {{- end }} +{{- end -}} + +{{/* +Return a nodeAffinity definition +{{ include "common.affinities.nodes" (dict "type" "soft" "key" "FOO" "values" (list "BAR" "BAZ")) -}} +*/}} +{{- define "common.affinities.nodes" -}} + {{- if eq .type "soft" }} + {{- include "common.affinities.nodes.soft" . -}} + {{- else if eq .type "hard" }} + {{- include "common.affinities.nodes.hard" . -}} + {{- end -}} +{{- end -}} + +{{/* +Return a topologyKey definition +{{ include "common.affinities.topologyKey" (dict "topologyKey" "BAR") -}} +*/}} +{{- define "common.affinities.topologyKey" -}} +{{ .topologyKey | default "kubernetes.io/hostname" -}} +{{- end -}} + +{{/* +Return a soft podAffinity/podAntiAffinity definition +{{ include "common.affinities.pods.soft" (dict "component" "FOO" "customLabels" .Values.podLabels "extraMatchLabels" .Values.extraMatchLabels "topologyKey" "BAR" "extraPodAffinityTerms" .Values.extraPodAffinityTerms "context" $) -}} +*/}} +{{- define "common.affinities.pods.soft" -}} +{{- $component := default "" .component -}} +{{- $customLabels := default (dict) .customLabels -}} +{{- $extraMatchLabels := default (dict) .extraMatchLabels -}} +{{- $extraPodAffinityTerms := default (list) .extraPodAffinityTerms -}} +preferredDuringSchedulingIgnoredDuringExecution: + - podAffinityTerm: + labelSelector: + matchLabels: {{- (include "common.labels.matchLabels" ( dict "customLabels" $customLabels "context" .context )) | nindent 10 }} + {{- if not (empty $component) }} + {{ printf "app.kubernetes.io/component: %s" $component }} + {{- end }} + {{- range $key, $value := $extraMatchLabels }} + {{ $key }}: {{ $value | quote }} + {{- end }} + topologyKey: {{ include "common.affinities.topologyKey" (dict "topologyKey" .topologyKey) }} + weight: 1 + {{- range $extraPodAffinityTerms }} + - podAffinityTerm: + labelSelector: + matchLabels: {{- (include "common.labels.matchLabels" ( dict "customLabels" $customLabels "context" $.context )) | nindent 10 }} + {{- if not (empty $component) }} + {{ printf "app.kubernetes.io/component: %s" $component }} + {{- end }} + {{- range $key, $value := .extraMatchLabels }} + {{ $key }}: {{ $value | quote }} + {{- end }} + topologyKey: {{ include "common.affinities.topologyKey" (dict "topologyKey" .topologyKey) }} + weight: {{ .weight | default 1 -}} + {{- end -}} +{{- end -}} + +{{/* +Return a hard podAffinity/podAntiAffinity definition +{{ include "common.affinities.pods.hard" (dict "component" "FOO" "customLabels" .Values.podLabels "extraMatchLabels" .Values.extraMatchLabels "topologyKey" "BAR" "extraPodAffinityTerms" .Values.extraPodAffinityTerms "context" $) -}} +*/}} +{{- define "common.affinities.pods.hard" -}} +{{- $component := default "" .component -}} +{{- $customLabels := default (dict) .customLabels -}} +{{- $extraMatchLabels := default (dict) .extraMatchLabels -}} +{{- $extraPodAffinityTerms := default (list) .extraPodAffinityTerms -}} +requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchLabels: {{- (include "common.labels.matchLabels" ( dict "customLabels" $customLabels "context" .context )) | nindent 8 }} + {{- if not (empty $component) }} + {{ printf "app.kubernetes.io/component: %s" $component }} + {{- end }} + {{- range $key, $value := $extraMatchLabels }} + {{ $key }}: {{ $value | quote }} + {{- end }} + topologyKey: {{ include "common.affinities.topologyKey" (dict "topologyKey" .topologyKey) }} + {{- range $extraPodAffinityTerms }} + - labelSelector: + matchLabels: {{- (include "common.labels.matchLabels" ( dict "customLabels" $customLabels "context" $.context )) | nindent 8 }} + {{- if not (empty $component) }} + {{ printf "app.kubernetes.io/component: %s" $component }} + {{- end }} + {{- range $key, $value := .extraMatchLabels }} + {{ $key }}: {{ $value | quote }} + {{- end }} + topologyKey: {{ include "common.affinities.topologyKey" (dict "topologyKey" .topologyKey) }} + {{- end -}} +{{- end -}} + +{{/* +Return a podAffinity/podAntiAffinity definition +{{ include "common.affinities.pods" (dict "type" "soft" "key" "FOO" "values" (list "BAR" "BAZ")) -}} +*/}} +{{- define "common.affinities.pods" -}} + {{- if eq .type "soft" }} + {{- include "common.affinities.pods.soft" . -}} + {{- else if eq .type "hard" }} + {{- include "common.affinities.pods.hard" . -}} + {{- end -}} +{{- end -}} diff --git a/packages/system/dashboard/charts/kubeapps/charts/redis/charts/common/templates/_capabilities.tpl b/packages/system/dashboard/charts/kubeapps/charts/redis/charts/common/templates/_capabilities.tpl new file mode 100644 index 00000000..115674af --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/charts/redis/charts/common/templates/_capabilities.tpl @@ -0,0 +1,229 @@ +{{/* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Return the target Kubernetes version +*/}} +{{- define "common.capabilities.kubeVersion" -}} +{{- if .Values.global }} + {{- if .Values.global.kubeVersion }} + {{- .Values.global.kubeVersion -}} + {{- else }} + {{- default .Capabilities.KubeVersion.Version .Values.kubeVersion -}} + {{- end -}} +{{- else }} +{{- default .Capabilities.KubeVersion.Version .Values.kubeVersion -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for poddisruptionbudget. +*/}} +{{- define "common.capabilities.policy.apiVersion" -}} +{{- if semverCompare "<1.21-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "policy/v1beta1" -}} +{{- else -}} +{{- print "policy/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for networkpolicy. +*/}} +{{- define "common.capabilities.networkPolicy.apiVersion" -}} +{{- if semverCompare "<1.7-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "extensions/v1beta1" -}} +{{- else -}} +{{- print "networking.k8s.io/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for cronjob. +*/}} +{{- define "common.capabilities.cronjob.apiVersion" -}} +{{- if semverCompare "<1.21-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "batch/v1beta1" -}} +{{- else -}} +{{- print "batch/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for daemonset. +*/}} +{{- define "common.capabilities.daemonset.apiVersion" -}} +{{- if semverCompare "<1.14-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "extensions/v1beta1" -}} +{{- else -}} +{{- print "apps/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for deployment. +*/}} +{{- define "common.capabilities.deployment.apiVersion" -}} +{{- if semverCompare "<1.14-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "extensions/v1beta1" -}} +{{- else -}} +{{- print "apps/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for statefulset. +*/}} +{{- define "common.capabilities.statefulset.apiVersion" -}} +{{- if semverCompare "<1.14-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "apps/v1beta1" -}} +{{- else -}} +{{- print "apps/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for ingress. +*/}} +{{- define "common.capabilities.ingress.apiVersion" -}} +{{- if .Values.ingress -}} +{{- if .Values.ingress.apiVersion -}} +{{- .Values.ingress.apiVersion -}} +{{- else if semverCompare "<1.14-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "extensions/v1beta1" -}} +{{- else if semverCompare "<1.19-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "networking.k8s.io/v1beta1" -}} +{{- else -}} +{{- print "networking.k8s.io/v1" -}} +{{- end }} +{{- else if semverCompare "<1.14-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "extensions/v1beta1" -}} +{{- else if semverCompare "<1.19-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "networking.k8s.io/v1beta1" -}} +{{- else -}} +{{- print "networking.k8s.io/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for RBAC resources. +*/}} +{{- define "common.capabilities.rbac.apiVersion" -}} +{{- if semverCompare "<1.17-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "rbac.authorization.k8s.io/v1beta1" -}} +{{- else -}} +{{- print "rbac.authorization.k8s.io/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for CRDs. +*/}} +{{- define "common.capabilities.crd.apiVersion" -}} +{{- if semverCompare "<1.19-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "apiextensions.k8s.io/v1beta1" -}} +{{- else -}} +{{- print "apiextensions.k8s.io/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for APIService. +*/}} +{{- define "common.capabilities.apiService.apiVersion" -}} +{{- if semverCompare "<1.10-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "apiregistration.k8s.io/v1beta1" -}} +{{- else -}} +{{- print "apiregistration.k8s.io/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for Horizontal Pod Autoscaler. +*/}} +{{- define "common.capabilities.hpa.apiVersion" -}} +{{- if semverCompare "<1.23-0" (include "common.capabilities.kubeVersion" .context) -}} +{{- if .beta2 -}} +{{- print "autoscaling/v2beta2" -}} +{{- else -}} +{{- print "autoscaling/v2beta1" -}} +{{- end -}} +{{- else -}} +{{- print "autoscaling/v2" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for Vertical Pod Autoscaler. +*/}} +{{- define "common.capabilities.vpa.apiVersion" -}} +{{- if semverCompare "<1.23-0" (include "common.capabilities.kubeVersion" .context) -}} +{{- if .beta2 -}} +{{- print "autoscaling/v2beta2" -}} +{{- else -}} +{{- print "autoscaling/v2beta1" -}} +{{- end -}} +{{- else -}} +{{- print "autoscaling/v2" -}} +{{- end -}} +{{- end -}} + +{{/* +Returns true if PodSecurityPolicy is supported +*/}} +{{- define "common.capabilities.psp.supported" -}} +{{- if semverCompare "<1.25-0" (include "common.capabilities.kubeVersion" .) -}} + {{- true -}} +{{- end -}} +{{- end -}} + +{{/* +Returns true if AdmissionConfiguration is supported +*/}} +{{- define "common.capabilities.admissionConfiguration.supported" -}} +{{- if semverCompare ">=1.23-0" (include "common.capabilities.kubeVersion" .) -}} + {{- true -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for AdmissionConfiguration. +*/}} +{{- define "common.capabilities.admissionConfiguration.apiVersion" -}} +{{- if semverCompare "<1.23-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "apiserver.config.k8s.io/v1alpha1" -}} +{{- else if semverCompare "<1.25-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "apiserver.config.k8s.io/v1beta1" -}} +{{- else -}} +{{- print "apiserver.config.k8s.io/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for PodSecurityConfiguration. +*/}} +{{- define "common.capabilities.podSecurityConfiguration.apiVersion" -}} +{{- if semverCompare "<1.23-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "pod-security.admission.config.k8s.io/v1alpha1" -}} +{{- else if semverCompare "<1.25-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "pod-security.admission.config.k8s.io/v1beta1" -}} +{{- else -}} +{{- print "pod-security.admission.config.k8s.io/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Returns true if the used Helm version is 3.3+. +A way to check the used Helm version was not introduced until version 3.3.0 with .Capabilities.HelmVersion, which contains an additional "{}}" structure. +This check is introduced as a regexMatch instead of {{ if .Capabilities.HelmVersion }} because checking for the key HelmVersion in <3.3 results in a "interface not found" error. +**To be removed when the catalog's minimun Helm version is 3.3** +*/}} +{{- define "common.capabilities.supportsHelmVersion" -}} +{{- if regexMatch "{(v[0-9])*[^}]*}}$" (.Capabilities | toString ) }} + {{- true -}} +{{- end -}} +{{- end -}} diff --git a/packages/system/dashboard/charts/kubeapps/charts/redis/charts/common/templates/_errors.tpl b/packages/system/dashboard/charts/kubeapps/charts/redis/charts/common/templates/_errors.tpl new file mode 100644 index 00000000..07ded6f6 --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/charts/redis/charts/common/templates/_errors.tpl @@ -0,0 +1,28 @@ +{{/* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Through error when upgrading using empty passwords values that must not be empty. + +Usage: +{{- $validationError00 := include "common.validations.values.single.empty" (dict "valueKey" "path.to.password00" "secret" "secretName" "field" "password-00") -}} +{{- $validationError01 := include "common.validations.values.single.empty" (dict "valueKey" "path.to.password01" "secret" "secretName" "field" "password-01") -}} +{{ include "common.errors.upgrade.passwords.empty" (dict "validationErrors" (list $validationError00 $validationError01) "context" $) }} + +Required password params: + - validationErrors - String - Required. List of validation strings to be return, if it is empty it won't throw error. + - context - Context - Required. Parent context. +*/}} +{{- define "common.errors.upgrade.passwords.empty" -}} + {{- $validationErrors := join "" .validationErrors -}} + {{- if and $validationErrors .context.Release.IsUpgrade -}} + {{- $errorString := "\nPASSWORDS ERROR: You must provide your current passwords when upgrading the release." -}} + {{- $errorString = print $errorString "\n Note that even after reinstallation, old credentials may be needed as they may be kept in persistent volume claims." -}} + {{- $errorString = print $errorString "\n Further information can be obtained at https://docs.bitnami.com/general/how-to/troubleshoot-helm-chart-issues/#credential-errors-while-upgrading-chart-releases" -}} + {{- $errorString = print $errorString "\n%s" -}} + {{- printf $errorString $validationErrors | fail -}} + {{- end -}} +{{- end -}} diff --git a/packages/system/dashboard/charts/kubeapps/charts/redis/charts/common/templates/_images.tpl b/packages/system/dashboard/charts/kubeapps/charts/redis/charts/common/templates/_images.tpl new file mode 100644 index 00000000..1bcb779d --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/charts/redis/charts/common/templates/_images.tpl @@ -0,0 +1,117 @@ +{{/* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Return the proper image name +{{ include "common.images.image" ( dict "imageRoot" .Values.path.to.the.image "global" .Values.global ) }} +*/}} +{{- define "common.images.image" -}} +{{- $registryName := .imageRoot.registry -}} +{{- $repositoryName := .imageRoot.repository -}} +{{- $separator := ":" -}} +{{- $termination := .imageRoot.tag | toString -}} +{{- if .global }} + {{- if .global.imageRegistry }} + {{- $registryName = .global.imageRegistry -}} + {{- end -}} +{{- end -}} +{{- if .imageRoot.digest }} + {{- $separator = "@" -}} + {{- $termination = .imageRoot.digest | toString -}} +{{- end -}} +{{- if $registryName }} + {{- printf "%s/%s%s%s" $registryName $repositoryName $separator $termination -}} +{{- else -}} + {{- printf "%s%s%s" $repositoryName $separator $termination -}} +{{- end -}} +{{- end -}} + +{{/* +Return the proper Docker Image Registry Secret Names (deprecated: use common.images.renderPullSecrets instead) +{{ include "common.images.pullSecrets" ( dict "images" (list .Values.path.to.the.image1, .Values.path.to.the.image2) "global" .Values.global) }} +*/}} +{{- define "common.images.pullSecrets" -}} + {{- $pullSecrets := list }} + + {{- if .global }} + {{- range .global.imagePullSecrets -}} + {{- if kindIs "map" . -}} + {{- $pullSecrets = append $pullSecrets .name -}} + {{- else -}} + {{- $pullSecrets = append $pullSecrets . -}} + {{- end }} + {{- end -}} + {{- end -}} + + {{- range .images -}} + {{- range .pullSecrets -}} + {{- if kindIs "map" . -}} + {{- $pullSecrets = append $pullSecrets .name -}} + {{- else -}} + {{- $pullSecrets = append $pullSecrets . -}} + {{- end -}} + {{- end -}} + {{- end -}} + + {{- if (not (empty $pullSecrets)) }} +imagePullSecrets: + {{- range $pullSecrets | uniq }} + - name: {{ . }} + {{- end }} + {{- end }} +{{- end -}} + +{{/* +Return the proper Docker Image Registry Secret Names evaluating values as templates +{{ include "common.images.renderPullSecrets" ( dict "images" (list .Values.path.to.the.image1, .Values.path.to.the.image2) "context" $) }} +*/}} +{{- define "common.images.renderPullSecrets" -}} + {{- $pullSecrets := list }} + {{- $context := .context }} + + {{- if $context.Values.global }} + {{- range $context.Values.global.imagePullSecrets -}} + {{- if kindIs "map" . -}} + {{- $pullSecrets = append $pullSecrets (include "common.tplvalues.render" (dict "value" .name "context" $context)) -}} + {{- else -}} + {{- $pullSecrets = append $pullSecrets (include "common.tplvalues.render" (dict "value" . "context" $context)) -}} + {{- end -}} + {{- end -}} + {{- end -}} + + {{- range .images -}} + {{- range .pullSecrets -}} + {{- if kindIs "map" . -}} + {{- $pullSecrets = append $pullSecrets (include "common.tplvalues.render" (dict "value" .name "context" $context)) -}} + {{- else -}} + {{- $pullSecrets = append $pullSecrets (include "common.tplvalues.render" (dict "value" . "context" $context)) -}} + {{- end -}} + {{- end -}} + {{- end -}} + + {{- if (not (empty $pullSecrets)) }} +imagePullSecrets: + {{- range $pullSecrets | uniq }} + - name: {{ . }} + {{- end }} + {{- end }} +{{- end -}} + +{{/* +Return the proper image version (ingores image revision/prerelease info & fallbacks to chart appVersion) +{{ include "common.images.version" ( dict "imageRoot" .Values.path.to.the.image "chart" .Chart ) }} +*/}} +{{- define "common.images.version" -}} +{{- $imageTag := .imageRoot.tag | toString -}} +{{/* regexp from https://github.com/Masterminds/semver/blob/23f51de38a0866c5ef0bfc42b3f735c73107b700/version.go#L41-L44 */}} +{{- if regexMatch `^([0-9]+)(\.[0-9]+)?(\.[0-9]+)?(-([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?(\+([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?$` $imageTag -}} + {{- $version := semver $imageTag -}} + {{- printf "%d.%d.%d" $version.Major $version.Minor $version.Patch -}} +{{- else -}} + {{- print .chart.AppVersion -}} +{{- end -}} +{{- end -}} + diff --git a/packages/system/dashboard/charts/kubeapps/charts/redis/charts/common/templates/_ingress.tpl b/packages/system/dashboard/charts/kubeapps/charts/redis/charts/common/templates/_ingress.tpl new file mode 100644 index 00000000..efa5b85c --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/charts/redis/charts/common/templates/_ingress.tpl @@ -0,0 +1,73 @@ +{{/* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Generate backend entry that is compatible with all Kubernetes API versions. + +Usage: +{{ include "common.ingress.backend" (dict "serviceName" "backendName" "servicePort" "backendPort" "context" $) }} + +Params: + - serviceName - String. Name of an existing service backend + - servicePort - String/Int. Port name (or number) of the service. It will be translated to different yaml depending if it is a string or an integer. + - context - Dict - Required. The context for the template evaluation. +*/}} +{{- define "common.ingress.backend" -}} +{{- $apiVersion := (include "common.capabilities.ingress.apiVersion" .context) -}} +{{- if or (eq $apiVersion "extensions/v1beta1") (eq $apiVersion "networking.k8s.io/v1beta1") -}} +serviceName: {{ .serviceName }} +servicePort: {{ .servicePort }} +{{- else -}} +service: + name: {{ .serviceName }} + port: + {{- if typeIs "string" .servicePort }} + name: {{ .servicePort }} + {{- else if or (typeIs "int" .servicePort) (typeIs "float64" .servicePort) }} + number: {{ .servicePort | int }} + {{- end }} +{{- end -}} +{{- end -}} + +{{/* +Print "true" if the API pathType field is supported +Usage: +{{ include "common.ingress.supportsPathType" . }} +*/}} +{{- define "common.ingress.supportsPathType" -}} +{{- if (semverCompare "<1.18-0" (include "common.capabilities.kubeVersion" .)) -}} +{{- print "false" -}} +{{- else -}} +{{- print "true" -}} +{{- end -}} +{{- end -}} + +{{/* +Returns true if the ingressClassname field is supported +Usage: +{{ include "common.ingress.supportsIngressClassname" . }} +*/}} +{{- define "common.ingress.supportsIngressClassname" -}} +{{- if semverCompare "<1.18-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "false" -}} +{{- else -}} +{{- print "true" -}} +{{- end -}} +{{- end -}} + +{{/* +Return true if cert-manager required annotations for TLS signed +certificates are set in the Ingress annotations +Ref: https://cert-manager.io/docs/usage/ingress/#supported-annotations +Usage: +{{ include "common.ingress.certManagerRequest" ( dict "annotations" .Values.path.to.the.ingress.annotations ) }} +*/}} +{{- define "common.ingress.certManagerRequest" -}} +{{ if or (hasKey .annotations "cert-manager.io/cluster-issuer") (hasKey .annotations "cert-manager.io/issuer") (hasKey .annotations "kubernetes.io/tls-acme") }} + {{- true -}} +{{- end -}} +{{- end -}} diff --git a/packages/system/dashboard/charts/kubeapps/charts/redis/charts/common/templates/_labels.tpl b/packages/system/dashboard/charts/kubeapps/charts/redis/charts/common/templates/_labels.tpl new file mode 100644 index 00000000..d90a6cdc --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/charts/redis/charts/common/templates/_labels.tpl @@ -0,0 +1,46 @@ +{{/* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Kubernetes standard labels +{{ include "common.labels.standard" (dict "customLabels" .Values.commonLabels "context" $) -}} +*/}} +{{- define "common.labels.standard" -}} +{{- if and (hasKey . "customLabels") (hasKey . "context") -}} +{{- $default := dict "app.kubernetes.io/name" (include "common.names.name" .context) "helm.sh/chart" (include "common.names.chart" .context) "app.kubernetes.io/instance" .context.Release.Name "app.kubernetes.io/managed-by" .context.Release.Service -}} +{{- with .context.Chart.AppVersion -}} +{{- $_ := set $default "app.kubernetes.io/version" . -}} +{{- end -}} +{{ template "common.tplvalues.merge" (dict "values" (list .customLabels $default) "context" .context) }} +{{- else -}} +app.kubernetes.io/name: {{ include "common.names.name" . }} +helm.sh/chart: {{ include "common.names.chart" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- with .Chart.AppVersion }} +app.kubernetes.io/version: {{ . | quote }} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Labels used on immutable fields such as deploy.spec.selector.matchLabels or svc.spec.selector +{{ include "common.labels.matchLabels" (dict "customLabels" .Values.podLabels "context" $) -}} + +We don't want to loop over custom labels appending them to the selector +since it's very likely that it will break deployments, services, etc. +However, it's important to overwrite the standard labels if the user +overwrote them on metadata.labels fields. +*/}} +{{- define "common.labels.matchLabels" -}} +{{- if and (hasKey . "customLabels") (hasKey . "context") -}} +{{ merge (pick (include "common.tplvalues.render" (dict "value" .customLabels "context" .context) | fromYaml) "app.kubernetes.io/name" "app.kubernetes.io/instance") (dict "app.kubernetes.io/name" (include "common.names.name" .context) "app.kubernetes.io/instance" .context.Release.Name ) | toYaml }} +{{- else -}} +app.kubernetes.io/name: {{ include "common.names.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end -}} +{{- end -}} diff --git a/packages/system/dashboard/charts/kubeapps/charts/redis/charts/common/templates/_names.tpl b/packages/system/dashboard/charts/kubeapps/charts/redis/charts/common/templates/_names.tpl new file mode 100644 index 00000000..a222924f --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/charts/redis/charts/common/templates/_names.tpl @@ -0,0 +1,71 @@ +{{/* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "common.names.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "common.names.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | 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 "common.names.fullname" -}} +{{- if .Values.fullnameOverride -}} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- if contains $name .Release.Name -}} +{{- .Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Create a default fully qualified dependency 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. +Usage: +{{ include "common.names.dependency.fullname" (dict "chartName" "dependency-chart-name" "chartValues" .Values.dependency-chart "context" $) }} +*/}} +{{- define "common.names.dependency.fullname" -}} +{{- if .chartValues.fullnameOverride -}} +{{- .chartValues.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .chartName .chartValues.nameOverride -}} +{{- if contains $name .context.Release.Name -}} +{{- .context.Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" .context.Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Allow the release namespace to be overridden for multi-namespace deployments in combined charts. +*/}} +{{- define "common.names.namespace" -}} +{{- default .Release.Namespace .Values.namespaceOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a fully qualified app name adding the installation's namespace. +*/}} +{{- define "common.names.fullname.namespace" -}} +{{- printf "%s-%s" (include "common.names.fullname" .) (include "common.names.namespace" .) | trunc 63 | trimSuffix "-" -}} +{{- end -}} diff --git a/packages/system/dashboard/charts/kubeapps/charts/redis/charts/common/templates/_secrets.tpl b/packages/system/dashboard/charts/kubeapps/charts/redis/charts/common/templates/_secrets.tpl new file mode 100644 index 00000000..a193c46b --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/charts/redis/charts/common/templates/_secrets.tpl @@ -0,0 +1,172 @@ +{{/* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Generate secret name. + +Usage: +{{ include "common.secrets.name" (dict "existingSecret" .Values.path.to.the.existingSecret "defaultNameSuffix" "mySuffix" "context" $) }} + +Params: + - existingSecret - ExistingSecret/String - Optional. The path to the existing secrets in the values.yaml given by the user + to be used instead of the default one. Allows for it to be of type String (just the secret name) for backwards compatibility. + +info: https://github.com/bitnami/charts/tree/main/bitnami/common#existingsecret + - defaultNameSuffix - String - Optional. It is used only if we have several secrets in the same deployment. + - context - Dict - Required. The context for the template evaluation. +*/}} +{{- define "common.secrets.name" -}} +{{- $name := (include "common.names.fullname" .context) -}} + +{{- if .defaultNameSuffix -}} +{{- $name = printf "%s-%s" $name .defaultNameSuffix | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{- with .existingSecret -}} +{{- if not (typeIs "string" .) -}} +{{- with .name -}} +{{- $name = . -}} +{{- end -}} +{{- else -}} +{{- $name = . -}} +{{- end -}} +{{- end -}} + +{{- printf "%s" $name -}} +{{- end -}} + +{{/* +Generate secret key. + +Usage: +{{ include "common.secrets.key" (dict "existingSecret" .Values.path.to.the.existingSecret "key" "keyName") }} + +Params: + - existingSecret - ExistingSecret/String - Optional. The path to the existing secrets in the values.yaml given by the user + to be used instead of the default one. Allows for it to be of type String (just the secret name) for backwards compatibility. + +info: https://github.com/bitnami/charts/tree/main/bitnami/common#existingsecret + - key - String - Required. Name of the key in the secret. +*/}} +{{- define "common.secrets.key" -}} +{{- $key := .key -}} + +{{- if .existingSecret -}} + {{- if not (typeIs "string" .existingSecret) -}} + {{- if .existingSecret.keyMapping -}} + {{- $key = index .existingSecret.keyMapping $.key -}} + {{- end -}} + {{- end }} +{{- end -}} + +{{- printf "%s" $key -}} +{{- end -}} + +{{/* +Generate secret password or retrieve one if already created. + +Usage: +{{ include "common.secrets.passwords.manage" (dict "secret" "secret-name" "key" "keyName" "providedValues" (list "path.to.password1" "path.to.password2") "length" 10 "strong" false "chartName" "chartName" "context" $) }} + +Params: + - secret - String - Required - Name of the 'Secret' resource where the password is stored. + - key - String - Required - Name of the key in the secret. + - providedValues - List - Required - The path to the validating value in the values.yaml, e.g: "mysql.password". Will pick first parameter with a defined value. + - length - int - Optional - Length of the generated random password. + - strong - Boolean - Optional - Whether to add symbols to the generated random password. + - chartName - String - Optional - Name of the chart used when said chart is deployed as a subchart. + - context - Context - Required - Parent context. + - failOnNew - Boolean - Optional - Default to true. If set to false, skip errors adding new keys to existing secrets. +The order in which this function returns a secret password: + 1. Already existing 'Secret' resource + (If a 'Secret' resource is found under the name provided to the 'secret' parameter to this function and that 'Secret' resource contains a key with the name passed as the 'key' parameter to this function then the value of this existing secret password will be returned) + 2. Password provided via the values.yaml + (If one of the keys passed to the 'providedValues' parameter to this function is a valid path to a key in the values.yaml and has a value, the value of the first key with a value will be returned) + 3. Randomly generated secret password + (A new random secret password with the length specified in the 'length' parameter will be generated and returned) + +*/}} +{{- define "common.secrets.passwords.manage" -}} + +{{- $password := "" }} +{{- $subchart := "" }} +{{- $failOnNew := default true .failOnNew }} +{{- $chartName := default "" .chartName }} +{{- $passwordLength := default 10 .length }} +{{- $providedPasswordKey := include "common.utils.getKeyFromList" (dict "keys" .providedValues "context" $.context) }} +{{- $providedPasswordValue := include "common.utils.getValueFromKey" (dict "key" $providedPasswordKey "context" $.context) }} +{{- $secretData := (lookup "v1" "Secret" (include "common.names.namespace" .context) .secret).data }} +{{- if $secretData }} + {{- if hasKey $secretData .key }} + {{- $password = index $secretData .key | quote }} + {{- else if $failOnNew }} + {{- printf "\nPASSWORDS ERROR: The secret \"%s\" does not contain the key \"%s\"\n" .secret .key | fail -}} + {{- end -}} +{{- else if $providedPasswordValue }} + {{- $password = $providedPasswordValue | toString | b64enc | quote }} +{{- else }} + + {{- if .context.Values.enabled }} + {{- $subchart = $chartName }} + {{- end -}} + + {{- $requiredPassword := dict "valueKey" $providedPasswordKey "secret" .secret "field" .key "subchart" $subchart "context" $.context -}} + {{- $requiredPasswordError := include "common.validations.values.single.empty" $requiredPassword -}} + {{- $passwordValidationErrors := list $requiredPasswordError -}} + {{- include "common.errors.upgrade.passwords.empty" (dict "validationErrors" $passwordValidationErrors "context" $.context) -}} + + {{- if .strong }} + {{- $subStr := list (lower (randAlpha 1)) (randNumeric 1) (upper (randAlpha 1)) | join "_" }} + {{- $password = randAscii $passwordLength }} + {{- $password = regexReplaceAllLiteral "\\W" $password "@" | substr 5 $passwordLength }} + {{- $password = printf "%s%s" $subStr $password | toString | shuffle | b64enc | quote }} + {{- else }} + {{- $password = randAlphaNum $passwordLength | b64enc | quote }} + {{- end }} +{{- end -}} +{{- printf "%s" $password -}} +{{- end -}} + +{{/* +Reuses the value from an existing secret, otherwise sets its value to a default value. + +Usage: +{{ include "common.secrets.lookup" (dict "secret" "secret-name" "key" "keyName" "defaultValue" .Values.myValue "context" $) }} + +Params: + - secret - String - Required - Name of the 'Secret' resource where the password is stored. + - key - String - Required - Name of the key in the secret. + - defaultValue - String - Required - The path to the validating value in the values.yaml, e.g: "mysql.password". Will pick first parameter with a defined value. + - context - Context - Required - Parent context. + +*/}} +{{- define "common.secrets.lookup" -}} +{{- $value := "" -}} +{{- $secretData := (lookup "v1" "Secret" (include "common.names.namespace" .context) .secret).data -}} +{{- if and $secretData (hasKey $secretData .key) -}} + {{- $value = index $secretData .key -}} +{{- else if .defaultValue -}} + {{- $value = .defaultValue | toString | b64enc -}} +{{- end -}} +{{- if $value -}} +{{- printf "%s" $value -}} +{{- end -}} +{{- end -}} + +{{/* +Returns whether a previous generated secret already exists + +Usage: +{{ include "common.secrets.exists" (dict "secret" "secret-name" "context" $) }} + +Params: + - secret - String - Required - Name of the 'Secret' resource where the password is stored. + - context - Context - Required - Parent context. +*/}} +{{- define "common.secrets.exists" -}} +{{- $secret := (lookup "v1" "Secret" (include "common.names.namespace" .context) .secret) }} +{{- if $secret }} + {{- true -}} +{{- end -}} +{{- end -}} diff --git a/packages/system/dashboard/charts/kubeapps/charts/redis/charts/common/templates/_storage.tpl b/packages/system/dashboard/charts/kubeapps/charts/redis/charts/common/templates/_storage.tpl new file mode 100644 index 00000000..16405a0f --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/charts/redis/charts/common/templates/_storage.tpl @@ -0,0 +1,28 @@ +{{/* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Return the proper Storage Class +{{ include "common.storage.class" ( dict "persistence" .Values.path.to.the.persistence "global" $) }} +*/}} +{{- define "common.storage.class" -}} + +{{- $storageClass := .persistence.storageClass -}} +{{- if .global -}} + {{- if .global.storageClass -}} + {{- $storageClass = .global.storageClass -}} + {{- end -}} +{{- end -}} + +{{- if $storageClass -}} + {{- if (eq "-" $storageClass) -}} + {{- printf "storageClassName: \"\"" -}} + {{- else }} + {{- printf "storageClassName: %s" $storageClass -}} + {{- end -}} +{{- end -}} + +{{- end -}} diff --git a/packages/system/dashboard/charts/kubeapps/charts/redis/charts/common/templates/_tplvalues.tpl b/packages/system/dashboard/charts/kubeapps/charts/redis/charts/common/templates/_tplvalues.tpl new file mode 100644 index 00000000..a8ed7637 --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/charts/redis/charts/common/templates/_tplvalues.tpl @@ -0,0 +1,38 @@ +{{/* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Renders a value that contains template perhaps with scope if the scope is present. +Usage: +{{ include "common.tplvalues.render" ( dict "value" .Values.path.to.the.Value "context" $ ) }} +{{ include "common.tplvalues.render" ( dict "value" .Values.path.to.the.Value "context" $ "scope" $app ) }} +*/}} +{{- define "common.tplvalues.render" -}} +{{- $value := typeIs "string" .value | ternary .value (.value | toYaml) }} +{{- if contains "{{" (toJson .value) }} + {{- if .scope }} + {{- tpl (cat "{{- with $.RelativeScope -}}" $value "{{- end }}") (merge (dict "RelativeScope" .scope) .context) }} + {{- else }} + {{- tpl $value .context }} + {{- end }} +{{- else }} + {{- $value }} +{{- end }} +{{- end -}} + +{{/* +Merge a list of values that contains template after rendering them. +Merge precedence is consistent with http://masterminds.github.io/sprig/dicts.html#merge-mustmerge +Usage: +{{ include "common.tplvalues.merge" ( dict "values" (list .Values.path.to.the.Value1 .Values.path.to.the.Value2) "context" $ ) }} +*/}} +{{- define "common.tplvalues.merge" -}} +{{- $dst := dict -}} +{{- range .values -}} +{{- $dst = include "common.tplvalues.render" (dict "value" . "context" $.context "scope" $.scope) | fromYaml | merge $dst -}} +{{- end -}} +{{ $dst | toYaml }} +{{- end -}} diff --git a/packages/system/dashboard/charts/kubeapps/charts/redis/charts/common/templates/_utils.tpl b/packages/system/dashboard/charts/kubeapps/charts/redis/charts/common/templates/_utils.tpl new file mode 100644 index 00000000..bfbddf05 --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/charts/redis/charts/common/templates/_utils.tpl @@ -0,0 +1,77 @@ +{{/* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Print instructions to get a secret value. +Usage: +{{ include "common.utils.secret.getvalue" (dict "secret" "secret-name" "field" "secret-value-field" "context" $) }} +*/}} +{{- define "common.utils.secret.getvalue" -}} +{{- $varname := include "common.utils.fieldToEnvVar" . -}} +export {{ $varname }}=$(kubectl get secret --namespace {{ include "common.names.namespace" .context | quote }} {{ .secret }} -o jsonpath="{.data.{{ .field }}}" | base64 -d) +{{- end -}} + +{{/* +Build env var name given a field +Usage: +{{ include "common.utils.fieldToEnvVar" dict "field" "my-password" }} +*/}} +{{- define "common.utils.fieldToEnvVar" -}} + {{- $fieldNameSplit := splitList "-" .field -}} + {{- $upperCaseFieldNameSplit := list -}} + + {{- range $fieldNameSplit -}} + {{- $upperCaseFieldNameSplit = append $upperCaseFieldNameSplit ( upper . ) -}} + {{- end -}} + + {{ join "_" $upperCaseFieldNameSplit }} +{{- end -}} + +{{/* +Gets a value from .Values given +Usage: +{{ include "common.utils.getValueFromKey" (dict "key" "path.to.key" "context" $) }} +*/}} +{{- define "common.utils.getValueFromKey" -}} +{{- $splitKey := splitList "." .key -}} +{{- $value := "" -}} +{{- $latestObj := $.context.Values -}} +{{- range $splitKey -}} + {{- if not $latestObj -}} + {{- printf "please review the entire path of '%s' exists in values" $.key | fail -}} + {{- end -}} + {{- $value = ( index $latestObj . ) -}} + {{- $latestObj = $value -}} +{{- end -}} +{{- printf "%v" (default "" $value) -}} +{{- end -}} + +{{/* +Returns first .Values key with a defined value or first of the list if all non-defined +Usage: +{{ include "common.utils.getKeyFromList" (dict "keys" (list "path.to.key1" "path.to.key2") "context" $) }} +*/}} +{{- define "common.utils.getKeyFromList" -}} +{{- $key := first .keys -}} +{{- $reverseKeys := reverse .keys }} +{{- range $reverseKeys }} + {{- $value := include "common.utils.getValueFromKey" (dict "key" . "context" $.context ) }} + {{- if $value -}} + {{- $key = . }} + {{- end -}} +{{- end -}} +{{- printf "%s" $key -}} +{{- end -}} + +{{/* +Checksum a template at "path" containing a *single* resource (ConfigMap,Secret) for use in pod annotations, excluding the metadata (see #18376). +Usage: +{{ include "common.utils.checksumTemplate" (dict "path" "/configmap.yaml" "context" $) }} +*/}} +{{- define "common.utils.checksumTemplate" -}} +{{- $obj := include (print .context.Template.BasePath .path) .context | fromYaml -}} +{{ omit $obj "apiVersion" "kind" "metadata" | toYaml | sha256sum }} +{{- end -}} diff --git a/packages/system/dashboard/charts/kubeapps/charts/redis/charts/common/templates/_warnings.tpl b/packages/system/dashboard/charts/kubeapps/charts/redis/charts/common/templates/_warnings.tpl new file mode 100644 index 00000000..66dffc1f --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/charts/redis/charts/common/templates/_warnings.tpl @@ -0,0 +1,19 @@ +{{/* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Warning about using rolling tag. +Usage: +{{ include "common.warnings.rollingTag" .Values.path.to.the.imageRoot }} +*/}} +{{- define "common.warnings.rollingTag" -}} + +{{- if and (contains "bitnami/" .repository) (not (.tag | toString | regexFind "-r\\d+$|sha256:")) }} +WARNING: Rolling tag detected ({{ .repository }}:{{ .tag }}), please note that it is strongly recommended to avoid using rolling tags in a production environment. ++info https://docs.bitnami.com/containers/how-to/understand-rolling-tags-containers/ +{{- end }} + +{{- end -}} diff --git a/packages/system/dashboard/charts/kubeapps/charts/redis/charts/common/templates/validations/_cassandra.tpl b/packages/system/dashboard/charts/kubeapps/charts/redis/charts/common/templates/validations/_cassandra.tpl new file mode 100644 index 00000000..eda9aada --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/charts/redis/charts/common/templates/validations/_cassandra.tpl @@ -0,0 +1,77 @@ +{{/* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Validate Cassandra required passwords are not empty. + +Usage: +{{ include "common.validations.values.cassandra.passwords" (dict "secret" "secretName" "subchart" false "context" $) }} +Params: + - secret - String - Required. Name of the secret where Cassandra values are stored, e.g: "cassandra-passwords-secret" + - subchart - Boolean - Optional. Whether Cassandra is used as subchart or not. Default: false +*/}} +{{- define "common.validations.values.cassandra.passwords" -}} + {{- $existingSecret := include "common.cassandra.values.existingSecret" . -}} + {{- $enabled := include "common.cassandra.values.enabled" . -}} + {{- $dbUserPrefix := include "common.cassandra.values.key.dbUser" . -}} + {{- $valueKeyPassword := printf "%s.password" $dbUserPrefix -}} + + {{- if and (or (not $existingSecret) (eq $existingSecret "\"\"")) (eq $enabled "true") -}} + {{- $requiredPasswords := list -}} + + {{- $requiredPassword := dict "valueKey" $valueKeyPassword "secret" .secret "field" "cassandra-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredPassword -}} + + {{- include "common.validations.values.multiple.empty" (dict "required" $requiredPasswords "context" .context) -}} + + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for existingSecret. + +Usage: +{{ include "common.cassandra.values.existingSecret" (dict "context" $) }} +Params: + - subchart - Boolean - Optional. Whether Cassandra is used as subchart or not. Default: false +*/}} +{{- define "common.cassandra.values.existingSecret" -}} + {{- if .subchart -}} + {{- .context.Values.cassandra.dbUser.existingSecret | quote -}} + {{- else -}} + {{- .context.Values.dbUser.existingSecret | quote -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled cassandra. + +Usage: +{{ include "common.cassandra.values.enabled" (dict "context" $) }} +*/}} +{{- define "common.cassandra.values.enabled" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.cassandra.enabled -}} + {{- else -}} + {{- printf "%v" (not .context.Values.enabled) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for the key dbUser + +Usage: +{{ include "common.cassandra.values.key.dbUser" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether Cassandra is used as subchart or not. Default: false +*/}} +{{- define "common.cassandra.values.key.dbUser" -}} + {{- if .subchart -}} + cassandra.dbUser + {{- else -}} + dbUser + {{- end -}} +{{- end -}} diff --git a/packages/system/dashboard/charts/kubeapps/charts/redis/charts/common/templates/validations/_mariadb.tpl b/packages/system/dashboard/charts/kubeapps/charts/redis/charts/common/templates/validations/_mariadb.tpl new file mode 100644 index 00000000..17d83a2f --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/charts/redis/charts/common/templates/validations/_mariadb.tpl @@ -0,0 +1,108 @@ +{{/* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Validate MariaDB required passwords are not empty. + +Usage: +{{ include "common.validations.values.mariadb.passwords" (dict "secret" "secretName" "subchart" false "context" $) }} +Params: + - secret - String - Required. Name of the secret where MariaDB values are stored, e.g: "mysql-passwords-secret" + - subchart - Boolean - Optional. Whether MariaDB is used as subchart or not. Default: false +*/}} +{{- define "common.validations.values.mariadb.passwords" -}} + {{- $existingSecret := include "common.mariadb.values.auth.existingSecret" . -}} + {{- $enabled := include "common.mariadb.values.enabled" . -}} + {{- $architecture := include "common.mariadb.values.architecture" . -}} + {{- $authPrefix := include "common.mariadb.values.key.auth" . -}} + {{- $valueKeyRootPassword := printf "%s.rootPassword" $authPrefix -}} + {{- $valueKeyUsername := printf "%s.username" $authPrefix -}} + {{- $valueKeyPassword := printf "%s.password" $authPrefix -}} + {{- $valueKeyReplicationPassword := printf "%s.replicationPassword" $authPrefix -}} + + {{- if and (or (not $existingSecret) (eq $existingSecret "\"\"")) (eq $enabled "true") -}} + {{- $requiredPasswords := list -}} + + {{- $requiredRootPassword := dict "valueKey" $valueKeyRootPassword "secret" .secret "field" "mariadb-root-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredRootPassword -}} + + {{- $valueUsername := include "common.utils.getValueFromKey" (dict "key" $valueKeyUsername "context" .context) }} + {{- if not (empty $valueUsername) -}} + {{- $requiredPassword := dict "valueKey" $valueKeyPassword "secret" .secret "field" "mariadb-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredPassword -}} + {{- end -}} + + {{- if (eq $architecture "replication") -}} + {{- $requiredReplicationPassword := dict "valueKey" $valueKeyReplicationPassword "secret" .secret "field" "mariadb-replication-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredReplicationPassword -}} + {{- end -}} + + {{- include "common.validations.values.multiple.empty" (dict "required" $requiredPasswords "context" .context) -}} + + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for existingSecret. + +Usage: +{{ include "common.mariadb.values.auth.existingSecret" (dict "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MariaDB is used as subchart or not. Default: false +*/}} +{{- define "common.mariadb.values.auth.existingSecret" -}} + {{- if .subchart -}} + {{- .context.Values.mariadb.auth.existingSecret | quote -}} + {{- else -}} + {{- .context.Values.auth.existingSecret | quote -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled mariadb. + +Usage: +{{ include "common.mariadb.values.enabled" (dict "context" $) }} +*/}} +{{- define "common.mariadb.values.enabled" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.mariadb.enabled -}} + {{- else -}} + {{- printf "%v" (not .context.Values.enabled) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for architecture + +Usage: +{{ include "common.mariadb.values.architecture" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MariaDB is used as subchart or not. Default: false +*/}} +{{- define "common.mariadb.values.architecture" -}} + {{- if .subchart -}} + {{- .context.Values.mariadb.architecture -}} + {{- else -}} + {{- .context.Values.architecture -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for the key auth + +Usage: +{{ include "common.mariadb.values.key.auth" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MariaDB is used as subchart or not. Default: false +*/}} +{{- define "common.mariadb.values.key.auth" -}} + {{- if .subchart -}} + mariadb.auth + {{- else -}} + auth + {{- end -}} +{{- end -}} diff --git a/packages/system/dashboard/charts/kubeapps/charts/redis/charts/common/templates/validations/_mongodb.tpl b/packages/system/dashboard/charts/kubeapps/charts/redis/charts/common/templates/validations/_mongodb.tpl new file mode 100644 index 00000000..bbb445b8 --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/charts/redis/charts/common/templates/validations/_mongodb.tpl @@ -0,0 +1,113 @@ +{{/* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Validate MongoDB® required passwords are not empty. + +Usage: +{{ include "common.validations.values.mongodb.passwords" (dict "secret" "secretName" "subchart" false "context" $) }} +Params: + - secret - String - Required. Name of the secret where MongoDB® values are stored, e.g: "mongodb-passwords-secret" + - subchart - Boolean - Optional. Whether MongoDB® is used as subchart or not. Default: false +*/}} +{{- define "common.validations.values.mongodb.passwords" -}} + {{- $existingSecret := include "common.mongodb.values.auth.existingSecret" . -}} + {{- $enabled := include "common.mongodb.values.enabled" . -}} + {{- $authPrefix := include "common.mongodb.values.key.auth" . -}} + {{- $architecture := include "common.mongodb.values.architecture" . -}} + {{- $valueKeyRootPassword := printf "%s.rootPassword" $authPrefix -}} + {{- $valueKeyUsername := printf "%s.username" $authPrefix -}} + {{- $valueKeyDatabase := printf "%s.database" $authPrefix -}} + {{- $valueKeyPassword := printf "%s.password" $authPrefix -}} + {{- $valueKeyReplicaSetKey := printf "%s.replicaSetKey" $authPrefix -}} + {{- $valueKeyAuthEnabled := printf "%s.enabled" $authPrefix -}} + + {{- $authEnabled := include "common.utils.getValueFromKey" (dict "key" $valueKeyAuthEnabled "context" .context) -}} + + {{- if and (or (not $existingSecret) (eq $existingSecret "\"\"")) (eq $enabled "true") (eq $authEnabled "true") -}} + {{- $requiredPasswords := list -}} + + {{- $requiredRootPassword := dict "valueKey" $valueKeyRootPassword "secret" .secret "field" "mongodb-root-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredRootPassword -}} + + {{- $valueUsername := include "common.utils.getValueFromKey" (dict "key" $valueKeyUsername "context" .context) }} + {{- $valueDatabase := include "common.utils.getValueFromKey" (dict "key" $valueKeyDatabase "context" .context) }} + {{- if and $valueUsername $valueDatabase -}} + {{- $requiredPassword := dict "valueKey" $valueKeyPassword "secret" .secret "field" "mongodb-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredPassword -}} + {{- end -}} + + {{- if (eq $architecture "replicaset") -}} + {{- $requiredReplicaSetKey := dict "valueKey" $valueKeyReplicaSetKey "secret" .secret "field" "mongodb-replica-set-key" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredReplicaSetKey -}} + {{- end -}} + + {{- include "common.validations.values.multiple.empty" (dict "required" $requiredPasswords "context" .context) -}} + + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for existingSecret. + +Usage: +{{ include "common.mongodb.values.auth.existingSecret" (dict "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MongoDb is used as subchart or not. Default: false +*/}} +{{- define "common.mongodb.values.auth.existingSecret" -}} + {{- if .subchart -}} + {{- .context.Values.mongodb.auth.existingSecret | quote -}} + {{- else -}} + {{- .context.Values.auth.existingSecret | quote -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled mongodb. + +Usage: +{{ include "common.mongodb.values.enabled" (dict "context" $) }} +*/}} +{{- define "common.mongodb.values.enabled" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.mongodb.enabled -}} + {{- else -}} + {{- printf "%v" (not .context.Values.enabled) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for the key auth + +Usage: +{{ include "common.mongodb.values.key.auth" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MongoDB® is used as subchart or not. Default: false +*/}} +{{- define "common.mongodb.values.key.auth" -}} + {{- if .subchart -}} + mongodb.auth + {{- else -}} + auth + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for architecture + +Usage: +{{ include "common.mongodb.values.architecture" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MongoDB® is used as subchart or not. Default: false +*/}} +{{- define "common.mongodb.values.architecture" -}} + {{- if .subchart -}} + {{- .context.Values.mongodb.architecture -}} + {{- else -}} + {{- .context.Values.architecture -}} + {{- end -}} +{{- end -}} diff --git a/packages/system/dashboard/charts/kubeapps/charts/redis/charts/common/templates/validations/_mysql.tpl b/packages/system/dashboard/charts/kubeapps/charts/redis/charts/common/templates/validations/_mysql.tpl new file mode 100644 index 00000000..ca3953f8 --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/charts/redis/charts/common/templates/validations/_mysql.tpl @@ -0,0 +1,108 @@ +{{/* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Validate MySQL required passwords are not empty. + +Usage: +{{ include "common.validations.values.mysql.passwords" (dict "secret" "secretName" "subchart" false "context" $) }} +Params: + - secret - String - Required. Name of the secret where MySQL values are stored, e.g: "mysql-passwords-secret" + - subchart - Boolean - Optional. Whether MySQL is used as subchart or not. Default: false +*/}} +{{- define "common.validations.values.mysql.passwords" -}} + {{- $existingSecret := include "common.mysql.values.auth.existingSecret" . -}} + {{- $enabled := include "common.mysql.values.enabled" . -}} + {{- $architecture := include "common.mysql.values.architecture" . -}} + {{- $authPrefix := include "common.mysql.values.key.auth" . -}} + {{- $valueKeyRootPassword := printf "%s.rootPassword" $authPrefix -}} + {{- $valueKeyUsername := printf "%s.username" $authPrefix -}} + {{- $valueKeyPassword := printf "%s.password" $authPrefix -}} + {{- $valueKeyReplicationPassword := printf "%s.replicationPassword" $authPrefix -}} + + {{- if and (or (not $existingSecret) (eq $existingSecret "\"\"")) (eq $enabled "true") -}} + {{- $requiredPasswords := list -}} + + {{- $requiredRootPassword := dict "valueKey" $valueKeyRootPassword "secret" .secret "field" "mysql-root-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredRootPassword -}} + + {{- $valueUsername := include "common.utils.getValueFromKey" (dict "key" $valueKeyUsername "context" .context) }} + {{- if not (empty $valueUsername) -}} + {{- $requiredPassword := dict "valueKey" $valueKeyPassword "secret" .secret "field" "mysql-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredPassword -}} + {{- end -}} + + {{- if (eq $architecture "replication") -}} + {{- $requiredReplicationPassword := dict "valueKey" $valueKeyReplicationPassword "secret" .secret "field" "mysql-replication-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredReplicationPassword -}} + {{- end -}} + + {{- include "common.validations.values.multiple.empty" (dict "required" $requiredPasswords "context" .context) -}} + + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for existingSecret. + +Usage: +{{ include "common.mysql.values.auth.existingSecret" (dict "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MySQL is used as subchart or not. Default: false +*/}} +{{- define "common.mysql.values.auth.existingSecret" -}} + {{- if .subchart -}} + {{- .context.Values.mysql.auth.existingSecret | quote -}} + {{- else -}} + {{- .context.Values.auth.existingSecret | quote -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled mysql. + +Usage: +{{ include "common.mysql.values.enabled" (dict "context" $) }} +*/}} +{{- define "common.mysql.values.enabled" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.mysql.enabled -}} + {{- else -}} + {{- printf "%v" (not .context.Values.enabled) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for architecture + +Usage: +{{ include "common.mysql.values.architecture" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MySQL is used as subchart or not. Default: false +*/}} +{{- define "common.mysql.values.architecture" -}} + {{- if .subchart -}} + {{- .context.Values.mysql.architecture -}} + {{- else -}} + {{- .context.Values.architecture -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for the key auth + +Usage: +{{ include "common.mysql.values.key.auth" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MySQL is used as subchart or not. Default: false +*/}} +{{- define "common.mysql.values.key.auth" -}} + {{- if .subchart -}} + mysql.auth + {{- else -}} + auth + {{- end -}} +{{- end -}} diff --git a/packages/system/dashboard/charts/kubeapps/charts/redis/charts/common/templates/validations/_postgresql.tpl b/packages/system/dashboard/charts/kubeapps/charts/redis/charts/common/templates/validations/_postgresql.tpl new file mode 100644 index 00000000..8c9aa570 --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/charts/redis/charts/common/templates/validations/_postgresql.tpl @@ -0,0 +1,134 @@ +{{/* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Validate PostgreSQL required passwords are not empty. + +Usage: +{{ include "common.validations.values.postgresql.passwords" (dict "secret" "secretName" "subchart" false "context" $) }} +Params: + - secret - String - Required. Name of the secret where postgresql values are stored, e.g: "postgresql-passwords-secret" + - subchart - Boolean - Optional. Whether postgresql is used as subchart or not. Default: false +*/}} +{{- define "common.validations.values.postgresql.passwords" -}} + {{- $existingSecret := include "common.postgresql.values.existingSecret" . -}} + {{- $enabled := include "common.postgresql.values.enabled" . -}} + {{- $valueKeyPostgresqlPassword := include "common.postgresql.values.key.postgressPassword" . -}} + {{- $valueKeyPostgresqlReplicationEnabled := include "common.postgresql.values.key.replicationPassword" . -}} + {{- if and (or (not $existingSecret) (eq $existingSecret "\"\"")) (eq $enabled "true") -}} + {{- $requiredPasswords := list -}} + {{- $requiredPostgresqlPassword := dict "valueKey" $valueKeyPostgresqlPassword "secret" .secret "field" "postgresql-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredPostgresqlPassword -}} + + {{- $enabledReplication := include "common.postgresql.values.enabled.replication" . -}} + {{- if (eq $enabledReplication "true") -}} + {{- $requiredPostgresqlReplicationPassword := dict "valueKey" $valueKeyPostgresqlReplicationEnabled "secret" .secret "field" "postgresql-replication-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredPostgresqlReplicationPassword -}} + {{- end -}} + + {{- include "common.validations.values.multiple.empty" (dict "required" $requiredPasswords "context" .context) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to decide whether evaluate global values. + +Usage: +{{ include "common.postgresql.values.use.global" (dict "key" "key-of-global" "context" $) }} +Params: + - key - String - Required. Field to be evaluated within global, e.g: "existingSecret" +*/}} +{{- define "common.postgresql.values.use.global" -}} + {{- if .context.Values.global -}} + {{- if .context.Values.global.postgresql -}} + {{- index .context.Values.global.postgresql .key | quote -}} + {{- end -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for existingSecret. + +Usage: +{{ include "common.postgresql.values.existingSecret" (dict "context" $) }} +*/}} +{{- define "common.postgresql.values.existingSecret" -}} + {{- $globalValue := include "common.postgresql.values.use.global" (dict "key" "existingSecret" "context" .context) -}} + + {{- if .subchart -}} + {{- default (.context.Values.postgresql.existingSecret | quote) $globalValue -}} + {{- else -}} + {{- default (.context.Values.existingSecret | quote) $globalValue -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled postgresql. + +Usage: +{{ include "common.postgresql.values.enabled" (dict "context" $) }} +*/}} +{{- define "common.postgresql.values.enabled" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.postgresql.enabled -}} + {{- else -}} + {{- printf "%v" (not .context.Values.enabled) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for the key postgressPassword. + +Usage: +{{ include "common.postgresql.values.key.postgressPassword" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether postgresql is used as subchart or not. Default: false +*/}} +{{- define "common.postgresql.values.key.postgressPassword" -}} + {{- $globalValue := include "common.postgresql.values.use.global" (dict "key" "postgresqlUsername" "context" .context) -}} + + {{- if not $globalValue -}} + {{- if .subchart -}} + postgresql.postgresqlPassword + {{- else -}} + postgresqlPassword + {{- end -}} + {{- else -}} + global.postgresql.postgresqlPassword + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled.replication. + +Usage: +{{ include "common.postgresql.values.enabled.replication" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether postgresql is used as subchart or not. Default: false +*/}} +{{- define "common.postgresql.values.enabled.replication" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.postgresql.replication.enabled -}} + {{- else -}} + {{- printf "%v" .context.Values.replication.enabled -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for the key replication.password. + +Usage: +{{ include "common.postgresql.values.key.replicationPassword" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether postgresql is used as subchart or not. Default: false +*/}} +{{- define "common.postgresql.values.key.replicationPassword" -}} + {{- if .subchart -}} + postgresql.replication.password + {{- else -}} + replication.password + {{- end -}} +{{- end -}} diff --git a/packages/system/dashboard/charts/kubeapps/charts/redis/charts/common/templates/validations/_redis.tpl b/packages/system/dashboard/charts/kubeapps/charts/redis/charts/common/templates/validations/_redis.tpl new file mode 100644 index 00000000..fc0d208d --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/charts/redis/charts/common/templates/validations/_redis.tpl @@ -0,0 +1,81 @@ +{{/* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + + +{{/* vim: set filetype=mustache: */}} +{{/* +Validate Redis® required passwords are not empty. + +Usage: +{{ include "common.validations.values.redis.passwords" (dict "secret" "secretName" "subchart" false "context" $) }} +Params: + - secret - String - Required. Name of the secret where redis values are stored, e.g: "redis-passwords-secret" + - subchart - Boolean - Optional. Whether redis is used as subchart or not. Default: false +*/}} +{{- define "common.validations.values.redis.passwords" -}} + {{- $enabled := include "common.redis.values.enabled" . -}} + {{- $valueKeyPrefix := include "common.redis.values.keys.prefix" . -}} + {{- $standarizedVersion := include "common.redis.values.standarized.version" . }} + + {{- $existingSecret := ternary (printf "%s%s" $valueKeyPrefix "auth.existingSecret") (printf "%s%s" $valueKeyPrefix "existingSecret") (eq $standarizedVersion "true") }} + {{- $existingSecretValue := include "common.utils.getValueFromKey" (dict "key" $existingSecret "context" .context) }} + + {{- $valueKeyRedisPassword := ternary (printf "%s%s" $valueKeyPrefix "auth.password") (printf "%s%s" $valueKeyPrefix "password") (eq $standarizedVersion "true") }} + {{- $valueKeyRedisUseAuth := ternary (printf "%s%s" $valueKeyPrefix "auth.enabled") (printf "%s%s" $valueKeyPrefix "usePassword") (eq $standarizedVersion "true") }} + + {{- if and (or (not $existingSecret) (eq $existingSecret "\"\"")) (eq $enabled "true") -}} + {{- $requiredPasswords := list -}} + + {{- $useAuth := include "common.utils.getValueFromKey" (dict "key" $valueKeyRedisUseAuth "context" .context) -}} + {{- if eq $useAuth "true" -}} + {{- $requiredRedisPassword := dict "valueKey" $valueKeyRedisPassword "secret" .secret "field" "redis-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredRedisPassword -}} + {{- end -}} + + {{- include "common.validations.values.multiple.empty" (dict "required" $requiredPasswords "context" .context) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled redis. + +Usage: +{{ include "common.redis.values.enabled" (dict "context" $) }} +*/}} +{{- define "common.redis.values.enabled" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.redis.enabled -}} + {{- else -}} + {{- printf "%v" (not .context.Values.enabled) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right prefix path for the values + +Usage: +{{ include "common.redis.values.key.prefix" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether redis is used as subchart or not. Default: false +*/}} +{{- define "common.redis.values.keys.prefix" -}} + {{- if .subchart -}}redis.{{- else -}}{{- end -}} +{{- end -}} + +{{/* +Checks whether the redis chart's includes the standarizations (version >= 14) + +Usage: +{{ include "common.redis.values.standarized.version" (dict "context" $) }} +*/}} +{{- define "common.redis.values.standarized.version" -}} + + {{- $standarizedAuth := printf "%s%s" (include "common.redis.values.keys.prefix" .) "auth" -}} + {{- $standarizedAuthValues := include "common.utils.getValueFromKey" (dict "key" $standarizedAuth "context" .context) }} + + {{- if $standarizedAuthValues -}} + {{- true -}} + {{- end -}} +{{- end -}} diff --git a/packages/system/dashboard/charts/kubeapps/charts/redis/charts/common/templates/validations/_validations.tpl b/packages/system/dashboard/charts/kubeapps/charts/redis/charts/common/templates/validations/_validations.tpl new file mode 100644 index 00000000..31ceda87 --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/charts/redis/charts/common/templates/validations/_validations.tpl @@ -0,0 +1,51 @@ +{{/* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Validate values must not be empty. + +Usage: +{{- $validateValueConf00 := (dict "valueKey" "path.to.value" "secret" "secretName" "field" "password-00") -}} +{{- $validateValueConf01 := (dict "valueKey" "path.to.value" "secret" "secretName" "field" "password-01") -}} +{{ include "common.validations.values.empty" (dict "required" (list $validateValueConf00 $validateValueConf01) "context" $) }} + +Validate value params: + - valueKey - String - Required. The path to the validating value in the values.yaml, e.g: "mysql.password" + - secret - String - Optional. Name of the secret where the validating value is generated/stored, e.g: "mysql-passwords-secret" + - field - String - Optional. Name of the field in the secret data, e.g: "mysql-password" +*/}} +{{- define "common.validations.values.multiple.empty" -}} + {{- range .required -}} + {{- include "common.validations.values.single.empty" (dict "valueKey" .valueKey "secret" .secret "field" .field "context" $.context) -}} + {{- end -}} +{{- end -}} + +{{/* +Validate a value must not be empty. + +Usage: +{{ include "common.validations.value.empty" (dict "valueKey" "mariadb.password" "secret" "secretName" "field" "my-password" "subchart" "subchart" "context" $) }} + +Validate value params: + - valueKey - String - Required. The path to the validating value in the values.yaml, e.g: "mysql.password" + - secret - String - Optional. Name of the secret where the validating value is generated/stored, e.g: "mysql-passwords-secret" + - field - String - Optional. Name of the field in the secret data, e.g: "mysql-password" + - subchart - String - Optional - Name of the subchart that the validated password is part of. +*/}} +{{- define "common.validations.values.single.empty" -}} + {{- $value := include "common.utils.getValueFromKey" (dict "key" .valueKey "context" .context) }} + {{- $subchart := ternary "" (printf "%s." .subchart) (empty .subchart) }} + + {{- if not $value -}} + {{- $varname := "my-value" -}} + {{- $getCurrentValue := "" -}} + {{- if and .secret .field -}} + {{- $varname = include "common.utils.fieldToEnvVar" . -}} + {{- $getCurrentValue = printf " To get the current value:\n\n %s\n" (include "common.utils.secret.getvalue" .) -}} + {{- end -}} + {{- printf "\n '%s' must not be empty, please add '--set %s%s=$%s' to the command.%s" .valueKey $subchart .valueKey $varname $getCurrentValue -}} + {{- end -}} +{{- end -}} diff --git a/packages/system/dashboard/charts/kubeapps/charts/redis/charts/common/values.yaml b/packages/system/dashboard/charts/kubeapps/charts/redis/charts/common/values.yaml new file mode 100644 index 00000000..9abe0e15 --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/charts/redis/charts/common/values.yaml @@ -0,0 +1,8 @@ +# Copyright VMware, Inc. +# SPDX-License-Identifier: APACHE-2.0 + +## bitnami/common +## It is required by CI/CD tools and processes. +## @skip exampleValue +## +exampleValue: common-chart diff --git a/packages/system/dashboard/charts/kubeapps/charts/redis/img/redis-cluster-topology.png b/packages/system/dashboard/charts/kubeapps/charts/redis/img/redis-cluster-topology.png new file mode 100644 index 0000000000000000000000000000000000000000..f0a02a9f8835381302731c9cb000b2835a45e7c9 GIT binary patch literal 11448 zcmeI2cUx22x9_8Zh@yyC0I4cPR3wC|kVp$H5PB1ZB#;m~gf1}_1O)^|QB*Y2#4gyt zMlbeAQxFvp712m>hX{m(GZyaOx!ZkSz`gf*j(>!>GS^(QjWNFCGu9zzC!56!6&9jU zsKs`+R<0=2Tv-%qj{Ji8aAni0vR)KQEHl>HJ2pI#N)HP{sbegEe^b}f4US~Qs$;Cw z_4G(lQ96Ni5-o-l&d`YniiJz?dw66Zok|Z1{M|-RS5J47uKp%8#vQGzjxpCah7XLM zj-j5O@9*{`T2RE_9UAE9LI+xoBnmwuHj)v%{&$O@SQ71bZ+Kl2DH#*!W~guJ6YNcK zHZTeO`>F9kF${WS#P4QkJslGrH2U}5u}M)uzb^*{#nUN4$W@Fr%;@i-!xQO$57ytD z8g7NACsAo=gGf@4U2vq4|L;yBNa25X;tb>6G}|@C+Q2i|iEP41uyWQ#JBJ%4#8?F< zhJ?qHVxj_RUKr=dpkNn9ac?y zjjf4Zb6GNz?1!C-z2!T|`I6FNrJxgzEdNh&X5<(5KrG*81T6sFq zW4#j0(FP$=R0ktuGQKhJ>5aE1x<}i)7{Yf-uoVV+b&Uyx|9F@?Q)9v%9i!kom8xr_ zZyDi8quLlJ$HoMDMv5Etu;N25ccDbf0|Q5Hey zuy9hmyN{lmxi_9+6lmk*8e~ZKun3K`af^yY(`;?=K0&@@N^D4|ZmdgqQerIL%hrxy zM`KVuoedc@Cs*&NU@z}TC!YjoOLVwfgp0XBq^=QOH`LfZDk)yy$}P!&oMd9pNV2eV za19GKbTn|V3?&(oC>TsM-pj)_-XqzO!f>`XcTI{5(F-#P4|eb+*@i_q#RWz9Cb}lU zY#Dly5oBMwdxVb>J|ZxR=Hn2B(esIp*C%@g#keGsV#(gFfsDuqU)z`@qaaF%b3~+m zaCivCJ1!{#Z-OS0%&mNabUj@xDKwK12OC|CUMSr<(LBO6#=*zKmh2FMcXPB0wAZ(G zOLT#y3^MdVd+FN4H&{DMs+$|$6}}_mun)3ByGD6M!*@NGc#37RH*(}cY~w5(g7s}^ zzJ{deP$OjHtPIHRcv})F*daVJ9OLS0Leg`Niu1-BQNyAVy)cG$-t^cQdT5*_#!w#< z6bFATlk}s>LCIl6HxqO;(KpT^F4{I2o&%lvSS5MJQIi?*1e?StBg+V5BGsE18|WMZ zW@PMb;;rjJh)Z(TCxklSlZ>ctaW=Yo)I?_w8+1I}9FDPYfEk{Rp z-ILpbFFK4J$#eW+T6n?W^l5qJZKu}h5eQ&HLB6NEPly?kFMd+9B*;21U%BtZEs%?pK-aOJA&_a1j0}?4#_1KVkJ~ zb1N$=!~T5LHEY(Ki6ShOkvZyUtN}kg)=-p%p8{pGCE=%=k}YB~GBVw%{}0_J=Dl%c zNm&_1!2faZ@ZlzI_bqfh*IP+9=vgI}rUzo0%pyLDCQ>#KFyN?VT{J-WBp zCg)?vCAY`Vo>`JeY8zKB+H+FMc}Q(BfZHZ_r67MSRsc_F7C zywt+dvh}JDW@2iJ{P>7kKAJK=H#hgl*|VFbw_3cM9SuWCQ8xa>xpUb;&rXoK%1McR zdnJ}CDoP!Dk~;a<;97Nc@fy+86}OQmPoC7l)OA^+lzf7Q)M`ViYrc0ZqM~%M)1#Jw zfq};3$}t=HHo0Bw?;rEaU97FebB`UnQf>OC*hZRgcFPL?lreG9^k2lGzd~ZiK3a#p zy)Aj;;m?Kl6GpPH?|86AUw`=-!|+_};cth8N7wOf@{BbUz8)iD>yD^dMsdu3sjgcm zW@l$t760Qj&u4MW_&1NM{x!;Vb#<@w7h9$;X)0sy)@H8k+&6o3!pHoJ>1>urexUjA z{*xzH?Mxn059_{ZJ+&^q>tPZG7Orn-Nb**9*6rK+L&p|ya{?=HmlwBKDP8rsHUCla zcztmWHlwP_c!*J;ZD_dCY!|w?1!4%~4*Dqs@kWrCfWZ=WDk*3@9_9&Rg z5F_^U)4UCdKkmGFRb;&gdi0)Bv?Q|{S_2<>6TK>ZjGG z9{XfuWax&!)fbyTe+?S#0yhM(;#x%99AT%DK(HZO64jEUVl(pL5m;Fr&fwZPdwct( z%F5ZbwcE;A()V1-YtksJyA;;q7Ewg>BpOX=mYSHHB=uG^+sd@U;l8gOmt?7&bDNkM zu3c;-9?ml75dN@2UC14Kwt46Ayu3oYV;XHVV{t*d3K&7wJ2t7s>ig?!V=XEy zTei8u;}z>#O<*5YkYo515Ix`}TT?sxu@^5d`*D}*ybg@r&so3e+v-a$5 zZUo2RH_Wjx%ILh}MVX!$Yom3g3NIn!T+5S?3nT>6XvGdEb=qi07N;DkD{zvz0b5=XcjZ z%dB}4OKjOLo4Fig7=&v@&9~z!vfyUH!r>W8>ohdhn40=cWhIkX&B#nMgdSzQe698C z&HwuHqLib$HKeUX^6As3C7g@0e3~gTl8)Z9$CYK#Xmq|lJ(njRXfx1~)AFtJO6k9w zkVqt3A`$kLt7TxY0_>xW)*>D8sh7e;aXnntiCP%~e12HDO9BW)FCB@FA<~X*CewMZ8<>mEH4zkm8a-`u%DeyvRRBF-r^R>#fZ%=tc?G*uabB8b?O`
    gt0u3YK+3VbZ)7Cr=g*&)YecY;+uHRLladT3#L-cG+Z4CN zKHgdOtr;9@>`b#Ba+WJ_{4yh$6P!auoRD{nC(pX_v#ErxkgbB-IsWFP&W_}s%qJmt z*68S5|2A?sI~z}@uitaVzm50v=e`T{#J^q`x%l~|^x)X1PD%ECQ3)6r7}&pZlW#!x z&7i92f%*0h4r6aaZ}j74CZ$tSQjUNV{3&o&kyxTw>qazFXX3Act31{S^Z5WvqP%;8 zRA3x!@p~>={SD~@*D62Me{9N}gIbv>4iVJ*7S*vcbLjhxnzRda8yg$XpFfY95st75=?aFC9}wq0 zF)@LdjmM0RV|#f>r?%h2M3;$#Pa{fO)5_jR(9T%&W!y0{L3|lv0qAhQ-1KmF^PQ#ZP>O;1`%Dz!7D2~MQU ziWTB2Dk_SwVr4}3^O^Dya_Y^8?nk&h01c(e<# zn#xC@6l4*7aQx)S269E;yL${|OE<2}jM=QQ;)KaRrkkog^P>D`le>${Uf8$b)1Kp> zs|yMWF0X0_-=xd4u&0Y3+CqaAK$nqa%A?fkq#lyJoui-Hen2>X}amW4T zsHl&Pl3-Q+5SF_hB#eanpW7uIe*?#A_w<-e)@q~SyPJD|z&6%iOR!QgO3a%bavc#AD>^6l_mA0H!azv|NZlSo-Y>{7yA@;9CP`qRRbUn%6+e)_JqE@(-#Tj($SLZ+CP~bsy z^z=kD2pv1Nx#8&8SRE{FDJOU-zYL2!Y4}F2TC*4mHh4*NbaWfddEQmOd&^+c{tSn~ z1k|3gva*{asc|0Qw8G!sK8kJ7>0&1%@zj--rXaiP*RVBWzVhzUM4V8cKhnFInYN=G zH(rj*4J;8!8EBy5Shg7(^gc>&AhW&&K%fp5%101T+q}K=U2!!ZR+L`2pe;1(yhCD5 zwZLA;2r!@WQK-ns$WLFsz)Bk!GrmY|iT$d|OtY-O3CYmGMWK8=bZ|_=(b>~egE`;B z&DC`utbzl(e>s=PLdF(@$Qo;F>;K4_clR(EnVF@3${I-&7|nq*XIAU@RjD#F9Ja!- z1gAUx{SAmEZGM?Fa-d@lh@@~DD8%M>?%ZkX;BXAvqz+>)+VLR1jdqa4x`}xGPujwJ zjrkWlZqbNgA0GNlNuA6sD9GCRDA|r(xQNS{?CRYFpMIBcClzE-x)A0>$IUe54MLV{ z5YKI7rd=<`4U$-_CQ(64=M>`}9L2G*vBc3jiKCFeFf-JY%#xS?czdS-j34BuI)Bic zdm|o%rQaRgNkv&y6rbx8JJcqgxpGr3w#j*=j^6?ni&d~S!D(vw4hk!~PV_BJXp*+! z*WgV`k!x(MK7_Aw8b^7^?KuC1QSW&W@?d1=cj}_1HTsUh>3@C-(>ADeNNAuaxTPcrHRdNQYOyka!)+4~pt_Se?%`LR z;xnbVV}q7fEhKKOH~ewy)Ya|Slm*-y!(D7)Ma_K*%o**nUm81s`t?3R<$}}M49N5# zO;E?-RNO8Q>V&^~b0AxTn{2rwaMM6V%>xSL3uu>2xLgQhlQT=!U!rWP1^I{yYZ~lH zCiu;Dr4yU|b(q->0jx?`SqgmC)WAIw&;orf@uOty$OokjUf03z=V70$*Vfi9CpRq= z6BFxuqRFa7_Xe7xHZ?Q6iq)$~_dm)_vy2nS?9xW&ct6KH?@M@!S2w7Qj z=(&&|);AuKJ$mZYdgjW#!lRHK-s#T|KF`4lq}0^Zf;%qCq)Ex|YizU%>b>pm?R_vc zRSXGr(F4tL*c4;KurAeqW_0EIH*LSGYHF$oXUzJ|^&Mz>+qx9d`YfxIVcpv04@u z7P_>TibzHZ0gUm@th>A0*2$^4z=W}M*)l}U-VX0sxfY*Qo3UcUk-WUm9lIV^fIX2} z*E1>gbxsAwdp~^&w6d{TYiukBsv-@H2jbq;uaTU`k8PiyHdu7U^IHAuYulqIMoAFE z)@W)<+`D%Vl!lF+oh0gfNr@P^e{hY~PEJeofU`lfu=n>@z+N=MaRRq@2)rNV)8nJT z@2b%EV~6$~IkFUaoQa9NiHS*l&Du`{aQhXwH+5(=#3Ug)*1bHtRYpZ6C+V**r214z zInzX4$S#&HU5fJe_fOoltD&J`-itFv$e}!K6uCrNS{k|d=FO@(bLK2qw5Xx4Za)P6 z0|_6JB*5sp?lCk$heZuEFCHT1#U4bGY#KpPcA?gW4GpmOE{Mljcuy6aXct?-SY!Dp z3!^+du-4Tf9pP_A2VlmeeOgNzIH%HHIGOnLW(iBYVtfv6^)iTckbN8)b|_e zoVEKYtaXQkm(nQ~GAVfY2Jx!TxY1AzKg z4W8SD1hSHnb$$=x9jC6&zn46&{rZM~PG4U@@aeQd%k+=!L|h&=GXz-6GC}dyXhKH= z2RD-ik+|;JvqhU9@s`~U>t4gmwFDg}4-1F*+3qmBukUG|ofzK+)Lv&ArD)0Pt3LZd z-u1WIs95{?74S@)R;*r~3HkcRiWX(dl$3`&lRqTHrj?s_W*^34BcsF5WXY98Q$y+qe39R*cE(Z(E%W;ALmX4_goK$fL!PTdlU!K_L zGZ#S${GQ0RvabpPh7{k+h|59y-9z+iMMVWtafpeDDIuauU^oMX>B{wQ?}V2ATkEct z1-3xFh3IQt>T@|OYirQg8@QaLu3rBN++g$_kzWV_bX-8s-S9SA)$!xUm-D{1T24vr z2w=Sg{!3!L9JEK2I^=1iqodoX)C;`zI_trjLECF>-h2{kEhacNi=@1UIHQz$az!l| z8)%lcvZ~uaCu?84c=5SCkAqGC7kmLkoDB}^lYD!N{7&jB&RM& zLL_Grvo2fFWDTItH85H@m+%ZR2)7Vtv%1**&5dUws}CJmvmB zGtS1^z4OMP90a2@w6(J{cXmF)lV1!SAerA&p@-{k0=K79n$nUDi8{9rS~df41@yU! zPg8_JTD8h3G71pC{{UNtA{1TRzuwRQ1S%=35%6pHJ^Yjj1%R3w-0SN*GK-4VKt?7H z+!zW;Nl8h@(I3T-s)4h!D)aJ1NHvB;hl3ET%cg*faQRJkm08o#)4X;fbmidWztg>;!#64Q4Gor0j7EW=${<=D*66b5 zujA|8puV!ZCvyl$p>fKDE~*bq0LeZf$BO##)&K#p0HJ_%O}wcQ9Y9h)n8zMKySw-s zXZgX*^dPPxyvOhfvCXxg%sc?h3$;R^(_K(P3*UU9 zmo=l*kS={AxsHB14URAhG(H6XjehrIFNH9@s`H1Z0V^NwC<~Q+g!6yY>m|$gN=Rl^ zC)eE2fUMg+rTS^MrFP;Z-c2n#cY!_uVPeiZze#uwRB7j-`Ucr7 z1d%86&I~B~qfip>kaqztb`AD8{~L0y=zSrD@@I~B`d2Tngq+?T{yoYEXi*LkuBUpH z0H|_0bQSw`DM}TKRR+*p$t3cnann&fH_kwO9H+mvI*@?5h2v`?1mF>%Lx?i#e=%R@ zUH7lahQrdIgA+lKduYc@^~aB7Sa?aW0Ti5oJ6nWrkqTQAxuWOM%e$d(bO`56eWtQ} zAwti*<#NWldf&6c`I?qc=!pDa3fZy)Qd5EY%4(=&UH>3%Ritcc}65Wn3V;U zGj2e~MHl15QJ{w7^`fl(h_e)2ahe3|wfW)bzFeGAc0@N6uhW(&X@lDYn22!P7*?JX zS_5i1OF&7$Q0K$m87KWL`6GbnHRhxCfFD-V(Sg!n$ez3nUTd_q?Wd&9l;h%{m%vmJ zYTjW<6sS6P{@L>DPstVMK}`bn6c@P7#^Y}sX9^jr!V9FNkWys-P#L=!m_#Y3d=bA4 zshnkXunU{T&JRo5MO)*iN!DDV5)vM-K@C$91wg?Pk52;}n%U9eURqOj-w@Jegh-NE zX+Y}we*8ELCNYG$IG^^iz#NJ$PzKfFm-!=I+`%_M==-;pa)8z>^u1K?EVY%s@=l- zy!B2{l-)a99)1PoVKEd^t^nOjr_({?$m#Ja;%i|Y6XALlsj?* z>f2SmNb!5t=79F8f=nm{tq1iagrj;_Mx5oXzuzcQ%oKKJ3r$X3;Sc6QhcC~WWrCv& zXf3jCE0cQ)RgQir2!ajTv5P`MK6d%PFUPe+eHQt}6WlYhv(uo|$me#iWoEQhPkvbq zRiQcH$&UT0Oko%H9MdEgMfO%NSiHCiiXkN&7kd{M8Aw*3GGGEM3_qo)KC5{Der=#X z{~{HX6C8=gD>te$AQ(BYi$kGmp1&nd8(e8RqDB}}dyzL1z;k#dz?_lSAL=Aj`lBCJ~vZaRd#_rNgaC%{d^a1(O*c4V(IEKPIWeu+|! z%s41R;Cpis01Q##f4*n&tq)o>%MwlZf?K7)8x|0Q+B8i-h>9Z>i#>Z#rjwtJ+1lD3 z!9G!kDkObY&CdG<*>PCB)+SAnpzcWopr+1YmyVP=wr>GG+}yaX!FnYg^j|U!I@Z5A*1U%+~3V zCPXPnD)TY4C4fAUv>D!~AU7VA@vb0?g9P~_1vT!1n$8ix_3$2(n1nwesZB`Vk~c;^CATva2ZRgf1zp?(eu{DL2oO*VOmYB7 zBSIoS4h$fnf{?E}XTO9r-rHMl?%cV3-@h+{@KL~<7Y!45Ic+v z^)Lto6Ar$AW@U!Y=x^d~2*j3yWE7t4A3^l?BOoM{bpL#lP?Yxy3?WM>=}9Omx&{Tw zdU(5f2D|!)$OaI|a0%}F2YPrDy$K$F+9=8^${&_jKCGaGRZx&n(pFN24@E^;byWqs zKkZ#T2?2ixRFRd30S=kEx_bwZ14Fzd|Fj^GT|NJdW~Fl2&%!mz$V#6`a8_3jwp5Pr z{?jIm5FFwi81Sc=0*o&UkNX`DIWmaw=duSO%-fy7xT=JLH~JeoJkk4au+G{41$dfjkSY4t(D}p^=!R^ z)U|CKrYmJoGw(?iivqLLdoBFF*ll?<2 z{d}S{4I;xL&BN8)(F%r&3f=@&csYzVH1I;Yo0Ig+@#@xYm`Gbo z6;m~mpLZnL*4@I=+EvXe#N5m`(AL<@!_3GsBE%yyGAcA&UeVCaP}fffP1ZH`@bDwr zhD2D}kpm6o6;)Mze6)RWD3Yg@kB^c!$`GxJM4>$4F##cp{%-QFkw)lnTQgk~MI&8P z9Tk10zyNPEcN7YiN#By}ZyI8$7_3L|v~!E_G_ke}4lu`u==l2t+o5oZCgwN=4ABVf zui&QcjmD~akyP<08^&v>n44=yl98cgJ8fdPxxR9gqDi2sKN3SAn}o{~-Th!}D@b7- zBK+@V8i5Z|Ggr5W#Ca+Q!5y+WQr{-X&)36BG1AnE5r%G*B_;-qhuCJ z3XxYc5B0Jokc_ z1Ak8sy+8wFWt6*~nwd6M)r1rorlJ;Lr9cdJSMxSgQB?OfRkKvnLmDd)4PlJ%D3S^z zavWp#D8Z=u|LmCG+Xw#siwR1ok~bZf5C~C(k)Ad-qG*2D7mHoyXI?BnJ}PN*Kx35p zB0Edh32l>qHgUl2g57l&%5g8&D_%rGS=zPh21n3VO3m93Nq4b_7)maAO;F`;?+;dI z-ItZmu3&nclXqOPbM=E;&Mi0Mw-@mX$2tScS4HKOIzK$%kW*?FHp&rSe6q*<=x6aE zqfMNg>J+N6p7{PeDbDP4JY7#u(T%p7vpxBL@S=FafS-O?m}=Pk;F*MkEia0-M7p}V zc-4c&*_k(Q+Pt~zwx>CH=JnS3p_-(c8nsiWPJNi4&-gY!bOoI+J3VmwAhdCn=amm0 zH+=HsiKwjX&TZSa_22d72@Vdnu(y|9yOvYvO3Uev{k8tx(8%cV+qw`=LBVvVhN#Cw zLjofsBfQ6=l+*S1@0E2(-XWms^8M5B)An}lxHwI-iyCKMzs6v(*hW9q&9zRg+}zxU z4j*ozS(RlK7iSg~34VOnAdr%hg0FI6f)VsHg)^$E+^rb`NfeiQbaZvIb8=46=~7+QAA^@?ael-1x%chcmnFW9`5+-`|sGz2%raXVf(`V0i3#DLBQH>AZa&2a2=T~O^{ytu7 z_ntkdHWCdMm|YOL>og08J_eIBjl3EpgIlwDo-b!G)p3ziNGKycoxO{cpb_=;P-$uD ztGW=+n+|mtvLNPAp49N0p}>*sdv4gE+APmW+f;m@<~!-shs{^TtOj?H z3|;Z`HzvWsiitagQf-_fQFqNX>Wm2l31a7^jLVlr{RVEKU_915DJBHl_U#HDPj~6* z>wl@t^21tLolZ_>-LiFS-A|R;t4C#UO^_=i3k#WFzmmHwvGX4upPufy!86%eET_S? z?FlB-z0B<5sp4XhVsiFCD!23pXetu_(~``!`vi6N+V0)EUqSA2@$jTkN{!B(Ia51V zQC~$G)9 zYeYmwrckuanlL?8u(o4U#qoQEP6w1;y}D)ie&`;d(?ut!bjv*l&7OQ7YeThN*2=zk zF=KHts7t|+D1+M(wcKMT8s+r`Ah^x8yOs<60_c?`zhDLm8KUmT?H?Qdx5)dH!?D_MFWZI#S$rq1v zB+wAf5s2Dv@Q!zXOEuAN&0x^rX?S5=J_%t|iN3u&ey6>3h?*0=V^7W~8OvepuYS zvHk<{P1I<&Q|vMhYh$B!B)(gK|5{m@Ze`yU$NDe^tnu^n1LmgXJ4J2#wb~hfxo<8z zJA2>w50|v&B#yC>B$0n!H2PB=3kroQb^j@GwmkvTY3y#FQ}dUJ=S&XqN==Q8$Nl=N z9^28KV?J*cH)DPl{V#bM3xnx-yaP3}NgPM4mWxYSY)bJ`M(cy1MRT<`7O_ zS&2B8pFj5K*SZ{Z1c=Sb&E4AIlqrGE!&jnn#BbWy?BtPi;`%AH>U+?v==j3B21pOa zB;M3b+DVT{dILn$>>~eRy6ei~_wNR=vB$oA`NG)Rzt$Jxdojmi*OV2Nl$a1Ul};_= z?PobfL^8X}%yo0bV>VW&u2)vJtu9TGzJ0Vs^!+N3k(S<$a8c%02z+;RZdn)^gotVo z1{PsuXUF#J(aM)~Je8T53HibT`LcEE))dMsv7wqkgPC?Jo;qch5&8iSAKyzjefpBwFgiTI=#4{#8O>d{c3I*NgCZ^R;=lN7vkDzJ4lIuE4zn=j{mtZ1sLs$wt;IpVe=%!g!U@8!+H#$KE(3~X|%7FAQ@$q{#L zN##by{X~*Agp7@i5eV4Hd~3^dNv*B=bB{e__HOSjw`YMB+|DC=`QE*~XAhd|!~FR8 z_+V}5F($YMJYDKqp64&E)$u*PG;18L#Q9MizAjh-arydnR*j20Z7LidKR(S;xIVZ6 z`9qfC6LR8|XW>^5JwXc_wE$g%13l{hqmSaUg!# zjYh}&`Q4OqD)UK$IdQm8ZeP>1$Ki0jow>QWBR~`Kg)d)rbbq~dL*S9w4vw^+7aF3! zkFHJ?GeCl|u~BJzRif_|-WkhKd)EjYCZWMRaFR-QW7#R#SmoLb`}iQQq6h2i?(Vw38r1=E|{@#%l6Kh&4Fnyf}Txn9EYy_yX2aTKPy=i-Trn`)RLyG(v zhK7c_{@|1P?E&_{z(9ao{Y#fFy`)T{W&z(%fKUONXTYj9kmY-06sQ9Jpy^lp^iU|^ z0LAml-n%J+>SBPj0Q#Kf$CkM?*S}f;8ZsRT``FlD?GE9vRAW_2tEzTwY-|9`ZT=c{ z%pwhLE@+L(sUPcZ!V|uOw&fy*U)$7l$KXAGX$WZ>8aE~-EzQZxdq{(M z_%cB3^@<9BqoM@rEVGZV@5szd3Zz&vWwaNvnZ+n4Xns%ys5%8Gx%A;fVU3HFHYaZJ z{rfiq)&V~_0LK%VcM2wh{7I&aSeqQ!!@PqZ0ZFKg)XGhCnc65)a zgoMOM$B_j+ZS9lOhYHStf~;_?cLO{ty^@tyjUDbExb4ZgYu5?F^Sl&FsU)adl#7cf z#BvbSMk7YzNlS}%W#3ri$<3u#t`Fur$E64#i*o5IMM3}LGPq5MqN9k1!n+e z_e)6pl}E#Gjx0Pl4U$XfHu0qn3Uy{0nToNtPQ0MxIZ8S5sgaJmq1U$Wj4SPRu^k}) z{qO}!``Lr_>jJN18T%_eU9Ydgu{vtm2Q*m;XfiP%BTeC$MeVN(??rt3D$caHaSF9d zKwei9U-EyQAL8LS_H|dz*|R7Eu`}+p98=Kmy95NbLynjfAvq76H451}^y<|KfM@rn zgl!DbaLv4!^7gGmSGA!8L(+0+{oGYjQsM=YrZt`K^kMsZ*T1!wr>3%rA3V4piR2X) z7UtE8J9^K5=)fO6>rovtWu~X6ciFsHbGo~XgZSe7NsuS3Q=PDH=dT%~(bfJ#swTyn zLf_v-%Q3U_o_PAy@G6y>LeZCM!$=GWX~hYC{`@&&@`C4wxw*7z_ck$QWv=aeWsdv! zNSPHOM_wNVP?x`8!YB|xWi#pyS;zY>5I+7kaR=~nUIjc z$j!yCUlSg?G$wQI-^I;+W_sF-Q5O}e1?m%t2ZBRFEFB!ub8>c{%grqT!P2;VWilVW zf=+8`X?gncB??-p2EI#=T$*%!c1|)mHMI#wk|&Moff5lF6-B@_C8wpGZuih3k*Yr| zuzK^Ma}yZk1x#G+*(odzxtenD(ut%b7Q31N&?2wyhx&q?YM!r!%8uyc zuo|8;&yf(ILG zbEkIiQGtmc`9lgxfZlG4A09InT-@kXem;+WIxneviCsif5Y`&X7x=9Gwef=l3dePQ zZCTdL{EZ;Is5+y(xN@b7j*~ViRNY}~Yg-$$st6kDG*HbIkl*o98z3MS7z00e@W29x zJM-d&38+x+9Pxbz4lu(jg>)U>x5kamb(pQOpGn*yP!RhN*rw)Plr&kxF-^9!t&JuA z$I$zr**7$zh`EW$_%~ynDr~z%z`fjeCT3=4Y1{7_!7$my#qr&pq-Y5n$oTG`J=U{6 zZ=Kq?@pSR}^z`(-{?yW-XbDd@T8>P>TVoc0ml$b($$(06wLB?xy%~FNG<2~9y^?ivgWfk=c}B{*6FA%m-FDSxA0+prtm z^D;;}bVoqtr!+v&f_txje5%j1ry<@t4R1%|n&awoi9}*5WxThx;XddaW|A~cGoW&? z1=Ev!tsI*p9zd09n#V;0eYcfkkJL8!fHpo;o9iP`V-pHWg|!Cry?GuNi>I@NL)jTX zeKL#_phZ?zR%7`&!5sMK_k~k$ zYjgQC^aH5k+XE^`tFeyh_L6mMH8u)(x-2x*8~rwGCxbgUYHe)XJm0g5rz--(;cu6p zu$PqNtg)GLr9B&OEk7rKplz$MiLAy7L8m(jLpP4%>0w@L?H%w}>d=jKJpJ(3q4IND zE$u=<(RYQ=%W^@|689-XzRzn-X$3EdP$akmBmy%x{#;#R6ua5`4Vql!Mdjsp9gF^^ z2Ws%u!`Nsj;l@7IFC@a&3#gx0Wmq4KyFdlthv-uTQ()163ZOn`f}&T)%xou+7wSD$ ztZ+b4q-How;ONn#LEneNo59@xtelE@d;BbQZT(KuMOI#>eqi_xITRU!GkQTtEHg~dIyyQo^1M~xbpWnHeGnJqeQ9*m?c>|JJs|260Rn4DW3Omd2LTs<>rFE= z3VJCkdMu_kPYQjvx*CX~ea*N11k+}D-(H!RpP$f>Muwe6qm^FCZVl3e(v24I?g1Y}sy)|R&dJZ83RVpkhfARl@^9Ewy1_-(ZQD+Y z8}S|qlhIuHuo-x!1u63E@(RXZgEz&jtoe4QW*Q(CUtGk&nc_tTi8AVxt5?N=7*E1@7dcvTXMu>j!0pg8FxbC; zzb;v@gd%(_6|^|{(_22M#<+x%xK1p6mZo+jxfw6d*Sv2nuX&dWf?;g7=LRtNvs`JL z#n))L5=I^NFs2Tu9x*kRDe147kni(vGlYX)|9_Yv!Au-sF>I$ZEbDY_>6sZ%u~&ArBk|wG!P{`p!p2V&BJGweO`jP?z&+k2NdN@ z=E~um(iJY9Y^GA9X5UDztgcGVY7-9QtKGK#TwnhTHB2f+XXl3)WYUePW&*V!E9(Rh zM`>+s|4iQm1soYtpJTY|SZfBT8X=@e$HcSMAR`)VU)~J;GA9;CHNrElKUz}tLrg72 zda`+jI#?6v9J4l4W>z1w)&K?oJFon4GP@5`N79^nv}Tbtop_s1NP~PlAfV!7zG?j7 zBS!?FE`X}0^vWw!$b{g@7$g<@lBo2cp~2GH`oP>oj=!u!EyCQ~{GqskE3DCno2yw3 zSRg-!d>op{9^15OlZCAu4ajB++Su5z$jQldDX7P_fSLuh;v5nU$7R4FWaZ%C5o$h6 z(mZEgv6@B2Izz=R<9Pqgi2QgAI#1>?6lHqg4i#}MXSr(%%J#(m_~yE@II{DMXkXOV zE`!fKHqI&FDN=`B<6Z?!;)(_jq=xYc{#Oz!Vrzt z4GIEprQpe`g;w-ba|OoK+}wanzVp&X|Jl;pkj|0Ck>*l&FSaS&BOfnt)HBLQQ3;8b zYfD**{sXtRa&mJ1_iiEj?jINCu8M%&y?==bKj{lmCfs zt#LEQhx&zwA>xJ4xp{c(7eq}#J}dYSDucg}>*=2i0xT(o|>K{kpItU_V5C|MX{qks>ED zsDof~;xw~jKaZk*{&@c@(X8zD#<`2?AqQsX<_d?s!K+|IfoKE|SRwL@2iPB1=yW!) zR%T{qs_-%qqbUa$flEq3k>!Ywd>puqII*@C^>a+*m&L@7TIc)ZZQxaxx?ks?I=#fy zkEa8^QO0+d-oMYEFXw!3qyE7IL7)j(5cqugNm*z>w3k-!Fbqu-7TqOUmNyjq|z zNO_NS?;>by79U8MmPx^Gr~-4OTrxk1vjtDydRRPY{K6EMscA0PjwuTSkqEzl$Y zJ-h;(7J$EfvxWra8@?e*1;MaFfKS_^7aEeFG>4UhLj#7-4pIT?)WiY5R!|E;FeCZz z%?wCZp@NLqYahGQ0ZkxMY3rNEq1FW}=HbSgFRU*>f=Ye2$pyu&fe%*?fMABIp?qp{ z+aN`v(R5N#qXKd5PhsHEh!sD_6FzTY0MP8JgL>j}^ITB>#Li~07R zRK(H2;^IzgZEdB03XL#@sy7jI$OyopzQ6yxNSq^NC1WmQolBr@-Rt-bTu>L)Lc;So zA8;yLmO8cMes8{wm0QE!ntoC}V5Ydfdk{&19UcXS%3`m5U<#$gr-)w@netuj+x;;pdLBjKx{+OdZa0uW*APf{{ za2?khGuHi;s2zGJ@RaVc@$($E#@vXe z=4OzFV~Z16OCG;{no~i4NUR*oblJWp;E<$bHiHAfpw!M3J_ao2Tf{Mu69OEGLo9yz zqT}dz(J$YCa)U}y z|MqaEnTt3GLA?x;KRLHhalLyc!p{h7GR0SSeQmlFraAspoDzB)_hX*XKuSsqJf(BDZYjPfQr{E)mc(LRZYQC!b6ex; zio0JunJ}i!|Hdq&O z5Dtc3m6?mcerHi4zGyTMiA`Xz7A4FIxVrzIzW~F60?g*w%*+l)KjN=nzt%I@zhg8e z`N|-sp$ps;#`%EfrAX$74<9n>2ylU_T^?_`dhOcilaxKOFRd&r5Mcal-M&{8tfR+| zA5XugZa-jh{siEysGM9UHIh<^>4V=Bg))8%@U(%X=>SF4nmwGI0JnmNqYDSaupM@Q zR%M(P^D1nDl8wPmU}YqkYp!m&aNz>O5h9Tkz+JZh1FxWfAJLb|<^*5CLIUNmAGilv zt&E>FXE?PF0KotMj!{=7h;wQ?rr`omD@a$t=x-mjF__(up9$XG*G6W_iuIu&TKhJ? zT}w-gJlDH}p}=8Fb8>MdfCX0yx(ZaV0LaQ$Am5=B9b -- bash + +In order to replicate the container startup scripts execute this command: + +For Redis: + + /opt/bitnami/scripts/redis/entrypoint.sh /opt/bitnami/scripts/redis/run.sh + +{{- if .Values.sentinel.enabled }} + +For Redis Sentinel: + + /opt/bitnami/scripts/redis-sentinel/entrypoint.sh /opt/bitnami/scripts/redis-sentinel/run.sh + +{{- end }} +{{- else }} + +{{- if contains .Values.master.service.type "LoadBalancer" }} +{{- if not .Values.auth.enabled }} +{{ if and (not .Values.networkPolicy.enabled) (.Values.networkPolicy.allowExternal) }} + +------------------------------------------------------------------------------- + WARNING + + By specifying "master.service.type=LoadBalancer" and "auth.enabled=false" you have + most likely exposed the Redis® service externally without any authentication + mechanism. + + For security reasons, we strongly suggest that you switch to "ClusterIP" or + "NodePort". As alternative, you can also switch to "auth.enabled=true" + providing a valid password on "password" parameter. + +------------------------------------------------------------------------------- +{{- end }} +{{- end }} +{{- end }} + +{{- if eq .Values.architecture "replication" }} +{{- if .Values.sentinel.enabled }} + +Redis® can be accessed via port {{ .Values.sentinel.service.ports.redis }} on the following DNS name from within your cluster: + + {{ template "common.names.fullname" . }}.{{ .Release.Namespace }}.svc.{{ .Values.clusterDomain }} for read only operations + +For read/write operations, first access the Redis® Sentinel cluster, which is available in port {{ .Values.sentinel.service.ports.sentinel }} using the same domain name above. + +{{- else }} + +Redis® can be accessed on the following DNS names from within your cluster: + + {{ printf "%s-master.%s.svc.%s" (include "common.names.fullname" .) .Release.Namespace .Values.clusterDomain }} for read/write operations (port {{ .Values.master.service.ports.redis }}) + {{ printf "%s-replicas.%s.svc.%s" (include "common.names.fullname" .) .Release.Namespace .Values.clusterDomain }} for read-only operations (port {{ .Values.replica.service.ports.redis }}) + +{{- end }} +{{- else }} + +Redis® can be accessed via port {{ .Values.master.service.ports.redis }} on the following DNS name from within your cluster: + + {{ template "common.names.fullname" . }}-master.{{ .Release.Namespace }}.svc.{{ .Values.clusterDomain }} + +{{- end }} + +{{ if .Values.auth.enabled }} + +To get your password run: + + export REDIS_PASSWORD=$(kubectl get secret --namespace {{ .Release.Namespace }} {{ template "redis.secretName" . }} -o jsonpath="{.data.redis-password}" | base64 -d) + +{{- end }} + +To connect to your Redis® server: + +1. Run a Redis® pod that you can use as a client: + + kubectl run --namespace {{ .Release.Namespace }} redis-client --restart='Never' {{ if .Values.auth.enabled }} --env REDIS_PASSWORD=$REDIS_PASSWORD {{ end }} --image {{ template "redis.image" . }} --command -- sleep infinity + +{{- if .Values.tls.enabled }} + + Copy your TLS certificates to the pod: + + kubectl cp --namespace {{ .Release.Namespace }} /path/to/client.cert redis-client:/tmp/client.cert + kubectl cp --namespace {{ .Release.Namespace }} /path/to/client.key redis-client:/tmp/client.key + kubectl cp --namespace {{ .Release.Namespace }} /path/to/CA.cert redis-client:/tmp/CA.cert + +{{- end }} + + Use the following command to attach to the pod: + + kubectl exec --tty -i redis-client \ + {{- if and (.Values.networkPolicy.enabled) (not .Values.networkPolicy.allowExternal) }}--labels="{{ template "common.names.fullname" . }}-client=true" \{{- end }} + --namespace {{ .Release.Namespace }} -- bash + +2. Connect using the Redis® CLI: + +{{- if eq .Values.architecture "replication" }} + {{- if .Values.sentinel.enabled }} + {{ if .Values.auth.enabled }}REDISCLI_AUTH="$REDIS_PASSWORD" {{ end }}redis-cli -h {{ template "common.names.fullname" . }} -p {{ .Values.sentinel.service.ports.redis }}{{ if .Values.tls.enabled }} --tls --cert /tmp/client.cert --key /tmp/client.key --cacert /tmp/CA.cert{{ end }} # Read only operations + {{ if .Values.auth.enabled }}REDISCLI_AUTH="$REDIS_PASSWORD" {{ end }}redis-cli -h {{ template "common.names.fullname" . }} -p {{ .Values.sentinel.service.ports.sentinel }}{{ if .Values.tls.enabled }} --tls --cert /tmp/client.cert --key /tmp/client.key --cacert /tmp/CA.cert{{ end }} # Sentinel access + {{- else }} + {{ if .Values.auth.enabled }}REDISCLI_AUTH="$REDIS_PASSWORD" {{ end }}redis-cli -h {{ printf "%s-master" (include "common.names.fullname" .) }}{{ if .Values.tls.enabled }} --tls --cert /tmp/client.cert --key /tmp/client.key --cacert /tmp/CA.cert{{ end }} + {{ if .Values.auth.enabled }}REDISCLI_AUTH="$REDIS_PASSWORD" {{ end }}redis-cli -h {{ printf "%s-replicas" (include "common.names.fullname" .) }}{{ if .Values.tls.enabled }} --tls --cert /tmp/client.cert --key /tmp/client.key --cacert /tmp/CA.cert{{ end }} + {{- end }} +{{- else }} + {{ if .Values.auth.enabled }}REDISCLI_AUTH="$REDIS_PASSWORD" {{ end }}redis-cli -h {{ template "common.names.fullname" . }}-master{{ if .Values.tls.enabled }} --tls --cert /tmp/client.cert --key /tmp/client.key --cacert /tmp/CA.cert{{ end }} +{{- end }} + +{{- if and (.Values.networkPolicy.enabled) (not .Values.networkPolicy.allowExternal) }} + +Note: Since NetworkPolicy is enabled, only pods with label {{ template "common.names.fullname" . }}-client=true" will be able to connect to redis. + +{{- else }} + +To connect to your database from outside the cluster execute the following commands: + +{{- if and (eq .Values.architecture "replication") .Values.sentinel.enabled }} +{{- if contains "NodePort" .Values.sentinel.service.type }} + + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ template "common.names.fullname" . }}) + {{ if .Values.auth.enabled }}REDISCLI_AUTH="$REDIS_PASSWORD" {{ end }}redis-cli -h $NODE_IP -p $NODE_PORT {{- if .Values.tls.enabled }} --tls --cert /tmp/client.cert --key /tmp/client.key --cacert /tmp/CA.cert{{ end }} + +{{- else if contains "LoadBalancer" .Values.sentinel.service.type }} + + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + Watch the status with: 'kubectl get svc --namespace {{ .Release.Namespace }} -w {{ template "common.names.fullname" . }}' + + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ template "common.names.fullname" . }} --template "{{ "{{ range (index .status.loadBalancer.ingress 0) }}{{ . }}{{ end }}" }}") + {{ if .Values.auth.enabled }}REDISCLI_AUTH="$REDIS_PASSWORD" {{ end }}redis-cli -h $SERVICE_IP -p {{ .Values.sentinel.service.ports.redis }} {{- if .Values.tls.enabled }} --tls --cert /tmp/client.cert --key /tmp/client.key --cacert /tmp/CA.cert{{ end }} + +{{- else if contains "ClusterIP" .Values.sentinel.service.type }} + + kubectl port-forward --namespace {{ .Release.Namespace }} svc/{{ template "common.names.fullname" . }} {{ .Values.sentinel.service.ports.redis }}:{{ .Values.sentinel.service.ports.redis }} & + {{ if .Values.auth.enabled }}REDISCLI_AUTH="$REDIS_PASSWORD" {{ end }}redis-cli -h 127.0.0.1 -p {{ .Values.sentinel.service.ports.redis }} {{- if .Values.tls.enabled }} --tls --cert /tmp/client.cert --key /tmp/client.key --cacert /tmp/CA.cert{{ end }} + +{{- end }} +{{- else }} +{{- if contains "NodePort" .Values.master.service.type }} + + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ printf "%s-master" (include "common.names.fullname" .) }}) + {{ if .Values.auth.enabled }}REDISCLI_AUTH="$REDIS_PASSWORD" {{ end }}redis-cli -h $NODE_IP -p $NODE_PORT {{- if .Values.tls.enabled }} --tls --cert /tmp/client.cert --key /tmp/client.key --cacert /tmp/CA.cert{{ end }} + +{{- else if contains "LoadBalancer" .Values.master.service.type }} + + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + Watch the status with: 'kubectl get svc --namespace {{ .Release.Namespace }} -w {{ template "common.names.fullname" . }}' + + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ printf "%s-master" (include "common.names.fullname" .) }} --template "{{ "{{ range (index .status.loadBalancer.ingress 0) }}{{ . }}{{ end }}" }}") + {{ if .Values.auth.enabled }}REDISCLI_AUTH="$REDIS_PASSWORD" {{ end }}redis-cli -h $SERVICE_IP -p {{ .Values.master.service.ports.redis }} {{- if .Values.tls.enabled }} --tls --cert /tmp/client.cert --key /tmp/client.key --cacert /tmp/CA.cert{{ end }} + +{{- else if contains "ClusterIP" .Values.master.service.type }} + + kubectl port-forward --namespace {{ .Release.Namespace }} svc/{{ printf "%s-master" (include "common.names.fullname" .) }} {{ .Values.master.service.ports.redis }}:{{ .Values.master.service.ports.redis }} & + {{ if .Values.auth.enabled }}REDISCLI_AUTH="$REDIS_PASSWORD" {{ end }}redis-cli -h 127.0.0.1 -p {{ .Values.master.service.ports.redis }} {{- if .Values.tls.enabled }} --tls --cert /tmp/client.cert --key /tmp/client.key --cacert /tmp/CA.cert{{ end }} + +{{- end }} +{{- end }} + +{{- end }} +{{- end }} +{{- include "redis.checkRollingTags" . }} +{{- include "common.warnings.rollingTag" .Values.volumePermissions.image }} +{{- include "common.warnings.rollingTag" .Values.sysctl.image }} +{{- include "redis.validateValues" . }} + +{{- if and (eq .Values.architecture "replication") .Values.sentinel.enabled (eq .Values.sentinel.service.type "NodePort") (not .Release.IsUpgrade ) }} +{{- if $.Values.sentinel.service.nodePorts.sentinel }} +No need to upgrade, ports and nodeports have been set from values +{{- else }} +#!#!#!#!#!#!#!# IMPORTANT #!#!#!#!#!#!#!# +YOU NEED TO PERFORM AN UPGRADE FOR THE SERVICES AND WORKLOAD TO BE CREATED +{{- end }} +{{- end }} diff --git a/packages/system/dashboard/charts/kubeapps/charts/redis/templates/_helpers.tpl b/packages/system/dashboard/charts/kubeapps/charts/redis/templates/_helpers.tpl new file mode 100644 index 00000000..a554418b --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/charts/redis/templates/_helpers.tpl @@ -0,0 +1,328 @@ +{{/* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Return the proper Redis image name +*/}} +{{- define "redis.image" -}} +{{ include "common.images.image" (dict "imageRoot" .Values.image "global" .Values.global) }} +{{- end -}} + +{{/* +Return the proper Redis Sentinel image name +*/}} +{{- define "redis.sentinel.image" -}} +{{ include "common.images.image" (dict "imageRoot" .Values.sentinel.image "global" .Values.global) }} +{{- end -}} + +{{/* +Return the proper image name (for the metrics image) +*/}} +{{- define "redis.metrics.image" -}} +{{ include "common.images.image" (dict "imageRoot" .Values.metrics.image "global" .Values.global) }} +{{- end -}} + +{{/* +Return the proper image name (for the init container volume-permissions image) +*/}} +{{- define "redis.volumePermissions.image" -}} +{{ include "common.images.image" (dict "imageRoot" .Values.volumePermissions.image "global" .Values.global) }} +{{- end -}} + +{{/* +Return sysctl image +*/}} +{{- define "redis.sysctl.image" -}} +{{ include "common.images.image" (dict "imageRoot" .Values.sysctl.image "global" .Values.global) }} +{{- end -}} + +{{/* +Return the proper Docker Image Registry Secret Names +*/}} +{{- define "redis.imagePullSecrets" -}} +{{- include "common.images.renderPullSecrets" (dict "images" (list .Values.image .Values.sentinel.image .Values.metrics.image .Values.volumePermissions.image .Values.sysctl.image) "context" $) -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for networkpolicy. +*/}} +{{- define "networkPolicy.apiVersion" -}} +{{- if semverCompare ">=1.4-0, <1.7-0" .Capabilities.KubeVersion.GitVersion -}} +{{- print "extensions/v1beta1" -}} +{{- else -}} +{{- print "networking.k8s.io/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiGroup for PodSecurityPolicy. +*/}} +{{- define "podSecurityPolicy.apiGroup" -}} +{{- if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} +{{- print "policy" -}} +{{- else -}} +{{- print "extensions" -}} +{{- end -}} +{{- end -}} + +{{/* +Return true if a TLS secret object should be created +*/}} +{{- define "redis.createTlsSecret" -}} +{{- if and .Values.tls.enabled .Values.tls.autoGenerated (and (not .Values.tls.existingSecret) (not .Values.tls.certificatesSecret)) }} + {{- true -}} +{{- end -}} +{{- end -}} + +{{/* +Return the secret containing Redis TLS certificates +*/}} +{{- define "redis.tlsSecretName" -}} +{{- $secretName := coalesce .Values.tls.existingSecret .Values.tls.certificatesSecret -}} +{{- if $secretName -}} + {{- printf "%s" (tpl $secretName $) -}} +{{- else -}} + {{- printf "%s-crt" (include "common.names.fullname" .) -}} +{{- end -}} +{{- end -}} + +{{/* +Return the path to the cert file. +*/}} +{{- define "redis.tlsCert" -}} +{{- if (include "redis.createTlsSecret" . ) -}} + {{- printf "/opt/bitnami/redis/certs/%s" "tls.crt" -}} +{{- else -}} + {{- required "Certificate filename is required when TLS in enabled" .Values.tls.certFilename | printf "/opt/bitnami/redis/certs/%s" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the path to the cert key file. +*/}} +{{- define "redis.tlsCertKey" -}} +{{- if (include "redis.createTlsSecret" . ) -}} + {{- printf "/opt/bitnami/redis/certs/%s" "tls.key" -}} +{{- else -}} + {{- required "Certificate Key filename is required when TLS in enabled" .Values.tls.certKeyFilename | printf "/opt/bitnami/redis/certs/%s" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the path to the CA cert file. +*/}} +{{- define "redis.tlsCACert" -}} +{{- if (include "redis.createTlsSecret" . ) -}} + {{- printf "/opt/bitnami/redis/certs/%s" "ca.crt" -}} +{{- else -}} + {{- required "Certificate CA filename is required when TLS in enabled" .Values.tls.certCAFilename | printf "/opt/bitnami/redis/certs/%s" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the path to the DH params file. +*/}} +{{- define "redis.tlsDHParams" -}} +{{- if .Values.tls.dhParamsFilename -}} +{{- printf "/opt/bitnami/redis/certs/%s" .Values.tls.dhParamsFilename -}} +{{- end -}} +{{- end -}} + +{{/* +Create the name of the shared service account to use +*/}} +{{- define "redis.serviceAccountName" -}} +{{- if .Values.serviceAccount.create -}} + {{ default (include "common.names.fullname" .) .Values.serviceAccount.name }} +{{- else -}} + {{ default "default" .Values.serviceAccount.name }} +{{- end -}} +{{- end -}} + +{{/* +Create the name of the master service account to use +*/}} +{{- define "redis.masterServiceAccountName" -}} +{{- if .Values.master.serviceAccount.create -}} + {{ default (printf "%s-master" (include "common.names.fullname" .)) .Values.master.serviceAccount.name }} +{{- else -}} + {{- if .Values.serviceAccount.create -}} + {{ template "redis.serviceAccountName" . }} + {{- else -}} + {{ default "default" .Values.master.serviceAccount.name }} + {{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Create the name of the replicas service account to use +*/}} +{{- define "redis.replicaServiceAccountName" -}} +{{- if .Values.replica.serviceAccount.create -}} + {{ default (printf "%s-replica" (include "common.names.fullname" .)) .Values.replica.serviceAccount.name }} +{{- else -}} + {{- if .Values.serviceAccount.create -}} + {{ template "redis.serviceAccountName" . }} + {{- else -}} + {{ default "default" .Values.replica.serviceAccount.name }} + {{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Return the configuration configmap name +*/}} +{{- define "redis.configmapName" -}} +{{- if .Values.existingConfigmap -}} + {{- printf "%s" (tpl .Values.existingConfigmap $) -}} +{{- else -}} + {{- printf "%s-configuration" (include "common.names.fullname" .) -}} +{{- end -}} +{{- end -}} + +{{/* +Return true if a configmap object should be created +*/}} +{{- define "redis.createConfigmap" -}} +{{- if empty .Values.existingConfigmap }} + {{- true -}} +{{- end -}} +{{- end -}} + +{{/* +Get the password secret. +*/}} +{{- define "redis.secretName" -}} +{{- if .Values.auth.existingSecret -}} +{{- printf "%s" (tpl .Values.auth.existingSecret $) -}} +{{- else -}} +{{- printf "%s" (include "common.names.fullname" .) -}} +{{- end -}} +{{- end -}} + +{{/* +Get the password key to be retrieved from Redis® secret. +*/}} +{{- define "redis.secretPasswordKey" -}} +{{- if and .Values.auth.existingSecret .Values.auth.existingSecretPasswordKey -}} +{{- printf "%s" (tpl .Values.auth.existingSecretPasswordKey $) -}} +{{- else -}} +{{- printf "redis-password" -}} +{{- end -}} +{{- end -}} + + +{{/* +Returns the available value for certain key in an existing secret (if it exists), +otherwise it generates a random value. +*/}} +{{- define "getValueFromSecret" }} + {{- $len := (default 16 .Length) | int -}} + {{- $obj := (lookup "v1" "Secret" .Namespace .Name).data -}} + {{- if $obj }} + {{- index $obj .Key | b64dec -}} + {{- else -}} + {{- randAlphaNum $len -}} + {{- end -}} +{{- end }} + +{{/* +Return Redis® password +*/}} +{{- define "redis.password" -}} +{{- if or .Values.auth.enabled .Values.global.redis.password }} + {{- if not (empty .Values.global.redis.password) }} + {{- .Values.global.redis.password -}} + {{- else if not (empty .Values.auth.password) -}} + {{- .Values.auth.password -}} + {{- else -}} + {{- include "getValueFromSecret" (dict "Namespace" .Release.Namespace "Name" (include "redis.secretName" .) "Length" 10 "Key" (include "redis.secretPasswordKey" .)) -}} + {{- end -}} +{{- end -}} +{{- end }} + +{{/* Check if there are rolling tags in the images */}} +{{- define "redis.checkRollingTags" -}} +{{- include "common.warnings.rollingTag" .Values.image }} +{{- include "common.warnings.rollingTag" .Values.sentinel.image }} +{{- include "common.warnings.rollingTag" .Values.metrics.image }} +{{- end -}} + +{{/* +Compile all warnings into a single message, and call fail. +*/}} +{{- define "redis.validateValues" -}} +{{- $messages := list -}} +{{- $messages := append $messages (include "redis.validateValues.topologySpreadConstraints" .) -}} +{{- $messages := append $messages (include "redis.validateValues.architecture" .) -}} +{{- $messages := append $messages (include "redis.validateValues.podSecurityPolicy.create" .) -}} +{{- $messages := append $messages (include "redis.validateValues.tls" .) -}} +{{- $messages := without $messages "" -}} +{{- $message := join "\n" $messages -}} + +{{- if $message -}} +{{- printf "\nVALUES VALIDATION:\n%s" $message | fail -}} +{{- end -}} +{{- end -}} + +{{/* Validate values of Redis® - spreadConstrainsts K8s version */}} +{{- define "redis.validateValues.topologySpreadConstraints" -}} +{{- if and (semverCompare "<1.16-0" .Capabilities.KubeVersion.GitVersion) .Values.replica.topologySpreadConstraints -}} +redis: topologySpreadConstraints + Pod Topology Spread Constraints are only available on K8s >= 1.16 + Find more information at https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/ +{{- end -}} +{{- end -}} + +{{/* Validate values of Redis® - must provide a valid architecture */}} +{{- define "redis.validateValues.architecture" -}} +{{- if and (ne .Values.architecture "standalone") (ne .Values.architecture "replication") -}} +redis: architecture + Invalid architecture selected. Valid values are "standalone" and + "replication". Please set a valid architecture (--set architecture="xxxx") +{{- end -}} +{{- if and .Values.sentinel.enabled (not (eq .Values.architecture "replication")) }} +redis: architecture + Using redis sentinel on standalone mode is not supported. + To deploy redis sentinel, please select the "replication" mode + (--set "architecture=replication,sentinel.enabled=true") +{{- end -}} +{{- end -}} + +{{/* Validate values of Redis® - PodSecurityPolicy create */}} +{{- define "redis.validateValues.podSecurityPolicy.create" -}} +{{- if and .Values.podSecurityPolicy.create (not .Values.podSecurityPolicy.enabled) }} +redis: podSecurityPolicy.create + In order to create PodSecurityPolicy, you also need to enable + podSecurityPolicy.enabled field +{{- end -}} +{{- end -}} + +{{/* Validate values of Redis® - TLS enabled */}} +{{- define "redis.validateValues.tls" -}} +{{- if and .Values.tls.enabled (not .Values.tls.autoGenerated) (not .Values.tls.existingSecret) (not .Values.tls.certificatesSecret) }} +redis: tls.enabled + In order to enable TLS, you also need to provide + an existing secret containing the TLS certificates or + enable auto-generated certificates. +{{- end -}} +{{- end -}} + +{{/* Define the suffix utilized for external-dns */}} +{{- define "redis.externalDNS.suffix" -}} +{{ printf "%s.%s" (include "common.names.fullname" .) .Values.useExternalDNS.suffix }} +{{- end -}} + +{{/* Compile all annotations utilized for external-dns */}} +{{- define "redis.externalDNS.annotations" -}} +{{- if and .Values.useExternalDNS.enabled .Values.useExternalDNS.annotationKey }} +{{ .Values.useExternalDNS.annotationKey }}hostname: {{ include "redis.externalDNS.suffix" . }} +{{- range $key, $val := .Values.useExternalDNS.additionalAnnotations }} +{{ $.Values.useExternalDNS.annotationKey }}{{ $key }}: {{ $val | quote }} +{{- end }} +{{- end }} +{{- end }} diff --git a/packages/system/dashboard/charts/kubeapps/charts/redis/templates/configmap.yaml b/packages/system/dashboard/charts/kubeapps/charts/redis/templates/configmap.yaml new file mode 100644 index 00000000..c616599c --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/charts/redis/templates/configmap.yaml @@ -0,0 +1,61 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if (include "redis.createConfigmap" .) }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ printf "%s-configuration" (include "common.names.fullname" .) }} + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +data: + redis.conf: |- + # User-supplied common configuration: + {{- if .Values.commonConfiguration }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonConfiguration "context" $ ) | nindent 4 }} + {{- end }} + # End of common configuration + master.conf: |- + dir {{ .Values.master.persistence.path }} + # User-supplied master configuration: + {{- if .Values.master.configuration }} + {{- include "common.tplvalues.render" ( dict "value" .Values.master.configuration "context" $ ) | nindent 4 }} + {{- end }} + {{- if .Values.master.disableCommands }} + {{- range .Values.master.disableCommands }} + rename-command {{ . }} "" + {{- end }} + {{- end }} + # End of master configuration + replica.conf: |- + dir {{ .Values.replica.persistence.path }} + # User-supplied replica configuration: + {{- if .Values.replica.configuration }} + {{- include "common.tplvalues.render" ( dict "value" .Values.replica.configuration "context" $ ) | nindent 4 }} + {{- end }} + {{- if .Values.replica.disableCommands }} + {{- range .Values.replica.disableCommands }} + rename-command {{ . }} "" + {{- end }} + {{- end }} + # End of replica configuration + {{- if .Values.sentinel.enabled }} + sentinel.conf: |- + dir "/tmp" + port {{ .Values.sentinel.containerPorts.sentinel }} + sentinel monitor {{ .Values.sentinel.masterSet }} {{ template "common.names.fullname" . }}-node-0.{{ template "common.names.fullname" . }}-headless.{{ .Release.Namespace }}.svc.{{ .Values.clusterDomain }} {{ .Values.sentinel.service.ports.redis }} {{ .Values.sentinel.quorum }} + sentinel down-after-milliseconds {{ .Values.sentinel.masterSet }} {{ .Values.sentinel.downAfterMilliseconds }} + sentinel failover-timeout {{ .Values.sentinel.masterSet }} {{ .Values.sentinel.failoverTimeout }} + sentinel parallel-syncs {{ .Values.sentinel.masterSet }} {{ .Values.sentinel.parallelSyncs }} + # User-supplied sentinel configuration: + {{- if .Values.sentinel.configuration }} + {{- include "common.tplvalues.render" ( dict "value" .Values.sentinel.configuration "context" $ ) | nindent 4 }} + {{- end }} + # End of sentinel configuration + {{- end }} +{{- end }} diff --git a/packages/system/dashboard/charts/kubeapps/charts/redis/templates/extra-list.yaml b/packages/system/dashboard/charts/kubeapps/charts/redis/templates/extra-list.yaml new file mode 100644 index 00000000..2d35a580 --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/charts/redis/templates/extra-list.yaml @@ -0,0 +1,9 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- range .Values.extraDeploy }} +--- +{{ include "common.tplvalues.render" (dict "value" . "context" $) }} +{{- end }} diff --git a/packages/system/dashboard/charts/kubeapps/charts/redis/templates/headless-svc.yaml b/packages/system/dashboard/charts/kubeapps/charts/redis/templates/headless-svc.yaml new file mode 100644 index 00000000..bd6121de --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/charts/redis/templates/headless-svc.yaml @@ -0,0 +1,33 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +apiVersion: v1 +kind: Service +metadata: + name: {{ printf "%s-headless" (include "common.names.fullname" .) }} + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + annotations: + {{- if or .Values.sentinel.service.headless.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.sentinel.service.headless.annotations .Values.commonAnnotations ) "context" . ) }} + {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} + {{- include "redis.externalDNS.annotations" . | nindent 4 }} +spec: + type: ClusterIP + clusterIP: None + {{- if .Values.sentinel.enabled }} + publishNotReadyAddresses: true + {{- end }} + ports: + - name: tcp-redis + port: {{ if .Values.sentinel.enabled }}{{ .Values.sentinel.service.ports.redis }}{{ else }}{{ .Values.master.service.ports.redis }}{{ end }} + targetPort: redis + {{- if .Values.sentinel.enabled }} + - name: tcp-sentinel + port: {{ .Values.sentinel.service.ports.sentinel }} + targetPort: redis-sentinel + {{- end }} + selector: {{- include "common.labels.matchLabels" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} diff --git a/packages/system/dashboard/charts/kubeapps/charts/redis/templates/health-configmap.yaml b/packages/system/dashboard/charts/kubeapps/charts/redis/templates/health-configmap.yaml new file mode 100644 index 00000000..95ade5c4 --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/charts/redis/templates/health-configmap.yaml @@ -0,0 +1,194 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ printf "%s-health" (include "common.names.fullname" .) }} + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +data: + ping_readiness_local.sh: |- + #!/bin/bash + + [[ -f $REDIS_PASSWORD_FILE ]] && export REDIS_PASSWORD="$(< "${REDIS_PASSWORD_FILE}")" + [[ -n "$REDIS_PASSWORD" ]] && export REDISCLI_AUTH="$REDIS_PASSWORD" + response=$( + timeout -s 15 $1 \ + redis-cli \ + -h localhost \ +{{- if .Values.tls.enabled }} + -p $REDIS_TLS_PORT \ + --tls \ + --cacert {{ template "redis.tlsCACert" . }} \ + {{- if .Values.tls.authClients }} + --cert {{ template "redis.tlsCert" . }} \ + --key {{ template "redis.tlsCertKey" . }} \ + {{- end }} +{{- else }} + -p $REDIS_PORT \ +{{- end }} + ping + ) + if [ "$?" -eq "124" ]; then + echo "Timed out" + exit 1 + fi + if [ "$response" != "PONG" ]; then + echo "$response" + exit 1 + fi + ping_liveness_local.sh: |- + #!/bin/bash + + [[ -f $REDIS_PASSWORD_FILE ]] && export REDIS_PASSWORD="$(< "${REDIS_PASSWORD_FILE}")" + [[ -n "$REDIS_PASSWORD" ]] && export REDISCLI_AUTH="$REDIS_PASSWORD" + response=$( + timeout -s 15 $1 \ + redis-cli \ + -h localhost \ +{{- if .Values.tls.enabled }} + -p $REDIS_TLS_PORT \ + --tls \ + --cacert {{ template "redis.tlsCACert" . }} \ + {{- if .Values.tls.authClients }} + --cert {{ template "redis.tlsCert" . }} \ + --key {{ template "redis.tlsCertKey" . }} \ + {{- end }} +{{- else }} + -p $REDIS_PORT \ +{{- end }} + ping + ) + if [ "$?" -eq "124" ]; then + echo "Timed out" + exit 1 + fi + responseFirstWord=$(echo $response | head -n1 | awk '{print $1;}') + if [ "$response" != "PONG" ] && [ "$responseFirstWord" != "LOADING" ] && [ "$responseFirstWord" != "MASTERDOWN" ]; then + echo "$response" + exit 1 + fi +{{- if .Values.sentinel.enabled }} + ping_sentinel.sh: |- + #!/bin/bash + +{{- if .Values.auth.sentinel }} + [[ -f $REDIS_PASSWORD_FILE ]] && export REDIS_PASSWORD="$(< "${REDIS_PASSWORD_FILE}")" + [[ -n "$REDIS_PASSWORD" ]] && export REDISCLI_AUTH="$REDIS_PASSWORD" +{{- end }} + response=$( + timeout -s 15 $1 \ + redis-cli \ + -h localhost \ +{{- if .Values.tls.enabled }} + -p $REDIS_SENTINEL_TLS_PORT_NUMBER \ + --tls \ + --cacert "$REDIS_SENTINEL_TLS_CA_FILE" \ + {{- if .Values.tls.authClients }} + --cert "$REDIS_SENTINEL_TLS_CERT_FILE" \ + --key "$REDIS_SENTINEL_TLS_KEY_FILE" \ + {{- end }} +{{- else }} + -p $REDIS_SENTINEL_PORT \ +{{- end }} + ping + ) + if [ "$?" -eq "124" ]; then + echo "Timed out" + exit 1 + fi + if [ "$response" != "PONG" ]; then + echo "$response" + exit 1 + fi + parse_sentinels.awk: |- + /ip/ {FOUND_IP=1} + /port/ {FOUND_PORT=1} + /runid/ {FOUND_RUNID=1} + !/ip|port|runid/ { + if (FOUND_IP==1) { + IP=$1; FOUND_IP=0; + } + else if (FOUND_PORT==1) { + PORT=$1; + FOUND_PORT=0; + } else if (FOUND_RUNID==1) { + printf "\nsentinel known-sentinel {{ .Values.sentinel.masterSet }} %s %s %s", IP, PORT, $0; FOUND_RUNID=0; + } + } +{{- end }} + ping_readiness_master.sh: |- + #!/bin/bash + + [[ -f $REDIS_MASTER_PASSWORD_FILE ]] && export REDIS_MASTER_PASSWORD="$(< "${REDIS_MASTER_PASSWORD_FILE}")" + [[ -n "$REDIS_MASTER_PASSWORD" ]] && export REDISCLI_AUTH="$REDIS_MASTER_PASSWORD" + response=$( + timeout -s 15 $1 \ + redis-cli \ + -h $REDIS_MASTER_HOST \ + -p $REDIS_MASTER_PORT_NUMBER \ +{{- if .Values.tls.enabled }} + --tls \ + --cacert {{ template "redis.tlsCACert" . }} \ + {{- if .Values.tls.authClients }} + --cert {{ template "redis.tlsCert" . }} \ + --key {{ template "redis.tlsCertKey" . }} \ + {{- end }} +{{- end }} + ping + ) + if [ "$?" -eq "124" ]; then + echo "Timed out" + exit 1 + fi + if [ "$response" != "PONG" ]; then + echo "$response" + exit 1 + fi + ping_liveness_master.sh: |- + #!/bin/bash + + [[ -f $REDIS_MASTER_PASSWORD_FILE ]] && export REDIS_MASTER_PASSWORD="$(< "${REDIS_MASTER_PASSWORD_FILE}")" + [[ -n "$REDIS_MASTER_PASSWORD" ]] && export REDISCLI_AUTH="$REDIS_MASTER_PASSWORD" + response=$( + timeout -s 15 $1 \ + redis-cli \ + -h $REDIS_MASTER_HOST \ + -p $REDIS_MASTER_PORT_NUMBER \ +{{- if .Values.tls.enabled }} + --tls \ + --cacert {{ template "redis.tlsCACert" . }} \ + {{- if .Values.tls.authClients }} + --cert {{ template "redis.tlsCert" . }} \ + --key {{ template "redis.tlsCertKey" . }} \ + {{- end }} +{{- end }} + ping + ) + if [ "$?" -eq "124" ]; then + echo "Timed out" + exit 1 + fi + responseFirstWord=$(echo $response | head -n1 | awk '{print $1;}') + if [ "$response" != "PONG" ] && [ "$responseFirstWord" != "LOADING" ]; then + echo "$response" + exit 1 + fi + ping_readiness_local_and_master.sh: |- + script_dir="$(dirname "$0")" + exit_status=0 + "$script_dir/ping_readiness_local.sh" $1 || exit_status=$? + "$script_dir/ping_readiness_master.sh" $1 || exit_status=$? + exit $exit_status + ping_liveness_local_and_master.sh: |- + script_dir="$(dirname "$0")" + exit_status=0 + "$script_dir/ping_liveness_local.sh" $1 || exit_status=$? + "$script_dir/ping_liveness_master.sh" $1 || exit_status=$? + exit $exit_status diff --git a/packages/system/dashboard/charts/kubeapps/charts/redis/templates/master/application.yaml b/packages/system/dashboard/charts/kubeapps/charts/redis/templates/master/application.yaml new file mode 100644 index 00000000..8fdaec12 --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/charts/redis/templates/master/application.yaml @@ -0,0 +1,532 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if gt (int64 .Values.master.count) 0 -}} +{{- if or (not (eq .Values.architecture "replication")) (not .Values.sentinel.enabled) }} +apiVersion: {{ include "common.capabilities.statefulset.apiVersion" . }} +kind: {{ .Values.master.kind }} +metadata: + name: {{ printf "%s-master" (include "common.names.fullname" .) }} + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: master + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + {{- if not (eq .Values.master.kind "DaemonSet") }} + replicas: {{ .Values.master.count }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.master.podLabels .Values.commonLabels ) "context" . ) }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 6 }} + app.kubernetes.io/component: master + {{- if (eq .Values.master.kind "StatefulSet") }} + serviceName: {{ printf "%s-headless" (include "common.names.fullname" .) }} + {{- end }} + {{- if .Values.master.updateStrategy }} + {{- if (eq .Values.master.kind "Deployment") }} + strategy: {{- toYaml .Values.master.updateStrategy | nindent 4 }} + {{- else }} + updateStrategy: {{- toYaml .Values.master.updateStrategy | nindent 4 }} + {{- end }} + {{- if and .Values.master.minReadySeconds (semverCompare ">= 1.23-0" (include "common.capabilities.kubeVersion" .)) }} + minReadySeconds: {{ .Values.master.minReadySeconds }} + {{- end }} + {{- end }} + template: + metadata: + labels: {{- include "common.labels.standard" ( dict "customLabels" $podLabels "context" $ ) | nindent 8 }} + app.kubernetes.io/component: master + {{- if and .Values.metrics.enabled .Values.metrics.podLabels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.podLabels "context" $ ) | nindent 8 }} + {{- end }} + annotations: + {{- if (include "redis.createConfigmap" .) }} + checksum/configmap: {{ pick ( include (print $.Template.BasePath "/configmap.yaml") . | fromYaml ) "data" | toYaml | sha256sum }} + {{- end }} + checksum/health: {{ pick ( include (print $.Template.BasePath "/health-configmap.yaml") . | fromYaml ) "data" | toYaml | sha256sum }} + checksum/scripts: {{ pick ( include (print $.Template.BasePath "/scripts-configmap.yaml") . | fromYaml ) "data" | toYaml | sha256sum }} + checksum/secret: {{ pick ( include (print $.Template.BasePath "/secret.yaml") . | fromYaml ) "data" | toYaml | sha256sum }} + {{- if .Values.master.podAnnotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.master.podAnnotations "context" $ ) | nindent 8 }} + {{- end }} + {{- if and .Values.metrics.enabled .Values.metrics.podAnnotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.podAnnotations "context" $ ) | nindent 8 }} + {{- end }} + spec: + {{- include "redis.imagePullSecrets" . | nindent 6 }} + {{- if .Values.master.hostAliases }} + hostAliases: {{- include "common.tplvalues.render" (dict "value" .Values.master.hostAliases "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.master.podSecurityContext.enabled }} + securityContext: {{- omit .Values.master.podSecurityContext "enabled" | toYaml | nindent 8 }} + {{- end }} + serviceAccountName: {{ template "redis.masterServiceAccountName" . }} + automountServiceAccountToken: {{ .Values.master.serviceAccount.automountServiceAccountToken }} + {{- if .Values.master.priorityClassName }} + priorityClassName: {{ .Values.master.priorityClassName | quote }} + {{- end }} + {{- if .Values.master.affinity }} + affinity: {{- include "common.tplvalues.render" (dict "value" .Values.master.affinity "context" $) | nindent 8 }} + {{- else }} + affinity: + podAffinity: {{- include "common.affinities.pods" (dict "type" .Values.master.podAffinityPreset "component" "master" "customLabels" $podLabels "context" $) | nindent 10 }} + podAntiAffinity: {{- include "common.affinities.pods" (dict "type" .Values.master.podAntiAffinityPreset "component" "master" "customLabels" $podLabels "context" $) | nindent 10 }} + nodeAffinity: {{- include "common.affinities.nodes" (dict "type" .Values.master.nodeAffinityPreset.type "key" .Values.master.nodeAffinityPreset.key "values" .Values.master.nodeAffinityPreset.values) | nindent 10 }} + {{- end }} + {{- if .Values.master.nodeSelector }} + nodeSelector: {{- include "common.tplvalues.render" (dict "value" .Values.master.nodeSelector "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.master.tolerations }} + tolerations: {{- include "common.tplvalues.render" (dict "value" .Values.master.tolerations "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.master.topologySpreadConstraints }} + topologySpreadConstraints: {{- include "common.tplvalues.render" (dict "value" .Values.master.topologySpreadConstraints "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.master.shareProcessNamespace }} + shareProcessNamespace: {{ .Values.master.shareProcessNamespace }} + {{- end }} + {{- if .Values.master.schedulerName }} + schedulerName: {{ .Values.master.schedulerName | quote }} + {{- end }} + {{- if .Values.master.dnsPolicy }} + dnsPolicy: {{ .Values.master.dnsPolicy }} + {{- end }} + {{- if .Values.master.dnsConfig }} + dnsConfig: {{- include "common.tplvalues.render" (dict "value" .Values.master.dnsConfig "context" $) | nindent 8 }} + {{- end }} + enableServiceLinks: {{ .Values.master.enableServiceLinks }} + terminationGracePeriodSeconds: {{ .Values.master.terminationGracePeriodSeconds }} + containers: + - name: redis + image: {{ template "redis.image" . }} + imagePullPolicy: {{ .Values.image.pullPolicy | quote }} + {{- if .Values.master.lifecycleHooks }} + lifecycle: {{- include "common.tplvalues.render" (dict "value" .Values.master.lifecycleHooks "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.master.containerSecurityContext.enabled }} + securityContext: {{- omit .Values.master.containerSecurityContext "enabled" | toYaml | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 12 }} + {{- else if .Values.master.command }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.master.command "context" $) | nindent 12 }} + {{- else }} + command: + - /bin/bash + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 12 }} + {{- else if .Values.master.args }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.master.args "context" $) | nindent 12 }} + {{- else }} + args: + - -c + - /opt/bitnami/scripts/start-scripts/start-master.sh + {{- end }} + env: + - name: BITNAMI_DEBUG + value: {{ ternary "true" "false" (or .Values.image.debug .Values.diagnosticMode.enabled) | quote }} + - name: REDIS_REPLICATION_MODE + value: master + - name: ALLOW_EMPTY_PASSWORD + value: {{ ternary "no" "yes" .Values.auth.enabled | quote }} + {{- if .Values.auth.enabled }} + {{- if .Values.auth.usePasswordFiles }} + - name: REDIS_PASSWORD_FILE + value: "/opt/bitnami/redis/secrets/redis-password" + {{- else }} + - name: REDIS_PASSWORD + valueFrom: + secretKeyRef: + name: {{ template "redis.secretName" . }} + key: {{ template "redis.secretPasswordKey" . }} + {{- end }} + {{- end }} + - name: REDIS_TLS_ENABLED + value: {{ ternary "yes" "no" .Values.tls.enabled | quote }} + {{- if .Values.tls.enabled }} + - name: REDIS_TLS_PORT + value: {{ .Values.master.containerPorts.redis | quote }} + - name: REDIS_TLS_AUTH_CLIENTS + value: {{ ternary "yes" "no" .Values.tls.authClients | quote }} + - name: REDIS_TLS_CERT_FILE + value: {{ template "redis.tlsCert" . }} + - name: REDIS_TLS_KEY_FILE + value: {{ template "redis.tlsCertKey" . }} + - name: REDIS_TLS_CA_FILE + value: {{ template "redis.tlsCACert" . }} + {{- if .Values.tls.dhParamsFilename }} + - name: REDIS_TLS_DH_PARAMS_FILE + value: {{ template "redis.tlsDHParams" . }} + {{- end }} + {{- else }} + - name: REDIS_PORT + value: {{ .Values.master.containerPorts.redis | quote }} + {{- end }} + {{- if .Values.master.extraEnvVars }} + {{- include "common.tplvalues.render" (dict "value" .Values.master.extraEnvVars "context" $) | nindent 12 }} + {{- end }} + {{- if or .Values.master.extraEnvVarsCM .Values.master.extraEnvVarsSecret }} + envFrom: + {{- if .Values.master.extraEnvVarsCM }} + - configMapRef: + name: {{ .Values.master.extraEnvVarsCM }} + {{- end }} + {{- if .Values.master.extraEnvVarsSecret }} + - secretRef: + name: {{ .Values.master.extraEnvVarsSecret }} + {{- end }} + {{- end }} + ports: + - name: redis + containerPort: {{ .Values.master.containerPorts.redis }} + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.master.customStartupProbe }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" .Values.master.customStartupProbe "context" $) | nindent 12 }} + {{- else if .Values.master.startupProbe.enabled }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.master.startupProbe "enabled") "context" $) | nindent 12 }} + tcpSocket: + port: redis + {{- end }} + {{- if .Values.master.customLivenessProbe }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.master.customLivenessProbe "context" $) | nindent 12 }} + {{- else if .Values.master.livenessProbe.enabled }} + livenessProbe: + initialDelaySeconds: {{ .Values.master.livenessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.master.livenessProbe.periodSeconds }} + # One second longer than command timeout should prevent generation of zombie processes. + timeoutSeconds: {{ add1 .Values.master.livenessProbe.timeoutSeconds }} + successThreshold: {{ .Values.master.livenessProbe.successThreshold }} + failureThreshold: {{ .Values.master.livenessProbe.failureThreshold }} + exec: + command: + - sh + - -c + - /health/ping_liveness_local.sh {{ .Values.master.livenessProbe.timeoutSeconds }} + {{- end }} + {{- if .Values.master.customReadinessProbe }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.master.customReadinessProbe "context" $) | nindent 12 }} + {{- else if .Values.master.readinessProbe.enabled }} + readinessProbe: + initialDelaySeconds: {{ .Values.master.readinessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.master.readinessProbe.periodSeconds }} + timeoutSeconds: {{ add1 .Values.master.readinessProbe.timeoutSeconds }} + successThreshold: {{ .Values.master.readinessProbe.successThreshold }} + failureThreshold: {{ .Values.master.readinessProbe.failureThreshold }} + exec: + command: + - sh + - -c + - /health/ping_readiness_local.sh {{ .Values.master.readinessProbe.timeoutSeconds }} + {{- end }} + {{- end }} + {{- if .Values.master.resources }} + resources: {{- toYaml .Values.master.resources | nindent 12 }} + {{- end }} + volumeMounts: + - name: start-scripts + mountPath: /opt/bitnami/scripts/start-scripts + - name: health + mountPath: /health + {{- if .Values.auth.usePasswordFiles }} + - name: redis-password + mountPath: /opt/bitnami/redis/secrets/ + {{- end }} + - name: redis-data + mountPath: {{ .Values.master.persistence.path }} + {{- if .Values.master.persistence.subPath }} + subPath: {{ .Values.master.persistence.subPath }} + {{- else if .Values.master.persistence.subPathExpr }} + subPathExpr: {{ .Values.master.persistence.subPathExpr }} + {{- end }} + - name: config + mountPath: /opt/bitnami/redis/mounted-etc + - name: redis-tmp-conf + mountPath: /opt/bitnami/redis/etc/ + - name: tmp + mountPath: /tmp + {{- if .Values.tls.enabled }} + - name: redis-certificates + mountPath: /opt/bitnami/redis/certs + readOnly: true + {{- end }} + {{- if .Values.master.extraVolumeMounts }} + {{- include "common.tplvalues.render" ( dict "value" .Values.master.extraVolumeMounts "context" $ ) | nindent 12 }} + {{- end }} + {{- if .Values.metrics.enabled }} + - name: metrics + image: {{ include "redis.metrics.image" . }} + imagePullPolicy: {{ .Values.metrics.image.pullPolicy | quote }} + {{- if .Values.metrics.containerSecurityContext.enabled }} + securityContext: {{- omit .Values.metrics.containerSecurityContext "enabled" | toYaml | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 12 }} + {{- else if .Values.metrics.command }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.command "context" $) | nindent 12 }} + {{- else }} + command: + - /bin/bash + - -c + - | + if [[ -f '/secrets/redis-password' ]]; then + export REDIS_PASSWORD=$(cat /secrets/redis-password) + fi + redis_exporter{{- range $key, $value := .Values.metrics.extraArgs }} --{{ $key }}={{ $value }}{{- end }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 12 }} + {{- end }} + env: + - name: REDIS_ALIAS + value: {{ template "common.names.fullname" . }} + {{- if .Values.auth.enabled }} + - name: REDIS_USER + value: default + {{- if (not .Values.auth.usePasswordFiles) }} + - name: REDIS_PASSWORD + valueFrom: + secretKeyRef: + name: {{ template "redis.secretName" . }} + key: {{ template "redis.secretPasswordKey" . }} + {{- end }} + {{- end }} + {{- if .Values.tls.enabled }} + - name: REDIS_ADDR + value: rediss://{{ .Values.metrics.redisTargetHost }}:{{ .Values.master.containerPorts.redis }} + {{- if .Values.tls.authClients }} + - name: REDIS_EXPORTER_TLS_CLIENT_KEY_FILE + value: {{ template "redis.tlsCertKey" . }} + - name: REDIS_EXPORTER_TLS_CLIENT_CERT_FILE + value: {{ template "redis.tlsCert" . }} + {{- end }} + - name: REDIS_EXPORTER_TLS_CA_CERT_FILE + value: {{ template "redis.tlsCACert" . }} + {{- end }} + {{- if .Values.metrics.extraEnvVars }} + {{- include "common.tplvalues.render" (dict "value" .Values.metrics.extraEnvVars "context" $) | nindent 12 }} + {{- end }} + ports: + - name: metrics + containerPort: 9121 + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.metrics.customStartupProbe }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.customStartupProbe "context" $) | nindent 12 }} + {{- else if .Values.metrics.startupProbe.enabled }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.metrics.startupProbe "enabled") "context" $) | nindent 12 }} + tcpSocket: + port: metrics + {{- end }} + {{- if .Values.metrics.customLivenessProbe }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.customLivenessProbe "context" $) | nindent 12 }} + {{- else if .Values.metrics.livenessProbe.enabled }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.metrics.livenessProbe "enabled") "context" $) | nindent 12 }} + tcpSocket: + port: metrics + {{- end }} + {{- if .Values.metrics.customReadinessProbe }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.customReadinessProbe "context" $) | nindent 12 }} + {{- else if .Values.metrics.readinessProbe.enabled }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.metrics.readinessProbe "enabled") "context" $) | nindent 12 }} + httpGet: + path: / + port: metrics + {{- end }} + {{- end }} + {{- if .Values.metrics.resources }} + resources: {{- toYaml .Values.metrics.resources | nindent 12 }} + {{- end }} + volumeMounts: + {{- if .Values.auth.usePasswordFiles }} + - name: redis-password + mountPath: /secrets/ + {{- end }} + {{- if .Values.tls.enabled }} + - name: redis-certificates + mountPath: /opt/bitnami/redis/certs + readOnly: true + {{- end }} + {{- if .Values.metrics.extraVolumeMounts }} + {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.extraVolumeMounts "context" $ ) | nindent 12 }} + {{- end }} + {{- end }} + {{- if .Values.master.sidecars }} + {{- include "common.tplvalues.render" (dict "value" .Values.master.sidecars "context" $) | nindent 8 }} + {{- end }} + {{- $needsVolumePermissions := and .Values.volumePermissions.enabled .Values.master.persistence.enabled .Values.master.podSecurityContext.enabled .Values.master.containerSecurityContext.enabled }} + {{- if or .Values.master.initContainers $needsVolumePermissions .Values.sysctl.enabled }} + initContainers: + {{- if .Values.master.initContainers }} + {{- include "common.tplvalues.render" (dict "value" .Values.master.initContainers "context" $) | nindent 8 }} + {{- end }} + {{- if $needsVolumePermissions }} + - name: volume-permissions + image: {{ include "redis.volumePermissions.image" . }} + imagePullPolicy: {{ .Values.volumePermissions.image.pullPolicy | quote }} + command: + - /bin/bash + - -ec + - | + {{- if eq ( toString ( .Values.volumePermissions.containerSecurityContext.runAsUser )) "auto" }} + chown -R `id -u`:`id -G | cut -d " " -f2` {{ .Values.master.persistence.path }} + {{- else }} + chown -R {{ .Values.master.containerSecurityContext.runAsUser }}:{{ .Values.master.podSecurityContext.fsGroup }} {{ .Values.master.persistence.path }} + {{- end }} + {{- if eq ( toString ( .Values.volumePermissions.containerSecurityContext.runAsUser )) "auto" }} + securityContext: {{- omit .Values.volumePermissions.containerSecurityContext "runAsUser" | toYaml | nindent 12 }} + {{- else }} + securityContext: {{- .Values.volumePermissions.containerSecurityContext | toYaml | nindent 12 }} + {{- end }} + {{- if .Values.volumePermissions.resources }} + resources: {{- toYaml .Values.volumePermissions.resources | nindent 12 }} + {{- end }} + volumeMounts: + - name: redis-data + mountPath: {{ .Values.master.persistence.path }} + {{- if .Values.master.persistence.subPath }} + subPath: {{ .Values.master.persistence.subPath }} + {{- else if .Values.master.persistence.subPathExpr }} + subPathExpr: {{ .Values.master.persistence.subPathExpr }} + {{- end }} + {{- end }} + {{- if .Values.sysctl.enabled }} + - name: init-sysctl + image: {{ include "redis.sysctl.image" . }} + imagePullPolicy: {{ default "" .Values.sysctl.image.pullPolicy | quote }} + securityContext: + privileged: true + runAsUser: 0 + {{- if .Values.sysctl.command }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.sysctl.command "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.sysctl.resources }} + resources: {{- toYaml .Values.sysctl.resources | nindent 12 }} + {{- end }} + {{- if .Values.sysctl.mountHostSys }} + volumeMounts: + - name: host-sys + mountPath: /host-sys + {{- end }} + {{- end }} + {{- end }} + volumes: + - name: start-scripts + configMap: + name: {{ printf "%s-scripts" (include "common.names.fullname" .) }} + defaultMode: 0755 + - name: health + configMap: + name: {{ printf "%s-health" (include "common.names.fullname" .) }} + defaultMode: 0755 + {{- if .Values.auth.usePasswordFiles }} + - name: redis-password + secret: + secretName: {{ template "redis.secretName" . }} + items: + - key: {{ template "redis.secretPasswordKey" . }} + path: redis-password + {{- end }} + - name: config + configMap: + name: {{ include "redis.configmapName" . }} + {{- if .Values.sysctl.mountHostSys }} + - name: host-sys + hostPath: + path: /sys + {{- end }} + - name: redis-tmp-conf + {{- if or .Values.master.persistence.medium .Values.master.persistence.sizeLimit }} + emptyDir: + {{- if .Values.master.persistence.medium }} + medium: {{ .Values.master.persistence.medium | quote }} + {{- end }} + {{- if .Values.master.persistence.sizeLimit }} + sizeLimit: {{ .Values.master.persistence.sizeLimit | quote }} + {{- end }} + {{- else }} + emptyDir: {} + {{- end }} + - name: tmp + {{- if or .Values.master.persistence.medium .Values.master.persistence.sizeLimit }} + emptyDir: + {{- if .Values.master.persistence.medium }} + medium: {{ .Values.master.persistence.medium | quote }} + {{- end }} + {{- if .Values.master.persistence.sizeLimit }} + sizeLimit: {{ .Values.master.persistence.sizeLimit | quote }} + {{- end }} + {{- else }} + emptyDir: {} + {{- end }} + {{- if .Values.tls.enabled }} + - name: redis-certificates + secret: + secretName: {{ include "redis.tlsSecretName" . }} + defaultMode: 256 + {{- end }} + {{- if .Values.master.extraVolumes }} + {{- include "common.tplvalues.render" ( dict "value" .Values.master.extraVolumes "context" $ ) | nindent 8 }} + {{- end }} + {{- if .Values.metrics.extraVolumes }} + {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.extraVolumes "context" $ ) | nindent 8 }} + {{- end }} + {{- if or (not .Values.master.persistence.enabled) (eq .Values.master.kind "DaemonSet") }} + - name: redis-data + {{- if or .Values.master.persistence.medium .Values.master.persistence.sizeLimit }} + emptyDir: + {{- if .Values.master.persistence.medium }} + medium: {{ .Values.master.persistence.medium | quote }} + {{- end }} + {{- if .Values.master.persistence.sizeLimit }} + sizeLimit: {{ .Values.master.persistence.sizeLimit | quote }} + {{- end }} + {{- else }} + emptyDir: {} + {{- end }} + {{- else if .Values.master.persistence.existingClaim }} + - name: redis-data + persistentVolumeClaim: + claimName: {{ printf "%s" (tpl .Values.master.persistence.existingClaim .) }} + {{- else if (eq .Values.master.kind "Deployment") }} + - name: redis-data + persistentVolumeClaim: + claimName: {{ printf "redis-data-%s-master" (include "common.names.fullname" .) }} + {{- else }} + {{- if .Values.master.persistentVolumeClaimRetentionPolicy.enabled }} + persistentVolumeClaimRetentionPolicy: + whenDeleted: {{ .Values.master.persistentVolumeClaimRetentionPolicy.whenDeleted }} + whenScaled: {{ .Values.master.persistentVolumeClaimRetentionPolicy.whenScaled }} + {{- end }} + volumeClaimTemplates: + - apiVersion: v1 + kind: PersistentVolumeClaim + metadata: + name: redis-data + {{- $claimLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.master.persistence.labels .Values.commonLabels ) "context" . ) }} + labels: {{- include "common.labels.matchLabels" ( dict "customLabels" $claimLabels "context" $ ) | nindent 10 }} + app.kubernetes.io/component: master + {{- if .Values.master.persistence.annotations }} + annotations: {{- toYaml .Values.master.persistence.annotations | nindent 10 }} + {{- end }} + spec: + accessModes: + {{- range .Values.master.persistence.accessModes }} + - {{ . | quote }} + {{- end }} + resources: + requests: + storage: {{ .Values.master.persistence.size | quote }} + {{- if .Values.master.persistence.selector }} + selector: {{- include "common.tplvalues.render" (dict "value" .Values.master.persistence.selector "context" $) | nindent 10 }} + {{- end }} + {{- if .Values.master.persistence.dataSource }} + dataSource: {{- include "common.tplvalues.render" (dict "value" .Values.master.persistence.dataSource "context" $) | nindent 10 }} + {{- end }} + {{- include "common.storage.class" (dict "persistence" .Values.master.persistence "global" .Values.global) | nindent 8 }} + {{- end }} +{{- end }} +{{- end }} diff --git a/packages/system/dashboard/charts/kubeapps/charts/redis/templates/master/psp.yaml b/packages/system/dashboard/charts/kubeapps/charts/redis/templates/master/psp.yaml new file mode 100644 index 00000000..368a2193 --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/charts/redis/templates/master/psp.yaml @@ -0,0 +1,47 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and (include "common.capabilities.psp.supported" .) .Values.podSecurityPolicy.create }} +apiVersion: policy/v1beta1 +kind: PodSecurityPolicy +metadata: + name: {{ printf "%s-master" (include "common.names.fullname" .) }} + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + allowPrivilegeEscalation: false + fsGroup: + rule: 'MustRunAs' + ranges: + - min: {{ .Values.master.podSecurityContext.fsGroup }} + max: {{ .Values.master.podSecurityContext.fsGroup }} + hostIPC: false + hostNetwork: false + hostPID: false + privileged: false + readOnlyRootFilesystem: false + requiredDropCapabilities: + - ALL + runAsUser: + rule: 'MustRunAs' + ranges: + - min: {{ .Values.master.containerSecurityContext.runAsUser }} + max: {{ .Values.master.containerSecurityContext.runAsUser }} + seLinux: + rule: 'RunAsAny' + supplementalGroups: + rule: 'MustRunAs' + ranges: + - min: {{ .Values.master.containerSecurityContext.runAsUser }} + max: {{ .Values.master.containerSecurityContext.runAsUser }} + volumes: + - 'configMap' + - 'secret' + - 'emptyDir' + - 'persistentVolumeClaim' +{{- end }} diff --git a/packages/system/dashboard/charts/kubeapps/charts/redis/templates/master/pvc.yaml b/packages/system/dashboard/charts/kubeapps/charts/redis/templates/master/pvc.yaml new file mode 100644 index 00000000..5c60d069 --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/charts/redis/templates/master/pvc.yaml @@ -0,0 +1,33 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and (eq .Values.architecture "standalone") (eq .Values.master.kind "Deployment") (.Values.master.persistence.enabled) (not .Values.master.persistence.existingClaim) }} +kind: PersistentVolumeClaim +apiVersion: v1 +metadata: + name: {{ printf "redis-data-%s-master" (include "common.names.fullname" .) }} + namespace: {{ .Release.Namespace | quote }} + {{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.master.persistence.labels .Values.commonLabels ) "context" . ) }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: master + {{- if .Values.master.persistence.annotations }} + annotations: {{- toYaml .Values.master.persistence.annotations | nindent 4 }} + {{- end }} +spec: + accessModes: + {{- range .Values.master.persistence.accessModes }} + - {{ . | quote }} + {{- end }} + resources: + requests: + storage: {{ .Values.master.persistence.size | quote }} + {{- if .Values.master.persistence.selector }} + selector: {{- include "common.tplvalues.render" (dict "value" .Values.master.persistence.selector "context" $) | nindent 4 }} + {{- end }} + {{- if .Values.master.persistence.dataSource }} + dataSource: {{- include "common.tplvalues.render" (dict "value" .Values.master.persistence.dataSource "context" $) | nindent 4 }} + {{- end }} + {{- include "common.storage.class" (dict "persistence" .Values.master.persistence "global" .Values.global) | nindent 2 }} +{{- end }} diff --git a/packages/system/dashboard/charts/kubeapps/charts/redis/templates/master/service.yaml b/packages/system/dashboard/charts/kubeapps/charts/redis/templates/master/service.yaml new file mode 100644 index 00000000..804f7b6e --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/charts/redis/templates/master/service.yaml @@ -0,0 +1,59 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and (not .Values.sentinel.enabled) (gt (int64 .Values.master.count) 0) }} +apiVersion: v1 +kind: Service +metadata: + name: {{ printf "%s-master" (include "common.names.fullname" .) }} + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: master + {{- if or .Values.master.service.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.master.service.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + type: {{ .Values.master.service.type }} + {{- if or (eq .Values.master.service.type "LoadBalancer") (eq .Values.master.service.type "NodePort") }} + externalTrafficPolicy: {{ .Values.master.service.externalTrafficPolicy | quote }} + {{- end }} + {{- if (semverCompare ">=1.22-0" (include "common.capabilities.kubeVersion" .)) }} + internalTrafficPolicy: {{ .Values.master.service.internalTrafficPolicy }} + {{- end }} + {{- if and (eq .Values.master.service.type "LoadBalancer") (not (empty .Values.master.service.loadBalancerIP)) }} + loadBalancerIP: {{ .Values.master.service.loadBalancerIP }} + {{- end }} + {{- if and (eq .Values.master.service.type "LoadBalancer") (not (empty .Values.master.service.loadBalancerSourceRanges)) }} + loadBalancerSourceRanges: {{ toYaml .Values.master.service.loadBalancerSourceRanges | nindent 4 }} + {{- end }} + {{- if and .Values.master.service.clusterIP (eq .Values.master.service.type "ClusterIP") }} + clusterIP: {{ .Values.master.service.clusterIP }} + {{- end }} + {{- if .Values.master.service.sessionAffinity }} + sessionAffinity: {{ .Values.master.service.sessionAffinity }} + {{- end }} + {{- if .Values.master.service.sessionAffinityConfig }} + sessionAffinityConfig: {{- include "common.tplvalues.render" (dict "value" .Values.master.service.sessionAffinityConfig "context" $) | nindent 4 }} + {{- end }} + {{- if .Values.master.service.externalIPs }} + externalIPs: {{- include "common.tplvalues.render" (dict "value" .Values.master.service.externalIPs "context" $) | nindent 4 }} + {{- end }} + ports: + - name: tcp-redis + port: {{ .Values.master.service.ports.redis }} + targetPort: redis + {{- if and (or (eq .Values.master.service.type "NodePort") (eq .Values.master.service.type "LoadBalancer")) .Values.master.service.nodePorts.redis}} + nodePort: {{ .Values.master.service.nodePorts.redis}} + {{- else if eq .Values.master.service.type "ClusterIP" }} + nodePort: null + {{- end }} + {{- if .Values.master.service.extraPorts }} + {{- include "common.tplvalues.render" (dict "value" .Values.master.service.extraPorts "context" $) | nindent 4 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.master.podLabels .Values.commonLabels ) "context" . ) }} + selector: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: master +{{- end }} diff --git a/packages/system/dashboard/charts/kubeapps/charts/redis/templates/master/serviceaccount.yaml b/packages/system/dashboard/charts/kubeapps/charts/redis/templates/master/serviceaccount.yaml new file mode 100644 index 00000000..bb6c42ae --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/charts/redis/templates/master/serviceaccount.yaml @@ -0,0 +1,18 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.master.serviceAccount.create }} +apiVersion: v1 +kind: ServiceAccount +automountServiceAccountToken: {{ .Values.master.serviceAccount.automountServiceAccountToken }} +metadata: + name: {{ template "redis.masterServiceAccountName" . }} + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if or .Values.master.serviceAccount.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.master.serviceAccount.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +{{- end }} diff --git a/packages/system/dashboard/charts/kubeapps/charts/redis/templates/metrics-svc.yaml b/packages/system/dashboard/charts/kubeapps/charts/redis/templates/metrics-svc.yaml new file mode 100644 index 00000000..7d1d683d --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/charts/redis/templates/metrics-svc.yaml @@ -0,0 +1,41 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.metrics.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ printf "%s-metrics" (include "common.names.fullname" .) }} + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: metrics + {{- if or .Values.metrics.service.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.metrics.service.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + type: {{ .Values.metrics.service.type }} + {{- if and .Values.metrics.service.clusterIP (eq .Values.metrics.service.type "ClusterIP") }} + clusterIP: {{ .Values.metrics.service.clusterIP }} + {{- end }} + {{- if eq .Values.metrics.service.type "LoadBalancer" }} + externalTrafficPolicy: {{ .Values.metrics.service.externalTrafficPolicy }} + {{- end }} + {{- if and (eq .Values.metrics.service.type "LoadBalancer") .Values.metrics.service.loadBalancerIP }} + loadBalancerIP: {{ .Values.metrics.service.loadBalancerIP }} + {{- end }} + {{- if and (eq .Values.metrics.service.type "LoadBalancer") .Values.metrics.service.loadBalancerSourceRanges }} + loadBalancerSourceRanges: {{- toYaml .Values.metrics.service.loadBalancerSourceRanges | nindent 4 }} + {{- end }} + ports: + - name: http-metrics + port: {{ .Values.metrics.service.port }} + protocol: TCP + targetPort: metrics + {{- if .Values.metrics.service.extraPorts }} + {{- include "common.tplvalues.render" (dict "value" .Values.metrics.service.extraPorts "context" $) | nindent 4 }} + {{- end }} + selector: {{- include "common.labels.matchLabels" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} +{{- end }} diff --git a/packages/system/dashboard/charts/kubeapps/charts/redis/templates/networkpolicy.yaml b/packages/system/dashboard/charts/kubeapps/charts/redis/templates/networkpolicy.yaml new file mode 100644 index 00000000..bd8594e3 --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/charts/redis/templates/networkpolicy.yaml @@ -0,0 +1,105 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.networkPolicy.enabled }} +kind: NetworkPolicy +apiVersion: {{ template "networkPolicy.apiVersion" . }} +metadata: + name: {{ template "common.names.fullname" . }} + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + podSelector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 6 }} + policyTypes: + - Ingress + {{- if or (eq .Values.architecture "replication") .Values.networkPolicy.extraEgress }} + - Egress + egress: + {{- if eq .Values.architecture "replication" }} + # Allow dns resolution + - ports: + - port: 53 + protocol: UDP + # Allow outbound connections to other cluster pods + - ports: + - port: {{ .Values.master.containerPorts.redis }} + {{- if .Values.sentinel.enabled }} + - port: {{ .Values.sentinel.containerPorts.sentinel }} + {{- end }} + to: + - podSelector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 14 }} + {{- end }} + {{- if .Values.networkPolicy.extraEgress }} + {{- include "common.tplvalues.render" ( dict "value" .Values.networkPolicy.extraEgress "context" $ ) | nindent 4 }} + {{- end }} + {{- end }} + ingress: + # Allow inbound connections + - ports: + - port: {{ .Values.master.containerPorts.redis }} + {{- if .Values.sentinel.enabled }} + - port: {{ .Values.sentinel.containerPorts.sentinel }} + {{- end }} + {{- if not .Values.networkPolicy.allowExternal }} + from: + - podSelector: + matchLabels: + {{ template "common.names.fullname" . }}-client: "true" + - podSelector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 14 }} + {{- if or .Values.networkPolicy.ingressNSMatchLabels .Values.networkPolicy.ingressNSPodMatchLabels }} + - namespaceSelector: + matchLabels: + {{- if .Values.networkPolicy.ingressNSMatchLabels }} + {{- range $key, $value := .Values.networkPolicy.ingressNSMatchLabels }} + {{ $key | quote }}: {{ $value | quote }} + {{- end }} + {{ else }} + {} + {{- end }} + {{- if .Values.networkPolicy.ingressNSPodMatchLabels }} + podSelector: + matchLabels: + {{- range $key, $value := .Values.networkPolicy.ingressNSPodMatchLabels }} + {{ $key | quote }}: {{ $value | quote }} + {{- end }} + {{- end }} + {{- end }} + {{- end }} + {{- if .Values.metrics.enabled }} + # Allow prometheus scrapes for metrics + - ports: + - port: 9121 + {{- if not .Values.networkPolicy.metrics.allowExternal }} + from: + {{- if or .Values.networkPolicy.metrics.ingressNSMatchLabels .Values.networkPolicy.metrics.ingressNSPodMatchLabels }} + - namespaceSelector: + matchLabels: + {{- if .Values.networkPolicy.metrics.ingressNSMatchLabels }} + {{- range $key, $value := .Values.networkPolicy.metrics.ingressNSMatchLabels }} + {{ $key | quote }}: {{ $value | quote }} + {{- end }} + {{ else }} + {} + {{- end }} + {{- if .Values.networkPolicy.metrics.ingressNSPodMatchLabels }} + podSelector: + matchLabels: + {{- range $key, $value := .Values.networkPolicy.metrics.ingressNSPodMatchLabels }} + {{ $key | quote }}: {{ $value | quote }} + {{- end }} + {{- end }} + {{- end }} + {{- end }} + {{- end }} + {{- if .Values.networkPolicy.extraIngress }} + {{- include "common.tplvalues.render" ( dict "value" .Values.networkPolicy.extraIngress "context" $ ) | nindent 4 }} + {{- end }} +{{- end }} diff --git a/packages/system/dashboard/charts/kubeapps/charts/redis/templates/pdb.yaml b/packages/system/dashboard/charts/kubeapps/charts/redis/templates/pdb.yaml new file mode 100644 index 00000000..3306a8ce --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/charts/redis/templates/pdb.yaml @@ -0,0 +1,25 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.pdb.create }} +apiVersion: {{ include "common.capabilities.policy.apiVersion" . }} +kind: PodDisruptionBudget +metadata: + name: {{ template "common.names.fullname" . }} + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + {{- if .Values.pdb.minAvailable }} + minAvailable: {{ .Values.pdb.minAvailable }} + {{- end }} + {{- if .Values.pdb.maxUnavailable }} + maxUnavailable: {{ .Values.pdb.maxUnavailable }} + {{- end }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 6 }} +{{- end }} diff --git a/packages/system/dashboard/charts/kubeapps/charts/redis/templates/podmonitor.yaml b/packages/system/dashboard/charts/kubeapps/charts/redis/templates/podmonitor.yaml new file mode 100644 index 00000000..a7c8bd94 --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/charts/redis/templates/podmonitor.yaml @@ -0,0 +1,52 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.metrics.enabled .Values.metrics.podMonitor.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: PodMonitor +metadata: + name: {{ template "common.names.fullname" . }} + namespace: {{ default .Release.Namespace .Values.metrics.podMonitor.namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.metrics.podMonitor.additionalLabels }} + {{- include "common.tplvalues.render" (dict "value" .Values.metrics.podMonitor.additionalLabels "context" $) | nindent 4 }} + {{- end }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + podMetricsEndpoints: + - port: http-metrics + {{- if .Values.metrics.podMonitor.interval }} + interval: {{ .Values.metrics.podMonitor.interval }} + {{- end }} + {{- if .Values.metrics.podMonitor.scrapeTimeout }} + scrapeTimeout: {{ .Values.metrics.podMonitor.scrapeTimeout }} + {{- end }} + {{- if .Values.metrics.podMonitor.honorLabels }} + honorLabels: {{ .Values.metrics.podMonitor.honorLabels }} + {{- end }} + {{- if .Values.metrics.podMonitor.relabellings }} + relabelings: {{- toYaml .Values.metrics.podMonitor.relabellings | nindent 6 }} + {{- end }} + {{- if .Values.metrics.podMonitor.metricRelabelings }} + metricRelabelings: {{- toYaml .Values.metrics.podMonitor.metricRelabelings | nindent 6 }} + {{- end }} + {{- if .Values.metrics.serviceMonitor.podTargetLabels }} + podTargetLabels: {{- toYaml .Values.metrics.podMonitor.podTargetLabels | nindent 4 }} + {{- end }} + {{- with .Values.metrics.podMonitor.sampleLimit -}} + sampleLimit: {{ . }} + {{- end }} + {{- with .Values.metrics.podMonitor.targetLimit -}} + targetLimit: {{ . }} + {{- end }} + namespaceSelector: + matchNames: + - {{ .Release.Namespace }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 6 }} + app.kubernetes.io/component: metrics +{{- end }} diff --git a/packages/system/dashboard/charts/kubeapps/charts/redis/templates/prometheusrule.yaml b/packages/system/dashboard/charts/kubeapps/charts/redis/templates/prometheusrule.yaml new file mode 100644 index 00000000..73c89e65 --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/charts/redis/templates/prometheusrule.yaml @@ -0,0 +1,23 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.metrics.enabled .Values.metrics.prometheusRule.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: PrometheusRule +metadata: + name: {{ template "common.names.fullname" . }} + namespace: {{ default .Release.Namespace .Values.metrics.prometheusRule.namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.metrics.prometheusRule.additionalLabels }} + {{- include "common.tplvalues.render" (dict "value" .Values.metrics.prometheusRule.additionalLabels "context" $) | nindent 4 }} + {{- end }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + groups: + - name: {{ include "common.names.fullname" . }} + rules: {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.prometheusRule.rules "context" $ ) | nindent 8 }} +{{- end }} diff --git a/packages/system/dashboard/charts/kubeapps/charts/redis/templates/replicas/application.yaml b/packages/system/dashboard/charts/kubeapps/charts/redis/templates/replicas/application.yaml new file mode 100644 index 00000000..821bf8d1 --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/charts/redis/templates/replicas/application.yaml @@ -0,0 +1,533 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and (eq .Values.architecture "replication") (not .Values.sentinel.enabled) }} +apiVersion: {{ include "common.capabilities.statefulset.apiVersion" . }} +kind: {{ .Values.replica.kind }} +metadata: + name: {{ printf "%s-replicas" (include "common.names.fullname" .) }} + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: replica + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + {{- if and (not (eq .Values.replica.kind "DaemonSet")) (not .Values.replica.autoscaling.enabled) }} + replicas: {{ .Values.replica.replicaCount }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.replica.podLabels .Values.commonLabels ) "context" . ) }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 6 }} + app.kubernetes.io/component: replica + {{- if (eq .Values.replica.kind "StatefulSet") }} + serviceName: {{ printf "%s-headless" (include "common.names.fullname" .) }} + {{- end }} + {{- if .Values.replica.updateStrategy }} + updateStrategy: {{- toYaml .Values.replica.updateStrategy | nindent 4 }} + {{- end }} + {{- if and .Values.replica.minReadySeconds (semverCompare ">= 1.23-0" (include "common.capabilities.kubeVersion" .)) }} + minReadySeconds: {{ .Values.replica.minReadySeconds }} + {{- end }} + {{- if .Values.replica.podManagementPolicy }} + podManagementPolicy: {{ .Values.replica.podManagementPolicy | quote }} + {{- end }} + template: + metadata: + labels: {{- include "common.labels.standard" ( dict "customLabels" $podLabels "context" $ ) | nindent 8 }} + app.kubernetes.io/component: replica + {{- if and .Values.metrics.enabled .Values.metrics.podLabels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.podLabels "context" $ ) | nindent 8 }} + {{- end }} + annotations: + {{- if (include "redis.createConfigmap" .) }} + checksum/configmap: {{ pick ( include (print $.Template.BasePath "/configmap.yaml") . | fromYaml ) "data" | toYaml | sha256sum }} + {{- end }} + checksum/health: {{ pick ( include (print $.Template.BasePath "/health-configmap.yaml") . | fromYaml ) "data" | toYaml | sha256sum }} + checksum/scripts: {{ pick ( include (print $.Template.BasePath "/scripts-configmap.yaml") . | fromYaml ) "data" | toYaml | sha256sum }} + checksum/secret: {{ pick ( include (print $.Template.BasePath "/secret.yaml") . | fromYaml ) "data" | toYaml | sha256sum }} + {{- if .Values.replica.podAnnotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.replica.podAnnotations "context" $ ) | nindent 8 }} + {{- end }} + {{- if and .Values.metrics.enabled .Values.metrics.podAnnotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.podAnnotations "context" $ ) | nindent 8 }} + {{- end }} + spec: + {{- include "redis.imagePullSecrets" . | nindent 6 }} + {{- if .Values.replica.hostAliases }} + hostAliases: {{- include "common.tplvalues.render" (dict "value" .Values.replica.hostAliases "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.replica.podSecurityContext.enabled }} + securityContext: {{- omit .Values.replica.podSecurityContext "enabled" | toYaml | nindent 8 }} + {{- end }} + serviceAccountName: {{ template "redis.replicaServiceAccountName" . }} + automountServiceAccountToken: {{ .Values.replica.serviceAccount.automountServiceAccountToken }} + {{- if .Values.replica.priorityClassName }} + priorityClassName: {{ .Values.replica.priorityClassName | quote }} + {{- end }} + {{- if .Values.replica.affinity }} + affinity: {{- include "common.tplvalues.render" (dict "value" .Values.replica.affinity "context" $) | nindent 8 }} + {{- else }} + affinity: + podAffinity: {{- include "common.affinities.pods" (dict "type" .Values.replica.podAffinityPreset "component" "replica" "customLabels" $podLabels "context" $) | nindent 10 }} + podAntiAffinity: {{- include "common.affinities.pods" (dict "type" .Values.replica.podAntiAffinityPreset "component" "replica" "customLabels" $podLabels "context" $) | nindent 10 }} + nodeAffinity: {{- include "common.affinities.nodes" (dict "type" .Values.replica.nodeAffinityPreset.type "key" .Values.replica.nodeAffinityPreset.key "values" .Values.replica.nodeAffinityPreset.values) | nindent 10 }} + {{- end }} + {{- if .Values.replica.nodeSelector }} + nodeSelector: {{- include "common.tplvalues.render" (dict "value" .Values.replica.nodeSelector "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.replica.tolerations }} + tolerations: {{- include "common.tplvalues.render" (dict "value" .Values.replica.tolerations "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.replica.topologySpreadConstraints }} + topologySpreadConstraints: {{- include "common.tplvalues.render" (dict "value" .Values.replica.topologySpreadConstraints "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.replica.shareProcessNamespace }} + shareProcessNamespace: {{ .Values.replica.shareProcessNamespace }} + {{- end }} + {{- if .Values.replica.schedulerName }} + schedulerName: {{ .Values.replica.schedulerName | quote }} + {{- end }} + {{- if .Values.replica.dnsPolicy }} + dnsPolicy: {{ .Values.replica.dnsPolicy }} + {{- end }} + {{- if .Values.replica.dnsConfig }} + dnsConfig: {{- include "common.tplvalues.render" (dict "value" .Values.replica.dnsConfig "context" $) | nindent 8 }} + {{- end }} + enableServiceLinks: {{ .Values.replica.enableServiceLinks }} + terminationGracePeriodSeconds: {{ .Values.replica.terminationGracePeriodSeconds }} + containers: + - name: redis + image: {{ template "redis.image" . }} + imagePullPolicy: {{ .Values.image.pullPolicy | quote }} + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.replica.lifecycleHooks }} + lifecycle: {{- include "common.tplvalues.render" (dict "value" .Values.replica.lifecycleHooks "context" $) | nindent 12 }} + {{- end }} + {{- end }} + {{- if .Values.replica.containerSecurityContext.enabled }} + securityContext: {{- omit .Values.replica.containerSecurityContext "enabled" | toYaml | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 12 }} + {{- else if .Values.replica.command }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.replica.command "context" $) | nindent 12 }} + {{- else }} + command: + - /bin/bash + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 12 }} + {{- else if .Values.replica.args }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.replica.args "context" $) | nindent 12 }} + {{- else }} + args: + - -c + - /opt/bitnami/scripts/start-scripts/start-replica.sh + {{- end }} + env: + - name: BITNAMI_DEBUG + value: {{ ternary "true" "false" (or .Values.image.debug .Values.diagnosticMode.enabled) | quote }} + - name: REDIS_REPLICATION_MODE + value: replica + - name: REDIS_MASTER_HOST + {{- if .Values.replica.externalMaster.enabled }} + value: {{ .Values.replica.externalMaster.host | quote }} + {{- else if and (eq (int64 .Values.master.count) 1) (eq .Values.master.kind "StatefulSet") }} + value: {{ template "common.names.fullname" . }}-master-0.{{ template "common.names.fullname" . }}-headless.{{ .Release.Namespace }}.svc.{{ .Values.clusterDomain }} + {{- else }} + value: {{ template "common.names.fullname" . }}-master.{{ .Release.Namespace }}.svc.{{ .Values.clusterDomain }} + {{- end }} + - name: REDIS_MASTER_PORT_NUMBER + {{- if .Values.replica.externalMaster.enabled }} + value: {{ .Values.replica.externalMaster.port | quote }} + {{- else }} + value: {{ .Values.master.containerPorts.redis | quote }} + {{- end }} + - name: ALLOW_EMPTY_PASSWORD + value: {{ ternary "no" "yes" .Values.auth.enabled | quote }} + {{- if .Values.auth.enabled }} + {{- if .Values.auth.usePasswordFiles }} + - name: REDIS_PASSWORD_FILE + value: "/opt/bitnami/redis/secrets/redis-password" + - name: REDIS_MASTER_PASSWORD_FILE + value: "/opt/bitnami/redis/secrets/redis-password" + {{- else }} + - name: REDIS_PASSWORD + valueFrom: + secretKeyRef: + name: {{ template "redis.secretName" . }} + key: {{ template "redis.secretPasswordKey" . }} + - name: REDIS_MASTER_PASSWORD + valueFrom: + secretKeyRef: + name: {{ template "redis.secretName" . }} + key: {{ template "redis.secretPasswordKey" . }} + {{- end }} + {{- end }} + - name: REDIS_TLS_ENABLED + value: {{ ternary "yes" "no" .Values.tls.enabled | quote }} + {{- if .Values.tls.enabled }} + - name: REDIS_TLS_PORT + value: {{ .Values.replica.containerPorts.redis | quote }} + - name: REDIS_TLS_AUTH_CLIENTS + value: {{ ternary "yes" "no" .Values.tls.authClients | quote }} + - name: REDIS_TLS_CERT_FILE + value: {{ template "redis.tlsCert" . }} + - name: REDIS_TLS_KEY_FILE + value: {{ template "redis.tlsCertKey" . }} + - name: REDIS_TLS_CA_FILE + value: {{ template "redis.tlsCACert" . }} + {{- if .Values.tls.dhParamsFilename }} + - name: REDIS_TLS_DH_PARAMS_FILE + value: {{ template "redis.tlsDHParams" . }} + {{- end }} + {{- else }} + - name: REDIS_PORT + value: {{ .Values.replica.containerPorts.redis | quote }} + {{- end }} + {{- if .Values.replica.extraEnvVars }} + {{- include "common.tplvalues.render" (dict "value" .Values.replica.extraEnvVars "context" $) | nindent 12 }} + {{- end }} + {{- if or .Values.replica.extraEnvVarsCM .Values.replica.extraEnvVarsSecret }} + envFrom: + {{- if .Values.replica.extraEnvVarsCM }} + - configMapRef: + name: {{ .Values.replica.extraEnvVarsCM }} + {{- end }} + {{- if .Values.replica.extraEnvVarsSecret }} + - secretRef: + name: {{ .Values.replica.extraEnvVarsSecret }} + {{- end }} + {{- end }} + ports: + - name: redis + containerPort: {{ .Values.replica.containerPorts.redis }} + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.replica.customStartupProbe }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" .Values.replica.customStartupProbe "context" $) | nindent 12 }} + {{- else if .Values.replica.startupProbe.enabled }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.replica.startupProbe "enabled") "context" $) | nindent 12 }} + tcpSocket: + port: redis + {{- end }} + {{- if .Values.replica.customLivenessProbe }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.replica.customLivenessProbe "context" $) | nindent 12 }} + {{- else if .Values.replica.livenessProbe.enabled }} + livenessProbe: + initialDelaySeconds: {{ .Values.replica.livenessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.replica.livenessProbe.periodSeconds }} + timeoutSeconds: {{ add1 .Values.replica.livenessProbe.timeoutSeconds }} + successThreshold: {{ .Values.replica.livenessProbe.successThreshold }} + failureThreshold: {{ .Values.replica.livenessProbe.failureThreshold }} + exec: + command: + - sh + - -c + - /health/ping_liveness_local_and_master.sh {{ .Values.replica.livenessProbe.timeoutSeconds }} + {{- end }} + {{- if .Values.replica.customReadinessProbe }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.replica.customReadinessProbe "context" $) | nindent 12 }} + {{- else if .Values.replica.readinessProbe.enabled }} + readinessProbe: + initialDelaySeconds: {{ .Values.replica.readinessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.replica.readinessProbe.periodSeconds }} + timeoutSeconds: {{ add1 .Values.replica.readinessProbe.timeoutSeconds }} + successThreshold: {{ .Values.replica.readinessProbe.successThreshold }} + failureThreshold: {{ .Values.replica.readinessProbe.failureThreshold }} + exec: + command: + - sh + - -c + - /health/ping_readiness_local_and_master.sh {{ .Values.replica.readinessProbe.timeoutSeconds }} + {{- end }} + {{- end }} + {{- if .Values.replica.resources }} + resources: {{- toYaml .Values.replica.resources | nindent 12 }} + {{- end }} + volumeMounts: + - name: start-scripts + mountPath: /opt/bitnami/scripts/start-scripts + - name: health + mountPath: /health + {{- if .Values.auth.usePasswordFiles }} + - name: redis-password + mountPath: /opt/bitnami/redis/secrets/ + {{- end }} + - name: redis-data + mountPath: /data + {{- if .Values.replica.persistence.subPath }} + subPath: {{ .Values.replica.persistence.subPath }} + {{- else if .Values.replica.persistence.subPathExpr }} + subPathExpr: {{ .Values.replica.persistence.subPathExpr }} + {{- end }} + - name: config + mountPath: /opt/bitnami/redis/mounted-etc + - name: redis-tmp-conf + mountPath: /opt/bitnami/redis/etc + {{- if .Values.tls.enabled }} + - name: redis-certificates + mountPath: /opt/bitnami/redis/certs + readOnly: true + {{- end }} + {{- if .Values.replica.extraVolumeMounts }} + {{- include "common.tplvalues.render" ( dict "value" .Values.replica.extraVolumeMounts "context" $ ) | nindent 12 }} + {{- end }} + {{- if .Values.metrics.enabled }} + - name: metrics + image: {{ include "redis.metrics.image" . }} + imagePullPolicy: {{ .Values.metrics.image.pullPolicy | quote }} + {{- if .Values.metrics.containerSecurityContext.enabled }} + securityContext: {{- omit .Values.metrics.containerSecurityContext "enabled" | toYaml | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 12 }} + {{- else if .Values.metrics.command }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.command "context" $) | nindent 12 }} + {{- else }} + command: + - /bin/bash + - -c + - | + if [[ -f '/secrets/redis-password' ]]; then + export REDIS_PASSWORD=$(cat /secrets/redis-password) + fi + redis_exporter{{- range $key, $value := .Values.metrics.extraArgs }} --{{ $key }}={{ $value }}{{- end }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 12 }} + {{- end }} + env: + - name: REDIS_ALIAS + value: {{ template "common.names.fullname" . }} + {{- if .Values.auth.enabled }} + - name: REDIS_USER + value: default + {{- if (not .Values.auth.usePasswordFiles) }} + - name: REDIS_PASSWORD + valueFrom: + secretKeyRef: + name: {{ template "redis.secretName" . }} + key: {{ template "redis.secretPasswordKey" . }} + {{- end }} + {{- end }} + {{- if .Values.tls.enabled }} + - name: REDIS_ADDR + value: rediss://{{ .Values.metrics.redisTargetHost }}:{{ .Values.replica.containerPorts.redis }} + {{- if .Values.tls.authClients }} + - name: REDIS_EXPORTER_TLS_CLIENT_KEY_FILE + value: {{ template "redis.tlsCertKey" . }} + - name: REDIS_EXPORTER_TLS_CLIENT_CERT_FILE + value: {{ template "redis.tlsCert" . }} + {{- end }} + - name: REDIS_EXPORTER_TLS_CA_CERT_FILE + value: {{ template "redis.tlsCACert" . }} + {{- end }} + {{- if .Values.metrics.extraEnvVars }} + {{- include "common.tplvalues.render" (dict "value" .Values.metrics.extraEnvVars "context" $) | nindent 12 }} + {{- end }} + ports: + - name: metrics + containerPort: 9121 + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.metrics.customStartupProbe }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.customStartupProbe "context" $) | nindent 12 }} + {{- else if .Values.metrics.startupProbe.enabled }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.metrics.startupProbe "enabled") "context" $) | nindent 12 }} + tcpSocket: + port: metrics + {{- end }} + {{- if .Values.metrics.customLivenessProbe }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.customLivenessProbe "context" $) | nindent 12 }} + {{- else if .Values.metrics.livenessProbe.enabled }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.metrics.livenessProbe "enabled") "context" $) | nindent 12 }} + tcpSocket: + port: metrics + {{- end }} + {{- if .Values.metrics.customReadinessProbe }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.customReadinessProbe "context" $) | nindent 12 }} + {{- else if .Values.metrics.readinessProbe.enabled }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.metrics.readinessProbe "enabled") "context" $) | nindent 12 }} + httpGet: + path: / + port: metrics + {{- end }} + {{- end }} + {{- if .Values.metrics.resources }} + resources: {{- toYaml .Values.metrics.resources | nindent 12 }} + {{- end }} + volumeMounts: + {{- if .Values.auth.usePasswordFiles }} + - name: redis-password + mountPath: /secrets/ + {{- end }} + {{- if .Values.tls.enabled }} + - name: redis-certificates + mountPath: /opt/bitnami/redis/certs + readOnly: true + {{- end }} + {{- if .Values.metrics.extraVolumeMounts }} + {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.extraVolumeMounts "context" $ ) | nindent 12 }} + {{- end }} + {{- end }} + {{- if .Values.replica.sidecars }} + {{- include "common.tplvalues.render" (dict "value" .Values.replica.sidecars "context" $) | nindent 8 }} + {{- end }} + {{- $needsVolumePermissions := and .Values.volumePermissions.enabled .Values.replica.persistence.enabled .Values.replica.podSecurityContext.enabled .Values.replica.containerSecurityContext.enabled }} + {{- if or .Values.replica.initContainers $needsVolumePermissions .Values.sysctl.enabled }} + initContainers: + {{- if .Values.replica.initContainers }} + {{- include "common.tplvalues.render" (dict "value" .Values.replica.initContainers "context" $) | nindent 8 }} + {{- end }} + {{- if $needsVolumePermissions }} + - name: volume-permissions + image: {{ include "redis.volumePermissions.image" . }} + imagePullPolicy: {{ .Values.volumePermissions.image.pullPolicy | quote }} + command: + - /bin/bash + - -ec + - | + {{- if eq ( toString ( .Values.volumePermissions.containerSecurityContext.runAsUser )) "auto" }} + chown -R `id -u`:`id -G | cut -d " " -f2` {{ .Values.replica.persistence.path }} + {{- else }} + chown -R {{ .Values.replica.containerSecurityContext.runAsUser }}:{{ .Values.replica.podSecurityContext.fsGroup }} {{ .Values.replica.persistence.path }} + {{- end }} + {{- if eq ( toString ( .Values.volumePermissions.containerSecurityContext.runAsUser )) "auto" }} + securityContext: {{- omit .Values.volumePermissions.containerSecurityContext "runAsUser" | toYaml | nindent 12 }} + {{- else }} + securityContext: {{- .Values.volumePermissions.containerSecurityContext | toYaml | nindent 12 }} + {{- end }} + {{- if .Values.volumePermissions.resources }} + resources: {{- toYaml .Values.volumePermissions.resources | nindent 12 }} + {{- end }} + volumeMounts: + - name: redis-data + mountPath: {{ .Values.replica.persistence.path }} + {{- if .Values.replica.persistence.subPath }} + subPath: {{ .Values.replica.persistence.subPath }} + {{- else if .Values.replica.persistence.subPathExpr }} + subPathExpr: {{ .Values.replica.persistence.subPathExpr }} + {{- end }} + {{- end }} + {{- if .Values.sysctl.enabled }} + - name: init-sysctl + image: {{ include "redis.sysctl.image" . }} + imagePullPolicy: {{ default "" .Values.sysctl.image.pullPolicy | quote }} + securityContext: + privileged: true + runAsUser: 0 + {{- if .Values.sysctl.command }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.sysctl.command "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.sysctl.resources }} + resources: {{- toYaml .Values.sysctl.resources | nindent 12 }} + {{- end }} + {{- if .Values.sysctl.mountHostSys }} + volumeMounts: + - name: host-sys + mountPath: /host-sys + {{- end }} + {{- end }} + {{- end }} + volumes: + - name: start-scripts + configMap: + name: {{ printf "%s-scripts" (include "common.names.fullname" .) }} + defaultMode: 0755 + - name: health + configMap: + name: {{ printf "%s-health" (include "common.names.fullname" .) }} + defaultMode: 0755 + {{- if .Values.auth.usePasswordFiles }} + - name: redis-password + secret: + secretName: {{ template "redis.secretName" . }} + items: + - key: {{ template "redis.secretPasswordKey" . }} + path: redis-password + {{- end }} + - name: config + configMap: + name: {{ include "redis.configmapName" . }} + {{- if .Values.sysctl.mountHostSys }} + - name: host-sys + hostPath: + path: /sys + {{- end }} + - name: redis-tmp-conf + {{- if or .Values.replica.persistence.medium .Values.replica.persistence.sizeLimit }} + emptyDir: + {{- if .Values.replica.persistence.medium }} + medium: {{ .Values.replica.persistence.medium | quote }} + {{- end }} + {{- if .Values.replica.persistence.sizeLimit }} + sizeLimit: {{ .Values.replica.persistence.sizeLimit | quote }} + {{- end }} + {{- else }} + emptyDir: {} + {{- end }} + {{- if .Values.tls.enabled }} + - name: redis-certificates + secret: + secretName: {{ include "redis.tlsSecretName" . }} + defaultMode: 256 + {{- end }} + {{- if .Values.replica.extraVolumes }} + {{- include "common.tplvalues.render" ( dict "value" .Values.replica.extraVolumes "context" $ ) | nindent 8 }} + {{- end }} + {{- if .Values.metrics.extraVolumes }} + {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.extraVolumes "context" $ ) | nindent 8 }} + {{- end }} + {{- if or (not .Values.replica.persistence.enabled) (not (eq .Values.replica.kind "StatefulSet")) }} + - name: redis-data + {{- if or .Values.replica.persistence.medium .Values.replica.persistence.sizeLimit }} + emptyDir: + {{- if .Values.replica.persistence.medium }} + medium: {{ .Values.replica.persistence.medium | quote }} + {{- end }} + {{- if .Values.replica.persistence.sizeLimit }} + sizeLimit: {{ .Values.replica.persistence.sizeLimit | quote }} + {{- end }} + {{- else }} + emptyDir: {} + {{- end }} + {{- else if .Values.replica.persistence.existingClaim }} + - name: redis-data + persistentVolumeClaim: + claimName: {{ printf "%s" (tpl .Values.replica.persistence.existingClaim .) }} + {{- else }} + {{- if .Values.replica.persistentVolumeClaimRetentionPolicy.enabled }} + persistentVolumeClaimRetentionPolicy: + whenDeleted: {{ .Values.replica.persistentVolumeClaimRetentionPolicy.whenDeleted }} + whenScaled: {{ .Values.replica.persistentVolumeClaimRetentionPolicy.whenScaled }} + {{- end }} + volumeClaimTemplates: + - apiVersion: v1 + kind: PersistentVolumeClaim + metadata: + name: redis-data + {{- $claimLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.master.persistence.labels .Values.commonLabels ) "context" . ) }} + labels: {{- include "common.labels.matchLabels" ( dict "customLabels" $claimLabels "context" $ ) | nindent 10 }} + app.kubernetes.io/component: replica + {{- if .Values.replica.persistence.annotations }} + annotations: {{- toYaml .Values.replica.persistence.annotations | nindent 10 }} + {{- end }} + spec: + accessModes: + {{- range .Values.replica.persistence.accessModes }} + - {{ . | quote }} + {{- end }} + resources: + requests: + storage: {{ .Values.replica.persistence.size | quote }} + {{- if .Values.replica.persistence.selector }} + selector: {{- include "common.tplvalues.render" (dict "value" .Values.replica.persistence.selector "context" $) | nindent 10 }} + {{- end }} + {{- if .Values.replica.persistence.dataSource }} + dataSource: {{- include "common.tplvalues.render" (dict "value" .Values.replica.persistence.dataSource "context" $) | nindent 10 }} + {{- end }} + {{- include "common.storage.class" (dict "persistence" .Values.replica.persistence "global" .Values.global) | nindent 8 }} + {{- end }} +{{- end }} diff --git a/packages/system/dashboard/charts/kubeapps/charts/redis/templates/replicas/hpa.yaml b/packages/system/dashboard/charts/kubeapps/charts/redis/templates/replicas/hpa.yaml new file mode 100644 index 00000000..37ecc831 --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/charts/redis/templates/replicas/hpa.yaml @@ -0,0 +1,49 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.replica.autoscaling.enabled (not .Values.sentinel.enabled) }} +apiVersion: {{ include "common.capabilities.hpa.apiVersion" ( dict "context" $ ) }} +kind: HorizontalPodAutoscaler +metadata: + name: {{ printf "%s-replicas" (include "common.names.fullname" .) }} + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: replica + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + scaleTargetRef: + apiVersion: {{ include "common.capabilities.deployment.apiVersion" . }} + kind: StatefulSet + name: {{ printf "%s-replicas" (include "common.names.fullname" .) }} + minReplicas: {{ .Values.replica.autoscaling.minReplicas }} + maxReplicas: {{ .Values.replica.autoscaling.maxReplicas }} + metrics: + {{- if .Values.replica.autoscaling.targetCPU }} + - type: Resource + resource: + name: cpu + {{- if semverCompare "<1.23-0" (include "common.capabilities.kubeVersion" .) }} + targetAverageUtilization: {{ .Values.replica.autoscaling.targetCPU }} + {{- else }} + target: + type: Utilization + averageUtilization: {{ .Values.replica.autoscaling.targetCPU }} + {{- end }} + {{- end }} + {{- if .Values.replica.autoscaling.targetMemory }} + - type: Resource + resource: + name: memory + {{- if semverCompare "<1.23-0" (include "common.capabilities.kubeVersion" .) }} + targetAverageUtilization: {{ .Values.replica.autoscaling.targetMemory }} + {{- else }} + target: + type: Utilization + averageUtilization: {{ .Values.replica.autoscaling.targetMemory }} + {{- end }} + {{- end }} +{{- end }} diff --git a/packages/system/dashboard/charts/kubeapps/charts/redis/templates/replicas/service.yaml b/packages/system/dashboard/charts/kubeapps/charts/redis/templates/replicas/service.yaml new file mode 100644 index 00000000..415771b6 --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/charts/redis/templates/replicas/service.yaml @@ -0,0 +1,56 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and (eq .Values.architecture "replication") (not .Values.sentinel.enabled) }} +apiVersion: v1 +kind: Service +metadata: + name: {{ printf "%s-replicas" (include "common.names.fullname" .) }} + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: replica + {{- if or .Values.replica.service.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.replica.service.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + type: {{ .Values.replica.service.type }} + {{- if or (eq .Values.replica.service.type "LoadBalancer") (eq .Values.replica.service.type "NodePort") }} + externalTrafficPolicy: {{ .Values.replica.service.externalTrafficPolicy | quote }} + {{- end }} + {{- if (semverCompare ">=1.22-0" (include "common.capabilities.kubeVersion" .)) }} + internalTrafficPolicy: {{ .Values.replica.service.internalTrafficPolicy }} + {{- end }} + {{- if and (eq .Values.replica.service.type "LoadBalancer") (not (empty .Values.replica.service.loadBalancerIP)) }} + loadBalancerIP: {{ .Values.replica.service.loadBalancerIP }} + {{- end }} + {{- if and (eq .Values.replica.service.type "LoadBalancer") (not (empty .Values.replica.service.loadBalancerSourceRanges)) }} + loadBalancerSourceRanges: {{ toYaml .Values.replica.service.loadBalancerSourceRanges | nindent 4 }} + {{- end }} + {{- if and .Values.replica.service.clusterIP (eq .Values.replica.service.type "ClusterIP") }} + clusterIP: {{ .Values.replica.service.clusterIP }} + {{- end }} + {{- if .Values.replica.service.sessionAffinity }} + sessionAffinity: {{ .Values.replica.service.sessionAffinity }} + {{- end }} + {{- if .Values.replica.service.sessionAffinityConfig }} + sessionAffinityConfig: {{- include "common.tplvalues.render" (dict "value" .Values.replica.service.sessionAffinityConfig "context" $) | nindent 4 }} + {{- end }} + ports: + - name: tcp-redis + port: {{ .Values.replica.service.ports.redis }} + targetPort: redis + {{- if and (or (eq .Values.replica.service.type "NodePort") (eq .Values.replica.service.type "LoadBalancer")) .Values.replica.service.nodePorts.redis}} + nodePort: {{ .Values.replica.service.nodePorts.redis}} + {{- else if eq .Values.replica.service.type "ClusterIP" }} + nodePort: null + {{- end }} + {{- if .Values.replica.service.extraPorts }} + {{- include "common.tplvalues.render" (dict "value" .Values.replica.service.extraPorts "context" $) | nindent 4 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.replica.podLabels .Values.commonLabels ) "context" . ) }} + selector: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: replica +{{- end }} diff --git a/packages/system/dashboard/charts/kubeapps/charts/redis/templates/replicas/serviceaccount.yaml b/packages/system/dashboard/charts/kubeapps/charts/redis/templates/replicas/serviceaccount.yaml new file mode 100644 index 00000000..616e8bc8 --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/charts/redis/templates/replicas/serviceaccount.yaml @@ -0,0 +1,18 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.replica.serviceAccount.create }} +apiVersion: v1 +kind: ServiceAccount +automountServiceAccountToken: {{ .Values.replica.serviceAccount.automountServiceAccountToken }} +metadata: + name: {{ template "redis.replicaServiceAccountName" . }} + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if or .Values.replica.serviceAccount.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.replica.serviceAccount.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +{{- end }} diff --git a/packages/system/dashboard/charts/kubeapps/charts/redis/templates/role.yaml b/packages/system/dashboard/charts/kubeapps/charts/redis/templates/role.yaml new file mode 100644 index 00000000..be042294 --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/charts/redis/templates/role.yaml @@ -0,0 +1,29 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.rbac.create }} +apiVersion: {{ include "common.capabilities.rbac.apiVersion" . }} +kind: Role +metadata: + name: {{ template "common.names.fullname" . }} + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +rules: + {{- if and (include "common.capabilities.psp.supported" .) .Values.podSecurityPolicy.enabled }} + - apiGroups: + - '{{ template "podSecurityPolicy.apiGroup" . }}' + resources: + - 'podsecuritypolicies' + verbs: + - 'use' + resourceNames: [{{ printf "%s-master" (include "common.names.fullname" .) }}] + {{- end }} + {{- if .Values.rbac.rules }} + {{- include "common.tplvalues.render" ( dict "value" .Values.rbac.rules "context" $ ) | nindent 2 }} + {{- end }} +{{- end }} diff --git a/packages/system/dashboard/charts/kubeapps/charts/redis/templates/rolebinding.yaml b/packages/system/dashboard/charts/kubeapps/charts/redis/templates/rolebinding.yaml new file mode 100644 index 00000000..7a1043e1 --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/charts/redis/templates/rolebinding.yaml @@ -0,0 +1,23 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.rbac.create }} +apiVersion: {{ include "common.capabilities.rbac.apiVersion" . }} +kind: RoleBinding +metadata: + name: {{ template "common.names.fullname" . }} + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ template "common.names.fullname" . }} +subjects: + - kind: ServiceAccount + name: {{ template "redis.serviceAccountName" . }} +{{- end }} diff --git a/packages/system/dashboard/charts/kubeapps/charts/redis/templates/scripts-configmap.yaml b/packages/system/dashboard/charts/kubeapps/charts/redis/templates/scripts-configmap.yaml new file mode 100644 index 00000000..9e81f8a2 --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/charts/redis/templates/scripts-configmap.yaml @@ -0,0 +1,757 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ printf "%s-scripts" (include "common.names.fullname" .) }} + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +data: +{{- if and (eq .Values.architecture "replication") .Values.sentinel.enabled }} + start-node.sh: | + #!/bin/bash + + . /opt/bitnami/scripts/libos.sh + . /opt/bitnami/scripts/liblog.sh + . /opt/bitnami/scripts/libvalidations.sh + + get_port() { + hostname="$1" + type="$2" + + port_var=$(echo "${hostname^^}_SERVICE_PORT_$type" | sed "s/-/_/g") + port=${!port_var} + + if [ -z "$port" ]; then + case $type in + "SENTINEL") + echo {{ .Values.sentinel.containerPorts.sentinel }} + ;; + "REDIS") + echo {{ .Values.master.containerPorts.redis }} + ;; + esac + else + echo $port + fi + } + + get_full_hostname() { + hostname="$1" + + {{- if .Values.useExternalDNS.enabled }} + full_hostname="${hostname}.{{- include "redis.externalDNS.suffix" . }}" + {{- else if eq .Values.sentinel.service.type "NodePort" }} + full_hostname="${hostname}.{{- .Release.Namespace }}" + {{- else }} + full_hostname="${hostname}.${HEADLESS_SERVICE}" + {{- end }} + + {{- if .Values.useHostnames }} + echo "${full_hostname}" + {{- else }} + retry_count=0 + until getent hosts "${full_hostname}" | awk '{ print $1; exit }' | grep .; do + if [[ $retry_count -lt {{ .Values.nameResolutionThreshold }} ]]; then + sleep {{ .Values.nameResolutionTimeout }} + else + error "IP address for ${full_hostname} not found" + exit 1 + fi + ((retry_count++)) + done + {{- end }} + } + + REDISPORT=$(get_port "$HOSTNAME" "REDIS") + + HEADLESS_SERVICE="{{ template "common.names.fullname" . }}-headless.{{ .Release.Namespace }}.svc.{{ .Values.clusterDomain }}" + + if [ -n "$REDIS_EXTERNAL_MASTER_HOST" ]; then + REDIS_SERVICE="$REDIS_EXTERNAL_MASTER_HOST" + else + REDIS_SERVICE="{{ template "common.names.fullname" . }}.{{ .Release.Namespace }}.svc.{{ .Values.clusterDomain }}" + fi + + SENTINEL_SERVICE_PORT=$(get_port "{{ include "common.names.fullname" . }}" "SENTINEL") + validate_quorum() { + if is_boolean_yes "$REDIS_TLS_ENABLED"; then + quorum_info_command="{{- if and .Values.auth.enabled .Values.auth.sentinel }}REDISCLI_AUTH="\$REDIS_PASSWORD" {{ end }}redis-cli -h $REDIS_SERVICE -p $SENTINEL_SERVICE_PORT --tls --cert ${REDIS_TLS_CERT_FILE} --key ${REDIS_TLS_KEY_FILE} --cacert ${REDIS_TLS_CA_FILE} sentinel master {{ .Values.sentinel.masterSet }}" + else + quorum_info_command="{{- if and .Values.auth.enabled .Values.auth.sentinel }}REDISCLI_AUTH="\$REDIS_PASSWORD" {{ end }}redis-cli -h $REDIS_SERVICE -p $SENTINEL_SERVICE_PORT sentinel master {{ .Values.sentinel.masterSet }}" + fi + info "about to run the command: $quorum_info_command" + eval $quorum_info_command | grep -Fq "s_down" + } + + trigger_manual_failover() { + if is_boolean_yes "$REDIS_TLS_ENABLED"; then + failover_command="{{- if and .Values.auth.enabled .Values.auth.sentinel }}REDISCLI_AUTH="\$REDIS_PASSWORD" {{ end }}redis-cli -h $REDIS_SERVICE -p $SENTINEL_SERVICE_PORT --tls --cert ${REDIS_TLS_CERT_FILE} --key ${REDIS_TLS_KEY_FILE} --cacert ${REDIS_TLS_CA_FILE} sentinel failover {{ .Values.sentinel.masterSet }}" + else + failover_command="{{- if and .Values.auth.enabled .Values.auth.sentinel }}REDISCLI_AUTH="\$REDIS_PASSWORD" {{ end }}redis-cli -h $REDIS_SERVICE -p $SENTINEL_SERVICE_PORT sentinel failover {{ .Values.sentinel.masterSet }}" + fi + + info "about to run the command: $failover_command" + eval $failover_command + } + + get_sentinel_master_info() { + if is_boolean_yes "$REDIS_TLS_ENABLED"; then + sentinel_info_command="{{- if and .Values.auth.enabled .Values.auth.sentinel }}REDISCLI_AUTH="\$REDIS_PASSWORD" {{ end }}timeout {{ .Values.sentinel.getMasterTimeout }} redis-cli -h $REDIS_SERVICE -p $SENTINEL_SERVICE_PORT --tls --cert ${REDIS_TLS_CERT_FILE} --key ${REDIS_TLS_KEY_FILE} --cacert ${REDIS_TLS_CA_FILE} sentinel get-master-addr-by-name {{ .Values.sentinel.masterSet }}" + else + sentinel_info_command="{{- if and .Values.auth.enabled .Values.auth.sentinel }}REDISCLI_AUTH="\$REDIS_PASSWORD" {{ end }}timeout {{ .Values.sentinel.getMasterTimeout }} redis-cli -h $REDIS_SERVICE -p $SENTINEL_SERVICE_PORT sentinel get-master-addr-by-name {{ .Values.sentinel.masterSet }}" + fi + + info "about to run the command: $sentinel_info_command" + retry_while "eval $sentinel_info_command" 2 5 + } + + {{- if and .Values.replica.containerSecurityContext.runAsUser (eq (.Values.replica.containerSecurityContext.runAsUser | int) 0) }} + useradd redis + chown -R redis {{ .Values.replica.persistence.path }} + {{- end }} + + [[ -f $REDIS_PASSWORD_FILE ]] && export REDIS_PASSWORD="$(< "${REDIS_PASSWORD_FILE}")" + [[ -f $REDIS_MASTER_PASSWORD_FILE ]] && export REDIS_MASTER_PASSWORD="$(< "${REDIS_MASTER_PASSWORD_FILE}")" + + # check if there is a master + master_in_persisted_conf="$(get_full_hostname "$HOSTNAME")" + master_port_in_persisted_conf="$REDIS_MASTER_PORT_NUMBER" + master_in_sentinel="$(get_sentinel_master_info)" + redisRetVal=$? + + {{- if .Values.sentinel.persistence.enabled }} + if [[ -f /opt/bitnami/redis-sentinel/etc/sentinel.conf ]]; then + master_in_persisted_conf="$(awk '/monitor/ {print $4}' /opt/bitnami/redis-sentinel/etc/sentinel.conf)" + master_port_in_persisted_conf="$(awk '/monitor/ {print $5}' /opt/bitnami/redis-sentinel/etc/sentinel.conf)" + info "Found previous master ${master_in_persisted_conf}:${master_port_in_persisted_conf} in /opt/bitnami/redis-sentinel/etc/sentinel.conf" + debug "$(cat /opt/bitnami/redis-sentinel/etc/sentinel.conf | grep monitor)" + touch /opt/bitnami/redis-sentinel/etc/.node_read + fi + {{- end }} + + if [[ $redisRetVal -ne 0 ]]; then + if [[ "$master_in_persisted_conf" == "$(get_full_hostname "$HOSTNAME")" ]]; then + # Case 1: No active sentinel and in previous sentinel.conf we were the master --> MASTER + info "Configuring the node as master" + export REDIS_REPLICATION_MODE="master" + else + # Case 2: No active sentinel and in previous sentinel.conf we were not master --> REPLICA + info "Configuring the node as replica" + export REDIS_REPLICATION_MODE="replica" + REDIS_MASTER_HOST=${master_in_persisted_conf} + REDIS_MASTER_PORT_NUMBER=${master_port_in_persisted_conf} + fi + else + # Fetches current master's host and port + REDIS_SENTINEL_INFO=($(get_sentinel_master_info)) + info "Current master: REDIS_SENTINEL_INFO=(${REDIS_SENTINEL_INFO[0]},${REDIS_SENTINEL_INFO[1]})" + REDIS_MASTER_HOST=${REDIS_SENTINEL_INFO[0]} + REDIS_MASTER_PORT_NUMBER=${REDIS_SENTINEL_INFO[1]} + + if [[ "$REDIS_MASTER_HOST" == "$(get_full_hostname "$HOSTNAME")" ]]; then + # Case 3: Active sentinel and master it is this node --> MASTER + info "Configuring the node as master" + export REDIS_REPLICATION_MODE="master" + else + # Case 4: Active sentinel and master is not this node --> REPLICA + info "Configuring the node as replica" + export REDIS_REPLICATION_MODE="replica" + + {{- if and .Values.sentinel.automateClusterRecovery (le (int .Values.sentinel.downAfterMilliseconds) 2000) }} + retry_count=1 + while validate_quorum + do + info "sleeping, waiting for Redis master to come up" + sleep 1s + if ! ((retry_count % 11)); then + info "Trying to manually failover" + failover_result=$(trigger_manual_failover) + + debug "Failover result: $failover_result" + fi + + ((retry_count+=1)) + done + info "Redis master is up now" + {{- end }} + fi + fi + + if [[ -n "$REDIS_EXTERNAL_MASTER_HOST" ]]; then + REDIS_MASTER_HOST="$REDIS_EXTERNAL_MASTER_HOST" + REDIS_MASTER_PORT_NUMBER="${REDIS_EXTERNAL_MASTER_PORT}" + fi + + if [[ -f /opt/bitnami/redis/mounted-etc/replica.conf ]];then + cp /opt/bitnami/redis/mounted-etc/replica.conf /opt/bitnami/redis/etc/replica.conf + fi + + if [[ -f /opt/bitnami/redis/mounted-etc/redis.conf ]];then + cp /opt/bitnami/redis/mounted-etc/redis.conf /opt/bitnami/redis/etc/redis.conf + fi + + echo "" >> /opt/bitnami/redis/etc/replica.conf + echo "replica-announce-port $REDISPORT" >> /opt/bitnami/redis/etc/replica.conf + echo "replica-announce-ip $(get_full_hostname "$HOSTNAME")" >> /opt/bitnami/redis/etc/replica.conf + + {{- if .Values.tls.enabled }} + ARGS=("--port" "0") + ARGS+=("--tls-port" "${REDIS_TLS_PORT}") + ARGS+=("--tls-cert-file" "${REDIS_TLS_CERT_FILE}") + ARGS+=("--tls-key-file" "${REDIS_TLS_KEY_FILE}") + ARGS+=("--tls-ca-cert-file" "${REDIS_TLS_CA_FILE}") + ARGS+=("--tls-auth-clients" "${REDIS_TLS_AUTH_CLIENTS}") + ARGS+=("--tls-replication" "yes") + {{- if .Values.tls.dhParamsFilename }} + ARGS+=("--tls-dh-params-file" "${REDIS_TLS_DH_PARAMS_FILE}") + {{- end }} + {{- else }} + ARGS=("--port" "${REDIS_PORT}") + {{- end }} + + if [[ "$REDIS_REPLICATION_MODE" = "slave" ]] || [[ "$REDIS_REPLICATION_MODE" = "replica" ]]; then + ARGS+=("--replicaof" "${REDIS_MASTER_HOST}" "${REDIS_MASTER_PORT_NUMBER}") + fi + + {{- if .Values.auth.enabled }} + ARGS+=("--requirepass" "${REDIS_PASSWORD}") + ARGS+=("--masterauth" "${REDIS_MASTER_PASSWORD}") + {{- else }} + ARGS+=("--protected-mode" "no") + {{- end }} + ARGS+=("--include" "/opt/bitnami/redis/etc/replica.conf") + ARGS+=("--include" "/opt/bitnami/redis/etc/redis.conf") + {{- if .Values.replica.extraFlags }} + {{- range .Values.replica.extraFlags }} + ARGS+=({{ . | quote }}) + {{- end }} + {{- end }} + + {{- if .Values.replica.preExecCmds }} + {{- .Values.replica.preExecCmds | nindent 4 }} + {{- end }} + + {{- if .Values.replica.command }} + exec {{ .Values.replica.command }} "${ARGS[@]}" + {{- else }} + exec redis-server "${ARGS[@]}" + {{- end }} + + start-sentinel.sh: | + #!/bin/bash + + . /opt/bitnami/scripts/libos.sh + . /opt/bitnami/scripts/libvalidations.sh + . /opt/bitnami/scripts/libfile.sh + + HEADLESS_SERVICE="{{ template "common.names.fullname" . }}-headless.{{ .Release.Namespace }}.svc.{{ .Values.clusterDomain }}" + REDIS_SERVICE="{{ template "common.names.fullname" . }}.{{ .Release.Namespace }}.svc.{{ .Values.clusterDomain }}" + + get_port() { + hostname="$1" + type="$2" + + port_var=$(echo "${hostname^^}_SERVICE_PORT_$type" | sed "s/-/_/g") + port=${!port_var} + + if [ -z "$port" ]; then + case $type in + "SENTINEL") + echo {{ .Values.sentinel.containerPorts.sentinel }} + ;; + "REDIS") + echo {{ .Values.master.containerPorts.redis }} + ;; + esac + else + echo $port + fi + } + + get_full_hostname() { + hostname="$1" + + {{- if .Values.useExternalDNS.enabled }} + full_hostname="${hostname}.{{- include "redis.externalDNS.suffix" . }}" + {{- else if eq .Values.sentinel.service.type "NodePort" }} + full_hostname="${hostname}.{{- .Release.Namespace }}" + {{- else }} + full_hostname="${hostname}.${HEADLESS_SERVICE}" + {{- end }} + + {{- if .Values.useHostnames }} + echo "${full_hostname}" + {{- else }} + retry_count=0 + until getent hosts "${full_hostname}" | awk '{ print $1; exit }' | grep .; do + if [[ $retry_count -lt {{ .Values.nameResolutionThreshold }} ]]; then + sleep {{ .Values.nameResolutionTimeout }} + else + error "IP address for ${full_hostname} not found" + exit 1 + fi + ((retry_count++)) + done + {{- end }} + } + + SERVPORT=$(get_port "$HOSTNAME" "SENTINEL") + REDISPORT=$(get_port "$HOSTNAME" "REDIS") + SENTINEL_SERVICE_PORT=$(get_port "{{ include "common.names.fullname" . }}" "SENTINEL") + + sentinel_conf_set() { + local -r key="${1:?missing key}" + local value="${2:-}" + + # Sanitize inputs + value="${value//\\/\\\\}" + value="${value//&/\\&}" + value="${value//\?/\\?}" + [[ "$value" = "" ]] && value="\"$value\"" + + replace_in_file "/opt/bitnami/redis-sentinel/etc/sentinel.conf" "^#*\s*${key} .*" "${key} ${value}" false + } + sentinel_conf_add() { + echo $'\n'"$@" >> "/opt/bitnami/redis-sentinel/etc/sentinel.conf" + } + host_id() { + echo "$1" | openssl sha1 | awk '{print $2}' + } + get_sentinel_master_info() { + if is_boolean_yes "$REDIS_SENTINEL_TLS_ENABLED"; then + sentinel_info_command="{{- if and .Values.auth.enabled .Values.auth.sentinel }}REDISCLI_AUTH="\$REDIS_PASSWORD" {{ end }}timeout {{ .Values.sentinel.getMasterTimeout }} redis-cli -h $REDIS_SERVICE -p $SENTINEL_SERVICE_PORT --tls --cert ${REDIS_SENTINEL_TLS_CERT_FILE} --key ${REDIS_SENTINEL_TLS_KEY_FILE} --cacert ${REDIS_SENTINEL_TLS_CA_FILE} sentinel get-master-addr-by-name {{ .Values.sentinel.masterSet }}" + else + sentinel_info_command="{{- if and .Values.auth.enabled .Values.auth.sentinel }}REDISCLI_AUTH="\$REDIS_PASSWORD" {{ end }}timeout {{ .Values.sentinel.getMasterTimeout }} redis-cli -h $REDIS_SERVICE -p $SENTINEL_SERVICE_PORT sentinel get-master-addr-by-name {{ .Values.sentinel.masterSet }}" + fi + info "about to run the command: $sentinel_info_command" + retry_while "eval $sentinel_info_command" 2 5 + } + + [[ -f $REDIS_PASSWORD_FILE ]] && export REDIS_PASSWORD="$(< "${REDIS_PASSWORD_FILE}")" + + master_in_persisted_conf="$(get_full_hostname "$HOSTNAME")" + + {{- if .Values.sentinel.persistence.enabled }} + if [[ -f /opt/bitnami/redis-sentinel/etc/sentinel.conf ]]; then + check_lock_file() { + [[ -f /opt/bitnami/redis-sentinel/etc/.node_read ]] + } + retry_while "check_lock_file" + rm -f /opt/bitnami/redis-sentinel/etc/.node_read + master_in_persisted_conf="$(awk '/monitor/ {print $4}' /opt/bitnami/redis-sentinel/etc/sentinel.conf)" + info "Found previous master $master_in_persisted_conf in /opt/bitnami/redis-sentinel/etc/sentinel.conf" + debug "$(cat /opt/bitnami/redis-sentinel/etc/sentinel.conf | grep monitor)" + fi + {{- end }} + if ! get_sentinel_master_info && [[ "$master_in_persisted_conf" == "$(get_full_hostname "$HOSTNAME")" ]]; then + # No master found, lets create a master node + export REDIS_REPLICATION_MODE="master" + + REDIS_MASTER_HOST=$(get_full_hostname "$HOSTNAME") + REDIS_MASTER_PORT_NUMBER="$REDISPORT" + else + export REDIS_REPLICATION_MODE="replica" + + # Fetches current master's host and port + REDIS_SENTINEL_INFO=($(get_sentinel_master_info)) + info "printing REDIS_SENTINEL_INFO=(${REDIS_SENTINEL_INFO[0]},${REDIS_SENTINEL_INFO[1]})" + REDIS_MASTER_HOST=${REDIS_SENTINEL_INFO[0]} + REDIS_MASTER_PORT_NUMBER=${REDIS_SENTINEL_INFO[1]} + fi + + if [[ -n "$REDIS_EXTERNAL_MASTER_HOST" ]]; then + REDIS_MASTER_HOST="$REDIS_EXTERNAL_MASTER_HOST" + REDIS_MASTER_PORT_NUMBER="${REDIS_EXTERNAL_MASTER_PORT}" + fi + + cp /opt/bitnami/redis-sentinel/mounted-etc/sentinel.conf /opt/bitnami/redis-sentinel/etc/sentinel.conf + {{- if .Values.auth.enabled }} + printf "\nsentinel auth-pass %s %s" "{{ .Values.sentinel.masterSet }}" "$REDIS_PASSWORD" >> /opt/bitnami/redis-sentinel/etc/sentinel.conf + {{- if and .Values.auth.enabled .Values.auth.sentinel }} + printf "\nrequirepass %s" "$REDIS_PASSWORD" >> /opt/bitnami/redis-sentinel/etc/sentinel.conf + {{- end }} + {{- end }} + printf "\nsentinel myid %s" "$(host_id "$HOSTNAME")" >> /opt/bitnami/redis-sentinel/etc/sentinel.conf + + if [[ -z "$REDIS_MASTER_HOST" ]] || [[ -z "$REDIS_MASTER_PORT_NUMBER" ]] + then + # Prevent incorrect configuration to be written to sentinel.conf + error "Redis master host is configured incorrectly (host: $REDIS_MASTER_HOST, port: $REDIS_MASTER_PORT_NUMBER)" + exit 1 + fi + + sentinel_conf_set "sentinel monitor" "{{ .Values.sentinel.masterSet }} "$REDIS_MASTER_HOST" "$REDIS_MASTER_PORT_NUMBER" {{ .Values.sentinel.quorum }}" + + add_known_sentinel() { + hostname="$1" + ip="$2" + + if [[ -n "$hostname" && -n "$ip" && "$hostname" != "$HOSTNAME" ]]; then + sentinel_conf_add "sentinel known-sentinel {{ .Values.sentinel.masterSet }} $(get_full_hostname "$hostname") $(get_port "$hostname" "SENTINEL") $(host_id "$hostname")" + fi + } + add_known_replica() { + hostname="$1" + ip="$2" + + if [[ -n "$ip" && "$(get_full_hostname "$hostname")" != "$REDIS_MASTER_HOST" ]]; then + sentinel_conf_add "sentinel known-replica {{ .Values.sentinel.masterSet }} $(get_full_hostname "$hostname") $(get_port "$hostname" "REDIS")" + fi + } + + # Add available hosts on the network as known replicas & sentinels + for node in $(seq 0 $(({{ .Values.replica.replicaCount }}-1))); do + hostname="{{ template "common.names.fullname" . }}-node-$node" + ip="$(getent hosts "$hostname.$HEADLESS_SERVICE" | awk '{ print $1 }')" + add_known_sentinel "$hostname" "$ip" + add_known_replica "$hostname" "$ip" + done + + echo "" >> /opt/bitnami/redis-sentinel/etc/sentinel.conf + {{- if not (contains "sentinel announce-hostnames" .Values.sentinel.configuration) }} + echo "sentinel announce-hostnames yes" >> /opt/bitnami/redis-sentinel/etc/sentinel.conf + {{- end }} + {{- if not (contains "sentinel resolve-hostnames" .Values.sentinel.configuration) }} + echo "sentinel resolve-hostnames yes" >> /opt/bitnami/redis-sentinel/etc/sentinel.conf + {{- end }} + {{- if not (contains "sentinel announce-port" .Values.sentinel.configuration) }} + echo "sentinel announce-port $SERVPORT" >> /opt/bitnami/redis-sentinel/etc/sentinel.conf + {{- end }} + {{- if not (contains "sentinel announce-ip" .Values.sentinel.configuration) }} + echo "sentinel announce-ip $(get_full_hostname "$HOSTNAME")" >> /opt/bitnami/redis-sentinel/etc/sentinel.conf + {{- end }} + + {{- if .Values.tls.enabled }} + ARGS=("--port" "0") + ARGS+=("--tls-port" "${REDIS_SENTINEL_TLS_PORT_NUMBER}") + ARGS+=("--tls-cert-file" "${REDIS_SENTINEL_TLS_CERT_FILE}") + ARGS+=("--tls-key-file" "${REDIS_SENTINEL_TLS_KEY_FILE}") + ARGS+=("--tls-ca-cert-file" "${REDIS_SENTINEL_TLS_CA_FILE}") + ARGS+=("--tls-replication" "yes") + ARGS+=("--tls-auth-clients" "${REDIS_SENTINEL_TLS_AUTH_CLIENTS}") + {{- if .Values.tls.dhParamsFilename }} + ARGS+=("--tls-dh-params-file" "${REDIS_SENTINEL_TLS_DH_PARAMS_FILE}") + {{- end }} + {{- end }} + {{- if .Values.sentinel.preExecCmds }} + {{ .Values.sentinel.preExecCmds | nindent 4 }} + {{- end }} + exec redis-server /opt/bitnami/redis-sentinel/etc/sentinel.conf {{- if .Values.tls.enabled }} "${ARGS[@]}" {{- end }} --sentinel + prestop-sentinel.sh: | + #!/bin/bash + + . /opt/bitnami/scripts/libvalidations.sh + . /opt/bitnami/scripts/libos.sh + + HEADLESS_SERVICE="{{ template "common.names.fullname" . }}-headless.{{ .Release.Namespace }}.svc.{{ .Values.clusterDomain }}" + + get_full_hostname() { + hostname="$1" + + {{- if .Values.useExternalDNS.enabled }} + full_hostname="${hostname}.{{- include "redis.externalDNS.suffix" . }}" + {{- else if eq .Values.sentinel.service.type "NodePort" }} + full_hostname="${hostname}.{{- .Release.Namespace }}" + {{- else }} + full_hostname="${hostname}.${HEADLESS_SERVICE}" + {{- end }} + + {{- if .Values.useHostnames }} + echo "${full_hostname}" + {{- else }} + retry_count=0 + until getent hosts "${full_hostname}" | awk '{ print $1; exit }' | grep .; do + if [[ $retry_count -lt {{ .Values.nameResolutionThreshold }} ]]; then + sleep {{ .Values.nameResolutionTimeout }} + else + error "IP address for ${full_hostname} not found" + exit 1 + fi + ((retry_count++)) + done + {{- end }} + } + + run_sentinel_command() { + if is_boolean_yes "$REDIS_SENTINEL_TLS_ENABLED"; then + redis-cli -h "$REDIS_SERVICE" -p "$REDIS_SENTINEL_PORT" --tls --cert "$REDIS_SENTINEL_TLS_CERT_FILE" --key "$REDIS_SENTINEL_TLS_KEY_FILE" --cacert "$REDIS_SENTINEL_TLS_CA_FILE" sentinel "$@" + else + redis-cli -h "$REDIS_SERVICE" -p "$REDIS_SENTINEL_PORT" sentinel "$@" + fi + } + sentinel_failover_finished() { + REDIS_SENTINEL_INFO=($(run_sentinel_command get-master-addr-by-name "{{ .Values.sentinel.masterSet }}")) + REDIS_MASTER_HOST="${REDIS_SENTINEL_INFO[0]}" + [[ "$REDIS_MASTER_HOST" != "$(get_full_hostname $HOSTNAME)" ]] + } + + REDIS_SERVICE="{{ include "common.names.fullname" . }}.{{ .Release.Namespace }}.svc.{{ .Values.clusterDomain }}" + + {{ if .Values.auth.sentinel -}} + # redis-cli automatically consumes credentials from the REDISCLI_AUTH variable + [[ -n "$REDIS_PASSWORD" ]] && export REDISCLI_AUTH="$REDIS_PASSWORD" + [[ -f "$REDIS_PASSWORD_FILE" ]] && export REDISCLI_AUTH="$(< "${REDIS_PASSWORD_FILE}")" + {{- end }} + + if ! sentinel_failover_finished; then + echo "I am the master pod and you are stopping me. Starting sentinel failover" + if retry_while "sentinel_failover_finished" "{{ sub .Values.sentinel.terminationGracePeriodSeconds 10 }}" 1; then + echo "Master has been successfuly failed over to a different pod." + exit 0 + else + echo "Master failover failed" + exit 1 + fi + else + exit 0 + fi + prestop-redis.sh: | + #!/bin/bash + + . /opt/bitnami/scripts/libvalidations.sh + . /opt/bitnami/scripts/libos.sh + + run_redis_command() { + if is_boolean_yes "$REDIS_TLS_ENABLED"; then + redis-cli -h 127.0.0.1 -p "$REDIS_TLS_PORT" --tls --cert "$REDIS_TLS_CERT_FILE" --key "$REDIS_TLS_KEY_FILE" --cacert "$REDIS_TLS_CA_FILE" "$@" + else + redis-cli -h 127.0.0.1 -p "$REDIS_PORT" "$@" + fi + } + is_master() { + REDIS_ROLE=$(run_redis_command role | head -1) + [[ "$REDIS_ROLE" == "master" ]] + } + + HEADLESS_SERVICE="{{ template "common.names.fullname" . }}-headless.{{ .Release.Namespace }}.svc.{{ .Values.clusterDomain }}" + + get_full_hostname() { + hostname="$1" + + {{- if .Values.useExternalDNS.enabled }} + full_hostname="${hostname}.{{- include "redis.externalDNS.suffix" . }}" + {{- else if eq .Values.sentinel.service.type "NodePort" }} + full_hostname="${hostname}.{{- .Release.Namespace }}" + {{- else }} + full_hostname="${hostname}.${HEADLESS_SERVICE}" + {{- end }} + + {{- if .Values.useHostnames }} + echo "${full_hostname}" + {{- else }} + retry_count=0 + until getent hosts "${full_hostname}" | awk '{ print $1; exit }' | grep .; do + if [[ $retry_count -lt {{ .Values.nameResolutionThreshold }} ]]; then + sleep {{ .Values.nameResolutionTimeout }} + else + error "IP address for ${full_hostname} not found" + exit 1 + fi + ((retry_count++)) + done + {{- end }} + } + + run_sentinel_command() { + if is_boolean_yes "$REDIS_SENTINEL_TLS_ENABLED"; then + {{ .Values.auth.sentinel | ternary "" "env -u REDISCLI_AUTH " -}} redis-cli -h "$REDIS_SERVICE" -p "$REDIS_SENTINEL_PORT" --tls --cert "$REDIS_SENTINEL_TLS_CERT_FILE" --key "$REDIS_SENTINEL_TLS_KEY_FILE" --cacert "$REDIS_SENTINEL_TLS_CA_FILE" sentinel "$@" + else + {{ .Values.auth.sentinel | ternary "" "env -u REDISCLI_AUTH " -}} redis-cli -h "$REDIS_SERVICE" -p "$REDIS_SENTINEL_PORT" sentinel "$@" + fi + } + sentinel_failover_finished() { + REDIS_SENTINEL_INFO=($(run_sentinel_command get-master-addr-by-name "{{ .Values.sentinel.masterSet }}")) + REDIS_MASTER_HOST="${REDIS_SENTINEL_INFO[0]}" + [[ "$REDIS_MASTER_HOST" != "$(get_full_hostname $HOSTNAME)" ]] + } + + REDIS_SERVICE="{{ include "common.names.fullname" . }}.{{ .Release.Namespace }}.svc.{{ .Values.clusterDomain }}" + + # redis-cli automatically consumes credentials from the REDISCLI_AUTH variable + [[ -n "$REDIS_PASSWORD" ]] && export REDISCLI_AUTH="$REDIS_PASSWORD" + [[ -f "$REDIS_PASSWORD_FILE" ]] && export REDISCLI_AUTH="$(< "${REDIS_PASSWORD_FILE}")" + + + if is_master && ! sentinel_failover_finished; then + echo "I am the master pod and you are stopping me. Pausing client connections." + # Pausing client write connections to avoid data loss + run_redis_command CLIENT PAUSE "{{ mul (add 2 (sub .Values.sentinel.terminationGracePeriodSeconds 10)) 1000 }}" WRITE + + echo "Issuing failover" + # if I am the master, issue a command to failover once + run_sentinel_command failover "{{ .Values.sentinel.masterSet }}" + + {{- if .Values.sentinel.redisShutdownWaitFailover }} + echo "Waiting for sentinel to complete failover for up to {{ sub .Values.sentinel.terminationGracePeriodSeconds 10 }}s" + retry_while "sentinel_failover_finished" "{{ sub .Values.sentinel.terminationGracePeriodSeconds 10 }}" 1 + {{- end }} + else + exit 0 + fi + +{{- else }} + start-master.sh: | + #!/bin/bash + + [[ -f $REDIS_PASSWORD_FILE ]] && export REDIS_PASSWORD="$(< "${REDIS_PASSWORD_FILE}")" + {{- if and .Values.master.containerSecurityContext.runAsUser (eq (.Values.master.containerSecurityContext.runAsUser | int) 0) }} + useradd redis + chown -R redis {{ .Values.master.persistence.path }} + {{- end }} + if [[ -f /opt/bitnami/redis/mounted-etc/master.conf ]];then + cp /opt/bitnami/redis/mounted-etc/master.conf /opt/bitnami/redis/etc/master.conf + fi + if [[ -f /opt/bitnami/redis/mounted-etc/redis.conf ]];then + cp /opt/bitnami/redis/mounted-etc/redis.conf /opt/bitnami/redis/etc/redis.conf + fi + {{- if .Values.tls.enabled }} + ARGS=("--port" "0") + ARGS+=("--tls-port" "${REDIS_TLS_PORT}") + ARGS+=("--tls-cert-file" "${REDIS_TLS_CERT_FILE}") + ARGS+=("--tls-key-file" "${REDIS_TLS_KEY_FILE}") + ARGS+=("--tls-ca-cert-file" "${REDIS_TLS_CA_FILE}") + ARGS+=("--tls-auth-clients" "${REDIS_TLS_AUTH_CLIENTS}") + {{- if .Values.tls.dhParamsFilename }} + ARGS+=("--tls-dh-params-file" "${REDIS_TLS_DH_PARAMS_FILE}") + {{- end }} + {{- else }} + ARGS=("--port" "${REDIS_PORT}") + {{- end }} + {{- if .Values.auth.enabled }} + ARGS+=("--requirepass" "${REDIS_PASSWORD}") + ARGS+=("--masterauth" "${REDIS_PASSWORD}") + {{- else }} + ARGS+=("--protected-mode" "no") + {{- end }} + ARGS+=("--include" "/opt/bitnami/redis/etc/redis.conf") + ARGS+=("--include" "/opt/bitnami/redis/etc/master.conf") + {{- if .Values.master.extraFlags }} + {{- range .Values.master.extraFlags }} + ARGS+=({{ . | quote }}) + {{- end }} + {{- end }} + {{- if .Values.master.preExecCmds }} + {{ .Values.master.preExecCmds | nindent 4 }} + {{- end }} + {{- if .Values.master.command }} + exec {{ .Values.master.command }} "${ARGS[@]}" + {{- else }} + exec redis-server "${ARGS[@]}" + {{- end }} + {{- if eq .Values.architecture "replication" }} + start-replica.sh: | + #!/bin/bash + + get_port() { + hostname="$1" + type="$2" + + port_var=$(echo "${hostname^^}_SERVICE_PORT_$type" | sed "s/-/_/g") + port=${!port_var} + + if [ -z "$port" ]; then + case $type in + "SENTINEL") + echo {{ .Values.sentinel.containerPorts.sentinel }} + ;; + "REDIS") + echo {{ .Values.master.containerPorts.redis }} + ;; + esac + else + echo $port + fi + } + + get_full_hostname() { + hostname="$1" + + {{- if .Values.useExternalDNS.enabled }} + full_hostname="${hostname}.{{- include "redis.externalDNS.suffix" . }}" + {{- else if eq .Values.sentinel.service.type "NodePort" }} + full_hostname="${hostname}.{{- .Release.Namespace }}" + {{- else }} + full_hostname="${hostname}.${HEADLESS_SERVICE}" + {{- end }} + + {{- if .Values.useHostnames }} + echo "${full_hostname}" + {{- else }} + retry_count=0 + until getent hosts "${full_hostname}" | awk '{ print $1; exit }' | grep .; do + if [[ $retry_count -lt {{ .Values.nameResolutionThreshold }} ]]; then + sleep {{ .Values.nameResolutionTimeout }} + else + error "IP address for ${full_hostname} not found" + exit 1 + fi + ((retry_count++)) + done + {{- end }} + } + + REDISPORT=$(get_port "$HOSTNAME" "REDIS") + HEADLESS_SERVICE="{{ template "common.names.fullname" . }}-headless.{{ .Release.Namespace }}.svc.{{ .Values.clusterDomain }}" + + [[ -f $REDIS_PASSWORD_FILE ]] && export REDIS_PASSWORD="$(< "${REDIS_PASSWORD_FILE}")" + [[ -f $REDIS_MASTER_PASSWORD_FILE ]] && export REDIS_MASTER_PASSWORD="$(< "${REDIS_MASTER_PASSWORD_FILE}")" + {{- if and .Values.replica.containerSecurityContext.runAsUser (eq (.Values.replica.containerSecurityContext.runAsUser | int) 0) }} + useradd redis + chown -R redis {{ .Values.replica.persistence.path }} + {{- end }} + if [[ -f /opt/bitnami/redis/mounted-etc/replica.conf ]];then + cp /opt/bitnami/redis/mounted-etc/replica.conf /opt/bitnami/redis/etc/replica.conf + fi + if [[ -f /opt/bitnami/redis/mounted-etc/redis.conf ]];then + cp /opt/bitnami/redis/mounted-etc/redis.conf /opt/bitnami/redis/etc/redis.conf + fi + + echo "" >> /opt/bitnami/redis/etc/replica.conf + echo "replica-announce-port $REDISPORT" >> /opt/bitnami/redis/etc/replica.conf + echo "replica-announce-ip $(get_full_hostname "$HOSTNAME")" >> /opt/bitnami/redis/etc/replica.conf + + {{- if .Values.tls.enabled }} + ARGS=("--port" "0") + ARGS+=("--tls-port" "${REDIS_TLS_PORT}") + ARGS+=("--tls-cert-file" "${REDIS_TLS_CERT_FILE}") + ARGS+=("--tls-key-file" "${REDIS_TLS_KEY_FILE}") + ARGS+=("--tls-ca-cert-file" "${REDIS_TLS_CA_FILE}") + ARGS+=("--tls-auth-clients" "${REDIS_TLS_AUTH_CLIENTS}") + ARGS+=("--tls-replication" "yes") + {{- if .Values.tls.dhParamsFilename }} + ARGS+=("--tls-dh-params-file" "${REDIS_TLS_DH_PARAMS_FILE}") + {{- end }} + {{- else }} + ARGS=("--port" "${REDIS_PORT}") + {{- end }} + ARGS+=("--replicaof" "${REDIS_MASTER_HOST}" "${REDIS_MASTER_PORT_NUMBER}") + {{- if .Values.auth.enabled }} + ARGS+=("--requirepass" "${REDIS_PASSWORD}") + ARGS+=("--masterauth" "${REDIS_MASTER_PASSWORD}") + {{- else }} + ARGS+=("--protected-mode" "no") + {{- end }} + ARGS+=("--include" "/opt/bitnami/redis/etc/redis.conf") + ARGS+=("--include" "/opt/bitnami/redis/etc/replica.conf") + {{- if .Values.replica.extraFlags }} + {{- range .Values.replica.extraFlags }} + ARGS+=({{ . | quote }}) + {{- end }} + {{- end }} + {{- if .Values.replica.preExecCmds }} + {{ .Values.replica.preExecCmds | nindent 4 }} + {{- end }} + {{- if .Values.replica.command }} + exec {{ .Values.replica.command }} "${ARGS[@]}" + {{- else }} + exec redis-server "${ARGS[@]}" + {{- end }} + {{- end }} +{{- end }} diff --git a/packages/system/dashboard/charts/kubeapps/charts/redis/templates/secret-svcbind.yaml b/packages/system/dashboard/charts/kubeapps/charts/redis/templates/secret-svcbind.yaml new file mode 100644 index 00000000..a1bfbe05 --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/charts/redis/templates/secret-svcbind.yaml @@ -0,0 +1,37 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.serviceBindings.enabled }} +{{- $host := include "common.names.fullname" . }} +{{- if not .Values.sentinel.enabled }} +{{- $host = printf "%s-master" (include "common.names.fullname" .) }} +{{- end }} +{{- $port := print .Values.master.service.ports.redis }} +{{- if .Values.sentinel.enabled }} +{{- $port = print .Values.sentinel.service.ports.redis }} +{{- end }} +{{- $password := include "redis.password" . }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "common.names.fullname" . }}-svcbind + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +type: servicebinding.io/redis +data: + provider: {{ print "bitnami" | b64enc | quote }} + type: {{ print "redis" | b64enc | quote }} + host: {{ print $host | b64enc | quote }} + port: {{ print $port | b64enc | quote }} + password: {{ print $password | b64enc | quote }} + {{- if $password }} + uri: {{ printf "redis://:%s@%s:%s" $password $host $port | b64enc | quote }} + {{- else }} + uri: {{ printf "redis://%s:%s" $host $port | b64enc | quote }} + {{- end }} +{{- end }} diff --git a/packages/system/dashboard/charts/kubeapps/charts/redis/templates/secret.yaml b/packages/system/dashboard/charts/kubeapps/charts/redis/templates/secret.yaml new file mode 100644 index 00000000..1838c7d4 --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/charts/redis/templates/secret.yaml @@ -0,0 +1,25 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.auth.enabled (not .Values.auth.existingSecret) -}} +apiVersion: v1 +kind: Secret +metadata: + name: {{ template "common.names.fullname" . }} + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if or .Values.secretAnnotations .Values.commonAnnotations }} + annotations: + {{- if .Values.secretAnnotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.secretAnnotations "context" $ ) | nindent 4 }} + {{- end }} + {{- if .Values.commonAnnotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} + {{- end }} +type: Opaque +data: + redis-password: {{ include "redis.password" . | b64enc | quote }} +{{- end -}} diff --git a/packages/system/dashboard/charts/kubeapps/charts/redis/templates/sentinel/hpa.yaml b/packages/system/dashboard/charts/kubeapps/charts/redis/templates/sentinel/hpa.yaml new file mode 100644 index 00000000..80859c00 --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/charts/redis/templates/sentinel/hpa.yaml @@ -0,0 +1,49 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.replica.autoscaling.enabled .Values.sentinel.enabled }} +apiVersion: {{ include "common.capabilities.hpa.apiVersion" ( dict "context" $ ) }} +kind: HorizontalPodAutoscaler +metadata: + name: {{ printf "%s-node" (include "common.names.fullname" .) }} + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: replica + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + scaleTargetRef: + apiVersion: {{ include "common.capabilities.deployment.apiVersion" . }} + kind: StatefulSet + name: {{ printf "%s-node" (include "common.names.fullname" .) }} + minReplicas: {{ .Values.replica.autoscaling.minReplicas }} + maxReplicas: {{ .Values.replica.autoscaling.maxReplicas }} + metrics: + {{- if .Values.replica.autoscaling.targetMemory }} + - type: Resource + resource: + name: memory + {{- if semverCompare "<1.23-0" (include "common.capabilities.kubeVersion" .) }} + targetAverageUtilization: {{ .Values.replica.autoscaling.targetMemory }} + {{- else }} + target: + type: Utilization + averageUtilization: {{ .Values.replica.autoscaling.targetMemory }} + {{- end }} + {{- end }} + {{- if .Values.replica.autoscaling.targetCPU }} + - type: Resource + resource: + name: cpu + {{- if semverCompare "<1.23-0" (include "common.capabilities.kubeVersion" .) }} + targetAverageUtilization: {{ .Values.replica.autoscaling.targetCPU }} + {{- else }} + target: + type: Utilization + averageUtilization: {{ .Values.replica.autoscaling.targetCPU }} + {{- end }} + {{- end }} +{{- end }} diff --git a/packages/system/dashboard/charts/kubeapps/charts/redis/templates/sentinel/node-services.yaml b/packages/system/dashboard/charts/kubeapps/charts/redis/templates/sentinel/node-services.yaml new file mode 100644 index 00000000..721185bc --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/charts/redis/templates/sentinel/node-services.yaml @@ -0,0 +1,67 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and (eq .Values.architecture "replication") .Values.sentinel.enabled (eq .Values.sentinel.service.type "NodePort") (or .Release.IsUpgrade .Values.sentinel.service.nodePorts.redis ) }} + +{{- range $i := until (int .Values.replica.replicaCount) }} + +{{ $portsmap := (lookup "v1" "ConfigMap" $.Release.Namespace (printf "%s-%s" ( include "common.names.fullname" $ ) "ports-configmap")).data }} + +{{ $sentinelport := 0}} +{{ $redisport := 0}} +{{- if $portsmap }} +{{ $sentinelport = index $portsmap (printf "%s-node-%s-%s" (include "common.names.fullname" $) (toString $i) "sentinel") }} +{{ $redisport = index $portsmap (printf "%s-node-%s-%s" (include "common.names.fullname" $) (toString $i) "redis") }} +{{- else }} +{{- end }} +apiVersion: v1 +kind: Service +metadata: + name: {{ template "common.names.fullname" $ }}-node-{{ $i }} + namespace: {{ $.Release.Namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $.Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: node + {{- if or $.Values.commonAnnotations $.Values.sentinel.service.annotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list $.Values.sentinel.service.annotations $.Values.commonAnnotations ) "context" $ ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + type: NodePort + ports: + - name: sentinel + {{- if $.Values.sentinel.service.nodePorts.sentinel }} + nodePort: {{ (add $.Values.sentinel.service.nodePorts.sentinel $i 1) }} + port: {{ (add $.Values.sentinel.service.nodePorts.sentinel $i 1) }} + {{- else }} + nodePort: {{ $sentinelport }} + port: {{ $sentinelport }} + {{- end }} + protocol: TCP + targetPort: {{ $.Values.sentinel.containerPorts.sentinel }} + - name: redis + {{- if $.Values.sentinel.service.nodePorts.redis }} + nodePort: {{ (add $.Values.sentinel.service.nodePorts.redis $i 1) }} + port: {{ (add $.Values.sentinel.service.nodePorts.redis $i 1) }} + {{- else }} + nodePort: {{ $redisport }} + port: {{ $redisport }} + {{- end }} + protocol: TCP + targetPort: {{ $.Values.replica.containerPorts.redis }} + - name: sentinel-internal + nodePort: null + port: {{ $.Values.sentinel.containerPorts.sentinel }} + protocol: TCP + targetPort: {{ $.Values.sentinel.containerPorts.sentinel }} + - name: redis-internal + nodePort: null + port: {{ $.Values.replica.containerPorts.redis }} + protocol: TCP + targetPort: {{ $.Values.replica.containerPorts.redis }} + selector: + statefulset.kubernetes.io/pod-name: {{ template "common.names.fullname" $ }}-node-{{ $i }} +--- +{{- end }} +{{- end }} diff --git a/packages/system/dashboard/charts/kubeapps/charts/redis/templates/sentinel/ports-configmap.yaml b/packages/system/dashboard/charts/kubeapps/charts/redis/templates/sentinel/ports-configmap.yaml new file mode 100644 index 00000000..1c0771a4 --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/charts/redis/templates/sentinel/ports-configmap.yaml @@ -0,0 +1,102 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and (eq .Values.architecture "replication") .Values.sentinel.enabled (eq .Values.sentinel.service.type "NodePort") (not .Values.sentinel.service.nodePorts.redis ) }} +{{- /* create a list to keep track of ports we choose to use */}} +{{ $chosenports := (list ) }} + +{{- /* Get list of all used nodeports */}} +{{ $usedports := (list ) }} +{{- range $index, $service := (lookup "v1" "Service" "" "").items }} + {{- range.spec.ports }} + {{- if .nodePort }} + {{- $usedports = (append $usedports .nodePort) }} + {{- end }} + {{- end }} +{{- end }} + +{{- /* +comments that start with # are rendered in the output when you debug, so you can less and search for them +Vars in the comment will be rendered out, so you can check their value this way. +https://helm.sh/docs/chart_best_practices/templates/#comments-yaml-comments-vs-template-comments + +remove the template comments and leave the yaml comments to help debug +*/}} + +{{- /* Sort the list */}} +{{ $usedports = $usedports | sortAlpha }} +#usedports {{ $usedports }} + +{{- /* How many nodeports per service do we want to create, except for the main service which is always two */}} +{{ $numberofPortsPerNodeService := 2 }} + +{{- /* for every nodeport we want, loop though the used ports to get an unused port */}} +{{- range $j := until (int (add (mul (int .Values.replica.replicaCount) $numberofPortsPerNodeService) 2)) }} + {{- /* #j={{ $j }} */}} + {{- $nodeport := (add $j 30000) }} + {{- $nodeportfound := false }} + {{- range $i := $usedports }} + {{- /* #i={{ $i }} + #nodeport={{ $nodeport }} + #usedports={{ $usedports }} */}} + {{- if and (has (toString $nodeport) $usedports) (eq $nodeportfound false) }} + {{- /* nodeport conflicts with in use */}} + {{- $nodeport = (add $nodeport 1) }} + {{- else if and ( has $nodeport $chosenports) (eq $nodeportfound false) }} + {{- /* nodeport already chosen, try another */}} + {{- $nodeport = (add $nodeport 1) }} + {{- else if (eq $nodeportfound false) }} + {{- /* nodeport free to use: not already claimed and not in use */}} + {{- /* select nodeport, and place into usedports */}} + {{- $chosenports = (append $chosenports $nodeport) }} + {{- $nodeportfound = true }} + {{- else }} + {{- /* nodeport has already been chosen and locked in, just work through the rest of the list to get to the next nodeport selection */}} + {{- end }} + {{- end }} + {{- if (eq $nodeportfound false) }} + {{- $chosenports = (append $chosenports $nodeport) }} + {{- end }} + +{{- end }} + +{{- /* print the usedports and chosenports for debugging */}} +#usedports {{ $usedports }} +#chosenports {{ $chosenports }}}} + +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ template "common.names.fullname" . }}-ports-configmap + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: + {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +data: +{{ $portsmap := (lookup "v1" "ConfigMap" $.Release.Namespace (printf "%s-%s" ( include "common.names.fullname" . ) "ports-configmap")).data }} +{{- if $portsmap }} +{{- /* configmap already exists, do not install again */ -}} + {{- range $name, $value := $portsmap }} + "{{ $name }}": "{{ $value }}" + {{- end }} +{{- else }} +{{- /* configmap being set for first time */ -}} + {{- range $index, $port := $chosenports }} + {{- $nodenumber := (floor (div $index 2)) }} + {{- if (eq $index 0) }} + "{{ template "common.names.fullname" $ }}-sentinel": "{{ $port }}" + {{- else if (eq $index 1) }} + "{{ template "common.names.fullname" $ }}-redis": "{{ $port }}" + {{- else if (eq (mod $index 2) 0) }} + "{{ template "common.names.fullname" $ }}-node-{{ (sub $nodenumber 1) }}-sentinel": "{{ $port }}" + {{- else if (eq (mod $index 2) 1) }} + "{{ template "common.names.fullname" $ }}-node-{{ (sub $nodenumber 1) }}-redis": "{{ $port }}" + {{- end }} + {{- end }} +{{- end }} +{{- end }} diff --git a/packages/system/dashboard/charts/kubeapps/charts/redis/templates/sentinel/service.yaml b/packages/system/dashboard/charts/kubeapps/charts/redis/templates/sentinel/service.yaml new file mode 100644 index 00000000..18126f4e --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/charts/redis/templates/sentinel/service.yaml @@ -0,0 +1,101 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if or .Release.IsUpgrade (ne .Values.sentinel.service.type "NodePort") .Values.sentinel.service.nodePorts.redis -}} +{{- if and (eq .Values.architecture "replication") .Values.sentinel.enabled }} +{{ $portsmap := (lookup "v1" "ConfigMap" $.Release.Namespace (printf "%s-%s" ( include "common.names.fullname" . ) "ports-configmap")).data }} + +{{ $sentinelport := 0}} +{{ $redisport := 0}} +{{- if $portsmap }} +{{ $sentinelport = index $portsmap (printf "%s-%s" (include "common.names.fullname" $) "sentinel") }} +{{ $redisport = index $portsmap (printf "%s-%s" (include "common.names.fullname" $) "redis") }} +{{- else }} +{{- end }} + +apiVersion: v1 +kind: Service +metadata: + name: {{ template "common.names.fullname" . }} + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: node + {{- if or .Values.sentinel.service.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.sentinel.service.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + type: {{ .Values.sentinel.service.type }} + {{- if or (eq .Values.sentinel.service.type "LoadBalancer") (eq .Values.sentinel.service.type "NodePort") }} + externalTrafficPolicy: {{ .Values.sentinel.service.externalTrafficPolicy | quote }} + {{- end }} + {{- if and (eq .Values.sentinel.service.type "LoadBalancer") (not (empty .Values.sentinel.service.loadBalancerIP)) }} + loadBalancerIP: {{ .Values.sentinel.service.loadBalancerIP }} + {{- end }} + {{- if and (eq .Values.sentinel.service.type "LoadBalancer") (not (empty .Values.sentinel.service.loadBalancerSourceRanges)) }} + loadBalancerSourceRanges: {{ toYaml .Values.sentinel.service.loadBalancerSourceRanges | nindent 4 }} + {{- end }} + {{- if and .Values.sentinel.service.clusterIP (eq .Values.sentinel.service.type "ClusterIP") }} + clusterIP: {{ .Values.sentinel.service.clusterIP }} + {{- end }} + {{- if .Values.sentinel.service.sessionAffinity }} + sessionAffinity: {{ .Values.sentinel.service.sessionAffinity }} + {{- end }} + {{- if .Values.sentinel.service.sessionAffinityConfig }} + sessionAffinityConfig: {{- include "common.tplvalues.render" (dict "value" .Values.sentinel.service.sessionAffinityConfig "context" $) | nindent 4 }} + {{- end }} + ports: + - name: tcp-redis + {{- if and (or (eq .Values.sentinel.service.type "NodePort") (eq .Values.sentinel.service.type "LoadBalancer")) .Values.sentinel.service.nodePorts.redis }} + port: {{ .Values.sentinel.service.nodePorts.redis }} + {{- else if eq .Values.sentinel.service.type "NodePort" }} + port: {{ $redisport }} + {{- else}} + port: {{ .Values.sentinel.service.ports.redis }} + {{- end }} + targetPort: {{ .Values.replica.containerPorts.redis }} + {{- if and (or (eq .Values.sentinel.service.type "NodePort") (eq .Values.sentinel.service.type "LoadBalancer")) .Values.sentinel.service.nodePorts.redis }} + nodePort: {{ .Values.sentinel.service.nodePorts.redis }} + {{- else if eq .Values.sentinel.service.type "ClusterIP" }} + nodePort: null + {{- else if eq .Values.sentinel.service.type "NodePort" }} + nodePort: {{ $redisport }} + {{- end }} + - name: tcp-sentinel + {{- if and (or (eq .Values.sentinel.service.type "NodePort") (eq .Values.sentinel.service.type "LoadBalancer")) .Values.sentinel.service.nodePorts.sentinel }} + port: {{ .Values.sentinel.service.nodePorts.sentinel }} + {{- else if eq .Values.sentinel.service.type "NodePort" }} + port: {{ $sentinelport }} + {{- else }} + port: {{ .Values.sentinel.service.ports.sentinel }} + {{- end }} + targetPort: {{ .Values.sentinel.containerPorts.sentinel }} + {{- if and (or (eq .Values.sentinel.service.type "NodePort") (eq .Values.sentinel.service.type "LoadBalancer")) .Values.sentinel.service.nodePorts.sentinel }} + nodePort: {{ .Values.sentinel.service.nodePorts.sentinel }} + {{- else if eq .Values.sentinel.service.type "ClusterIP" }} + nodePort: null + {{- else if eq .Values.sentinel.service.type "NodePort" }} + nodePort: {{ $sentinelport }} + {{- end }} + {{- if eq .Values.sentinel.service.type "NodePort" }} + - name: sentinel-internal + nodePort: null + port: {{ .Values.sentinel.containerPorts.sentinel }} + protocol: TCP + targetPort: {{ .Values.sentinel.containerPorts.sentinel }} + - name: redis-internal + nodePort: null + port: {{ .Values.replica.containerPorts.redis }} + protocol: TCP + targetPort: {{ .Values.replica.containerPorts.redis }} + {{- end }} + {{- if .Values.sentinel.service.extraPorts }} + {{- include "common.tplvalues.render" (dict "value" .Values.sentinel.service.extraPorts "context" $) | nindent 4 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.replica.podLabels .Values.commonLabels ) "context" . ) }} + selector: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: node +{{- end }} +{{- end }} diff --git a/packages/system/dashboard/charts/kubeapps/charts/redis/templates/sentinel/statefulset.yaml b/packages/system/dashboard/charts/kubeapps/charts/redis/templates/sentinel/statefulset.yaml new file mode 100644 index 00000000..55d0e90e --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/charts/redis/templates/sentinel/statefulset.yaml @@ -0,0 +1,785 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if or .Release.IsUpgrade (ne .Values.sentinel.service.type "NodePort") .Values.sentinel.service.nodePorts.redis -}} +{{- if and (eq .Values.architecture "replication") .Values.sentinel.enabled }} +apiVersion: {{ include "common.capabilities.statefulset.apiVersion" . }} +kind: StatefulSet +metadata: + name: {{ printf "%s-node" (include "common.names.fullname" .) }} + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: node + {{- if or .Values.commonAnnotations .Values.sentinel.annotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.sentinel.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + replicas: {{ .Values.replica.replicaCount }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.replica.podLabels .Values.commonLabels ) "context" . ) }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 6 }} + app.kubernetes.io/component: node + serviceName: {{ printf "%s-headless" (include "common.names.fullname" .) }} + {{- if .Values.replica.updateStrategy }} + updateStrategy: {{- toYaml .Values.replica.updateStrategy | nindent 4 }} + {{- end }} + {{- if and .Values.replica.minReadySeconds (semverCompare ">= 1.23-0" (include "common.capabilities.kubeVersion" .)) }} + minReadySeconds: {{ .Values.replica.minReadySeconds }} + {{- end }} + {{- if .Values.replica.podManagementPolicy }} + podManagementPolicy: {{ .Values.replica.podManagementPolicy | quote }} + {{- end }} + template: + metadata: + labels: {{- include "common.labels.standard" ( dict "customLabels" $podLabels "context" $ ) | nindent 8 }} + app.kubernetes.io/component: node + {{- if and .Values.metrics.enabled .Values.metrics.podLabels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.podLabels "context" $ ) | nindent 8 }} + {{- end }} + annotations: + {{- if (include "redis.createConfigmap" .) }} + checksum/configmap: {{ pick ( include (print $.Template.BasePath "/configmap.yaml") . | fromYaml ) "data" | toYaml | sha256sum }} + {{- end }} + checksum/health: {{ pick ( include (print $.Template.BasePath "/health-configmap.yaml") . | fromYaml ) "data" | toYaml | sha256sum }} + checksum/scripts: {{ pick ( include (print $.Template.BasePath "/scripts-configmap.yaml") . | fromYaml ) "data" | toYaml | sha256sum }} + checksum/secret: {{ pick ( include (print $.Template.BasePath "/secret.yaml") . | fromYaml ) "data" | toYaml | sha256sum }} + {{- if .Values.replica.podAnnotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.replica.podAnnotations "context" $ ) | nindent 8 }} + {{- end }} + {{- if and .Values.metrics.enabled .Values.metrics.podAnnotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.podAnnotations "context" $ ) | nindent 8 }} + {{- end }} + spec: + {{- include "redis.imagePullSecrets" . | nindent 6 }} + {{- if .Values.replica.hostAliases }} + hostAliases: {{- include "common.tplvalues.render" (dict "value" .Values.replica.hostAliases "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.replica.podSecurityContext.enabled }} + securityContext: {{- omit .Values.replica.podSecurityContext "enabled" | toYaml | nindent 8 }} + {{- end }} + automountServiceAccountToken: {{ .Values.serviceAccount.automountServiceAccountToken }} + serviceAccountName: {{ template "redis.serviceAccountName" . }} + {{- if .Values.replica.priorityClassName }} + priorityClassName: {{ .Values.replica.priorityClassName | quote }} + {{- end }} + {{- if .Values.replica.affinity }} + affinity: {{- include "common.tplvalues.render" (dict "value" .Values.replica.affinity "context" $) | nindent 8 }} + {{- else }} + affinity: + podAffinity: {{- include "common.affinities.pods" (dict "type" .Values.replica.podAffinityPreset "component" "node" "customLabels" $podLabels "context" $) | nindent 10 }} + podAntiAffinity: {{- include "common.affinities.pods" (dict "type" .Values.replica.podAntiAffinityPreset "component" "node" "customLabels" $podLabels "context" $) | nindent 10 }} + nodeAffinity: {{- include "common.affinities.nodes" (dict "type" .Values.replica.nodeAffinityPreset.type "key" .Values.replica.nodeAffinityPreset.key "values" .Values.replica.nodeAffinityPreset.values) | nindent 10 }} + {{- end }} + {{- if .Values.replica.nodeSelector }} + nodeSelector: {{- include "common.tplvalues.render" (dict "value" .Values.replica.nodeSelector "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.replica.tolerations }} + tolerations: {{- include "common.tplvalues.render" (dict "value" .Values.replica.tolerations "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.replica.topologySpreadConstraints }} + topologySpreadConstraints: {{- include "common.tplvalues.render" (dict "value" .Values.replica.topologySpreadConstraints "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.replica.shareProcessNamespace }} + shareProcessNamespace: {{ .Values.replica.shareProcessNamespace }} + {{- end }} + {{- if .Values.replica.schedulerName }} + schedulerName: {{ .Values.replica.schedulerName | quote }} + {{- end }} + {{- if .Values.replica.dnsPolicy }} + dnsPolicy: {{ .Values.replica.dnsPolicy }} + {{- end }} + {{- if .Values.replica.dnsConfig }} + dnsConfig: {{- include "common.tplvalues.render" (dict "value" .Values.replica.dnsConfig "context" $) | nindent 8 }} + {{- end }} + enableServiceLinks: {{ .Values.sentinel.enableServiceLinks }} + terminationGracePeriodSeconds: {{ .Values.sentinel.terminationGracePeriodSeconds }} + containers: + - name: redis + image: {{ template "redis.image" . }} + imagePullPolicy: {{ .Values.image.pullPolicy | quote }} + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.replica.lifecycleHooks }} + lifecycle: {{- include "common.tplvalues.render" (dict "value" .Values.replica.lifecycleHooks "context" $) | nindent 12 }} + {{- else }} + lifecycle: + preStop: + exec: + command: + - /bin/bash + - -c + - /opt/bitnami/scripts/start-scripts/prestop-redis.sh + {{- end }} + {{- end }} + {{- if .Values.replica.containerSecurityContext.enabled }} + securityContext: {{- omit .Values.replica.containerSecurityContext "enabled" | toYaml | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 12 }} + {{- else if .Values.replica.command }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.replica.command "context" $) | nindent 12 }} + {{- else }} + command: + - /bin/bash + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 12 }} + {{- else if .Values.replica.args }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.replica.args "context" $) | nindent 12 }} + {{- else }} + args: + - -c + - /opt/bitnami/scripts/start-scripts/start-node.sh + {{- end }} + env: + - name: BITNAMI_DEBUG + value: {{ ternary "true" "false" (or .Values.image.debug .Values.diagnosticMode.enabled) | quote }} + - name: REDIS_MASTER_PORT_NUMBER + value: {{ .Values.replica.containerPorts.redis | quote }} + - name: ALLOW_EMPTY_PASSWORD + value: {{ ternary "no" "yes" .Values.auth.enabled | quote }} + {{- if .Values.auth.enabled }} + {{- if .Values.auth.usePasswordFiles }} + - name: REDIS_PASSWORD_FILE + value: "/opt/bitnami/redis/secrets/redis-password" + - name: REDIS_MASTER_PASSWORD_FILE + value: "/opt/bitnami/redis/secrets/redis-password" + {{- else }} + - name: REDIS_PASSWORD + valueFrom: + secretKeyRef: + name: {{ template "redis.secretName" . }} + key: {{ template "redis.secretPasswordKey" . }} + - name: REDIS_MASTER_PASSWORD + valueFrom: + secretKeyRef: + name: {{ template "redis.secretName" . }} + key: {{ template "redis.secretPasswordKey" . }} + {{- end }} + {{- end }} + - name: REDIS_TLS_ENABLED + value: {{ ternary "yes" "no" .Values.tls.enabled | quote }} + {{- if .Values.tls.enabled }} + - name: REDIS_TLS_PORT + value: {{ .Values.replica.containerPorts.redis | quote }} + - name: REDIS_TLS_AUTH_CLIENTS + value: {{ ternary "yes" "no" .Values.tls.authClients | quote }} + - name: REDIS_TLS_CERT_FILE + value: {{ template "redis.tlsCert" . }} + - name: REDIS_TLS_KEY_FILE + value: {{ template "redis.tlsCertKey" . }} + - name: REDIS_TLS_CA_FILE + value: {{ template "redis.tlsCACert" . }} + {{- if .Values.tls.dhParamsFilename }} + - name: REDIS_TLS_DH_PARAMS_FILE + value: {{ template "redis.tlsDHParams" . }} + {{- end }} + {{- else }} + - name: REDIS_PORT + value: {{ .Values.replica.containerPorts.redis | quote }} + {{- end }} + - name: REDIS_SENTINEL_TLS_ENABLED + value: {{ ternary "yes" "no" .Values.tls.enabled | quote }} + {{- if .Values.tls.enabled }} + - name: REDIS_SENTINEL_TLS_PORT_NUMBER + value: {{ .Values.sentinel.containerPorts.sentinel | quote }} + - name: REDIS_SENTINEL_TLS_AUTH_CLIENTS + value: {{ ternary "yes" "no" .Values.tls.authClients | quote }} + - name: REDIS_SENTINEL_TLS_CERT_FILE + value: {{ template "redis.tlsCert" . }} + - name: REDIS_SENTINEL_TLS_KEY_FILE + value: {{ template "redis.tlsCertKey" . }} + - name: REDIS_SENTINEL_TLS_CA_FILE + value: {{ template "redis.tlsCACert" . }} + {{- if .Values.tls.dhParamsFilename }} + - name: REDIS_SENTINEL_TLS_DH_PARAMS_FILE + value: {{ template "redis.tlsDHParams" . }} + {{- end }} + {{- else }} + - name: REDIS_SENTINEL_PORT + value: {{ .Values.sentinel.containerPorts.sentinel | quote }} + {{- end }} + - name: REDIS_DATA_DIR + value: {{ .Values.replica.persistence.path }} + {{- if .Values.replica.externalMaster.enabled }} + - name: REDIS_EXTERNAL_MASTER_HOST + value: {{ .Values.replica.externalMaster.host | quote }} + - name: REDIS_EXTERNAL_MASTER_PORT + value: {{ .Values.replica.externalMaster.port | quote }} + {{- end }} + {{- if .Values.replica.extraEnvVars }} + {{- include "common.tplvalues.render" ( dict "value" .Values.replica.extraEnvVars "context" $ ) | nindent 12 }} + {{- end }} + {{- if or .Values.replica.extraEnvVarsCM .Values.replica.extraEnvVarsSecret }} + envFrom: + {{- if .Values.replica.extraEnvVarsCM }} + - configMapRef: + name: {{ .Values.replica.extraEnvVarsCM }} + {{- end }} + {{- if .Values.replica.extraEnvVarsSecret }} + - secretRef: + name: {{ .Values.replica.extraEnvVarsSecret }} + {{- end }} + {{- end }} + ports: + - name: redis + containerPort: {{ .Values.replica.containerPorts.redis }} + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.replica.customStartupProbe }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" .Values.replica.customStartupProbe "context" $) | nindent 12 }} + {{- else if .Values.replica.startupProbe.enabled }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.replica.startupProbe "enabled") "context" $) | nindent 12 }} + exec: + command: + - sh + - -c + - /health/ping_liveness_local.sh {{ .Values.replica.livenessProbe.timeoutSeconds }} + {{- end }} + {{- if .Values.replica.customLivenessProbe }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.replica.customLivenessProbe "context" $) | nindent 12 }} + {{- else if .Values.replica.livenessProbe.enabled }} + livenessProbe: + initialDelaySeconds: {{ .Values.replica.livenessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.replica.livenessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.replica.livenessProbe.timeoutSeconds }} + successThreshold: {{ .Values.replica.livenessProbe.successThreshold }} + failureThreshold: {{ .Values.replica.livenessProbe.failureThreshold }} + exec: + command: + - sh + - -c + - /health/ping_liveness_local.sh {{ .Values.replica.livenessProbe.timeoutSeconds }} + {{- end }} + {{- if .Values.replica.customReadinessProbe }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.replica.customReadinessProbe "context" $) | nindent 12 }} + {{- else if .Values.replica.readinessProbe.enabled }} + readinessProbe: + initialDelaySeconds: {{ .Values.replica.readinessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.replica.readinessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.replica.readinessProbe.timeoutSeconds }} + successThreshold: {{ .Values.replica.readinessProbe.successThreshold }} + failureThreshold: {{ .Values.replica.readinessProbe.failureThreshold }} + exec: + command: + - sh + - -c + - /health/ping_readiness_local.sh {{ .Values.replica.readinessProbe.timeoutSeconds }} + {{- end }} + {{- end }} + {{- if .Values.replica.resources }} + resources: {{- toYaml .Values.replica.resources | nindent 12 }} + {{- end }} + volumeMounts: + - name: start-scripts + mountPath: /opt/bitnami/scripts/start-scripts + - name: health + mountPath: /health + {{- if .Values.sentinel.persistence.enabled }} + - name: sentinel-data + mountPath: /opt/bitnami/redis-sentinel/etc + {{- end }} + {{- if .Values.auth.usePasswordFiles }} + - name: redis-password + mountPath: /opt/bitnami/redis/secrets/ + {{- end }} + - name: redis-data + mountPath: {{ .Values.replica.persistence.path }} + {{- if .Values.replica.persistence.subPath }} + subPath: {{ .Values.replica.persistence.subPath }} + {{- else if .Values.replica.persistence.subPathExpr }} + subPathExpr: {{ .Values.replica.persistence.subPathExpr }} + {{- end }} + - name: config + mountPath: /opt/bitnami/redis/mounted-etc + - name: redis-tmp-conf + mountPath: /opt/bitnami/redis/etc + - name: tmp + mountPath: /tmp + {{- if .Values.tls.enabled }} + - name: redis-certificates + mountPath: /opt/bitnami/redis/certs + readOnly: true + {{- end }} + {{- if .Values.replica.extraVolumeMounts }} + {{- include "common.tplvalues.render" ( dict "value" .Values.replica.extraVolumeMounts "context" $ ) | nindent 12 }} + {{- end }} + - name: sentinel + image: {{ template "redis.sentinel.image" . }} + imagePullPolicy: {{ .Values.sentinel.image.pullPolicy | quote }} + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.sentinel.lifecycleHooks }} + lifecycle: {{- include "common.tplvalues.render" (dict "value" .Values.sentinel.lifecycleHooks "context" $) | nindent 12 }} + {{- else }} + lifecycle: + preStop: + exec: + command: + - /bin/bash + - -c + - /opt/bitnami/scripts/start-scripts/prestop-sentinel.sh + {{- end }} + {{- end }} + {{- if .Values.sentinel.containerSecurityContext.enabled }} + securityContext: {{- omit .Values.sentinel.containerSecurityContext "enabled" | toYaml | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 12 }} + {{- else if .Values.sentinel.command }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.sentinel.command "context" $) | nindent 12 }} + {{- else }} + command: + - /bin/bash + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 12 }} + {{- else if .Values.sentinel.args }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.sentinel.args "context" $) | nindent 12 }} + {{- else }} + args: + - -c + - /opt/bitnami/scripts/start-scripts/start-sentinel.sh + {{- end }} + env: + - name: BITNAMI_DEBUG + value: {{ ternary "true" "false" (or .Values.sentinel.image.debug .Values.diagnosticMode.enabled) | quote }} + {{- if .Values.auth.enabled }} + {{- if .Values.auth.usePasswordFiles }} + - name: REDIS_PASSWORD_FILE + value: "/opt/bitnami/redis/secrets/redis-password" + {{- else }} + - name: REDIS_PASSWORD + valueFrom: + secretKeyRef: + name: {{ template "redis.secretName" . }} + key: {{ template "redis.secretPasswordKey" . }} + {{- end }} + {{- else }} + - name: ALLOW_EMPTY_PASSWORD + value: "yes" + {{- end }} + - name: REDIS_SENTINEL_TLS_ENABLED + value: {{ ternary "yes" "no" .Values.tls.enabled | quote }} + {{- if .Values.tls.enabled }} + - name: REDIS_SENTINEL_TLS_PORT_NUMBER + value: {{ .Values.sentinel.containerPorts.sentinel | quote }} + - name: REDIS_SENTINEL_TLS_AUTH_CLIENTS + value: {{ ternary "yes" "no" .Values.tls.authClients | quote }} + - name: REDIS_SENTINEL_TLS_CERT_FILE + value: {{ template "redis.tlsCert" . }} + - name: REDIS_SENTINEL_TLS_KEY_FILE + value: {{ template "redis.tlsCertKey" . }} + - name: REDIS_SENTINEL_TLS_CA_FILE + value: {{ template "redis.tlsCACert" . }} + {{- if .Values.tls.dhParamsFilename }} + - name: REDIS_SENTINEL_TLS_DH_PARAMS_FILE + value: {{ template "redis.tlsDHParams" . }} + {{- end }} + {{- else }} + - name: REDIS_SENTINEL_PORT + value: {{ .Values.sentinel.containerPorts.sentinel | quote }} + {{- end }} + {{- if .Values.sentinel.externalMaster.enabled }} + - name: REDIS_EXTERNAL_MASTER_HOST + value: {{ .Values.sentinel.externalMaster.host | quote }} + - name: REDIS_EXTERNAL_MASTER_PORT + value: {{ .Values.sentinel.externalMaster.port | quote }} + {{- end }} + {{- if .Values.sentinel.extraEnvVars }} + {{- include "common.tplvalues.render" ( dict "value" .Values.sentinel.extraEnvVars "context" $ ) | nindent 12 }} + {{- end }} + {{- if or .Values.sentinel.extraEnvVarsCM .Values.sentinel.extraEnvVarsSecret }} + envFrom: + {{- if .Values.sentinel.extraEnvVarsCM }} + - configMapRef: + name: {{ .Values.sentinel.extraEnvVarsCM }} + {{- end }} + {{- if .Values.sentinel.extraEnvVarsSecret }} + - secretRef: + name: {{ .Values.sentinel.extraEnvVarsSecret }} + {{- end }} + {{- end }} + ports: + - name: redis-sentinel + containerPort: {{ .Values.sentinel.containerPorts.sentinel }} + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.sentinel.customStartupProbe }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" .Values.sentinel.customStartupProbe "context" $) | nindent 12 }} + {{- else if .Values.sentinel.startupProbe.enabled }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.sentinel.startupProbe "enabled") "context" $) | nindent 12 }} + exec: + command: + - sh + - -c + - /health/ping_sentinel.sh {{ .Values.sentinel.livenessProbe.timeoutSeconds }} + {{- end }} + {{- if .Values.sentinel.customLivenessProbe }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.sentinel.customLivenessProbe "context" $) | nindent 12 }} + {{- else if .Values.sentinel.livenessProbe.enabled }} + livenessProbe: + initialDelaySeconds: {{ .Values.sentinel.livenessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.sentinel.livenessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.sentinel.livenessProbe.timeoutSeconds }} + successThreshold: {{ .Values.sentinel.livenessProbe.successThreshold }} + failureThreshold: {{ .Values.sentinel.livenessProbe.failureThreshold }} + exec: + command: + - sh + - -c + - /health/ping_sentinel.sh {{ .Values.sentinel.livenessProbe.timeoutSeconds }} + {{- end }} + {{- end }} + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.sentinel.customReadinessProbe }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.sentinel.customReadinessProbe "context" $) | nindent 12 }} + {{- else if .Values.sentinel.readinessProbe.enabled }} + readinessProbe: + initialDelaySeconds: {{ .Values.sentinel.readinessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.sentinel.readinessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.sentinel.readinessProbe.timeoutSeconds }} + successThreshold: {{ .Values.sentinel.readinessProbe.successThreshold }} + failureThreshold: {{ .Values.sentinel.readinessProbe.failureThreshold }} + exec: + command: + - sh + - -c + - /health/ping_sentinel.sh {{ .Values.sentinel.readinessProbe.timeoutSeconds }} + {{- end }} + {{- end }} + {{- if .Values.sentinel.resources }} + resources: {{- toYaml .Values.sentinel.resources | nindent 12 }} + {{- end }} + volumeMounts: + - name: start-scripts + mountPath: /opt/bitnami/scripts/start-scripts + - name: health + mountPath: /health + - name: sentinel-data + mountPath: /opt/bitnami/redis-sentinel/etc + {{- if .Values.auth.usePasswordFiles }} + - name: redis-password + mountPath: /opt/bitnami/redis/secrets/ + {{- end }} + - name: redis-data + mountPath: {{ .Values.replica.persistence.path }} + {{- if .Values.replica.persistence.subPath }} + subPath: {{ .Values.replica.persistence.subPath }} + {{- else if .Values.replica.persistence.subPathExpr }} + subPathExpr: {{ .Values.replica.persistence.subPathExpr }} + {{- end }} + - name: config + mountPath: /opt/bitnami/redis-sentinel/mounted-etc + {{- if .Values.tls.enabled }} + - name: redis-certificates + mountPath: /opt/bitnami/redis/certs + readOnly: true + {{- end }} + {{- if .Values.sentinel.extraVolumeMounts }} + {{- include "common.tplvalues.render" ( dict "value" .Values.sentinel.extraVolumeMounts "context" $ ) | nindent 12 }} + {{- end }} + {{- if .Values.metrics.enabled }} + - name: metrics + image: {{ template "redis.metrics.image" . }} + imagePullPolicy: {{ .Values.metrics.image.pullPolicy | quote }} + {{- if .Values.metrics.containerSecurityContext.enabled }} + securityContext: {{- omit .Values.metrics.containerSecurityContext "enabled" | toYaml | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 12 }} + {{- else }} + command: + - /bin/bash + - -c + - | + if [[ -f '/secrets/redis-password' ]]; then + export REDIS_PASSWORD=$(cat /secrets/redis-password) + fi + redis_exporter{{- range $key, $value := .Values.metrics.extraArgs }} --{{ $key }}={{ $value }}{{- end }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 12 }} + {{- end }} + env: + - name: REDIS_ALIAS + value: {{ template "common.names.fullname" . }} + {{- if .Values.auth.enabled }} + - name: REDIS_USER + value: default + {{- if (not .Values.auth.usePasswordFiles) }} + - name: REDIS_PASSWORD + valueFrom: + secretKeyRef: + name: {{ template "redis.secretName" . }} + key: {{ template "redis.secretPasswordKey" . }} + {{- end }} + {{- end }} + {{- if .Values.tls.enabled }} + - name: REDIS_ADDR + value: rediss://{{ .Values.metrics.redisTargetHost }}:{{ .Values.replica.containerPorts.redis }} + {{- if .Values.tls.authClients }} + - name: REDIS_EXPORTER_TLS_CLIENT_KEY_FILE + value: {{ template "redis.tlsCertKey" . }} + - name: REDIS_EXPORTER_TLS_CLIENT_CERT_FILE + value: {{ template "redis.tlsCert" . }} + {{- end }} + - name: REDIS_EXPORTER_TLS_CA_CERT_FILE + value: {{ template "redis.tlsCACert" . }} + {{- end }} + {{- if .Values.metrics.extraEnvVars }} + {{- include "common.tplvalues.render" (dict "value" .Values.metrics.extraEnvVars "context" $) | nindent 12 }} + {{- end }} + ports: + - name: metrics + containerPort: 9121 + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.metrics.customStartupProbe }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.customStartupProbe "context" $) | nindent 12 }} + {{- else if .Values.metrics.startupProbe.enabled }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.metrics.startupProbe "enabled") "context" $) | nindent 12 }} + tcpSocket: + port: metrics + {{- end }} + {{- if .Values.metrics.customLivenessProbe }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.customLivenessProbe "context" $) | nindent 12 }} + {{- else if .Values.metrics.livenessProbe.enabled }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.metrics.livenessProbe "enabled") "context" $) | nindent 12 }} + tcpSocket: + port: metrics + {{- end }} + {{- if .Values.metrics.customReadinessProbe }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.customReadinessProbe "context" $) | nindent 12 }} + {{- else if .Values.metrics.readinessProbe.enabled }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.metrics.readinessProbe "enabled") "context" $) | nindent 12 }} + httpGet: + path: / + port: metrics + {{- end }} + {{- end }} + {{- if .Values.metrics.resources }} + resources: {{- toYaml .Values.metrics.resources | nindent 12 }} + {{- end }} + volumeMounts: + {{- if .Values.auth.usePasswordFiles }} + - name: redis-password + mountPath: /secrets/ + {{- end }} + {{- if .Values.tls.enabled }} + - name: redis-certificates + mountPath: /opt/bitnami/redis/certs + readOnly: true + {{- end }} + {{- if .Values.metrics.extraVolumeMounts }} + {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.extraVolumeMounts "context" $ ) | nindent 12 }} + {{- end }} + {{- end }} + {{- if .Values.replica.sidecars }} + {{- include "common.tplvalues.render" (dict "value" .Values.replica.sidecars "context" $) | nindent 8 }} + {{- end }} + {{- $needsVolumePermissions := and .Values.volumePermissions.enabled .Values.replica.persistence.enabled .Values.replica.podSecurityContext.enabled .Values.replica.containerSecurityContext.enabled }} + {{- if or .Values.replica.initContainers $needsVolumePermissions .Values.sysctl.enabled }} + initContainers: + {{- if .Values.replica.initContainers }} + {{- include "common.tplvalues.render" (dict "value" .Values.replica.initContainers "context" $) | nindent 8 }} + {{- end }} + {{- if $needsVolumePermissions }} + - name: volume-permissions + image: {{ include "redis.volumePermissions.image" . }} + imagePullPolicy: {{ .Values.volumePermissions.image.pullPolicy | quote }} + command: + - /bin/bash + - -ec + - | + {{- if eq ( toString ( .Values.volumePermissions.containerSecurityContext.runAsUser )) "auto" }} + chown -R `id -u`:`id -G | cut -d " " -f2` {{ .Values.replica.persistence.path }} + {{- else }} + chown -R {{ .Values.replica.containerSecurityContext.runAsUser }}:{{ .Values.replica.podSecurityContext.fsGroup }} {{ .Values.replica.persistence.path }} + {{- end }} + {{- if eq ( toString ( .Values.volumePermissions.containerSecurityContext.runAsUser )) "auto" }} + securityContext: {{- omit .Values.volumePermissions.containerSecurityContext "runAsUser" | toYaml | nindent 12 }} + {{- else }} + securityContext: {{- .Values.volumePermissions.containerSecurityContext | toYaml | nindent 12 }} + {{- end }} + {{- if .Values.volumePermissions.resources }} + resources: {{- toYaml .Values.volumePermissions.resources | nindent 12 }} + {{- end }} + volumeMounts: + - name: redis-data + mountPath: {{ .Values.replica.persistence.path }} + {{- if .Values.replica.persistence.subPath }} + subPath: {{ .Values.replica.persistence.subPath }} + {{- else if .Values.replica.persistence.subPathExpr }} + subPathExpr: {{ .Values.replica.persistence.subPathExpr }} + {{- end }} + {{- end }} + {{- if .Values.sysctl.enabled }} + - name: init-sysctl + image: {{ include "redis.sysctl.image" . }} + imagePullPolicy: {{ default "" .Values.sysctl.image.pullPolicy | quote }} + securityContext: + privileged: true + runAsUser: 0 + {{- if .Values.sysctl.command }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.sysctl.command "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.sysctl.resources }} + resources: {{- toYaml .Values.sysctl.resources | nindent 12 }} + {{- end }} + {{- if .Values.sysctl.mountHostSys }} + volumeMounts: + - name: host-sys + mountPath: /host-sys + {{- end }} + {{- end }} + {{- end }} + volumes: + - name: start-scripts + configMap: + name: {{ printf "%s-scripts" (include "common.names.fullname" .) }} + defaultMode: 0755 + - name: health + configMap: + name: {{ printf "%s-health" (include "common.names.fullname" .) }} + defaultMode: 0755 + {{- if .Values.auth.usePasswordFiles }} + - name: redis-password + secret: + secretName: {{ template "redis.secretName" . }} + items: + - key: {{ template "redis.secretPasswordKey" . }} + path: redis-password + {{- end }} + - name: config + configMap: + name: {{ include "redis.configmapName" . }} + {{- if .Values.sysctl.mountHostSys }} + - name: host-sys + hostPath: + path: /sys + {{- end }} + {{- if not .Values.sentinel.persistence.enabled }} + - name: sentinel-data + {{- if or .Values.sentinel.persistence.medium .Values.sentinel.persistence.sizeLimit }} + emptyDir: + {{- if .Values.sentinel.persistence.medium }} + medium: {{ .Values.sentinel.persistence.medium | quote }} + {{- end }} + {{- if .Values.sentinel.persistence.sizeLimit }} + sizeLimit: {{ .Values.sentinel.persistence.sizeLimit | quote }} + {{- end }} + {{- else }} + emptyDir: {} + {{- end }} + {{- end }} + - name: redis-tmp-conf + {{- if or .Values.sentinel.persistence.medium .Values.sentinel.persistence.sizeLimit }} + emptyDir: + {{- if .Values.sentinel.persistence.medium }} + medium: {{ .Values.sentinel.persistence.medium | quote }} + {{- end }} + {{- if .Values.sentinel.persistence.sizeLimit }} + sizeLimit: {{ .Values.sentinel.persistence.sizeLimit | quote }} + {{- end }} + {{- else }} + emptyDir: {} + {{- end }} + - name: tmp + {{- if or .Values.sentinel.persistence.medium .Values.sentinel.persistence.sizeLimit }} + emptyDir: + {{- if .Values.sentinel.persistence.medium }} + medium: {{ .Values.sentinel.persistence.medium | quote }} + {{- end }} + {{- if .Values.sentinel.persistence.sizeLimit }} + sizeLimit: {{ .Values.sentinel.persistence.sizeLimit | quote }} + {{- end }} + {{- else }} + emptyDir: {} + {{- end }} + {{- if .Values.replica.extraVolumes }} + {{- include "common.tplvalues.render" ( dict "value" .Values.replica.extraVolumes "context" $ ) | nindent 8 }} + {{- end }} + {{- if .Values.metrics.extraVolumes }} + {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.extraVolumes "context" $ ) | nindent 8 }} + {{- end }} + {{- if .Values.sentinel.extraVolumes }} + {{- include "common.tplvalues.render" ( dict "value" .Values.sentinel.extraVolumes "context" $ ) | nindent 8 }} + {{- end }} + {{- if .Values.tls.enabled }} + - name: redis-certificates + secret: + secretName: {{ include "redis.tlsSecretName" . }} + defaultMode: 256 + {{- end }} + {{- if not .Values.replica.persistence.enabled }} + - name: redis-data + {{- if or .Values.replica.persistence.medium .Values.replica.persistence.sizeLimit }} + emptyDir: + {{- if .Values.replica.persistence.medium }} + medium: {{ .Values.replica.persistence.medium | quote }} + {{- end }} + {{- if .Values.replica.persistence.sizeLimit }} + sizeLimit: {{ .Values.replica.persistence.sizeLimit | quote }} + {{- end }} + {{- else }} + emptyDir: {} + {{- end }} + {{- else if .Values.replica.persistence.existingClaim }} + - name: redis-data + persistentVolumeClaim: + claimName: {{ printf "%s" (tpl .Values.replica.persistence.existingClaim .) }} + {{- else }} + {{- if .Values.sentinel.persistentVolumeClaimRetentionPolicy.enabled }} + persistentVolumeClaimRetentionPolicy: + whenDeleted: {{ .Values.sentinel.persistentVolumeClaimRetentionPolicy.whenDeleted }} + whenScaled: {{ .Values.sentinel.persistentVolumeClaimRetentionPolicy.whenScaled }} + {{- end }} + volumeClaimTemplates: + - apiVersion: v1 + kind: PersistentVolumeClaim + metadata: + name: redis-data + labels: {{- include "common.labels.matchLabels" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 10 }} + app.kubernetes.io/component: node + {{- if .Values.replica.persistence.annotations }} + annotations: {{- toYaml .Values.replica.persistence.annotations | nindent 10 }} + {{- end }} + spec: + accessModes: + {{- range .Values.replica.persistence.accessModes }} + - {{ . | quote }} + {{- end }} + resources: + requests: + storage: {{ .Values.replica.persistence.size | quote }} + {{- if .Values.replica.persistence.selector }} + selector: {{- include "common.tplvalues.render" ( dict "value" .Values.replica.persistence.selector "context" $) | nindent 10 }} + {{- end }} + {{- include "common.storage.class" (dict "persistence" .Values.replica.persistence "global" .Values.global) | nindent 8 }} + {{- if .Values.sentinel.persistence.enabled }} + - metadata: + name: sentinel-data + {{- $claimLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.sentinel.persistence.labels .Values.commonLabels ) "context" . ) }} + labels: {{- include "common.labels.matchLabels" ( dict "customLabels" $claimLabels "context" $ ) | nindent 10 }} + app.kubernetes.io/component: node + {{- if .Values.sentinel.persistence.annotations }} + annotations: {{- toYaml .Values.sentinel.persistence.annotations | nindent 10 }} + {{- end }} + spec: + accessModes: + {{- range .Values.sentinel.persistence.accessModes }} + - {{ . | quote }} + {{- end }} + resources: + requests: + storage: {{ .Values.sentinel.persistence.size | quote }} + {{- if .Values.sentinel.persistence.selector }} + selector: {{- include "common.tplvalues.render" ( dict "value" .Values.sentinel.persistence.selector "context" $) | nindent 10 }} + {{- end }} + {{- if .Values.sentinel.persistence.dataSource }} + dataSource: {{- include "common.tplvalues.render" (dict "value" .Values.sentinel.persistence.dataSource "context" $) | nindent 10 }} + {{- end }} + {{- include "common.storage.class" (dict "persistence" .Values.sentinel.persistence "global" .Values.global) | nindent 8 }} + {{- end }} + {{- end }} +{{- end }} +{{- end }} diff --git a/packages/system/dashboard/charts/kubeapps/charts/redis/templates/serviceaccount.yaml b/packages/system/dashboard/charts/kubeapps/charts/redis/templates/serviceaccount.yaml new file mode 100644 index 00000000..4306b3e8 --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/charts/redis/templates/serviceaccount.yaml @@ -0,0 +1,18 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.serviceAccount.create (and (not .Values.master.serviceAccount.create) (not .Values.replica.serviceAccount.create)) }} +apiVersion: v1 +kind: ServiceAccount +automountServiceAccountToken: {{ .Values.serviceAccount.automountServiceAccountToken }} +metadata: + name: {{ template "redis.serviceAccountName" . }} + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if or .Values.commonAnnotations .Values.serviceAccount.annotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.serviceAccount.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +{{- end }} diff --git a/packages/system/dashboard/charts/kubeapps/charts/redis/templates/servicemonitor.yaml b/packages/system/dashboard/charts/kubeapps/charts/redis/templates/servicemonitor.yaml new file mode 100644 index 00000000..ee925afc --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/charts/redis/templates/servicemonitor.yaml @@ -0,0 +1,52 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.metrics.enabled .Values.metrics.serviceMonitor.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ template "common.names.fullname" . }} + namespace: {{ default .Release.Namespace .Values.metrics.serviceMonitor.namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.metrics.serviceMonitor.additionalLabels }} + {{- include "common.tplvalues.render" (dict "value" .Values.metrics.serviceMonitor.additionalLabels "context" $) | nindent 4 }} + {{- end }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + endpoints: + - port: http-metrics + {{- if .Values.metrics.serviceMonitor.interval }} + interval: {{ .Values.metrics.serviceMonitor.interval }} + {{- end }} + {{- if .Values.metrics.serviceMonitor.scrapeTimeout }} + scrapeTimeout: {{ .Values.metrics.serviceMonitor.scrapeTimeout }} + {{- end }} + {{- if .Values.metrics.serviceMonitor.honorLabels }} + honorLabels: {{ .Values.metrics.serviceMonitor.honorLabels }} + {{- end }} + {{- if .Values.metrics.serviceMonitor.relabellings }} + relabelings: {{- toYaml .Values.metrics.serviceMonitor.relabellings | nindent 6 }} + {{- end }} + {{- if .Values.metrics.serviceMonitor.metricRelabelings }} + metricRelabelings: {{- toYaml .Values.metrics.serviceMonitor.metricRelabelings | nindent 6 }} + {{- end }} + {{- if .Values.metrics.serviceMonitor.podTargetLabels }} + podTargetLabels: {{- toYaml .Values.metrics.serviceMonitor.podTargetLabels | nindent 4 }} + {{- end }} + {{ with .Values.metrics.serviceMonitor.sampleLimit }} + sampleLimit: {{ . }} + {{- end }} + {{ with .Values.metrics.serviceMonitor.targetLimit }} + targetLimit: {{ . }} + {{- end }} + namespaceSelector: + matchNames: + - {{ .Release.Namespace }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 6 }} + app.kubernetes.io/component: metrics +{{- end }} diff --git a/packages/system/dashboard/charts/kubeapps/charts/redis/templates/tls-secret.yaml b/packages/system/dashboard/charts/kubeapps/charts/redis/templates/tls-secret.yaml new file mode 100644 index 00000000..b1f7153e --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/charts/redis/templates/tls-secret.yaml @@ -0,0 +1,31 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if (include "redis.createTlsSecret" .) }} +{{- $secretName := printf "%s-crt" (include "common.names.fullname" .) }} +{{- $ca := genCA "redis-ca" 365 }} +{{- $releaseNamespace := .Release.Namespace }} +{{- $clusterDomain := .Values.clusterDomain }} +{{- $fullname := include "common.names.fullname" . }} +{{- $serviceName := include "common.names.fullname" . }} +{{- $headlessServiceName := printf "%s-headless" (include "common.names.fullname" .) }} +{{- $masterServiceName := printf "%s-master" (include "common.names.fullname" .) }} +{{- $altNames := list (printf "*.%s.%s.svc.%s" $serviceName $releaseNamespace $clusterDomain) (printf "%s.%s.svc.%s" $masterServiceName $releaseNamespace $clusterDomain) (printf "*.%s.%s.svc.%s" $masterServiceName $releaseNamespace $clusterDomain) (printf "*.%s.%s.svc.%s" $headlessServiceName $releaseNamespace $clusterDomain) (printf "%s.%s.svc.%s" $headlessServiceName $releaseNamespace $clusterDomain) "127.0.0.1" "localhost" $fullname }} +{{- $cert := genSignedCert $fullname nil $altNames 365 $ca }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ $secretName }} + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +type: kubernetes.io/tls +data: + tls.crt: {{ include "common.secrets.lookup" (dict "secret" $secretName "key" "tls.crt" "defaultValue" $cert.Cert "context" $) }} + tls.key: {{ include "common.secrets.lookup" (dict "secret" $secretName "key" "tls.key" "defaultValue" $cert.Key "context" $) }} + ca.crt: {{ include "common.secrets.lookup" (dict "secret" $secretName "key" "ca.crt" "defaultValue" $ca.Cert "context" $) }} +{{- end }} diff --git a/packages/system/dashboard/charts/kubeapps/charts/redis/values.schema.json b/packages/system/dashboard/charts/kubeapps/charts/redis/values.schema.json new file mode 100644 index 00000000..e9feba6a --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/charts/redis/values.schema.json @@ -0,0 +1,163 @@ +{ + "$schema": "http://json-schema.org/schema#", + "type": "object", + "properties": { + "architecture": { + "type": "string", + "title": "Redis architecture", + "form": true, + "description": "Allowed values: `standalone` or `replication`", + "enum": ["standalone", "replication"] + }, + "auth": { + "type": "object", + "title": "Authentication configuration", + "form": true, + "properties": { + "enabled": { + "type": "boolean", + "form": true, + "title": "Use password authentication" + }, + "password": { + "type": "string", + "title": "Redis password", + "form": true, + "description": "Defaults to a random 10-character alphanumeric string if not set", + "hidden": { + "value": false, + "path": "auth/enabled" + } + } + } + }, + "master": { + "type": "object", + "title": "Master replicas settings", + "form": true, + "properties": { + "kind": { + "type": "string", + "title": "Workload Kind", + "form": true, + "description": "Allowed values: `Deployment`, `StatefulSet` or `DaemonSet`", + "enum": ["Deployment", "StatefulSet", "DaemonSet"] + }, + "persistence": { + "type": "object", + "title": "Persistence for master replicas", + "form": true, + "properties": { + "enabled": { + "type": "boolean", + "form": true, + "title": "Enable persistence", + "description": "Enable persistence using Persistent Volume Claims" + }, + "size": { + "type": "string", + "title": "Persistent Volume Size", + "form": true, + "render": "slider", + "sliderMin": 1, + "sliderMax": 100, + "sliderUnit": "Gi", + "hidden": { + "value": false, + "path": "master/persistence/enabled" + } + } + } + } + } + }, + "replica": { + "type": "object", + "title": "Redis replicas settings", + "form": true, + "hidden": { + "value": "standalone", + "path": "architecture" + }, + "properties": { + "kind": { + "type": "string", + "title": "Workload Kind", + "form": true, + "description": "Allowed values: `DaemonSet` or `StatefulSet`", + "enum": ["DaemonSet", "StatefulSet"] + }, + "replicaCount": { + "type": "integer", + "form": true, + "title": "Number of Redis replicas" + }, + "persistence": { + "type": "object", + "title": "Persistence for Redis replicas", + "form": true, + "properties": { + "enabled": { + "type": "boolean", + "form": true, + "title": "Enable persistence", + "description": "Enable persistence using Persistent Volume Claims" + }, + "size": { + "type": "string", + "title": "Persistent Volume Size", + "form": true, + "render": "slider", + "sliderMin": 1, + "sliderMax": 100, + "sliderUnit": "Gi", + "hidden": { + "value": false, + "path": "replica/persistence/enabled" + } + } + } + } + } + }, + "volumePermissions": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "form": true, + "title": "Enable Init Containers", + "description": "Use an init container to set required folder permissions on the data volume before mounting it in the final destination" + } + } + }, + "metrics": { + "type": "object", + "form": true, + "title": "Prometheus metrics details", + "properties": { + "enabled": { + "type": "boolean", + "title": "Create Prometheus metrics exporter", + "description": "Create a side-car container to expose Prometheus metrics", + "form": true + }, + "serviceMonitor": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "title": "Create Prometheus Operator ServiceMonitor", + "description": "Create a ServiceMonitor to track metrics using Prometheus Operator", + "form": true, + "hidden": { + "value": false, + "path": "metrics/enabled" + } + } + } + } + } + } + } +} diff --git a/packages/system/dashboard/charts/kubeapps/charts/redis/values.yaml b/packages/system/dashboard/charts/kubeapps/charts/redis/values.yaml new file mode 100644 index 00000000..f2d53313 --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/charts/redis/values.yaml @@ -0,0 +1,1939 @@ +# Copyright VMware, Inc. +# SPDX-License-Identifier: APACHE-2.0 + +## @section Global parameters +## Global Docker image parameters +## Please, note that this will override the image parameters, including dependencies, configured to use the global value +## Current available global Docker image parameters: imageRegistry, imagePullSecrets and storageClass +## + +## @param global.imageRegistry Global Docker image registry +## @param global.imagePullSecrets Global Docker registry secret names as an array +## @param global.storageClass Global StorageClass for Persistent Volume(s) +## @param global.redis.password Global Redis® password (overrides `auth.password`) +## +global: + imageRegistry: "" + ## E.g. + ## imagePullSecrets: + ## - myRegistryKeySecretName + ## + imagePullSecrets: [] + storageClass: "" + redis: + password: "" + +## @section Common parameters +## + +## @param kubeVersion Override Kubernetes version +## +kubeVersion: "" +## @param nameOverride String to partially override common.names.fullname +## +nameOverride: "" +## @param fullnameOverride String to fully override common.names.fullname +## +fullnameOverride: "" +## @param commonLabels Labels to add to all deployed objects +## +commonLabels: {} +## @param commonAnnotations Annotations to add to all deployed objects +## +commonAnnotations: {} +## @param secretAnnotations Annotations to add to secret +## +secretAnnotations: {} +## @param clusterDomain Kubernetes cluster domain name +## +clusterDomain: cluster.local +## @param extraDeploy Array of extra objects to deploy with the release +## +extraDeploy: [] +## @param useHostnames Use hostnames internally when announcing replication. If false, the hostname will be resolved to an IP address +## +useHostnames: true +## @param nameResolutionThreshold Failure threshold for internal hostnames resolution +## +nameResolutionThreshold: 5 +## @param nameResolutionTimeout Timeout seconds between probes for internal hostnames resolution +## +nameResolutionTimeout: 5 + +## Enable diagnostic mode in the deployment +## +diagnosticMode: + ## @param diagnosticMode.enabled Enable diagnostic mode (all probes will be disabled and the command will be overridden) + ## + enabled: false + ## @param diagnosticMode.command Command to override all containers in the deployment + ## + command: + - sleep + ## @param diagnosticMode.args Args to override all containers in the deployment + ## + args: + - infinity + +## @section Redis® Image parameters +## + +## Bitnami Redis® image +## ref: https://hub.docker.com/r/bitnami/redis/tags/ +## @param image.registry [default: REGISTRY_NAME] Redis® image registry +## @param image.repository [default: REPOSITORY_NAME/redis] Redis® image repository +## @skip image.tag Redis® image tag (immutable tags are recommended) +## @param image.digest Redis® image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag +## @param image.pullPolicy Redis® image pull policy +## @param image.pullSecrets Redis® image pull secrets +## @param image.debug Enable image debug mode +## +image: + registry: docker.io + repository: bitnami/redis + tag: 7.2.3-debian-11-r1 + digest: "" + ## Specify a imagePullPolicy + ## Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent' + ## ref: https://kubernetes.io/docs/user-guide/images/#pre-pulling-images + ## + pullPolicy: IfNotPresent + ## Optionally specify an array of imagePullSecrets. + ## Secrets must be manually created in the namespace. + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ + ## e.g: + ## pullSecrets: + ## - myRegistryKeySecretName + ## + pullSecrets: [] + ## Enable debug mode + ## + debug: false + +## @section Redis® common configuration parameters +## https://github.com/bitnami/containers/tree/main/bitnami/redis#configuration +## + +## @param architecture Redis® architecture. Allowed values: `standalone` or `replication` +## +architecture: replication +## Redis® Authentication parameters +## ref: https://github.com/bitnami/containers/tree/main/bitnami/redis#setting-the-server-password-on-first-run +## +auth: + ## @param auth.enabled Enable password authentication + ## + enabled: true + ## @param auth.sentinel Enable password authentication on sentinels too + ## + sentinel: true + ## @param auth.password Redis® password + ## Defaults to a random 10-character alphanumeric string if not set + ## + password: "" + ## @param auth.existingSecret The name of an existing secret with Redis® credentials + ## NOTE: When it's set, the previous `auth.password` parameter is ignored + ## + existingSecret: "" + ## @param auth.existingSecretPasswordKey Password key to be retrieved from existing secret + ## NOTE: ignored unless `auth.existingSecret` parameter is set + ## + existingSecretPasswordKey: "" + ## @param auth.usePasswordFiles Mount credentials as files instead of using an environment variable + ## + usePasswordFiles: false + +## @param commonConfiguration [string] Common configuration to be added into the ConfigMap +## ref: https://redis.io/topics/config +## +commonConfiguration: |- + # Enable AOF https://redis.io/topics/persistence#append-only-file + appendonly yes + # Disable RDB persistence, AOF persistence already enabled. + save "" +## @param existingConfigmap The name of an existing ConfigMap with your custom configuration for Redis® nodes +## +existingConfigmap: "" + +## @section Redis® master configuration parameters +## + +master: + ## @param master.count Number of Redis® master instances to deploy (experimental, requires additional configuration) + ## + count: 1 + ## @param master.configuration Configuration for Redis® master nodes + ## ref: https://redis.io/topics/config + ## + configuration: "" + ## @param master.disableCommands Array with Redis® commands to disable on master nodes + ## Commands will be completely disabled by renaming each to an empty string. + ## ref: https://redis.io/topics/security#disabling-of-specific-commands + ## + disableCommands: + - FLUSHDB + - FLUSHALL + ## @param master.command Override default container command (useful when using custom images) + ## + command: [] + ## @param master.args Override default container args (useful when using custom images) + ## + args: [] + ## @param master.enableServiceLinks Whether information about services should be injected into pod's environment variable + ## + enableServiceLinks: true + ## @param master.preExecCmds Additional commands to run prior to starting Redis® master + ## + preExecCmds: [] + ## @param master.extraFlags Array with additional command line flags for Redis® master + ## e.g: + ## extraFlags: + ## - "--maxmemory-policy volatile-ttl" + ## - "--repl-backlog-size 1024mb" + ## + extraFlags: [] + ## @param master.extraEnvVars Array with extra environment variables to add to Redis® master nodes + ## e.g: + ## extraEnvVars: + ## - name: FOO + ## value: "bar" + ## + extraEnvVars: [] + ## @param master.extraEnvVarsCM Name of existing ConfigMap containing extra env vars for Redis® master nodes + ## + extraEnvVarsCM: "" + ## @param master.extraEnvVarsSecret Name of existing Secret containing extra env vars for Redis® master nodes + ## + extraEnvVarsSecret: "" + ## @param master.containerPorts.redis Container port to open on Redis® master nodes + ## + containerPorts: + redis: 6379 + ## Configure extra options for Redis® containers' liveness and readiness probes + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/#configure-probes + ## @param master.startupProbe.enabled Enable startupProbe on Redis® master nodes + ## @param master.startupProbe.initialDelaySeconds Initial delay seconds for startupProbe + ## @param master.startupProbe.periodSeconds Period seconds for startupProbe + ## @param master.startupProbe.timeoutSeconds Timeout seconds for startupProbe + ## @param master.startupProbe.failureThreshold Failure threshold for startupProbe + ## @param master.startupProbe.successThreshold Success threshold for startupProbe + ## + startupProbe: + enabled: false + initialDelaySeconds: 20 + periodSeconds: 5 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 5 + ## @param master.livenessProbe.enabled Enable livenessProbe on Redis® master nodes + ## @param master.livenessProbe.initialDelaySeconds Initial delay seconds for livenessProbe + ## @param master.livenessProbe.periodSeconds Period seconds for livenessProbe + ## @param master.livenessProbe.timeoutSeconds Timeout seconds for livenessProbe + ## @param master.livenessProbe.failureThreshold Failure threshold for livenessProbe + ## @param master.livenessProbe.successThreshold Success threshold for livenessProbe + ## + livenessProbe: + enabled: true + initialDelaySeconds: 20 + periodSeconds: 5 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 5 + ## @param master.readinessProbe.enabled Enable readinessProbe on Redis® master nodes + ## @param master.readinessProbe.initialDelaySeconds Initial delay seconds for readinessProbe + ## @param master.readinessProbe.periodSeconds Period seconds for readinessProbe + ## @param master.readinessProbe.timeoutSeconds Timeout seconds for readinessProbe + ## @param master.readinessProbe.failureThreshold Failure threshold for readinessProbe + ## @param master.readinessProbe.successThreshold Success threshold for readinessProbe + ## + readinessProbe: + enabled: true + initialDelaySeconds: 20 + periodSeconds: 5 + timeoutSeconds: 1 + successThreshold: 1 + failureThreshold: 5 + ## @param master.customStartupProbe Custom startupProbe that overrides the default one + ## + customStartupProbe: {} + ## @param master.customLivenessProbe Custom livenessProbe that overrides the default one + ## + customLivenessProbe: {} + ## @param master.customReadinessProbe Custom readinessProbe that overrides the default one + ## + customReadinessProbe: {} + ## Redis® master resource requests and limits + ## ref: https://kubernetes.io/docs/user-guide/compute-resources/ + ## @param master.resources.limits The resources limits for the Redis® master containers + ## @param master.resources.requests The requested resources for the Redis® master containers + ## + resources: + limits: {} + requests: {} + ## Configure Pods Security Context + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod + ## @param master.podSecurityContext.enabled Enabled Redis® master pods' Security Context + ## @param master.podSecurityContext.fsGroup Set Redis® master pod's Security Context fsGroup + ## + podSecurityContext: + enabled: true + fsGroup: 1001 + ## Configure Container Security Context + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod + ## @param master.containerSecurityContext.enabled Enabled Redis® master containers' Security Context + ## @param master.containerSecurityContext.runAsUser Set Redis® master containers' Security Context runAsUser + ## @param master.containerSecurityContext.runAsGroup Set Redis® master containers' Security Context runAsGroup + ## @param master.containerSecurityContext.runAsNonRoot Set Redis® master containers' Security Context runAsNonRoot + ## @param master.containerSecurityContext.allowPrivilegeEscalation Is it possible to escalate Redis® pod(s) privileges + ## @param master.containerSecurityContext.seccompProfile.type Set Redis® master containers' Security Context seccompProfile + ## @param master.containerSecurityContext.capabilities.drop Set Redis® master containers' Security Context capabilities to drop + ## + containerSecurityContext: + enabled: true + runAsUser: 1001 + runAsGroup: 0 + runAsNonRoot: true + allowPrivilegeEscalation: false + seccompProfile: + type: RuntimeDefault + capabilities: + drop: + - ALL + ## @param master.kind Use either Deployment, StatefulSet (default) or DaemonSet + ## ref: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/ + ## + kind: StatefulSet + ## @param master.schedulerName Alternate scheduler for Redis® master pods + ## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ + ## + schedulerName: "" + ## @param master.updateStrategy.type Redis® master statefulset strategy type + ## @skip master.updateStrategy.rollingUpdate + ## ref: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#update-strategies + ## + updateStrategy: + ## StrategyType + ## Can be set to RollingUpdate, OnDelete (statefulset), Recreate (deployment) + ## + type: RollingUpdate + ## @param master.minReadySeconds How many seconds a pod needs to be ready before killing the next, during update + ## + minReadySeconds: 0 + ## @param master.priorityClassName Redis® master pods' priorityClassName + ## + priorityClassName: "" + ## @param master.hostAliases Redis® master pods host aliases + ## https://kubernetes.io/docs/concepts/services-networking/add-entries-to-pod-etc-hosts-with-host-aliases/ + ## + hostAliases: [] + ## @param master.podLabels Extra labels for Redis® master pods + ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ + ## + podLabels: {} + ## @param master.podAnnotations Annotations for Redis® master pods + ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ + ## + podAnnotations: {} + ## @param master.shareProcessNamespace Share a single process namespace between all of the containers in Redis® master pods + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/share-process-namespace/ + ## + shareProcessNamespace: false + ## @param master.podAffinityPreset Pod affinity preset. Ignored if `master.affinity` is set. Allowed values: `soft` or `hard` + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity + ## + podAffinityPreset: "" + ## @param master.podAntiAffinityPreset Pod anti-affinity preset. Ignored if `master.affinity` is set. Allowed values: `soft` or `hard` + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity + ## + podAntiAffinityPreset: soft + ## Node master.affinity preset + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#node-affinity + ## + nodeAffinityPreset: + ## @param master.nodeAffinityPreset.type Node affinity preset type. Ignored if `master.affinity` is set. Allowed values: `soft` or `hard` + ## + type: "" + ## @param master.nodeAffinityPreset.key Node label key to match. Ignored if `master.affinity` is set + ## + key: "" + ## @param master.nodeAffinityPreset.values Node label values to match. Ignored if `master.affinity` is set + ## E.g. + ## values: + ## - e2e-az1 + ## - e2e-az2 + ## + values: [] + ## @param master.affinity Affinity for Redis® master pods assignment + ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity + ## NOTE: `master.podAffinityPreset`, `master.podAntiAffinityPreset`, and `master.nodeAffinityPreset` will be ignored when it's set + ## + affinity: {} + ## @param master.nodeSelector Node labels for Redis® master pods assignment + ## ref: https://kubernetes.io/docs/user-guide/node-selection/ + ## + nodeSelector: {} + ## @param master.tolerations Tolerations for Redis® master pods assignment + ## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ + ## + tolerations: [] + ## @param master.topologySpreadConstraints Spread Constraints for Redis® master pod assignment + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/ + ## E.g. + ## topologySpreadConstraints: + ## - maxSkew: 1 + ## topologyKey: node + ## whenUnsatisfiable: DoNotSchedule + ## + topologySpreadConstraints: [] + ## @param master.dnsPolicy DNS Policy for Redis® master pod + ## ref: https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/ + ## E.g. + ## dnsPolicy: ClusterFirst + ## + dnsPolicy: "" + ## @param master.dnsConfig DNS Configuration for Redis® master pod + ## ref: https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/ + ## E.g. + ## dnsConfig: + ## options: + ## - name: ndots + ## value: "4" + ## - name: single-request-reopen + ## + dnsConfig: {} + ## @param master.lifecycleHooks for the Redis® master container(s) to automate configuration before or after startup + ## + lifecycleHooks: {} + ## @param master.extraVolumes Optionally specify extra list of additional volumes for the Redis® master pod(s) + ## + extraVolumes: [] + ## @param master.extraVolumeMounts Optionally specify extra list of additional volumeMounts for the Redis® master container(s) + ## + extraVolumeMounts: [] + ## @param master.sidecars Add additional sidecar containers to the Redis® master pod(s) + ## e.g: + ## sidecars: + ## - name: your-image-name + ## image: your-image + ## imagePullPolicy: Always + ## ports: + ## - name: portname + ## containerPort: 1234 + ## + sidecars: [] + ## @param master.initContainers Add additional init containers to the Redis® master pod(s) + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/init-containers/ + ## e.g: + ## initContainers: + ## - name: your-image-name + ## image: your-image + ## imagePullPolicy: Always + ## command: ['sh', '-c', 'echo "hello world"'] + ## + initContainers: [] + ## Persistence parameters + ## ref: https://kubernetes.io/docs/user-guide/persistent-volumes/ + ## + persistence: + ## @param master.persistence.enabled Enable persistence on Redis® master nodes using Persistent Volume Claims + ## + enabled: true + ## @param master.persistence.medium Provide a medium for `emptyDir` volumes. + ## + medium: "" + ## @param master.persistence.sizeLimit Set this to enable a size limit for `emptyDir` volumes. + ## + sizeLimit: "" + ## @param master.persistence.path The path the volume will be mounted at on Redis® master containers + ## NOTE: Useful when using different Redis® images + ## + path: /data + ## @param master.persistence.subPath The subdirectory of the volume to mount on Redis® master containers + ## NOTE: Useful in dev environments + ## + subPath: "" + ## @param master.persistence.subPathExpr Used to construct the subPath subdirectory of the volume to mount on Redis® master containers + ## + subPathExpr: "" + ## @param master.persistence.storageClass Persistent Volume storage class + ## If defined, storageClassName: + ## If set to "-", storageClassName: "", which disables dynamic provisioning + ## If undefined (the default) or set to null, no storageClassName spec is set, choosing the default provisioner + ## + storageClass: "" + ## @param master.persistence.accessModes Persistent Volume access modes + ## + accessModes: + - ReadWriteOnce + ## @param master.persistence.size Persistent Volume size + ## + size: 8Gi + ## @param master.persistence.annotations Additional custom annotations for the PVC + ## + annotations: {} + ## @param master.persistence.labels Additional custom labels for the PVC + ## + labels: {} + ## @param master.persistence.selector Additional labels to match for the PVC + ## e.g: + ## selector: + ## matchLabels: + ## app: my-app + ## + selector: {} + ## @param master.persistence.dataSource Custom PVC data source + ## + dataSource: {} + ## @param master.persistence.existingClaim Use a existing PVC which must be created manually before bound + ## NOTE: requires master.persistence.enabled: true + ## + existingClaim: "" + ## persistentVolumeClaimRetentionPolicy + ## ref: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#persistentvolumeclaim-retention + ## @param master.persistentVolumeClaimRetentionPolicy.enabled Controls if and how PVCs are deleted during the lifecycle of a StatefulSet + ## @param master.persistentVolumeClaimRetentionPolicy.whenScaled Volume retention behavior when the replica count of the StatefulSet is reduced + ## @param master.persistentVolumeClaimRetentionPolicy.whenDeleted Volume retention behavior that applies when the StatefulSet is deleted + ## + persistentVolumeClaimRetentionPolicy: + enabled: false + whenScaled: Retain + whenDeleted: Retain + ## Redis® master service parameters + ## + service: + ## @param master.service.type Redis® master service type + ## + type: ClusterIP + ## @param master.service.ports.redis Redis® master service port + ## + ports: + redis: 6379 + ## @param master.service.nodePorts.redis Node port for Redis® master + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport + ## NOTE: choose port between <30000-32767> + ## + nodePorts: + redis: "" + ## @param master.service.externalTrafficPolicy Redis® master service external traffic policy + ## ref: https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip + ## + externalTrafficPolicy: Cluster + ## @param master.service.extraPorts Extra ports to expose (normally used with the `sidecar` value) + ## + extraPorts: [] + ## @param master.service.internalTrafficPolicy Redis® master service internal traffic policy (requires Kubernetes v1.22 or greater to be usable) + ## ref: https://kubernetes.io/docs/concepts/services-networking/service-traffic-policy/ + ## + internalTrafficPolicy: Cluster + ## @param master.service.clusterIP Redis® master service Cluster IP + ## + clusterIP: "" + ## @param master.service.loadBalancerIP Redis® master service Load Balancer IP + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#internal-load-balancer + ## + loadBalancerIP: "" + ## @param master.service.loadBalancerSourceRanges Redis® master service Load Balancer sources + ## https://kubernetes.io/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/#restrict-access-for-loadbalancer-service + ## e.g. + ## loadBalancerSourceRanges: + ## - 10.10.10.0/24 + ## + loadBalancerSourceRanges: [] + ## @param master.service.externalIPs Redis® master service External IPs + ## https://kubernetes.io/docs/concepts/services-networking/service/#external-ips + ## e.g. + ## externalIPs: + ## - 10.10.10.1 + ## - 201.22.30.1 + ## + externalIPs: [] + ## @param master.service.annotations Additional custom annotations for Redis® master service + ## + annotations: {} + ## @param master.service.sessionAffinity Session Affinity for Kubernetes service, can be "None" or "ClientIP" + ## If "ClientIP", consecutive client requests will be directed to the same Pod + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#virtual-ips-and-service-proxies + ## + sessionAffinity: None + ## @param master.service.sessionAffinityConfig Additional settings for the sessionAffinity + ## sessionAffinityConfig: + ## clientIP: + ## timeoutSeconds: 300 + ## + sessionAffinityConfig: {} + ## @param master.terminationGracePeriodSeconds Integer setting the termination grace period for the redis-master pods + ## + terminationGracePeriodSeconds: 30 + ## ServiceAccount configuration + ## + serviceAccount: + ## @param master.serviceAccount.create Specifies whether a ServiceAccount should be created + ## + create: false + ## @param master.serviceAccount.name The name of the ServiceAccount to use. + ## If not set and create is true, a name is generated using the common.names.fullname template + ## + name: "" + ## @param master.serviceAccount.automountServiceAccountToken Whether to auto mount the service account token + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#use-the-default-service-account-to-access-the-api-server + ## + automountServiceAccountToken: true + ## @param master.serviceAccount.annotations Additional custom annotations for the ServiceAccount + ## + annotations: {} + +## @section Redis® replicas configuration parameters +## + +replica: + ## @param replica.kind Use either DaemonSet or StatefulSet (default) + ## ref: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/ + ## + kind: StatefulSet + ## @param replica.replicaCount Number of Redis® replicas to deploy + ## + replicaCount: 3 + ## @param replica.configuration Configuration for Redis® replicas nodes + ## ref: https://redis.io/topics/config + ## + configuration: "" + ## @param replica.disableCommands Array with Redis® commands to disable on replicas nodes + ## Commands will be completely disabled by renaming each to an empty string. + ## ref: https://redis.io/topics/security#disabling-of-specific-commands + ## + disableCommands: + - FLUSHDB + - FLUSHALL + ## @param replica.command Override default container command (useful when using custom images) + ## + command: [] + ## @param replica.args Override default container args (useful when using custom images) + ## + args: [] + ## @param replica.enableServiceLinks Whether information about services should be injected into pod's environment variable + ## + enableServiceLinks: true + ## @param replica.preExecCmds Additional commands to run prior to starting Redis® replicas + ## + preExecCmds: [] + ## @param replica.extraFlags Array with additional command line flags for Redis® replicas + ## e.g: + ## extraFlags: + ## - "--maxmemory-policy volatile-ttl" + ## - "--repl-backlog-size 1024mb" + ## + extraFlags: [] + ## @param replica.extraEnvVars Array with extra environment variables to add to Redis® replicas nodes + ## e.g: + ## extraEnvVars: + ## - name: FOO + ## value: "bar" + ## + extraEnvVars: [] + ## @param replica.extraEnvVarsCM Name of existing ConfigMap containing extra env vars for Redis® replicas nodes + ## + extraEnvVarsCM: "" + ## @param replica.extraEnvVarsSecret Name of existing Secret containing extra env vars for Redis® replicas nodes + ## + extraEnvVarsSecret: "" + ## @param replica.externalMaster.enabled Use external master for bootstrapping + ## @param replica.externalMaster.host External master host to bootstrap from + ## @param replica.externalMaster.port Port for Redis service external master host + ## + externalMaster: + enabled: false + host: "" + port: 6379 + ## @param replica.containerPorts.redis Container port to open on Redis® replicas nodes + ## + containerPorts: + redis: 6379 + ## Configure extra options for Redis® containers' liveness and readiness probes + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/#configure-probes + ## @param replica.startupProbe.enabled Enable startupProbe on Redis® replicas nodes + ## @param replica.startupProbe.initialDelaySeconds Initial delay seconds for startupProbe + ## @param replica.startupProbe.periodSeconds Period seconds for startupProbe + ## @param replica.startupProbe.timeoutSeconds Timeout seconds for startupProbe + ## @param replica.startupProbe.failureThreshold Failure threshold for startupProbe + ## @param replica.startupProbe.successThreshold Success threshold for startupProbe + ## + startupProbe: + enabled: true + initialDelaySeconds: 10 + periodSeconds: 10 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 22 + ## @param replica.livenessProbe.enabled Enable livenessProbe on Redis® replicas nodes + ## @param replica.livenessProbe.initialDelaySeconds Initial delay seconds for livenessProbe + ## @param replica.livenessProbe.periodSeconds Period seconds for livenessProbe + ## @param replica.livenessProbe.timeoutSeconds Timeout seconds for livenessProbe + ## @param replica.livenessProbe.failureThreshold Failure threshold for livenessProbe + ## @param replica.livenessProbe.successThreshold Success threshold for livenessProbe + ## + livenessProbe: + enabled: true + initialDelaySeconds: 20 + periodSeconds: 5 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 5 + ## @param replica.readinessProbe.enabled Enable readinessProbe on Redis® replicas nodes + ## @param replica.readinessProbe.initialDelaySeconds Initial delay seconds for readinessProbe + ## @param replica.readinessProbe.periodSeconds Period seconds for readinessProbe + ## @param replica.readinessProbe.timeoutSeconds Timeout seconds for readinessProbe + ## @param replica.readinessProbe.failureThreshold Failure threshold for readinessProbe + ## @param replica.readinessProbe.successThreshold Success threshold for readinessProbe + ## + readinessProbe: + enabled: true + initialDelaySeconds: 20 + periodSeconds: 5 + timeoutSeconds: 1 + successThreshold: 1 + failureThreshold: 5 + ## @param replica.customStartupProbe Custom startupProbe that overrides the default one + ## + customStartupProbe: {} + ## @param replica.customLivenessProbe Custom livenessProbe that overrides the default one + ## + customLivenessProbe: {} + ## @param replica.customReadinessProbe Custom readinessProbe that overrides the default one + ## + customReadinessProbe: {} + ## Redis® replicas resource requests and limits + ## ref: https://kubernetes.io/docs/user-guide/compute-resources/ + ## @param replica.resources.limits The resources limits for the Redis® replicas containers + ## @param replica.resources.requests The requested resources for the Redis® replicas containers + ## + resources: + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + limits: {} + # cpu: 250m + # memory: 256Mi + requests: {} + # cpu: 250m + # memory: 256Mi + ## Configure Pods Security Context + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod + ## @param replica.podSecurityContext.enabled Enabled Redis® replicas pods' Security Context + ## @param replica.podSecurityContext.fsGroup Set Redis® replicas pod's Security Context fsGroup + ## + podSecurityContext: + enabled: true + fsGroup: 1001 + ## Configure Container Security Context + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod + ## @param replica.containerSecurityContext.enabled Enabled Redis® replicas containers' Security Context + ## @param replica.containerSecurityContext.runAsUser Set Redis® replicas containers' Security Context runAsUser + ## @param replica.containerSecurityContext.runAsGroup Set Redis® replicas containers' Security Context runAsGroup + ## @param replica.containerSecurityContext.runAsNonRoot Set Redis® replicas containers' Security Context runAsNonRoot + ## @param replica.containerSecurityContext.allowPrivilegeEscalation Set Redis® replicas pod's Security Context allowPrivilegeEscalation + ## @param replica.containerSecurityContext.seccompProfile.type Set Redis® replicas containers' Security Context seccompProfile + ## @param replica.containerSecurityContext.capabilities.drop Set Redis® replicas containers' Security Context capabilities to drop + ## + containerSecurityContext: + enabled: true + runAsUser: 1001 + runAsGroup: 0 + runAsNonRoot: true + allowPrivilegeEscalation: false + seccompProfile: + type: RuntimeDefault + capabilities: + drop: + - ALL + ## @param replica.schedulerName Alternate scheduler for Redis® replicas pods + ## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ + ## + schedulerName: "" + ## @param replica.updateStrategy.type Redis® replicas statefulset strategy type + ## @skip replica.updateStrategy.rollingUpdate + ## ref: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#update-strategies + ## + updateStrategy: + ## StrategyType + ## Can be set to RollingUpdate, OnDelete (statefulset), Recreate (deployment) + ## + type: RollingUpdate + ## @param replica.minReadySeconds How many seconds a pod needs to be ready before killing the next, during update + ## + minReadySeconds: 0 + ## @param replica.priorityClassName Redis® replicas pods' priorityClassName + ## + priorityClassName: "" + ## @param replica.podManagementPolicy podManagementPolicy to manage scaling operation of %%MAIN_CONTAINER_NAME%% pods + ## ref: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#pod-management-policies + ## + podManagementPolicy: "" + ## @param replica.hostAliases Redis® replicas pods host aliases + ## https://kubernetes.io/docs/concepts/services-networking/add-entries-to-pod-etc-hosts-with-host-aliases/ + ## + hostAliases: [] + ## @param replica.podLabels Extra labels for Redis® replicas pods + ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ + ## + podLabels: {} + ## @param replica.podAnnotations Annotations for Redis® replicas pods + ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ + ## + podAnnotations: {} + ## @param replica.shareProcessNamespace Share a single process namespace between all of the containers in Redis® replicas pods + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/share-process-namespace/ + ## + shareProcessNamespace: false + ## @param replica.podAffinityPreset Pod affinity preset. Ignored if `replica.affinity` is set. Allowed values: `soft` or `hard` + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity + ## + podAffinityPreset: "" + ## @param replica.podAntiAffinityPreset Pod anti-affinity preset. Ignored if `replica.affinity` is set. Allowed values: `soft` or `hard` + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity + ## + podAntiAffinityPreset: soft + ## Node affinity preset + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#node-affinity + ## + nodeAffinityPreset: + ## @param replica.nodeAffinityPreset.type Node affinity preset type. Ignored if `replica.affinity` is set. Allowed values: `soft` or `hard` + ## + type: "" + ## @param replica.nodeAffinityPreset.key Node label key to match. Ignored if `replica.affinity` is set + ## + key: "" + ## @param replica.nodeAffinityPreset.values Node label values to match. Ignored if `replica.affinity` is set + ## E.g. + ## values: + ## - e2e-az1 + ## - e2e-az2 + ## + values: [] + ## @param replica.affinity Affinity for Redis® replicas pods assignment + ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity + ## NOTE: `replica.podAffinityPreset`, `replica.podAntiAffinityPreset`, and `replica.nodeAffinityPreset` will be ignored when it's set + ## + affinity: {} + ## @param replica.nodeSelector Node labels for Redis® replicas pods assignment + ## ref: https://kubernetes.io/docs/user-guide/node-selection/ + ## + nodeSelector: {} + ## @param replica.tolerations Tolerations for Redis® replicas pods assignment + ## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ + ## + tolerations: [] + ## @param replica.topologySpreadConstraints Spread Constraints for Redis® replicas pod assignment + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/ + ## E.g. + ## topologySpreadConstraints: + ## - maxSkew: 1 + ## topologyKey: node + ## whenUnsatisfiable: DoNotSchedule + ## + topologySpreadConstraints: [] + ## @param replica.dnsPolicy DNS Policy for Redis® replica pods + ## ref: https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/ + ## E.g. + ## dnsPolicy: ClusterFirst + ## + dnsPolicy: "" + ## @param replica.dnsConfig DNS Configuration for Redis® replica pods + ## ref: https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/ + ## E.g. + ## dnsConfig: + ## options: + ## - name: ndots + ## value: "4" + ## - name: single-request-reopen + ## + dnsConfig: {} + ## @param replica.lifecycleHooks for the Redis® replica container(s) to automate configuration before or after startup + ## + lifecycleHooks: {} + ## @param replica.extraVolumes Optionally specify extra list of additional volumes for the Redis® replicas pod(s) + ## + extraVolumes: [] + ## @param replica.extraVolumeMounts Optionally specify extra list of additional volumeMounts for the Redis® replicas container(s) + ## + extraVolumeMounts: [] + ## @param replica.sidecars Add additional sidecar containers to the Redis® replicas pod(s) + ## e.g: + ## sidecars: + ## - name: your-image-name + ## image: your-image + ## imagePullPolicy: Always + ## ports: + ## - name: portname + ## containerPort: 1234 + ## + sidecars: [] + ## @param replica.initContainers Add additional init containers to the Redis® replicas pod(s) + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/init-containers/ + ## e.g: + ## initContainers: + ## - name: your-image-name + ## image: your-image + ## imagePullPolicy: Always + ## command: ['sh', '-c', 'echo "hello world"'] + ## + initContainers: [] + ## Persistence Parameters + ## ref: https://kubernetes.io/docs/user-guide/persistent-volumes/ + ## + persistence: + ## @param replica.persistence.enabled Enable persistence on Redis® replicas nodes using Persistent Volume Claims + ## + enabled: true + ## @param replica.persistence.medium Provide a medium for `emptyDir` volumes. + ## + medium: "" + ## @param replica.persistence.sizeLimit Set this to enable a size limit for `emptyDir` volumes. + ## + sizeLimit: "" + ## @param replica.persistence.path The path the volume will be mounted at on Redis® replicas containers + ## NOTE: Useful when using different Redis® images + ## + path: /data + ## @param replica.persistence.subPath The subdirectory of the volume to mount on Redis® replicas containers + ## NOTE: Useful in dev environments + ## + subPath: "" + ## @param replica.persistence.subPathExpr Used to construct the subPath subdirectory of the volume to mount on Redis® replicas containers + ## + subPathExpr: "" + ## @param replica.persistence.storageClass Persistent Volume storage class + ## If defined, storageClassName: + ## If set to "-", storageClassName: "", which disables dynamic provisioning + ## If undefined (the default) or set to null, no storageClassName spec is set, choosing the default provisioner + ## + storageClass: "" + ## @param replica.persistence.accessModes Persistent Volume access modes + ## + accessModes: + - ReadWriteOnce + ## @param replica.persistence.size Persistent Volume size + ## + size: 8Gi + ## @param replica.persistence.annotations Additional custom annotations for the PVC + ## + annotations: {} + ## @param replica.persistence.labels Additional custom labels for the PVC + ## + labels: {} + ## @param replica.persistence.selector Additional labels to match for the PVC + ## e.g: + ## selector: + ## matchLabels: + ## app: my-app + ## + selector: {} + ## @param replica.persistence.dataSource Custom PVC data source + ## + dataSource: {} + ## @param replica.persistence.existingClaim Use a existing PVC which must be created manually before bound + ## NOTE: requires replica.persistence.enabled: true + ## + existingClaim: "" + ## persistentVolumeClaimRetentionPolicy + ## ref: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#persistentvolumeclaim-retention + ## @param replica.persistentVolumeClaimRetentionPolicy.enabled Controls if and how PVCs are deleted during the lifecycle of a StatefulSet + ## @param replica.persistentVolumeClaimRetentionPolicy.whenScaled Volume retention behavior when the replica count of the StatefulSet is reduced + ## @param replica.persistentVolumeClaimRetentionPolicy.whenDeleted Volume retention behavior that applies when the StatefulSet is deleted + ## + persistentVolumeClaimRetentionPolicy: + enabled: false + whenScaled: Retain + whenDeleted: Retain + ## Redis® replicas service parameters + ## + service: + ## @param replica.service.type Redis® replicas service type + ## + type: ClusterIP + ## @param replica.service.ports.redis Redis® replicas service port + ## + ports: + redis: 6379 + ## @param replica.service.nodePorts.redis Node port for Redis® replicas + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport + ## NOTE: choose port between <30000-32767> + ## + nodePorts: + redis: "" + ## @param replica.service.externalTrafficPolicy Redis® replicas service external traffic policy + ## ref: https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip + ## + externalTrafficPolicy: Cluster + ## @param replica.service.internalTrafficPolicy Redis® replicas service internal traffic policy (requires Kubernetes v1.22 or greater to be usable) + ## ref: https://kubernetes.io/docs/concepts/services-networking/service-traffic-policy/ + ## + internalTrafficPolicy: Cluster + ## @param replica.service.extraPorts Extra ports to expose (normally used with the `sidecar` value) + ## + extraPorts: [] + ## @param replica.service.clusterIP Redis® replicas service Cluster IP + ## + clusterIP: "" + ## @param replica.service.loadBalancerIP Redis® replicas service Load Balancer IP + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#internal-load-balancer + ## + loadBalancerIP: "" + ## @param replica.service.loadBalancerSourceRanges Redis® replicas service Load Balancer sources + ## https://kubernetes.io/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/#restrict-access-for-loadbalancer-service + ## e.g. + ## loadBalancerSourceRanges: + ## - 10.10.10.0/24 + ## + loadBalancerSourceRanges: [] + ## @param replica.service.annotations Additional custom annotations for Redis® replicas service + ## + annotations: {} + ## @param replica.service.sessionAffinity Session Affinity for Kubernetes service, can be "None" or "ClientIP" + ## If "ClientIP", consecutive client requests will be directed to the same Pod + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#virtual-ips-and-service-proxies + ## + sessionAffinity: None + ## @param replica.service.sessionAffinityConfig Additional settings for the sessionAffinity + ## sessionAffinityConfig: + ## clientIP: + ## timeoutSeconds: 300 + ## + sessionAffinityConfig: {} + ## @param replica.terminationGracePeriodSeconds Integer setting the termination grace period for the redis-replicas pods + ## + terminationGracePeriodSeconds: 30 + ## Autoscaling configuration + ## + autoscaling: + ## @param replica.autoscaling.enabled Enable replica autoscaling settings + ## + enabled: false + ## @param replica.autoscaling.minReplicas Minimum replicas for the pod autoscaling + ## + minReplicas: 1 + ## @param replica.autoscaling.maxReplicas Maximum replicas for the pod autoscaling + ## + maxReplicas: 11 + ## @param replica.autoscaling.targetCPU Percentage of CPU to consider when autoscaling + ## + targetCPU: "" + ## @param replica.autoscaling.targetMemory Percentage of Memory to consider when autoscaling + ## + targetMemory: "" + ## ServiceAccount configuration + ## + serviceAccount: + ## @param replica.serviceAccount.create Specifies whether a ServiceAccount should be created + ## + create: false + ## @param replica.serviceAccount.name The name of the ServiceAccount to use. + ## If not set and create is true, a name is generated using the common.names.fullname template + ## + name: "" + ## @param replica.serviceAccount.automountServiceAccountToken Whether to auto mount the service account token + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#use-the-default-service-account-to-access-the-api-server + ## + automountServiceAccountToken: true + ## @param replica.serviceAccount.annotations Additional custom annotations for the ServiceAccount + ## + annotations: {} +## @section Redis® Sentinel configuration parameters +## + +sentinel: + ## @param sentinel.enabled Use Redis® Sentinel on Redis® pods. + ## IMPORTANT: this will disable the master and replicas services and + ## create a single Redis® service exposing both the Redis and Sentinel ports + ## + enabled: false + ## Bitnami Redis® Sentinel image version + ## ref: https://hub.docker.com/r/bitnami/redis-sentinel/tags/ + ## @param sentinel.image.registry [default: REGISTRY_NAME] Redis® Sentinel image registry + ## @param sentinel.image.repository [default: REPOSITORY_NAME/redis-sentinel] Redis® Sentinel image repository + ## @skip sentinel.image.tag Redis® Sentinel image tag (immutable tags are recommended) + ## @param sentinel.image.digest Redis® Sentinel image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag + ## @param sentinel.image.pullPolicy Redis® Sentinel image pull policy + ## @param sentinel.image.pullSecrets Redis® Sentinel image pull secrets + ## @param sentinel.image.debug Enable image debug mode + ## + image: + registry: docker.io + repository: bitnami/redis-sentinel + tag: 7.2.3-debian-11-r1 + digest: "" + ## Specify a imagePullPolicy + ## Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent' + ## ref: https://kubernetes.io/docs/user-guide/images/#pre-pulling-images + ## + pullPolicy: IfNotPresent + ## Optionally specify an array of imagePullSecrets. + ## Secrets must be manually created in the namespace. + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ + ## e.g: + ## pullSecrets: + ## - myRegistryKeySecretName + ## + pullSecrets: [] + ## Enable debug mode + ## + debug: false + ## @param sentinel.annotations Additional custom annotations for Redis® Sentinel resource + ## + annotations: {} + ## @param sentinel.masterSet Master set name + ## + masterSet: mymaster + ## @param sentinel.quorum Sentinel Quorum + ## + quorum: 2 + ## @param sentinel.getMasterTimeout Amount of time to allow before get_sentinel_master_info() times out. + ## + getMasterTimeout: 90 + ## @param sentinel.automateClusterRecovery Automate cluster recovery in cases where the last replica is not considered a good replica and Sentinel won't automatically failover to it. + ## This also prevents any new replica from starting until the last remaining replica is elected as master to guarantee that it is the one to be elected by Sentinel, and not a newly started replica with no data. + ## NOTE: This feature requires a "downAfterMilliseconds" value less or equal to 2000. + ## + automateClusterRecovery: false + ## @param sentinel.redisShutdownWaitFailover Whether the Redis® master container waits for the failover at shutdown (in addition to the Redis® Sentinel container). + ## + redisShutdownWaitFailover: true + ## Sentinel timing restrictions + ## @param sentinel.downAfterMilliseconds Timeout for detecting a Redis® node is down + ## @param sentinel.failoverTimeout Timeout for performing a election failover + ## + downAfterMilliseconds: 60000 + failoverTimeout: 180000 + ## @param sentinel.parallelSyncs Number of replicas that can be reconfigured in parallel to use the new master after a failover + ## + parallelSyncs: 1 + ## @param sentinel.configuration Configuration for Redis® Sentinel nodes + ## ref: https://redis.io/topics/sentinel + ## + configuration: "" + ## @param sentinel.command Override default container command (useful when using custom images) + ## + command: [] + ## @param sentinel.args Override default container args (useful when using custom images) + ## + args: [] + ## @param sentinel.enableServiceLinks Whether information about services should be injected into pod's environment variable + ## + enableServiceLinks: true + ## @param sentinel.preExecCmds Additional commands to run prior to starting Redis® Sentinel + ## + preExecCmds: [] + ## @param sentinel.extraEnvVars Array with extra environment variables to add to Redis® Sentinel nodes + ## e.g: + ## extraEnvVars: + ## - name: FOO + ## value: "bar" + ## + extraEnvVars: [] + ## @param sentinel.extraEnvVarsCM Name of existing ConfigMap containing extra env vars for Redis® Sentinel nodes + ## + extraEnvVarsCM: "" + ## @param sentinel.extraEnvVarsSecret Name of existing Secret containing extra env vars for Redis® Sentinel nodes + ## + extraEnvVarsSecret: "" + ## @param sentinel.externalMaster.enabled Use external master for bootstrapping + ## @param sentinel.externalMaster.host External master host to bootstrap from + ## @param sentinel.externalMaster.port Port for Redis service external master host + ## + externalMaster: + enabled: false + host: "" + port: 6379 + ## @param sentinel.containerPorts.sentinel Container port to open on Redis® Sentinel nodes + ## + containerPorts: + sentinel: 26379 + ## Configure extra options for Redis® containers' liveness and readiness probes + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/#configure-probes + ## @param sentinel.startupProbe.enabled Enable startupProbe on Redis® Sentinel nodes + ## @param sentinel.startupProbe.initialDelaySeconds Initial delay seconds for startupProbe + ## @param sentinel.startupProbe.periodSeconds Period seconds for startupProbe + ## @param sentinel.startupProbe.timeoutSeconds Timeout seconds for startupProbe + ## @param sentinel.startupProbe.failureThreshold Failure threshold for startupProbe + ## @param sentinel.startupProbe.successThreshold Success threshold for startupProbe + ## + startupProbe: + enabled: true + initialDelaySeconds: 10 + periodSeconds: 10 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 22 + ## @param sentinel.livenessProbe.enabled Enable livenessProbe on Redis® Sentinel nodes + ## @param sentinel.livenessProbe.initialDelaySeconds Initial delay seconds for livenessProbe + ## @param sentinel.livenessProbe.periodSeconds Period seconds for livenessProbe + ## @param sentinel.livenessProbe.timeoutSeconds Timeout seconds for livenessProbe + ## @param sentinel.livenessProbe.failureThreshold Failure threshold for livenessProbe + ## @param sentinel.livenessProbe.successThreshold Success threshold for livenessProbe + ## + livenessProbe: + enabled: true + initialDelaySeconds: 20 + periodSeconds: 10 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 6 + ## @param sentinel.readinessProbe.enabled Enable readinessProbe on Redis® Sentinel nodes + ## @param sentinel.readinessProbe.initialDelaySeconds Initial delay seconds for readinessProbe + ## @param sentinel.readinessProbe.periodSeconds Period seconds for readinessProbe + ## @param sentinel.readinessProbe.timeoutSeconds Timeout seconds for readinessProbe + ## @param sentinel.readinessProbe.failureThreshold Failure threshold for readinessProbe + ## @param sentinel.readinessProbe.successThreshold Success threshold for readinessProbe + ## + readinessProbe: + enabled: true + initialDelaySeconds: 20 + periodSeconds: 5 + timeoutSeconds: 1 + successThreshold: 1 + failureThreshold: 6 + ## @param sentinel.customStartupProbe Custom startupProbe that overrides the default one + ## + customStartupProbe: {} + ## @param sentinel.customLivenessProbe Custom livenessProbe that overrides the default one + ## + customLivenessProbe: {} + ## @param sentinel.customReadinessProbe Custom readinessProbe that overrides the default one + ## + customReadinessProbe: {} + ## Persistence parameters + ## ref: https://kubernetes.io/docs/user-guide/persistent-volumes/ + ## + persistence: + ## @param sentinel.persistence.enabled Enable persistence on Redis® sentinel nodes using Persistent Volume Claims (Experimental) + ## + enabled: false + ## @param sentinel.persistence.storageClass Persistent Volume storage class + ## If defined, storageClassName: + ## If set to "-", storageClassName: "", which disables dynamic provisioning + ## If undefined (the default) or set to null, no storageClassName spec is set, choosing the default provisioner + ## + storageClass: "" + ## @param sentinel.persistence.accessModes Persistent Volume access modes + ## + accessModes: + - ReadWriteOnce + ## @param sentinel.persistence.size Persistent Volume size + ## + size: 100Mi + ## @param sentinel.persistence.annotations Additional custom annotations for the PVC + ## + annotations: {} + ## @param sentinel.persistence.labels Additional custom labels for the PVC + ## + labels: {} + ## @param sentinel.persistence.selector Additional labels to match for the PVC + ## e.g: + ## selector: + ## matchLabels: + ## app: my-app + ## + selector: {} + ## @param sentinel.persistence.dataSource Custom PVC data source + ## + dataSource: {} + ## @param sentinel.persistence.medium Provide a medium for `emptyDir` volumes. + ## + medium: "" + ## @param sentinel.persistence.sizeLimit Set this to enable a size limit for `emptyDir` volumes. + ## + sizeLimit: "" + ## persistentVolumeClaimRetentionPolicy + ## ref: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#persistentvolumeclaim-retention + ## @param sentinel.persistentVolumeClaimRetentionPolicy.enabled Controls if and how PVCs are deleted during the lifecycle of a StatefulSet + ## @param sentinel.persistentVolumeClaimRetentionPolicy.whenScaled Volume retention behavior when the replica count of the StatefulSet is reduced + ## @param sentinel.persistentVolumeClaimRetentionPolicy.whenDeleted Volume retention behavior that applies when the StatefulSet is deleted + ## + persistentVolumeClaimRetentionPolicy: + enabled: false + whenScaled: Retain + whenDeleted: Retain + ## Redis® Sentinel resource requests and limits + ## ref: https://kubernetes.io/docs/user-guide/compute-resources/ + ## @param sentinel.resources.limits The resources limits for the Redis® Sentinel containers + ## @param sentinel.resources.requests The requested resources for the Redis® Sentinel containers + ## + resources: + limits: {} + requests: {} + ## Configure Container Security Context + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod + ## @param sentinel.containerSecurityContext.enabled Enabled Redis® Sentinel containers' Security Context + ## @param sentinel.containerSecurityContext.runAsUser Set Redis® Sentinel containers' Security Context runAsUser + ## @param sentinel.containerSecurityContext.runAsGroup Set Redis® Sentinel containers' Security Context runAsGroup + ## @param sentinel.containerSecurityContext.runAsNonRoot Set Redis® Sentinel containers' Security Context runAsNonRoot + ## @param sentinel.containerSecurityContext.allowPrivilegeEscalation Set Redis® Sentinel containers' Security Context allowPrivilegeEscalation + ## @param sentinel.containerSecurityContext.seccompProfile.type Set Redis® Sentinel containers' Security Context seccompProfile + ## @param sentinel.containerSecurityContext.capabilities.drop Set Redis® Sentinel containers' Security Context capabilities to drop + ## + containerSecurityContext: + enabled: true + runAsUser: 1001 + runAsGroup: 0 + runAsNonRoot: true + allowPrivilegeEscalation: false + seccompProfile: + type: RuntimeDefault + capabilities: + drop: + - ALL + ## @param sentinel.lifecycleHooks for the Redis® sentinel container(s) to automate configuration before or after startup + ## + lifecycleHooks: {} + ## @param sentinel.extraVolumes Optionally specify extra list of additional volumes for the Redis® Sentinel + ## + extraVolumes: [] + ## @param sentinel.extraVolumeMounts Optionally specify extra list of additional volumeMounts for the Redis® Sentinel container(s) + ## + extraVolumeMounts: [] + ## Redis® Sentinel service parameters + ## + service: + ## @param sentinel.service.type Redis® Sentinel service type + ## + type: ClusterIP + ## @param sentinel.service.ports.redis Redis® service port for Redis® + ## @param sentinel.service.ports.sentinel Redis® service port for Redis® Sentinel + ## + ports: + redis: 6379 + sentinel: 26379 + ## @param sentinel.service.nodePorts.redis Node port for Redis® + ## @param sentinel.service.nodePorts.sentinel Node port for Sentinel + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport + ## NOTE: choose port between <30000-32767> + ## NOTE: By leaving these values blank, they will be generated by ports-configmap + ## If setting manually, please leave at least replica.replicaCount + 1 in between sentinel.service.nodePorts.redis and sentinel.service.nodePorts.sentinel to take into account the ports that will be created while incrementing that base port + ## + nodePorts: + redis: "" + sentinel: "" + ## @param sentinel.service.externalTrafficPolicy Redis® Sentinel service external traffic policy + ## ref: https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip + ## + externalTrafficPolicy: Cluster + ## @param sentinel.service.extraPorts Extra ports to expose (normally used with the `sidecar` value) + ## + extraPorts: [] + ## @param sentinel.service.clusterIP Redis® Sentinel service Cluster IP + ## + clusterIP: "" + ## @param sentinel.service.loadBalancerIP Redis® Sentinel service Load Balancer IP + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#internal-load-balancer + ## + loadBalancerIP: "" + ## @param sentinel.service.loadBalancerSourceRanges Redis® Sentinel service Load Balancer sources + ## https://kubernetes.io/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/#restrict-access-for-loadbalancer-service + ## e.g. + ## loadBalancerSourceRanges: + ## - 10.10.10.0/24 + ## + loadBalancerSourceRanges: [] + ## @param sentinel.service.annotations Additional custom annotations for Redis® Sentinel service + ## + annotations: {} + ## @param sentinel.service.sessionAffinity Session Affinity for Kubernetes service, can be "None" or "ClientIP" + ## If "ClientIP", consecutive client requests will be directed to the same Pod + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#virtual-ips-and-service-proxies + ## + sessionAffinity: None + ## @param sentinel.service.sessionAffinityConfig Additional settings for the sessionAffinity + ## sessionAffinityConfig: + ## clientIP: + ## timeoutSeconds: 300 + ## + sessionAffinityConfig: {} + ## Headless service properties + ## + headless: + ## @param sentinel.service.headless.annotations Annotations for the headless service. + ## + annotations: {} + ## @param sentinel.terminationGracePeriodSeconds Integer setting the termination grace period for the redis-node pods + ## + terminationGracePeriodSeconds: 30 + +## @section Other Parameters +## + +## @param serviceBindings.enabled Create secret for service binding (Experimental) +## Ref: https://servicebinding.io/service-provider/ +## +serviceBindings: + enabled: false + +## Network Policy configuration +## ref: https://kubernetes.io/docs/concepts/services-networking/network-policies/ +## +networkPolicy: + ## @param networkPolicy.enabled Enable creation of NetworkPolicy resources + ## + enabled: false + ## @param networkPolicy.allowExternal Don't require client label for connections + ## When set to false, only pods with the correct client label will have network access to the ports + ## Redis® is listening on. When true, Redis® will accept connections from any source + ## (with the correct destination port). + ## + allowExternal: true + ## @param networkPolicy.extraIngress Add extra ingress rules to the NetworkPolicy + ## e.g: + ## extraIngress: + ## - ports: + ## - port: 1234 + ## from: + ## - podSelector: + ## - matchLabels: + ## - role: frontend + ## - podSelector: + ## - matchExpressions: + ## - key: role + ## operator: In + ## values: + ## - frontend + ## + extraIngress: [] + ## @param networkPolicy.extraEgress Add extra egress rules to the NetworkPolicy + ## e.g: + ## extraEgress: + ## - ports: + ## - port: 1234 + ## to: + ## - podSelector: + ## - matchLabels: + ## - role: frontend + ## - podSelector: + ## - matchExpressions: + ## - key: role + ## operator: In + ## values: + ## - frontend + ## + extraEgress: [] + ## @param networkPolicy.ingressNSMatchLabels Labels to match to allow traffic from other namespaces + ## @param networkPolicy.ingressNSPodMatchLabels Pod labels to match to allow traffic from other namespaces + ## + ingressNSMatchLabels: {} + ingressNSPodMatchLabels: {} + + metrics: + ## @param networkPolicy.metrics.allowExternal Don't require client label for connections for metrics endpoint + ## When set to false, only pods with the correct client label will have network access to the metrics port + ## + allowExternal: true + ## @param networkPolicy.metrics.ingressNSMatchLabels Labels to match to allow traffic from other namespaces to metrics endpoint + ## @param networkPolicy.metrics.ingressNSPodMatchLabels Pod labels to match to allow traffic from other namespaces to metrics endpoint + ## + ingressNSMatchLabels: {} + ingressNSPodMatchLabels: {} + +## PodSecurityPolicy configuration +## ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/ +## +podSecurityPolicy: + ## @param podSecurityPolicy.create Whether to create a PodSecurityPolicy. WARNING: PodSecurityPolicy is deprecated in Kubernetes v1.21 or later, unavailable in v1.25 or later + ## + create: false + ## @param podSecurityPolicy.enabled Enable PodSecurityPolicy's RBAC rules + ## + enabled: false +## RBAC configuration +## +rbac: + ## @param rbac.create Specifies whether RBAC resources should be created + ## + create: false + ## @param rbac.rules Custom RBAC rules to set + ## e.g: + ## rules: + ## - apiGroups: + ## - "" + ## resources: + ## - pods + ## verbs: + ## - get + ## - list + ## + rules: [] +## ServiceAccount configuration +## +serviceAccount: + ## @param serviceAccount.create Specifies whether a ServiceAccount should be created + ## + create: true + ## @param serviceAccount.name The name of the ServiceAccount to use. + ## If not set and create is true, a name is generated using the common.names.fullname template + ## + name: "" + ## @param serviceAccount.automountServiceAccountToken Whether to auto mount the service account token + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#use-the-default-service-account-to-access-the-api-server + ## + automountServiceAccountToken: true + ## @param serviceAccount.annotations Additional custom annotations for the ServiceAccount + ## + annotations: {} +## Redis® Pod Disruption Budget configuration +## ref: https://kubernetes.io/docs/tasks/run-application/configure-pdb/ +## +pdb: + ## @param pdb.create Specifies whether a PodDisruptionBudget should be created + ## + create: false + ## @param pdb.minAvailable Min number of pods that must still be available after the eviction + ## + minAvailable: 1 + ## @param pdb.maxUnavailable Max number of pods that can be unavailable after the eviction + ## + maxUnavailable: "" +## TLS configuration +## +tls: + ## @param tls.enabled Enable TLS traffic + ## + enabled: false + ## @param tls.authClients Require clients to authenticate + ## + authClients: true + ## @param tls.autoGenerated Enable autogenerated certificates + ## + autoGenerated: false + ## @param tls.existingSecret The name of the existing secret that contains the TLS certificates + ## + existingSecret: "" + ## @param tls.certificatesSecret DEPRECATED. Use existingSecret instead. + ## + certificatesSecret: "" + ## @param tls.certFilename Certificate filename + ## + certFilename: "" + ## @param tls.certKeyFilename Certificate Key filename + ## + certKeyFilename: "" + ## @param tls.certCAFilename CA Certificate filename + ## + certCAFilename: "" + ## @param tls.dhParamsFilename File containing DH params (in order to support DH based ciphers) + ## + dhParamsFilename: "" + +## @section Metrics Parameters +## + +metrics: + ## @param metrics.enabled Start a sidecar prometheus exporter to expose Redis® metrics + ## + enabled: false + ## Bitnami Redis® Exporter image + ## ref: https://hub.docker.com/r/bitnami/redis-exporter/tags/ + ## @param metrics.image.registry [default: REGISTRY_NAME] Redis® Exporter image registry + ## @param metrics.image.repository [default: REPOSITORY_NAME/redis-exporter] Redis® Exporter image repository + ## @skip metrics.image.tag Redis® Exporter image tag (immutable tags are recommended) + ## @param metrics.image.digest Redis® Exporter image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag + ## @param metrics.image.pullPolicy Redis® Exporter image pull policy + ## @param metrics.image.pullSecrets Redis® Exporter image pull secrets + ## + image: + registry: docker.io + repository: bitnami/redis-exporter + tag: 1.55.0-debian-11-r2 + digest: "" + pullPolicy: IfNotPresent + ## Optionally specify an array of imagePullSecrets. + ## Secrets must be manually created in the namespace. + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ + ## e.g: + ## pullSecrets: + ## - myRegistryKeySecretName + ## + pullSecrets: [] + ## Configure extra options for Redis® containers' liveness, readiness & startup probes + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/ + ## @param metrics.startupProbe.enabled Enable startupProbe on Redis® replicas nodes + ## @param metrics.startupProbe.initialDelaySeconds Initial delay seconds for startupProbe + ## @param metrics.startupProbe.periodSeconds Period seconds for startupProbe + ## @param metrics.startupProbe.timeoutSeconds Timeout seconds for startupProbe + ## @param metrics.startupProbe.failureThreshold Failure threshold for startupProbe + ## @param metrics.startupProbe.successThreshold Success threshold for startupProbe + ## + startupProbe: + enabled: false + initialDelaySeconds: 10 + periodSeconds: 10 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 5 + ## @param metrics.livenessProbe.enabled Enable livenessProbe on Redis® replicas nodes + ## @param metrics.livenessProbe.initialDelaySeconds Initial delay seconds for livenessProbe + ## @param metrics.livenessProbe.periodSeconds Period seconds for livenessProbe + ## @param metrics.livenessProbe.timeoutSeconds Timeout seconds for livenessProbe + ## @param metrics.livenessProbe.failureThreshold Failure threshold for livenessProbe + ## @param metrics.livenessProbe.successThreshold Success threshold for livenessProbe + ## + livenessProbe: + enabled: true + initialDelaySeconds: 10 + periodSeconds: 10 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 5 + ## @param metrics.readinessProbe.enabled Enable readinessProbe on Redis® replicas nodes + ## @param metrics.readinessProbe.initialDelaySeconds Initial delay seconds for readinessProbe + ## @param metrics.readinessProbe.periodSeconds Period seconds for readinessProbe + ## @param metrics.readinessProbe.timeoutSeconds Timeout seconds for readinessProbe + ## @param metrics.readinessProbe.failureThreshold Failure threshold for readinessProbe + ## @param metrics.readinessProbe.successThreshold Success threshold for readinessProbe + ## + readinessProbe: + enabled: true + initialDelaySeconds: 5 + periodSeconds: 10 + timeoutSeconds: 1 + successThreshold: 1 + failureThreshold: 3 + ## @param metrics.customStartupProbe Custom startupProbe that overrides the default one + ## + customStartupProbe: {} + ## @param metrics.customLivenessProbe Custom livenessProbe that overrides the default one + ## + customLivenessProbe: {} + ## @param metrics.customReadinessProbe Custom readinessProbe that overrides the default one + ## + customReadinessProbe: {} + ## @param metrics.command Override default metrics container init command (useful when using custom images) + ## + command: [] + ## @param metrics.redisTargetHost A way to specify an alternative Redis® hostname + ## Useful for certificate CN/SAN matching + ## + redisTargetHost: "localhost" + ## @param metrics.extraArgs Extra arguments for Redis® exporter, for example: + ## e.g.: + ## extraArgs: + ## check-keys: myKey,myOtherKey + ## + extraArgs: {} + ## @param metrics.extraEnvVars Array with extra environment variables to add to Redis® exporter + ## e.g: + ## extraEnvVars: + ## - name: FOO + ## value: "bar" + ## + extraEnvVars: [] + ## Configure Container Security Context + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod + ## @param metrics.containerSecurityContext.enabled Enabled Redis® exporter containers' Security Context + ## @param metrics.containerSecurityContext.runAsUser Set Redis® exporter containers' Security Context runAsUser + ## @param metrics.containerSecurityContext.runAsGroup Set Redis® exporter containers' Security Context runAsGroup + ## @param metrics.containerSecurityContext.runAsNonRoot Set Redis® exporter containers' Security Context runAsNonRoot + ## @param metrics.containerSecurityContext.allowPrivilegeEscalation Set Redis® exporter containers' Security Context allowPrivilegeEscalation + ## @param metrics.containerSecurityContext.seccompProfile.type Set Redis® exporter containers' Security Context seccompProfile + ## @param metrics.containerSecurityContext.capabilities.drop Set Redis® exporter containers' Security Context capabilities to drop + ## + containerSecurityContext: + enabled: true + runAsUser: 1001 + runAsGroup: 0 + runAsNonRoot: true + allowPrivilegeEscalation: false + seccompProfile: + type: RuntimeDefault + capabilities: + drop: + - ALL + ## @param metrics.extraVolumes Optionally specify extra list of additional volumes for the Redis® metrics sidecar + ## + extraVolumes: [] + ## @param metrics.extraVolumeMounts Optionally specify extra list of additional volumeMounts for the Redis® metrics sidecar + ## + extraVolumeMounts: [] + ## Redis® exporter resource requests and limits + ## ref: https://kubernetes.io/docs/user-guide/compute-resources/ + ## @param metrics.resources.limits The resources limits for the Redis® exporter container + ## @param metrics.resources.requests The requested resources for the Redis® exporter container + ## + resources: + limits: {} + requests: {} + ## @param metrics.podLabels Extra labels for Redis® exporter pods + ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ + ## + podLabels: {} + ## @param metrics.podAnnotations [object] Annotations for Redis® exporter pods + ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ + ## + podAnnotations: + prometheus.io/scrape: "true" + prometheus.io/port: "9121" + ## Redis® exporter service parameters + ## + service: + ## @param metrics.service.type Redis® exporter service type + ## + type: ClusterIP + ## @param metrics.service.port Redis® exporter service port + ## + port: 9121 + ## @param metrics.service.externalTrafficPolicy Redis® exporter service external traffic policy + ## ref: https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip + ## + externalTrafficPolicy: Cluster + ## @param metrics.service.extraPorts Extra ports to expose (normally used with the `sidecar` value) + ## + extraPorts: [] + ## @param metrics.service.loadBalancerIP Redis® exporter service Load Balancer IP + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#internal-load-balancer + ## + loadBalancerIP: "" + ## @param metrics.service.loadBalancerSourceRanges Redis® exporter service Load Balancer sources + ## https://kubernetes.io/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/#restrict-access-for-loadbalancer-service + ## e.g. + ## loadBalancerSourceRanges: + ## - 10.10.10.0/24 + ## + loadBalancerSourceRanges: [] + ## @param metrics.service.annotations Additional custom annotations for Redis® exporter service + ## + annotations: {} + ## @param metrics.service.clusterIP Redis® exporter service Cluster IP + ## + clusterIP: "" + ## Prometheus Service Monitor + ## ref: https://github.com/coreos/prometheus-operator + ## https://github.com/coreos/prometheus-operator/blob/master/Documentation/api.md#endpoint + ## + serviceMonitor: + ## @param metrics.serviceMonitor.enabled Create ServiceMonitor resource(s) for scraping metrics using PrometheusOperator + ## + enabled: false + ## @param metrics.serviceMonitor.namespace The namespace in which the ServiceMonitor will be created + ## + namespace: "" + ## @param metrics.serviceMonitor.interval The interval at which metrics should be scraped + ## + interval: 30s + ## @param metrics.serviceMonitor.scrapeTimeout The timeout after which the scrape is ended + ## + scrapeTimeout: "" + ## @param metrics.serviceMonitor.relabellings Metrics RelabelConfigs to apply to samples before scraping. + ## + relabellings: [] + ## @param metrics.serviceMonitor.metricRelabelings Metrics RelabelConfigs to apply to samples before ingestion. + ## + metricRelabelings: [] + ## @param metrics.serviceMonitor.honorLabels Specify honorLabels parameter to add the scrape endpoint + ## + honorLabels: false + ## @param metrics.serviceMonitor.additionalLabels Additional labels that can be used so ServiceMonitor resource(s) can be discovered by Prometheus + ## + additionalLabels: {} + ## @param metrics.serviceMonitor.podTargetLabels Labels from the Kubernetes pod to be transferred to the created metrics + ## + podTargetLabels: [] + ## @param metrics.serviceMonitor.sampleLimit Limit of how many samples should be scraped from every Pod + ## + sampleLimit: false + ## @param metrics.serviceMonitor.targetLimit Limit of how many targets should be scraped + ## + targetLimit: false + ## Prometheus Pod Monitor + ## ref: https://github.com/coreos/prometheus-operator + ## https://github.com/coreos/prometheus-operator/blob/master/Documentation/api.md#podmonitor + ## + podMonitor: + ## @param metrics.podMonitor.enabled Create PodMonitor resource(s) for scraping metrics using PrometheusOperator + ## + enabled: false + ## @param metrics.podMonitor.namespace The namespace in which the PodMonitor will be created + ## + namespace: "" + ## @param metrics.podMonitor.interval The interval at which metrics should be scraped + ## + interval: 30s + ## @param metrics.podMonitor.scrapeTimeout The timeout after which the scrape is ended + ## + scrapeTimeout: "" + ## @param metrics.podMonitor.relabellings Metrics RelabelConfigs to apply to samples before scraping. + ## + relabellings: [] + ## @param metrics.podMonitor.metricRelabelings Metrics RelabelConfigs to apply to samples before ingestion. + ## + metricRelabelings: [] + ## @param metrics.podMonitor.honorLabels Specify honorLabels parameter to add the scrape endpoint + ## + honorLabels: false + ## @param metrics.podMonitor.additionalLabels Additional labels that can be used so PodMonitor resource(s) can be discovered by Prometheus + ## + additionalLabels: {} + ## @param metrics.podMonitor.podTargetLabels Labels from the Kubernetes pod to be transferred to the created metrics + ## + podTargetLabels: [] + ## @param metrics.podMonitor.sampleLimit Limit of how many samples should be scraped from every Pod + ## + sampleLimit: false + ## @param metrics.podMonitor.targetLimit Limit of how many targets should be scraped + ## + targetLimit: false + + ## Custom PrometheusRule to be defined + ## ref: https://github.com/coreos/prometheus-operator#customresourcedefinitions + ## + prometheusRule: + ## @param metrics.prometheusRule.enabled Create a custom prometheusRule Resource for scraping metrics using PrometheusOperator + ## + enabled: false + ## @param metrics.prometheusRule.namespace The namespace in which the prometheusRule will be created + ## + namespace: "" + ## @param metrics.prometheusRule.additionalLabels Additional labels for the prometheusRule + ## + additionalLabels: {} + ## @param metrics.prometheusRule.rules Custom Prometheus rules + ## e.g: + ## rules: + ## - alert: RedisDown + ## expr: redis_up{service="{{ template "common.names.fullname" . }}-metrics"} == 0 + ## for: 2m + ## labels: + ## severity: error + ## annotations: + ## summary: Redis® instance {{ "{{ $labels.instance }}" }} down + ## description: Redis® instance {{ "{{ $labels.instance }}" }} is down + ## - alert: RedisMemoryHigh + ## expr: > + ## redis_memory_used_bytes{service="{{ template "common.names.fullname" . }}-metrics"} * 100 + ## / + ## redis_memory_max_bytes{service="{{ template "common.names.fullname" . }}-metrics"} + ## > 90 + ## for: 2m + ## labels: + ## severity: error + ## annotations: + ## summary: Redis® instance {{ "{{ $labels.instance }}" }} is using too much memory + ## description: | + ## Redis® instance {{ "{{ $labels.instance }}" }} is using {{ "{{ $value }}" }}% of its available memory. + ## - alert: RedisKeyEviction + ## expr: | + ## increase(redis_evicted_keys_total{service="{{ template "common.names.fullname" . }}-metrics"}[5m]) > 0 + ## for: 1s + ## labels: + ## severity: error + ## annotations: + ## summary: Redis® instance {{ "{{ $labels.instance }}" }} has evicted keys + ## description: | + ## Redis® instance {{ "{{ $labels.instance }}" }} has evicted {{ "{{ $value }}" }} keys in the last 5 minutes. + ## + rules: [] + +## @section Init Container Parameters +## + +## 'volumePermissions' init container parameters +## Changes the owner and group of the persistent volume mount point to runAsUser:fsGroup values +## based on the *podSecurityContext/*containerSecurityContext parameters +## +volumePermissions: + ## @param volumePermissions.enabled Enable init container that changes the owner/group of the PV mount point to `runAsUser:fsGroup` + ## + enabled: false + ## OS Shell + Utility image + ## ref: https://hub.docker.com/r/bitnami/os-shell/tags/ + ## @param volumePermissions.image.registry [default: REGISTRY_NAME] OS Shell + Utility image registry + ## @param volumePermissions.image.repository [default: REPOSITORY_NAME/os-shell] OS Shell + Utility image repository + ## @skip volumePermissions.image.tag OS Shell + Utility image tag (immutable tags are recommended) + ## @param volumePermissions.image.digest OS Shell + Utility image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag + ## @param volumePermissions.image.pullPolicy OS Shell + Utility image pull policy + ## @param volumePermissions.image.pullSecrets OS Shell + Utility image pull secrets + ## + image: + registry: docker.io + repository: bitnami/os-shell + tag: 11-debian-11-r91 + digest: "" + pullPolicy: IfNotPresent + ## Optionally specify an array of imagePullSecrets. + ## Secrets must be manually created in the namespace. + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ + ## e.g: + ## pullSecrets: + ## - myRegistryKeySecretName + ## + pullSecrets: [] + ## Init container's resource requests and limits + ## ref: https://kubernetes.io/docs/user-guide/compute-resources/ + ## @param volumePermissions.resources.limits The resources limits for the init container + ## @param volumePermissions.resources.requests The requested resources for the init container + ## + resources: + limits: {} + requests: {} + ## Init container Container Security Context + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container + ## @param volumePermissions.containerSecurityContext.runAsUser Set init container's Security Context runAsUser + ## NOTE: when runAsUser is set to special value "auto", init container will try to chown the + ## data folder to auto-determined user&group, using commands: `id -u`:`id -G | cut -d" " -f2` + ## "auto" is especially useful for OpenShift which has scc with dynamic user ids (and 0 is not allowed) + ## + containerSecurityContext: + runAsUser: 0 + +## init-sysctl container parameters +## used to perform sysctl operation to modify Kernel settings (needed sometimes to avoid warnings) +## +sysctl: + ## @param sysctl.enabled Enable init container to modify Kernel settings + ## + enabled: false + ## OS Shell + Utility image + ## ref: https://hub.docker.com/r/bitnami/os-shell/tags/ + ## @param sysctl.image.registry [default: REGISTRY_NAME] OS Shell + Utility image registry + ## @param sysctl.image.repository [default: REPOSITORY_NAME/os-shell] OS Shell + Utility image repository + ## @skip sysctl.image.tag OS Shell + Utility image tag (immutable tags are recommended) + ## @param sysctl.image.digest OS Shell + Utility image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag + ## @param sysctl.image.pullPolicy OS Shell + Utility image pull policy + ## @param sysctl.image.pullSecrets OS Shell + Utility image pull secrets + ## + image: + registry: docker.io + repository: bitnami/os-shell + tag: 11-debian-11-r91 + digest: "" + pullPolicy: IfNotPresent + ## Optionally specify an array of imagePullSecrets. + ## Secrets must be manually created in the namespace. + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ + ## e.g: + ## pullSecrets: + ## - myRegistryKeySecretName + ## + pullSecrets: [] + ## @param sysctl.command Override default init-sysctl container command (useful when using custom images) + ## + command: [] + ## @param sysctl.mountHostSys Mount the host `/sys` folder to `/host-sys` + ## + mountHostSys: false + ## Init container's resource requests and limits + ## ref: https://kubernetes.io/docs/user-guide/compute-resources/ + ## @param sysctl.resources.limits The resources limits for the init container + ## @param sysctl.resources.requests The requested resources for the init container + ## + resources: + limits: {} + requests: {} + +## @section useExternalDNS Parameters +## +## @param useExternalDNS.enabled Enable various syntax that would enable external-dns to work. Note this requires a working installation of `external-dns` to be usable. +## @param useExternalDNS.additionalAnnotations Extra annotations to be utilized when `external-dns` is enabled. +## @param useExternalDNS.annotationKey The annotation key utilized when `external-dns` is enabled. Setting this to `false` will disable annotations. +## @param useExternalDNS.suffix The DNS suffix utilized when `external-dns` is enabled. Note that we prepend the suffix with the full name of the release. +## +useExternalDNS: + enabled: false + suffix: "" + annotationKey: external-dns.alpha.kubernetes.io/ + additionalAnnotations: {} diff --git a/packages/system/dashboard/charts/kubeapps/crds/apprepository-crd.yaml b/packages/system/dashboard/charts/kubeapps/crds/apprepository-crd.yaml new file mode 100644 index 00000000..0bf8e831 --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/crds/apprepository-crd.yaml @@ -0,0 +1,116 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: apprepositories.kubeapps.com +spec: + group: kubeapps.com + scope: Namespaced + names: + kind: AppRepository + plural: apprepositories + shortNames: + - apprepos + versions: + - name: v1alpha1 + storage: true + served: true + schema: + openAPIV3Schema: + type: object + required: + - spec + properties: + spec: + type: object + required: + - type + - url + properties: + type: + type: string + enum: ["helm", "oci"] + url: + type: string + description: + type: string + auth: + type: object + properties: + header: + type: object + required: + - secretKeyRef + properties: + secretKeyRef: + type: object + required: + - key + - name + properties: + key: + type: string + name: + type: string + customCA: + type: object + required: + - secretKeyRef + properties: + secretKeyRef: + type: object + required: + - key + - name + properties: + key: + type: string + name: + type: string + dockerRegistrySecrets: + type: array + items: + type: string + tlsInsecureSkipVerify: + type: boolean + passCredentials: + type: boolean + interval: + type: string + filterRule: + type: object + properties: + jq: + type: string + variables: + type: object + additionalProperties: + type: string + ociRepositories: + type: array + items: + type: string + resyncRequests: + type: integer + syncJobPodTemplate: + type: object + properties: + metadata: + type: object + x-kubernetes-preserve-unknown-fields: true + spec: + type: object + x-kubernetes-preserve-unknown-fields: true + status: + type: object + properties: + status: + type: string + additionalPrinterColumns: + - name: Type + type: string + description: The type of this repository. + jsonPath: .spec.type + - name: URL + type: string + description: The URL of this repository. + jsonPath: .spec.url diff --git a/packages/system/dashboard/charts/kubeapps/images b/packages/system/dashboard/charts/kubeapps/images new file mode 120000 index 00000000..5fa69870 --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/images @@ -0,0 +1 @@ +../../images \ No newline at end of file diff --git a/packages/system/dashboard/charts/kubeapps/templates/NOTES.txt b/packages/system/dashboard/charts/kubeapps/templates/NOTES.txt new file mode 100644 index 00000000..a25bcf62 --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/templates/NOTES.txt @@ -0,0 +1,87 @@ +CHART NAME: {{ .Chart.Name }} +CHART VERSION: {{ .Chart.Version }} +APP VERSION: {{ .Chart.AppVersion }} + +{{- $postgresqlSecretName := include "kubeapps.postgresql.secretName" . -}} + +{{- $redisSecretName := include "kubeapps.redis.secretName" . -}} + +** Please be patient while the chart is being deployed ** + +{{- if .Values.diagnosticMode.enabled }} +The chart has been deployed in diagnostic mode. All probes have been disabled and the command has been overwritten with: + + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 4 }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 4 }} + +Get the list of pods by executing: + + kubectl get pods --namespace {{ .Release.Namespace }} -l app.kubernetes.io/instance={{ .Release.Name }} + +Access the pods you want to debug by executing + + kubectl exec --namespace {{ .Release.Namespace }} -ti -- bash + +{{- else }} + +Tip: + + Watch the deployment status using the command: kubectl get pods -w --namespace {{ .Release.Namespace }} + +Kubeapps can be accessed via port {{ .Values.frontend.service.ports.http }} on the following DNS name from within your cluster: + + {{ template "common.names.fullname" . }}.{{ .Release.Namespace }}.svc.cluster.local + +{{- $reposWithOrphanSecrets := include "kubeapps.repos-with-orphan-secrets" . }} +{{- if ne $reposWithOrphanSecrets "" }} + +CAVEAT: + Some App Repositories have been installed with a custom CA or authorization header. + This generates secrets that won't be cleaned up if the repository is deleted through the Web application. + You can delete them manually or when uninstalling this chart. + +{{- end }} + +To access Kubeapps from outside your K8s cluster, follow the steps below: + +{{- if .Values.ingress.enabled }} + +1. Get the Kubeapps URL and associate Kubeapps hostname to your cluster external IP: + + export CLUSTER_IP=$(minikube ip) # On Minikube. Use: `kubectl cluster-info` on others K8s clusters + echo "Kubeapps URL: {{ printf "%s://%s/" (ternary "http" "https" .Values.ingress.tls) .Values.ingress.hostname }}" + echo "$CLUSTER_IP {{ .Values.ingress.hostname }}" | sudo tee -a /etc/hosts + +{{- else }} + +1. Get the Kubeapps URL by running these commands: + +{{- if contains "NodePort" .Values.frontend.service.type }} + + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ template "common.names.fullname" . }}) + echo "Kubeapps URL: http://$NODE_IP:$NODE_PORT" + +{{- else if contains "LoadBalancer" .Values.frontend.service.type }} + + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + Watch the status by running 'kubectl get svc --namespace {{ .Release.Namespace }} -w {{ template "common.names.fullname" . }}' + + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ template "common.names.fullname" . }} --template "{{ "{{ range (index .status.loadBalancer.ingress 0) }}{{ . }}{{ end }}" }}") + echo "Kubeapps URL: {{ printf "%s://$SERVICE_IP:%d" (ternary "http" "https" (eq ( .Values.frontend.service.ports.http | toString ) "443")) (int .Values.frontend.service.ports.http) }}" + +{{- else if contains "ClusterIP" .Values.frontend.service.type }} + +{{- $portNumber := include "kubeapps.frontend-port-number" . }} + echo "Kubeapps URL: http://127.0.0.1:{{ $portNumber }}" + kubectl port-forward --namespace {{ .Release.Namespace }} service/{{ template "common.names.fullname" . }} {{ $portNumber }}:{{ .Values.frontend.service.ports.http }} + +{{- end }} +{{- end }} + +2. Open a browser and access Kubeapps using the obtained URL. + +{{- end }} + +{{- include "kubeapps.checkRollingTags" . }} +{{- include "kubeapps.validateValues" . }} diff --git a/packages/system/dashboard/charts/kubeapps/templates/_helpers.tpl b/packages/system/dashboard/charts/kubeapps/templates/_helpers.tpl new file mode 100644 index 00000000..e3c2e524 --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/templates/_helpers.tpl @@ -0,0 +1,371 @@ +{{/* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Return the proper Docker Image Registry Secret Names +*/}} +{{- define "kubeapps.imagePullSecrets" -}} +{{ include "common.images.pullSecrets" (dict "images" (list .Values.frontend.image .Values.dashboard.image .Values.apprepository.image .Values.apprepository.syncImage .Values.authProxy.image .Values.pinnipedProxy.image .Values.kubeappsapis.image) "global" .Values.global) }} +{{- end -}} + +{{/* +Return the proper Kubeapps apprepository-controller image name +*/}} +{{- define "kubeapps.apprepository.image" -}} +{{- include "common.images.image" (dict "imageRoot" .Values.apprepository.image "global" .Values.global) -}} +{{- end -}} + +{{/* +Return the proper apprepository-controller sync image name +*/}} +{{- define "kubeapps.apprepository.syncImage" -}} +{{- include "common.images.image" (dict "imageRoot" .Values.apprepository.syncImage "global" .Values.global) -}} +{{- end -}} + +{{/* +Return the proper dashboard image name +*/}} +{{- define "kubeapps.dashboard.image" -}} +{{- include "common.images.image" (dict "imageRoot" .Values.dashboard.image "global" .Values.global) -}} +{{- end -}} + +{{/* +Return the proper frontend image name +*/}} +{{- define "kubeapps.frontend.image" -}} +{{- include "common.images.image" (dict "imageRoot" .Values.frontend.image "global" .Values.global) -}} +{{- end -}} + +{{/* +Return the proper auth proxy image name +*/}} +{{- define "kubeapps.authProxy.image" -}} +{{- include "common.images.image" (dict "imageRoot" .Values.authProxy.image "global" .Values.global) -}} +{{- end -}} + +{{/* +Return the proper pinniped proxy image name +*/}} +{{- define "kubeapps.pinnipedProxy.image" -}} +{{- include "common.images.image" (dict "imageRoot" .Values.pinnipedProxy.image "global" .Values.global) -}} +{{- end -}} + +{{/* +Return the proper kubeappsapis image name +*/}} +{{- define "kubeapps.kubeappsapis.image" -}} +{{- include "common.images.image" (dict "imageRoot" .Values.kubeappsapis.image "global" .Values.global) -}} +{{- end -}} + +{{/* +Return the proper oci-catalog image name +*/}} +{{- define "kubeapps.ociCatalog.image" -}} +{{- include "common.images.image" (dict "imageRoot" .Values.ociCatalog.image "global" .Values.global) -}} +{{- end -}} + +{{/* +Create a default fully qualified app name for PostgreSQL dependency. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +*/}} +{{- define "kubeapps.postgresql.fullname" -}} +{{- include "common.names.dependency.fullname" (dict "chartName" "postgresql" "chartValues" .Values.postgresql "context" $) -}} +{{- end -}} + +{{/* +Return the Postgresql Hostname +*/}} +{{- define "kubeapps.postgresql.host" -}} +{{- if .Values.postgresql.enabled }} + {{- if eq .Values.postgresql.architecture "replication" }} + {{- printf "%s-primary" (include "kubeapps.postgresql.fullname" .) | trunc 63 | trimSuffix "-" -}} + {{- else -}} + {{- printf "%s" (include "kubeapps.postgresql.fullname" .) -}} + {{- end -}} +{{- else -}} + {{- printf "%s" .Values.externalDatabase.host -}} +{{- end -}} +{{- end -}} + +{{/* +Return the Postgresql Port +*/}} +{{- define "kubeapps.postgresql.port" -}} +{{- if .Values.postgresql.enabled }} + {{- print "5432" -}} +{{- else -}} + {{- printf "%d" (int .Values.externalDatabase.port) -}} +{{- end -}} +{{- end -}} + +{{/* +Create a default fully qualified app name for Redis dependency. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +*/}} +{{- define "kubeapps.redis.fullname" -}} +{{- include "common.names.dependency.fullname" (dict "chartName" "redis" "chartValues" .Values.redis "context" $) -}} +{{- end -}} + +{{/* +Create name for the apprepository-controller based on the fullname +*/}} +{{- define "kubeapps.apprepository.fullname" -}} +{{- printf "%s-internal-apprepository-controller" (include "common.names.fullname" .) | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create name for the apprepository-controller based on the namespace +*/}} +{{- define "kubeapps.apprepository.fullname.namespace" -}} +{{- printf "%s-internal-apprepository-controller" (include "common.names.fullname.namespace" .) | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create name for the dashboard based on the fullname +*/}} +{{- define "kubeapps.dashboard.fullname" -}} +{{- printf "%s-internal-dashboard" (include "common.names.fullname" .) | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create name for the dashboard config based on the fullname +*/}} +{{- define "kubeapps.dashboard-config.fullname" -}} +{{- printf "%s-internal-dashboard-config" (include "common.names.fullname" .) | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create name for the frontend config based on the fullname +*/}} +{{- define "kubeapps.frontend-config.fullname" -}} +{{- printf "%s-frontend-config" (include "common.names.fullname" .) | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create name for kubeappsapis based on the fullname +*/}} +{{- define "kubeapps.kubeappsapis.fullname" -}} +{{- printf "%s-internal-kubeappsapis" (include "common.names.fullname" .) | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create name for the clusters config based on the fullname +*/}} +{{- define "kubeapps.clusters-config.fullname" -}} +{{- printf "%s-clusters-config" (include "common.names.fullname" .) | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create the name of the apprepository-controller service account to use +*/}} +{{- define "kubeapps.apprepository.serviceAccountName" -}} +{{- if .Values.apprepository.serviceAccount.create -}} + {{- default (include "kubeapps.apprepository.fullname" .) .Values.apprepository.serviceAccount.name -}} +{{- else -}} + {{- default "default" .Values.apprepository.serviceAccount.name -}} +{{- end -}} +{{- end -}} + +{{/* +Create the name of the kubeappsapis service account to use +*/}} +{{- define "kubeapps.kubeappsapis.serviceAccountName" -}} +{{- if .Values.kubeappsapis.serviceAccount.create -}} + {{- default (include "kubeapps.kubeappsapis.fullname" .) .Values.kubeappsapis.serviceAccount.name -}} +{{- else -}} + {{- default "default" .Values.kubeappsapis.serviceAccount.name -}} +{{- end -}} +{{- end -}} + +{{/* +Create proxy_pass for the kubeappsapis +*/}} +{{- define "kubeapps.kubeappsapis.proxy_pass" -}} +{{- printf "http://%s:%d" (include "kubeapps.kubeappsapis.fullname" .) (int .Values.kubeappsapis.service.ports.http) -}} +{{- end -}} + +{{/* +Create name for the secrets related to oauth2_proxy +*/}} +{{- define "kubeapps.oauth2_proxy-secret.name" -}} +{{- if .Values.authProxy.existingOauth2Secret -}} +{{- printf "%s" (tpl .Values.authProxy.existingOauth2Secret $) -}} +{{- else -}} +{{- printf "%s-oauth2" (include "common.names.fullname" .) | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} + +{{/* +Create name for pinniped-proxy based on the fullname. +Currently used for a service name only. +*/}} +{{- define "kubeapps.pinniped-proxy.fullname" -}} +{{- printf "%s-internal-pinniped-proxy" (include "common.names.fullname" .) | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Repositories that include a caCert or an authorizationHeader +*/}} +{{- define "kubeapps.repos-with-orphan-secrets" -}} +{{- range .Values.apprepository.initialRepos }} +{{- if or .caCert .authorizationHeader }} +{{- print "%s" .name -}} +{{- end }} +{{- end }} +{{- end -}} + +{{/* +Frontend service port number +*/}} +{{- define "kubeapps.frontend-port-number" -}} +{{- if .Values.authProxy.enabled -}} +{{ .Values.authProxy.containerPorts.proxy | int }} +{{- else -}} +{{ .Values.frontend.containerPorts.http | int }} +{{- end -}} +{{- end -}} + +{{/* +Returns the kubeappsCluster based on the configured clusters by finding the cluster without +a defined apiServiceURL. +*/}} +{{- define "kubeapps.kubeappsCluster" -}} + {{- $kubeappsCluster := "" }} + {{- if eq (len .Values.clusters) 0 }} + {{- fail "At least one cluster must be defined." }} + {{- end }} + {{- range .Values.clusters }} + {{- if or .isKubeappsCluster ( eq (.apiServiceURL | toString) "") }} + {{- if eq $kubeappsCluster "" }} + {{- $kubeappsCluster = .name }} + {{- else }} + {{- fail "Only one cluster can be configured using either 'isKubeappsCluster: true' or without an apiServiceURL to refer to the cluster on which Kubeapps is installed. Please check the provided 'clusters' configuration." }} + {{- end }} + {{- end }} + {{- end }} + {{- $kubeappsCluster }} +{{- end -}} + +{{/* +Returns a JSON list of cluster names only (without sensitive tokens etc.) +*/}} +{{- define "kubeapps.clusterNames" -}} + {{- $sanitizedClusters := list }} + {{- range .Values.clusters }} + {{- $sanitizedClusters = append $sanitizedClusters .name }} + {{- end }} + {{- $sanitizedClusters | toJson }} +{{- end -}} + +{{/* +Returns the name of the global packaging namespace for the Helm plugin. +It uses the value passed in the plugin's config, but falls back to the "release namespace + suffix" formula. +*/}} +{{- define "kubeapps.helmGlobalPackagingNamespace" -}} + {{- if .Values.kubeappsapis.pluginConfig.helm.packages.v1alpha1.globalPackagingNamespace }} + {{- printf "%s" .Values.kubeappsapis.pluginConfig.helm.packages.v1alpha1.globalPackagingNamespace -}} + {{- else -}} + {{- printf "%s%s" .Release.Namespace .Values.apprepository.globalReposNamespaceSuffix -}} + {{- end -}} +{{- end -}} + +{{/* +Return the Postgresql secret name +*/}} +{{- define "kubeapps.postgresql.secretName" -}} + {{- if .Values.postgresql.auth.existingSecret }} + {{- printf "%s" .Values.postgresql.auth.existingSecret -}} + {{- else -}} + {{- printf "%s" (include "kubeapps.postgresql.fullname" .) -}} + {{- end -}} +{{- end -}} + +{{/* +Return the Redis secret name +*/}} +{{- define "kubeapps.redis.secretName" -}} + {{- if .Values.redis.auth.existingSecret }} + {{- printf "%s" .Values.redis.auth.existingSecret -}} + {{- else -}} + {{- printf "%s" (include "kubeapps.redis.fullname" .) -}} + {{- end -}} +{{- end -}} + +{{/* +Compile all warnings into a single message, and call fail. +*/}} +{{- define "kubeapps.validateValues" -}} +{{- $messages := list -}} +{{- $messages := append $messages (include "kubeapps.validateValues.ingress.tls" .) -}} +{{- $messages := without $messages "" -}} +{{- $message := join "\n" $messages -}} + +{{- if $message -}} +{{- printf "\nVALUES VALIDATION:\n%s" $message | fail -}} +{{- end -}} +{{- end -}} + +{{/* +Validate values of Kubeapps - TLS configuration for Ingress +*/}} +{{- define "kubeapps.validateValues.ingress.tls" -}} +{{- if and .Values.ingress.enabled .Values.ingress.tls (not (include "common.ingress.certManagerRequest" ( dict "annotations" .Values.ingress.annotations ))) (not .Values.ingress.selfSigned) (empty .Values.ingress.extraTls) }} +kubeapps: ingress.tls + You enabled the TLS configuration for the default ingress hostname but + you did not enable any of the available mechanisms to create the TLS secret + to be used by the Ingress Controller. + Please use any of these alternatives: + - Use the `ingress.extraTls` and `ingress.secrets` parameters to provide your custom TLS certificates. + - Rely on cert-manager to create it by adding its supported annotations in `ingress.annotations` + - Rely on Helm to create self-signed certificates by setting `ingress.selfSigned=true` +{{- end -}} +{{- end -}} + +{{/* +# Calculate the kubeappsapis enabledPlugins. +*/}} +{{- define "kubeapps.kubeappsapis.enabledPlugins" -}} + {{- $enabledPlugins := list }} + {{- if .Values.kubeappsapis.enabledPlugins }} + {{- $enabledPlugins = .Values.kubeappsapis.enabledPlugins }} + {{- else }} + {{- if and .Values.packaging.flux.enabled .Values.packaging.helm.enabled }} + {{- fail "packaging: Please enable only one of the flux and helm plugins, since they both operate on Helm releases." }} + {{- end -}} + {{- range $plugin, $options := .Values.packaging }} + {{- if $options.enabled }} + {{- if eq $plugin "carvel" }} + {{- $enabledPlugins = append $enabledPlugins "kapp-controller-packages" }} + {{- else if eq $plugin "flux" }} + {{- $enabledPlugins = append $enabledPlugins "fluxv2-packages" }} + {{- else if eq $plugin "helm" }} + {{- $enabledPlugins = append $enabledPlugins "helm-packages" }} + {{- else }} + {{ $msg := printf "packaging: Unsupported packaging option: %s" $plugin }} + {{- fail $msg }} + {{- end }} + {{- end }} + {{- end }} + {{- if not $enabledPlugins }} + {{- fail "packaging: Please enable at least one of the packaging plugins." }} + {{- end }} + {{- $enabledPlugins = append $enabledPlugins "resources" }} + {{- end }} + {{- $enabledPlugins | toJson }} +{{- end -}} + +{{/* +Check if there are rolling tags in the images +*/}} +{{- define "kubeapps.checkRollingTags" -}} +{{- include "common.warnings.rollingTag" .Values.frontend.image }} +{{- include "common.warnings.rollingTag" .Values.dashboard.image }} +{{- include "common.warnings.rollingTag" .Values.apprepository.image }} +{{- include "common.warnings.rollingTag" .Values.authProxy.image }} +{{- include "common.warnings.rollingTag" .Values.pinnipedProxy.image }} +{{- include "common.warnings.rollingTag" .Values.kubeappsapis.image }} +{{- end -}} diff --git a/packages/system/dashboard/charts/kubeapps/templates/apprepository/apprepositories-secret.yaml b/packages/system/dashboard/charts/kubeapps/templates/apprepository/apprepositories-secret.yaml new file mode 100644 index 00000000..e5f8ed06 --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/templates/apprepository/apprepositories-secret.yaml @@ -0,0 +1,60 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.packaging.helm.enabled }} +{{- $versionLabel := dict "app.kubernetes.io/version" ( include "common.images.version" ( dict "imageRoot" .Values.apprepository.image "chart" .Chart ) ) }} +{{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.commonLabels $versionLabel ) "context" . ) }} +{{- range .Values.apprepository.initialRepos }} +{{- if or .caCert .authorizationHeader .basicAuth }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ printf "apprepo-%s-secrets" .name }} + namespace: {{ default (include "kubeapps.helmGlobalPackagingNamespace" $) .namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + {{- if $.Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $.Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +data: + {{- if .caCert }} + ca.crt: |- + {{ .caCert | b64enc }} + {{- end }} + {{- $authorizationHeader := "" }} + {{- if .authorizationHeader }} + {{- $authorizationHeader = .authorizationHeader }} + {{- else if .basicAuth }} + {{- $authorizationHeader = printf "Basic %s" (printf "%s:%s" .basicAuth.user .basicAuth.password | b64enc) }} + {{- end }} + {{- if $authorizationHeader }} + authorizationHeader: |- + {{ $authorizationHeader | b64enc }} + {{- end }} +--- +{{/* credentials are required in the release namespace for syncer jobs */}} +{{- if or .namespace $.Values.apprepository.globalReposNamespaceSuffix $.Values.kubeappsapis.pluginConfig.helm.packages.v1alpha1.globalPackagingNamespace}} +apiVersion: v1 +kind: Secret +metadata: + name: {{ printf "%s-apprepo-%s" (default (include "kubeapps.helmGlobalPackagingNamespace" $) .namespace) .name }} + namespace: {{ $.Release.Namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + {{- if $.Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $.Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +data: + {{- if .caCert }} + ca.crt: |- + {{ .caCert | b64enc }} + {{- end }} + {{- if $authorizationHeader }} + authorizationHeader: |- + {{ $authorizationHeader | b64enc }} + {{- end }} +--- +{{- end }} +{{- end }} +{{- end }} +{{- end }} diff --git a/packages/system/dashboard/charts/kubeapps/templates/apprepository/apprepositories.yaml b/packages/system/dashboard/charts/kubeapps/templates/apprepository/apprepositories.yaml new file mode 100644 index 00000000..b3688ce2 --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/templates/apprepository/apprepositories.yaml @@ -0,0 +1,78 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.packaging.helm.enabled }} +{{- $versionLabel := dict "app.kubernetes.io/version" ( include "common.images.version" ( dict "imageRoot" .Values.apprepository.image "chart" .Chart ) ) }} +{{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.commonLabels $versionLabel ) "context" . ) }} +{{- range .Values.apprepository.initialRepos }} +apiVersion: kubeapps.com/v1alpha1 +kind: AppRepository +metadata: + name: {{ .name }} + namespace: {{ default (include "kubeapps.helmGlobalPackagingNamespace" $) .namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + {{- if $.Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $.Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + type: {{ default "helm" .type }} + url: {{ .url }} + {{- if .ociRepositories }} + ociRepositories: + {{- range .ociRepositories }} + - {{ . }} + {{- end }} + {{- end }} + {{- if or $.Values.apprepository.podSecurityContext.enabled $.Values.apprepository.containerSecurityContext.enabled $.Values.apprepository.initialReposProxy.enabled .nodeSelector .tolerations}} + syncJobPodTemplate: + spec: + {{- if or $.Values.apprepository.initialReposProxy.enabled $.Values.apprepository.containerSecurityContext.enabled }} + containers: + - + {{- if $.Values.apprepository.initialReposProxy.enabled }} + env: + - name: https_proxy + value: {{ $.Values.apprepository.initialReposProxy.httpsProxy }} + - name: http_proxy + value: {{ $.Values.apprepository.initialReposProxy.httpProxy }} + - name: no_proxy + value: {{ $.Values.apprepository.initialReposProxy.noProxy }} + {{- end }} + {{- if $.Values.apprepository.containerSecurityContext.enabled }} + securityContext: {{- omit $.Values.apprepository.containerSecurityContext "enabled" | toYaml | nindent 12 }} + {{- end }} + {{- end }} + {{- if $.Values.apprepository.podSecurityContext.enabled }} + securityContext: {{- omit $.Values.apprepository.podSecurityContext "enabled" | toYaml | nindent 8 }} + {{- end }} + {{- if .nodeSelector }} + nodeSelector: {{- toYaml .nodeSelector | nindent 8 }} + {{- end }} + {{- if .tolerations }} + tolerations: {{- toYaml .tolerations | nindent 8 }} + {{- end }} + {{- end }} + {{- if or .caCert .authorizationHeader .basicAuth }} + auth: + {{- if .caCert }} + customCA: + secretKeyRef: + key: ca.crt + name: {{ printf "apprepo-%s-secrets" .name }} + {{- end }} + {{- if or .authorizationHeader .basicAuth }} + header: + secretKeyRef: + key: authorizationHeader + name: {{ printf "apprepo-%s-secrets" .name }} + {{- end }} + {{- end }} + {{- if .filterRule }} + filterRule: + {{- toYaml .filterRule | nindent 4 }} + {{- end }} +--- +{{ end -}} +{{- end -}} diff --git a/packages/system/dashboard/charts/kubeapps/templates/apprepository/deployment.yaml b/packages/system/dashboard/charts/kubeapps/templates/apprepository/deployment.yaml new file mode 100644 index 00000000..f7961875 --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/templates/apprepository/deployment.yaml @@ -0,0 +1,156 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.packaging.helm.enabled }} +apiVersion: {{ include "common.capabilities.deployment.apiVersion" . }} +kind: Deployment +metadata: + name: {{ template "kubeapps.apprepository.fullname" . }} + namespace: {{ .Release.Namespace | quote }} + {{- $versionLabel := dict "app.kubernetes.io/version" ( include "common.images.version" ( dict "imageRoot" .Values.apprepository.image "chart" .Chart ) ) }} + {{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.commonLabels $versionLabel ) "context" . ) }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: apprepository + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + replicas: {{ .Values.apprepository.replicaCount }} + {{- if .Values.apprepository.updateStrategy }} + strategy: {{- toYaml .Values.apprepository.updateStrategy | nindent 4 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.apprepository.podLabels .Values.commonLabels $versionLabel ) "context" . ) }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 6 }} + app.kubernetes.io/component: apprepository + template: + metadata: + {{- if .Values.apprepository.podAnnotations }} + annotations: {{- include "common.tplvalues.render" (dict "value" .Values.apprepository.podAnnotations "context" $) | nindent 8 }} + {{- end }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $podLabels "context" $ ) | nindent 8 }} + app.kubernetes.io/component: apprepository + spec: + {{- include "kubeapps.imagePullSecrets" . | indent 6 }} + serviceAccountName: {{ template "kubeapps.apprepository.serviceAccountName" . }} + {{- if .Values.apprepository.hostAliases }} + hostAliases: {{- include "common.tplvalues.render" (dict "value" .Values.apprepository.hostAliases "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.apprepository.affinity }} + affinity: {{- include "common.tplvalues.render" (dict "value" .Values.apprepository.affinity "context" $) | nindent 8 }} + {{- else }} + affinity: + podAffinity: {{- include "common.affinities.pods" (dict "type" .Values.apprepository.podAffinityPreset "component" "apprepository" "customLabels" $podLabels "context" $) | nindent 10 }} + podAntiAffinity: {{- include "common.affinities.pods" (dict "type" .Values.apprepository.podAntiAffinityPreset "component" "apprepository" "customLabels" $podLabels "context" $) | nindent 10 }} + nodeAffinity: {{- include "common.affinities.nodes" (dict "type" .Values.apprepository.nodeAffinityPreset.type "key" .Values.apprepository.nodeAffinityPreset.key "values" .Values.apprepository.nodeAffinityPreset.values) | nindent 10 }} + {{- end }} + {{- if .Values.apprepository.schedulerName }} + schedulerName: {{ .Values.apprepository.schedulerName }} + {{- end }} + {{- if .Values.apprepository.topologySpreadConstraints }} + topologySpreadConstraints: {{- include "common.tplvalues.render" (dict "value" .Values.apprepository.topologySpreadConstraints "context" .) | nindent 8 }} + {{- end }} + {{- if .Values.apprepository.nodeSelector }} + nodeSelector: {{- include "common.tplvalues.render" (dict "value" .Values.apprepository.nodeSelector "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.apprepository.tolerations }} + tolerations: {{- include "common.tplvalues.render" (dict "value" .Values.apprepository.tolerations "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.apprepository.priorityClassName }} + priorityClassName: {{ .Values.apprepository.priorityClassName | quote }} + {{- end }} + {{- if .Values.apprepository.podSecurityContext.enabled }} + securityContext: {{- omit .Values.apprepository.podSecurityContext "enabled" | toYaml | nindent 8 }} + {{- end }} + {{- if .Values.apprepository.initContainers }} + initContainers: {{- include "common.tplvalues.render" (dict "value" .Values.apprepository.initContainers "context" $) | trim | nindent 8 }} + {{- end }} + containers: + - name: controller + image: {{ include "kubeapps.apprepository.image" . }} + imagePullPolicy: {{ .Values.apprepository.image.pullPolicy | quote }} + {{- if .Values.apprepository.containerSecurityContext.enabled }} + securityContext: {{- omit .Values.apprepository.containerSecurityContext "enabled" | toYaml | nindent 12 }} + {{- end }} + {{- if .Values.apprepository.lifecycleHooks }} + lifecycle: {{- include "common.tplvalues.render" (dict "value" .Values.apprepository.lifecycleHooks "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.apprepository.command }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.apprepository.command "context" $) | nindent 12 }} + {{- else }} + command: + - /apprepository-controller + {{- end }} + {{- if .Values.apprepository.args }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.apprepository.args "context" $) | nindent 12 }} + {{- else }} + args: + - --user-agent-comment={{ printf "kubeapps/%s" .Chart.AppVersion }} + - --repo-sync-image=$(REPO_SYNC_IMAGE) + {{- if .Values.global }} + {{- if.Values.global.imagePullSecrets }} + {{- range $key, $value := .Values.global.imagePullSecrets }} + - --repo-sync-image-pullsecrets={{ $value | quote }} + {{- end }} + {{- end }} + {{- end }} + - --repo-sync-cmd=/asset-syncer + - --namespace={{ .Release.Namespace }} + - --global-repos-namespace={{ include "kubeapps.helmGlobalPackagingNamespace" . }} + - --database-secret-name={{ include "kubeapps.postgresql.secretName" . }} + - --database-secret-key=postgres-password + - --database-url={{ printf "%s:%d" (include "kubeapps.postgresql.host" .) (int (include "kubeapps.postgresql.port" .)) }} + - --database-user={{ .Values.postgresql.auth.username }} + - --database-name={{ .Values.postgresql.auth.database }} + {{- if .Values.apprepository.crontab }} + - --crontab={{ .Values.apprepository.crontab }} + {{- end }} + - --repos-per-namespace={{ .Values.apprepository.watchAllNamespaces }} + {{- if.Values.apprepository.customAnnotations }} + {{- range $key, $value := .Values.apprepository.customAnnotations }} + - --custom-annotations={{ (print $key "=" $value) | quote }} + {{- end }} + {{- end }} + {{- if.Values.apprepository.customLabels }} + {{- range $key, $value := .Values.apprepository.customLabels }} + - --custom-labels={{ (print $key "=" $value) | quote }} + {{- end }} + {{- end }} + {{- range .Values.apprepository.extraFlags }} + - {{ . }} + {{- end }} + {{- end }} + env: + - name: REPO_SYNC_IMAGE + value: {{ include "kubeapps.apprepository.syncImage" . }} + {{- if .Values.ociCatalog.enabled }} + - name: OCI_CATALOG_URL + value: {{ printf "%s:%d" (include "kubeapps.kubeappsapis.fullname" .) (int .Values.ociCatalog.containerPorts.grpc) | quote }} + {{- end }} + {{- if .Values.apprepository.extraEnvVars }} + {{- include "common.tplvalues.render" (dict "value" .Values.apprepository.extraEnvVars "context" $) | nindent 12 }} + {{- end }} + envFrom: + {{- if .Values.apprepository.extraEnvVarsCM }} + - configMapRef: + name: {{ include "common.tplvalues.render" (dict "value" .Values.apprepository.extraEnvVarsCM "context" $) }} + {{- end }} + {{- if .Values.apprepository.extraEnvVarsSecret }} + - secretRef: + name: {{ include "common.tplvalues.render" (dict "value" .Values.apprepository.extraEnvVarsSecret "context" $) }} + {{- end }} + {{- if .Values.apprepository.extraVolumeMounts }} + volumeMounts: {{- include "common.tplvalues.render" (dict "value" .Values.apprepository.extraVolumeMounts "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.apprepository.resources }} + resources: {{- toYaml .Values.apprepository.resources | nindent 12 }} + {{- end }} + {{- if .Values.apprepository.sidecars }} + {{- include "common.tplvalues.render" (dict "value" .Values.apprepository.sidecars "context" $) | trim | nindent 8 }} + {{- end }} + {{- if .Values.apprepository.extraVolumes }} + volumes: {{- include "common.tplvalues.render" (dict "value" .Values.apprepository.extraVolumes "context" $) | nindent 8 }} + {{- end }} +{{- end }} diff --git a/packages/system/dashboard/charts/kubeapps/templates/apprepository/rbac.yaml b/packages/system/dashboard/charts/kubeapps/templates/apprepository/rbac.yaml new file mode 100644 index 00000000..b59df30f --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/templates/apprepository/rbac.yaml @@ -0,0 +1,256 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.packaging.helm.enabled }} +{{- $versionLabel := dict "app.kubernetes.io/version" ( include "common.images.version" ( dict "imageRoot" .Values.apprepository.image "chart" .Chart ) ) }} +{{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.commonLabels $versionLabel ) "context" . ) }} +{{- if .Values.rbac.create -}} +# Role for managing events, jobs and cronjobs in the release namespace +apiVersion: {{ include "common.capabilities.rbac.apiVersion" . }} +kind: Role +metadata: + name: {{ template "kubeapps.apprepository.fullname" . }} + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: apprepository + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +rules: + - apiGroups: + - "" + resources: + - events + verbs: + - create + - patch + - apiGroups: + - batch + resources: + - cronjobs + verbs: + - create + - get + - list + - update + - watch + - delete + - apiGroups: + - batch + resources: + - jobs + verbs: + - create +--- +# ClusterRole for managing AppRepository objects in every namespace, +# so that we can update the finalizers on AppRepository objects +apiVersion: {{ include "common.capabilities.rbac.apiVersion" . }} +kind: ClusterRole +metadata: + name: {{ template "kubeapps.apprepository.fullname.namespace" . }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: apprepository + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +rules: + - apiGroups: + - kubeapps.com + resources: + - apprepositories + - apprepositories/finalizers + verbs: + - get + - list + - watch + - create + - update + - patch +--- +apiVersion: {{ include "common.capabilities.rbac.apiVersion" . }} +kind: RoleBinding +metadata: + name: {{ template "kubeapps.apprepository.fullname" . }} + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: apprepository + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ template "kubeapps.apprepository.fullname" . }} +subjects: + - kind: ServiceAccount + name: {{ template "kubeapps.apprepository.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} +--- +# ClusterRoleBinding for the apprepository controller SA +apiVersion: {{ include "common.capabilities.rbac.apiVersion" . }} +kind: ClusterRoleBinding +metadata: + name: {{ template "kubeapps.apprepository.fullname.namespace" . }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: apprepository + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ template "kubeapps.apprepository.fullname.namespace" . }} +subjects: + - kind: ServiceAccount + name: {{ template "kubeapps.apprepository.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} +--- +# Define role, but no binding, so users can be bound to this role +apiVersion: {{ include "common.capabilities.rbac.apiVersion" . }} +kind: Role +metadata: + name: {{ printf "%s-repositories-read" .Release.Name }} + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: apprepository + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +rules: + - apiGroups: + - kubeapps.com + resources: + - apprepositories + verbs: + - list + - get +--- +# Define role, but no binding, so users can be bound to this role +apiVersion: {{ include "common.capabilities.rbac.apiVersion" . }} +kind: Role +metadata: + name: {{ printf "%s-repositories-write" .Release.Name }} + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: apprepository + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +rules: + - apiGroups: + - kubeapps.com + resources: + - apprepositories + verbs: + - "*" + - apiGroups: + - "" + resources: + - secrets + verbs: + - create +--- +# The Kubeapps app repository controller can read and watch its own +# AppRepository resources cluster-wide. The read and write cluster-roles can +# also be bound to users in specific namespaces as required. +apiVersion: {{ include "common.capabilities.rbac.apiVersion" . }} +kind: ClusterRole +metadata: + name: {{ printf "kubeapps:%s:apprepositories-read" .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: apprepository + rbac.authorization.k8s.io/aggregate-to-view: "true" + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +rules: + - apiGroups: + - kubeapps.com + resources: + - apprepositories + - apprepositories/finalizers + verbs: + - get + - list + - watch +--- +apiVersion: {{ include "common.capabilities.rbac.apiVersion" . }} +kind: ClusterRoleBinding +metadata: + name: {{ printf "kubeapps:controller:%s:apprepositories-read" .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: apprepository + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ printf "kubeapps:%s:apprepositories-read" .Release.Namespace | quote }} +subjects: + - kind: ServiceAccount + name: {{ template "kubeapps.apprepository.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} +--- +apiVersion: {{ include "common.capabilities.rbac.apiVersion" . }} +kind: ClusterRole +metadata: + name: {{ printf "kubeapps:%s:apprepositories-write" .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: apprepository + rbac.authorization.k8s.io/aggregate-to-edit: "true" + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +rules: + - apiGroups: + - kubeapps.com + resources: + - apprepositories + verbs: + - '*' + - apiGroups: + - "" + resources: + - secrets + verbs: + - '*' +--- +apiVersion: {{ include "common.capabilities.rbac.apiVersion" . }} +kind: ClusterRole +metadata: + name: {{ printf "kubeapps:%s:apprepositories-refresh" .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: apprepository + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +rules: + - apiGroups: + - kubeapps.com + resources: + - apprepositories + verbs: + - get + - update +--- +apiVersion: {{ include "common.capabilities.rbac.apiVersion" . }} +kind: RoleBinding +metadata: + name: {{ printf "kubeapps:%s:global-repos-read" .Release.Namespace | quote }} + namespace: {{ include "kubeapps.helmGlobalPackagingNamespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ printf "kubeapps:%s:apprepositories-read" .Release.Namespace | quote }} +subjects: + - kind: Group + name: system:authenticated +{{- end -}} +{{- end -}} diff --git a/packages/system/dashboard/charts/kubeapps/templates/apprepository/serviceaccount.yaml b/packages/system/dashboard/charts/kubeapps/templates/apprepository/serviceaccount.yaml new file mode 100644 index 00000000..00d56352 --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/templates/apprepository/serviceaccount.yaml @@ -0,0 +1,21 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.apprepository.serviceAccount.create .Values.packaging.helm.enabled }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ template "kubeapps.apprepository.serviceAccountName" . }} + namespace: {{ .Release.Namespace | quote }} + {{- $versionLabel := dict "app.kubernetes.io/version" ( include "common.images.version" ( dict "imageRoot" .Values.apprepository.image "chart" .Chart ) ) }} + {{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.commonLabels $versionLabel ) "context" . ) }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: apprepository + {{- if or .Values.apprepository.serviceAccount.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.apprepository.serviceAccount.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +automountServiceAccountToken: {{ .Values.apprepository.serviceAccount.automountServiceAccountToken }} +{{- end -}} diff --git a/packages/system/dashboard/charts/kubeapps/templates/dashboard/configmap.yaml b/packages/system/dashboard/charts/kubeapps/templates/dashboard/configmap.yaml new file mode 100644 index 00000000..af217e56 --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/templates/dashboard/configmap.yaml @@ -0,0 +1,92 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.dashboard.enabled -}} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ template "kubeapps.dashboard-config.fullname" . }} + namespace: {{ .Release.Namespace | quote }} + {{- $versionLabel := dict "app.kubernetes.io/version" ( include "common.images.version" ( dict "imageRoot" .Values.dashboard.image "chart" .Chart ) ) }} + {{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.commonLabels $versionLabel ) "context" . ) }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: dashboard + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +data: + vhost.conf: |- + server { + listen {{ .Values.dashboard.containerPorts.http }}; + {{- if .Values.frontend.largeClientHeaderBuffers }} + large_client_header_buffers {{ .Values.frontend.largeClientHeaderBuffers }}; + {{- end }} + {{- if .Values.enableIPv6 }} + listen [::]:{{ .Values.dashboard.containerPorts.http }}; + {{- end }} + server_name _; + + gzip on; + gzip_static on; + + location /custom_style.css { + root /app/custom-css/; + } + + location /custom_locale.json { + root /app/custom-locale/; + } + + location /custom_components.js { + root /app/custom-components/; + } + + location / { + # Redirects are required to be relative otherwise the internal hostname will be exposed + absolute_redirect off; + + # Trailing / is required in the path for the React app to be loaded correctly + # The rewrite rule adds a trailing "/" to any path that does not contain "." neither "/". + # i.e kubeapps => kubeapps/ + rewrite ^([^.]*[^/])$ $1/ permanent; + + # Support for ingress prefixes maintaining compatibility with the default / + # 1 - Exactly two fragment URLs for files existing inside of the public/ dir + # i.e /[prefix]/config.json => /config.json + rewrite ^/[^/]+/([^/]+)$ /$1 break; + + # 2 - Any static files bundled by webpack referenced by 3 or more URL segments + # i.e /[prefix]/static/main.js => static/main.js + rewrite ^/[^/]+/static/(.*) /static/$1 break; + + try_files $uri /index.html; + } + } + custom_style.css: |- +{{- .Values.dashboard.customStyle | nindent 4 }} + custom_components.js: |- +{{- .Values.dashboard.customComponents | nindent 4 }} + custom_locale.json: |- +{{- .Values.dashboard.customLocale | toJson | nindent 4 }} + config.json: |- + { + "kubeappsCluster": {{ include "kubeapps.kubeappsCluster" . | quote }}, + "kubeappsNamespace": {{ .Release.Namespace | quote }}, + "helmGlobalNamespace": {{ include "kubeapps.helmGlobalPackagingNamespace" . | quote }}, + "carvelGlobalNamespace": {{ .Values.kubeappsapis.pluginConfig.kappController.packages.v1alpha1.globalPackagingNamespace | quote }}, + "appVersion": {{ printf "v%s" .Chart.AppVersion | quote }}, + "authProxyEnabled": {{ .Values.authProxy.enabled }}, + "oauthLoginURI": {{ .Values.authProxy.oauthLoginURI | quote }}, + "oauthLogoutURI": {{ .Values.authProxy.oauthLogoutURI | quote }}, + "authProxySkipLoginPage": {{ .Values.authProxy.skipKubeappsLoginPage }}, + "featureFlags": {{ .Values.featureFlags | toJson }}, + "clusters": {{ include "kubeapps.clusterNames" . }}, + "theme": {{ .Values.dashboard.defaultTheme | quote }}, + "remoteComponentsUrl": {{ .Values.dashboard.remoteComponentsUrl | quote }}, + "customAppViews": {{ .Values.dashboard.customAppViews | toJson }}, + "skipAvailablePackageDetails": {{ .Values.dashboard.skipAvailablePackageDetails }}, + "createNamespaceLabels": {{ .Values.dashboard.createNamespaceLabels | toJson }} + } +{{- end -}} diff --git a/packages/system/dashboard/charts/kubeapps/templates/dashboard/deployment.yaml b/packages/system/dashboard/charts/kubeapps/templates/dashboard/deployment.yaml new file mode 100644 index 00000000..12b27876 --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/templates/dashboard/deployment.yaml @@ -0,0 +1,189 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.dashboard.enabled -}} +apiVersion: {{ include "common.capabilities.deployment.apiVersion" . }} +kind: Deployment +metadata: + name: {{ template "kubeapps.dashboard.fullname" . }} + namespace: {{ .Release.Namespace | quote }} + {{- $versionLabel := dict "app.kubernetes.io/version" ( include "common.images.version" ( dict "imageRoot" .Values.dashboard.image "chart" .Chart ) ) }} + {{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.commonLabels $versionLabel ) "context" . ) }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: dashboard + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + replicas: {{ .Values.dashboard.replicaCount }} + {{- if .Values.dashboard.updateStrategy }} + strategy: {{- toYaml .Values.dashboard.updateStrategy | nindent 4 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.dashboard.podLabels .Values.commonLabels $versionLabel ) "context" . ) }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 6 }} + app.kubernetes.io/component: dashboard + template: + metadata: + annotations: + checksum/config: {{ include (print $.Template.BasePath "/dashboard/configmap.yaml") . | sha256sum }} + {{- if .Values.dashboard.podAnnotations }} + {{- include "common.tplvalues.render" (dict "value" .Values.dashboard.podAnnotations "context" $) | nindent 8 }} + {{- end }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $podLabels "context" $ ) | nindent 8 }} + app.kubernetes.io/component: dashboard + spec: + {{- include "kubeapps.imagePullSecrets" . | indent 6 }} + {{- if .Values.dashboard.hostAliases }} + hostAliases: {{- include "common.tplvalues.render" (dict "value" .Values.dashboard.hostAliases "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.dashboard.affinity }} + affinity: {{- include "common.tplvalues.render" (dict "value" .Values.dashboard.affinity "context" $) | nindent 8 }} + {{- else }} + affinity: + podAffinity: {{- include "common.affinities.pods" (dict "type" .Values.dashboard.podAffinityPreset "component" "dashboard" "customLabels" $podLabels "context" $) | nindent 10 }} + podAntiAffinity: {{- include "common.affinities.pods" (dict "type" .Values.dashboard.podAntiAffinityPreset "component" "dashboard" "customLabels" $podLabels "context" $) | nindent 10 }} + nodeAffinity: {{- include "common.affinities.nodes" (dict "type" .Values.dashboard.nodeAffinityPreset.type "key" .Values.dashboard.nodeAffinityPreset.key "values" .Values.dashboard.nodeAffinityPreset.values) | nindent 10 }} + {{- end }} + {{- if .Values.dashboard.schedulerName }} + schedulerName: {{ .Values.dashboard.schedulerName }} + {{- end }} + {{- if .Values.dashboard.topologySpreadConstraints }} + topologySpreadConstraints: {{- include "common.tplvalues.render" (dict "value" .Values.dashboard.topologySpreadConstraints "context" .) | nindent 8 }} + {{- end }} + {{- if .Values.dashboard.nodeSelector }} + nodeSelector: {{- include "common.tplvalues.render" (dict "value" .Values.dashboard.nodeSelector "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.dashboard.tolerations }} + tolerations: {{- include "common.tplvalues.render" (dict "value" .Values.dashboard.tolerations "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.dashboard.priorityClassName }} + priorityClassName: {{ .Values.dashboard.priorityClassName | quote }} + {{- end }} + {{- if .Values.dashboard.podSecurityContext.enabled }} + securityContext: {{- omit .Values.dashboard.podSecurityContext "enabled" | toYaml | nindent 8 }} + {{- end }} + {{- if .Values.dashboard.initContainers }} + initContainers: {{- include "common.tplvalues.render" (dict "value" .Values.dashboard.initContainers "context" $) | nindent 8 }} + {{- end }} + containers: + - name: dashboard + image: {{ include "kubeapps.dashboard.image" . }} + imagePullPolicy: {{ .Values.dashboard.image.pullPolicy | quote }} + {{- if .Values.dashboard.containerSecurityContext.enabled }} + securityContext: {{- omit .Values.dashboard.containerSecurityContext "enabled" | toYaml | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 12 }} + {{- else if .Values.dashboard.command }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.dashboard.command "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 12 }} + {{- else if .Values.dashboard.args }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.dashboard.args "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.dashboard.lifecycleHooks }} + lifecycle: {{- include "common.tplvalues.render" (dict "value" .Values.dashboard.lifecycleHooks "context" $) | nindent 12 }} + {{- end }} + env: + - name: BITNAMI_DEBUG + value: {{ ternary "true" "false" .Values.dashboard.image.debug | quote }} + {{- if .Values.dashboard.extraEnvVars }} + {{- include "common.tplvalues.render" (dict "value" .Values.dashboard.extraEnvVars "context" $) | nindent 12 }} + {{- end }} + envFrom: + {{- if .Values.dashboard.extraEnvVarsCM }} + - configMapRef: + name: {{ include "common.tplvalues.render" (dict "value" .Values.dashboard.extraEnvVarsCM "context" $) }} + {{- end }} + {{- if .Values.dashboard.extraEnvVarsSecret }} + - secretRef: + name: {{ include "common.tplvalues.render" (dict "value" .Values.dashboard.extraEnvVarsSecret "context" $) }} + {{- end }} + ports: + - name: http + containerPort: {{ .Values.dashboard.containerPorts.http }} + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.dashboard.customLivenessProbe }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.dashboard.customLivenessProbe "context" $) | nindent 12 }} + {{- else if .Values.dashboard.livenessProbe.enabled }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.dashboard.livenessProbe "enabled") "context" $) | nindent 12 }} + httpGet: + path: / + port: http + {{- end }} + {{- if .Values.dashboard.customReadinessProbe }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.dashboard.customReadinessProbe "context" $) | nindent 12 }} + {{- else if .Values.dashboard.readinessProbe.enabled }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.dashboard.readinessProbe "enabled") "context" $) | nindent 12 }} + httpGet: + path: / + port: http + {{- end }} + {{- if .Values.dashboard.customStartupProbe }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" .Values.dashboard.customStartupProbe "context" $) | nindent 12 }} + {{- else if .Values.dashboard.startupProbe.enabled }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.dashboard.startupProbe "enabled") "context" $) | nindent 12 }} + tcpSocket: + port: http + {{- end }} + {{- end }} + {{- if .Values.dashboard.resources }} + resources: {{- toYaml .Values.dashboard.resources | nindent 12 }} + {{- end }} + volumeMounts: + - name: vhost + mountPath: /opt/bitnami/nginx/conf/server_blocks + - name: config + mountPath: /app/config.json + subPath: config.json + - mountPath: /app/custom-css + name: custom-css + - mountPath: /app/custom-locale + name: custom-locale + - mountPath: /app/custom-components + name: custom-components + {{- if .Values.dashboard.extraVolumeMounts }} + {{- include "common.tplvalues.render" (dict "value" .Values.dashboard.extraVolumeMounts "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.dashboard.sidecars }} + {{- include "common.tplvalues.render" (dict "value" .Values.dashboard.sidecars "context" $) | nindent 8 }} + {{- end }} + volumes: + - name: vhost + configMap: + name: {{ template "kubeapps.dashboard-config.fullname" . }} + items: + - key: vhost.conf + path: vhost.conf + - name: config + configMap: + name: {{ template "kubeapps.dashboard-config.fullname" . }} + items: + - key: config.json + path: config.json + - name: custom-css + configMap: + name: {{ template "kubeapps.dashboard-config.fullname" . }} + items: + - key: custom_style.css + path: custom_style.css + - name: custom-locale + configMap: + name: {{ template "kubeapps.dashboard-config.fullname" . }} + items: + - key: custom_locale.json + path: custom_locale.json + - name: custom-components + configMap: + name: {{ template "kubeapps.dashboard-config.fullname" . }} + items: + - key: custom_components.js + path: custom_components.js + {{- if .Values.dashboard.extraVolumes }} + {{- include "common.tplvalues.render" (dict "value" .Values.dashboard.extraVolumes "context" $) | nindent 8 }} + {{- end }} +{{- end -}} diff --git a/packages/system/dashboard/charts/kubeapps/templates/dashboard/service.yaml b/packages/system/dashboard/charts/kubeapps/templates/dashboard/service.yaml new file mode 100644 index 00000000..0f9da93b --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/templates/dashboard/service.yaml @@ -0,0 +1,30 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.dashboard.enabled -}} +apiVersion: v1 +kind: Service +metadata: + name: {{ template "kubeapps.dashboard.fullname" . }} + namespace: {{ .Release.Namespace | quote }} + {{- $versionLabel := dict "app.kubernetes.io/version" ( include "common.images.version" ( dict "imageRoot" .Values.dashboard.image "chart" .Chart ) ) }} + {{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.commonLabels $versionLabel ) "context" . ) }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: dashboard + {{- if or .Values.dashboard.service.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.dashboard.service.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + type: ClusterIP + ports: + - port: {{ .Values.dashboard.service.ports.http }} + targetPort: http + protocol: TCP + name: http + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.dashboard.podLabels .Values.commonLabels ) "context" . ) }} + selector: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: dashboard +{{- end -}} diff --git a/packages/system/dashboard/charts/kubeapps/templates/extra-list.yaml b/packages/system/dashboard/charts/kubeapps/templates/extra-list.yaml new file mode 100644 index 00000000..2d35a580 --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/templates/extra-list.yaml @@ -0,0 +1,9 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- range .Values.extraDeploy }} +--- +{{ include "common.tplvalues.render" (dict "value" . "context" $) }} +{{- end }} diff --git a/packages/system/dashboard/charts/kubeapps/templates/frontend/configmap.yaml b/packages/system/dashboard/charts/kubeapps/templates/frontend/configmap.yaml new file mode 100644 index 00000000..44c10132 --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/templates/frontend/configmap.yaml @@ -0,0 +1,139 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ template "kubeapps.frontend-config.fullname" . }} + namespace: {{ .Release.Namespace | quote }} + {{- $versionLabel := dict "app.kubernetes.io/version" ( include "common.images.version" ( dict "imageRoot" .Values.frontend.image "chart" .Chart ) ) }} + {{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.commonLabels $versionLabel ) "context" . ) }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: frontend + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +data: + k8s-api-proxy.conf: |- + # Deactivate buffering for log streaming + proxy_buffering off; + # Hide Www-Authenticate to prevent it triggering a basic auth prompt in + # the browser with some clusters + proxy_hide_header Www-Authenticate; + + # Keep the connection open with the API server even if idle (the default is 60 seconds) + # Setting it to 1 hour which should be enough for our current use case of deploying/upgrading apps + # If we enable other use-cases in the future we might need to bump this value + # More info here https://github.com/vmware-tanzu/kubeapps/issues/766 + proxy_read_timeout 1h; + + {{- if .Values.frontend.proxypassAccessTokenAsBearer }} + # Google Kubernetes Engine requires the access_token as the Bearer when talking to the k8s api server. + proxy_set_header Authorization "Bearer $http_x_forwarded_access_token"; + {{- end }} +{{- range .Values.clusters }} + {{- if .certificateAuthorityData }} + {{ printf "%s-ca.pem" .name }}: {{ .certificateAuthorityData }} + {{- end }} +{{- end }} + vhost.conf: |- + # Retain the default nginx handling of requests without a "Connection" header + map $http_upgrade $connection_upgrade { + default upgrade; + '' close; + } + + # Allow websocket connections + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $connection_upgrade; + + server { + listen {{ .Values.frontend.containerPorts.http }}; + {{- if .Values.frontend.largeClientHeaderBuffers }} + large_client_header_buffers {{ .Values.frontend.largeClientHeaderBuffers }}; + {{- end }} + {{- if .Values.enableIPv6 }} + listen [::]:{{ .Values.frontend.containerPorts.http }}; + {{- end }} + server_name _; + + location /healthz { + access_log off; + default_type text/plain; + return 200 "healthy\n"; + } + + # Only proxy to k8s API endpoints if operators are enabled. + {{- if $.Values.featureFlags.operators }} + + # Ensure each cluster can be reached (should only be + # used with an auth-proxy where k8s credentials never leave + # the cluster). See clusters option. + {{- range .Values.clusters }} + + location ~* /api/clusters/{{ .name }} { + {{/* We need to split the API service URL(s) into the base url and the path segment so + those configurations using a path can be appropriately rewritten below while + ensuring the proxy_pass statement is given the base URL only. */}} + {{- $parsed := urlParse (default "https://kubernetes.default" .apiServiceURL) }} + {{- $apiServiceBaseURL := urlJoin (pick $parsed "scheme" "host") }} + {{- $apiServiceURLPath := $parsed.path }} + rewrite /api/clusters/{{ .name }}/(.*) {{ $apiServiceURLPath }}/$1 break; + rewrite /api/clusters/{{ .name }} {{ $apiServiceURLPath }}/ break; + + {{/* Helm returns a nil pointer error when accessing foo.bar if foo doesn't + exist, even with the `default` function. + See https://github.com/helm/helm/issues/8026#issuecomment-756538254 */}} + {{- $pinnipedConfig := .pinnipedConfig | default dict }} + {{- if and $.Values.pinnipedProxy.enabled (or $pinnipedConfig.enabled $pinnipedConfig.enable) }} + # If pinniped proxy is enabled *and* the current cluster is configured + # to exchange credentials then we route via pinnipedProxy to exchange + # credentials for client certificates. Note, we are currently still supporting + # the deprecated `pinnipedConfig.enable` until the next feature release. + # All documentation should now reference the cluster-specific `pinnipedConfig.enabled`. + {{- if .apiServiceURL }} + proxy_set_header PINNIPED_PROXY_API_SERVER_URL {{ .apiServiceURL }}; + {{- end }} + {{- if .certificateAuthorityData }} + proxy_set_header PINNIPED_PROXY_API_SERVER_CERT {{ .certificateAuthorityData }}; + {{- end }} + proxy_pass {{ printf "http://%s.%s:%d" (include "kubeapps.pinniped-proxy.fullname" $) $.Release.Namespace (int $.Values.pinnipedProxy.service.ports.pinnipedProxy) }}; + {{- else }} + # Otherwise we route directly through to the clusters with existing credentials. + proxy_pass {{ $apiServiceBaseURL }}; + {{- if .certificateAuthorityData }} + proxy_ssl_trusted_certificate {{ printf "./server_blocks/%s-ca.pem" .name | quote }}; + {{- end }} + {{- end }} + include "./server_blocks/k8s-api-proxy.conf"; + } + {{- end }} + {{- end }} + + location ~* /apis { + rewrite ^ $request_uri; # pass the encoded url downstream as is, + rewrite /apis/([^?]*) /$1 break; + rewrite /apis / break; + + {{- if .Values.frontend.proxypassExtraSetHeader }} + proxy_set_header {{ .Values.frontend.proxypassExtraSetHeader }}; + {{- end }} + + {{- if .Values.frontend.proxypassAccessTokenAsBearer }} + # Google Kubernetes Engine requires the access_token as the Bearer when talking to the k8s api server. + proxy_set_header Authorization "Bearer $http_x_forwarded_access_token"; + {{- end }} + + proxy_pass {{ include "kubeapps.kubeappsapis.proxy_pass" . -}}; + } + + {{- if .Values.dashboard.enabled }} + location / { + # Add the Authorization header if exists + add_header Authorization $http_authorization; + proxy_pass {{ printf "http://%s:%d" (include "kubeapps.dashboard.fullname" .) (int .Values.dashboard.service.ports.http) }}; + } + {{- end }} + } diff --git a/packages/system/dashboard/charts/kubeapps/templates/frontend/deployment.yaml b/packages/system/dashboard/charts/kubeapps/templates/frontend/deployment.yaml new file mode 100644 index 00000000..baf54af8 --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/templates/frontend/deployment.yaml @@ -0,0 +1,311 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +apiVersion: {{ include "common.capabilities.deployment.apiVersion" . }} +kind: Deployment +metadata: + name: {{ template "common.names.fullname" . }} + namespace: {{ .Release.Namespace | quote }} + {{- $versionLabel := dict "app.kubernetes.io/version" ( include "common.images.version" ( dict "imageRoot" .Values.frontend.image "chart" .Chart ) ) }} + {{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.commonLabels $versionLabel ) "context" . ) }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: frontend + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + replicas: {{ .Values.frontend.replicaCount }} + {{- if .Values.frontend.updateStrategy }} + strategy: {{- toYaml .Values.frontend.updateStrategy | nindent 4 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.frontend.podLabels .Values.commonLabels $versionLabel ) "context" . ) }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 6 }} + app.kubernetes.io/component: frontend + template: + metadata: + annotations: + checksum/config: {{ include (print $.Template.BasePath "/frontend/configmap.yaml") . | sha256sum }} + {{- if .Values.frontend.podAnnotations }} + {{- include "common.tplvalues.render" (dict "value" .Values.frontend.podAnnotations "context" $) | nindent 8 }} + {{- end }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $podLabels "context" $ ) | nindent 8 }} + app.kubernetes.io/component: frontend + spec: + {{- include "kubeapps.imagePullSecrets" . | indent 6 }} + {{- if .Values.frontend.hostAliases }} + hostAliases: {{- include "common.tplvalues.render" (dict "value" .Values.frontend.hostAliases "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.frontend.affinity }} + affinity: {{- include "common.tplvalues.render" (dict "value" .Values.frontend.affinity "context" $) | nindent 8 }} + {{- else }} + affinity: + podAffinity: {{- include "common.affinities.pods" (dict "type" .Values.frontend.podAffinityPreset "component" "frontend" "customLabels" $podLabels "context" $) | nindent 10 }} + podAntiAffinity: {{- include "common.affinities.pods" (dict "type" .Values.frontend.podAntiAffinityPreset "component" "frontend" "customLabels" $podLabels "context" $) | nindent 10 }} + nodeAffinity: {{- include "common.affinities.nodes" (dict "type" .Values.frontend.nodeAffinityPreset.type "key" .Values.frontend.nodeAffinityPreset.key "values" .Values.frontend.nodeAffinityPreset.values) | nindent 10 }} + {{- end }} + {{- if .Values.frontend.schedulerName }} + schedulerName: {{ .Values.frontend.schedulerName }} + {{- end }} + {{- if .Values.frontend.topologySpreadConstraints }} + topologySpreadConstraints: {{- include "common.tplvalues.render" (dict "value" .Values.frontend.topologySpreadConstraints "context" .) | nindent 8 }} + {{- end }} + {{- if .Values.frontend.nodeSelector }} + nodeSelector: {{- include "common.tplvalues.render" (dict "value" .Values.frontend.nodeSelector "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.frontend.tolerations }} + tolerations: {{- include "common.tplvalues.render" (dict "value" .Values.frontend.tolerations "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.frontend.priorityClassName }} + priorityClassName: {{ .Values.frontend.priorityClassName | quote }} + {{- end }} + {{- if .Values.frontend.podSecurityContext.enabled }} + securityContext: {{- omit .Values.frontend.podSecurityContext "enabled" | toYaml | nindent 8 }} + {{- end }} + {{- if .Values.frontend.initContainers }} + initContainers: {{- include "common.tplvalues.render" (dict "value" .Values.frontend.initContainers "context" $) | nindent 8 }} + {{- end }} + containers: + - name: nginx + image: {{ include "kubeapps.frontend.image" . }} + imagePullPolicy: {{ .Values.frontend.image.pullPolicy | quote }} + {{- if .Values.frontend.containerSecurityContext.enabled }} + securityContext: {{- omit .Values.frontend.containerSecurityContext "enabled" | toYaml | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 12 }} + {{- else if .Values.frontend.command }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.frontend.command "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 12 }} + {{- else if .Values.frontend.args }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.frontend.args "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.frontend.lifecycleHooks }} + lifecycle: {{- include "common.tplvalues.render" (dict "value" .Values.frontend.lifecycleHooks "context" $) | nindent 12 }} + {{- end }} + env: + - name: BITNAMI_DEBUG + value: {{ ternary "true" "false" .Values.frontend.image.debug | quote }} + {{- if .Values.frontend.extraEnvVars }} + {{- include "common.tplvalues.render" (dict "value" .Values.frontend.extraEnvVars "context" $) | nindent 12 }} + {{- end }} + envFrom: + {{- if .Values.frontend.extraEnvVarsCM }} + - configMapRef: + name: {{ include "common.tplvalues.render" (dict "value" .Values.frontend.extraEnvVarsCM "context" $) }} + {{- end }} + {{- if .Values.frontend.extraEnvVarsSecret }} + - secretRef: + name: {{ include "common.tplvalues.render" (dict "value" .Values.frontend.extraEnvVarsSecret "context" $) }} + {{- end }} + ports: + - name: http + containerPort: {{ .Values.frontend.containerPorts.http }} + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.frontend.customLivenessProbe }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.frontend.customLivenessProbe "context" $) | nindent 12 }} + {{- else if .Values.frontend.livenessProbe.enabled }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.frontend.livenessProbe "enabled") "context" $) | nindent 12 }} + httpGet: + path: /healthz + port: http + {{- end }} + {{- if .Values.frontend.customReadinessProbe }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.frontend.customReadinessProbe "context" $) | nindent 12 }} + {{- else if .Values.frontend.readinessProbe.enabled }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.frontend.readinessProbe "enabled") "context" $) | nindent 12 }} + httpGet: + path: / + port: http + {{- end }} + {{- if .Values.frontend.customStartupProbe }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" .Values.frontend.customStartupProbe "context" $) | nindent 12 }} + {{- else if .Values.frontend.startupProbe.enabled }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.frontend.startupProbe "enabled") "context" $) | nindent 12 }} + tcpSocket: + port: http + {{- end }} + {{- end }} + {{- if .Values.frontend.resources }} + resources: {{- toYaml .Values.frontend.resources | nindent 12 }} + {{- end }} + volumeMounts: + - name: vhost + mountPath: /opt/bitnami/nginx/conf/server_blocks + {{- if .Values.frontend.extraVolumeMounts }} + {{- include "common.tplvalues.render" (dict "value" .Values.frontend.extraVolumeMounts "context" $) | nindent 12 }} + {{- end }} + {{- if and .Values.authProxy.enabled (not .Values.authProxy.external) }} + - name: auth-proxy + image: {{ include "kubeapps.authProxy.image" . }} + imagePullPolicy: {{ .Values.authProxy.image.pullPolicy | quote }} + {{- if .Values.authProxy.containerSecurityContext.enabled }} + securityContext: {{- omit .Values.authProxy.containerSecurityContext "enabled" | toYaml | nindent 12 }} + {{- end }} + {{- if .Values.authProxy.lifecycleHooks }} + lifecycle: {{- include "common.tplvalues.render" (dict "value" .Values.authProxy.lifecycleHooks "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 12 }} + {{- else if .Values.authProxy.command }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.authProxy.command "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 12 }} + {{- else if .Values.authProxy.args }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.authProxy.args "context" $) | nindent 12 }} + {{- else }} + args: + - --provider={{ required "You must fill \".Values.authProxy.provider\" with the provider. Valid values at https://oauth2-proxy.github.io/oauth2-proxy/docs/configuration/overview" .Values.authProxy.provider }} + - --upstream=http://localhost:{{ .Values.frontend.containerPorts.http }}/ + - --http-address=0.0.0.0:{{ .Values.authProxy.containerPorts.proxy }} + - --email-domain={{ .Values.authProxy.emailDomain }} + - --pass-basic-auth=false + - --pass-access-token=true + - --pass-authorization-header=true + - --skip-auth-regex=^\/config\.json$ + - --skip-auth-regex=^\/site\.webmanifest$ + - --skip-auth-regex=^\/custom_style\.css$ + - --skip-auth-regex=^\/clr-ui.min\.css$ + - --skip-auth-regex=^\/clr-ui-dark.min\.css$ + - --skip-auth-regex=^\/custom_locale\.json$ + - --skip-auth-regex=^\/favicon.*\.png$ + - --skip-auth-regex=^\/favicon.*\.ico$ + - --skip-auth-regex=^\/android-chrome-.*\.png$ + - --skip-auth-regex=^\/static\/ + - --skip-auth-regex=^\/apis/core/plugins/v1alpha1/configured-plugins$ + - --skip-auth-regex=^\/apis/kubeappsapis.core.plugins.v1alpha1.PluginsService/GetConfiguredPlugins$ + - --skip-auth-regex=^\/$ + - --scope={{ .Values.authProxy.scope }} + - --cookie-refresh={{ .Values.authProxy.cookieRefresh }} + {{- range .Values.authProxy.extraFlags }} + - {{ . }} + {{- end }} + {{- end }} + env: + - name: OAUTH2_PROXY_CLIENT_ID + valueFrom: + secretKeyRef: + name: {{ template "kubeapps.oauth2_proxy-secret.name" . }} + key: clientID + - name: OAUTH2_PROXY_CLIENT_SECRET + valueFrom: + secretKeyRef: + name: {{ template "kubeapps.oauth2_proxy-secret.name" . }} + key: clientSecret + - name: OAUTH2_PROXY_COOKIE_SECRET + valueFrom: + secretKeyRef: + name: {{ template "kubeapps.oauth2_proxy-secret.name" . }} + key: cookieSecret + {{- if .Values.authProxy.extraEnvVars }} + {{- include "common.tplvalues.render" (dict "value" .Values.authProxy.extraEnvVars "context" $) | nindent 12 }} + {{- end }} + envFrom: + {{- if .Values.authProxy.extraEnvVarsCM }} + - configMapRef: + name: {{ include "common.tplvalues.render" (dict "value" .Values.authProxy.extraEnvVarsCM "context" $) }} + {{- end }} + {{- if .Values.authProxy.extraEnvVarsSecret }} + - secretRef: + name: {{ include "common.tplvalues.render" (dict "value" .Values.authProxy.extraEnvVarsSecret "context" $) }} + {{- end }} + ports: + - name: proxy + containerPort: {{ .Values.authProxy.containerPorts.proxy }} + {{- if .Values.authProxy.resources }} + resources: {{- toYaml .Values.authProxy.resources | nindent 12 }} + {{- end }} + {{- if .Values.authProxy.extraVolumeMounts }} + volumeMounts: {{- include "common.tplvalues.render" (dict "value" .Values.authProxy.extraVolumeMounts "context" $) | nindent 12 }} + {{- end }} + {{- end }} + {{- if and (gt (len .Values.clusters) 1) (not .Values.authProxy.enabled) }} + {{ fail "clusters can be configured only when using an auth proxy for cluster oidc authentication." }} + {{- end }} + {{- if .Values.pinnipedProxy.enabled }} + - name: pinniped-proxy + image: {{ include "kubeapps.pinnipedProxy.image" . }} + imagePullPolicy: {{ .Values.pinnipedProxy.image.pullPolicy | quote }} + {{- if .Values.pinnipedProxy.containerSecurityContext.enabled }} + securityContext: {{- omit .Values.pinnipedProxy.containerSecurityContext "enabled" | toYaml | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 12 }} + {{- else if .Values.pinnipedProxy.command }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.pinnipedProxy.command "context" $) | nindent 12 }} + {{- else }} + command: + - pinniped-proxy + {{- if .Values.pinnipedProxy.tls.existingSecret }} + - --proxy-tls-cert=/etc/pinniped-tls/tls.crt + - --proxy-tls-cert-key=/etc/pinniped-tls/tls.key + {{- end }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 12 }} + {{- else if .Values.pinnipedProxy.args }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.pinnipedProxy.args "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.pinnipedProxy.lifecycleHooks }} + lifecycle: {{- include "common.tplvalues.render" (dict "value" .Values.pinnipedProxy.lifecycleHooks "context" $) | nindent 12 }} + {{- end }} + env: + - name: DEFAULT_PINNIPED_NAMESPACE + value: {{ .Values.pinnipedProxy.defaultPinnipedNamespace | quote }} + - name: DEFAULT_PINNIPED_AUTHENTICATOR_TYPE + value: {{ .Values.pinnipedProxy.defaultAuthenticatorType | quote }} + - name: DEFAULT_PINNIPED_AUTHENTICATOR_NAME + value: {{ .Values.pinnipedProxy.defaultAuthenticatorName | quote }} + - name: DEFAULT_PINNIPED_API_SUFFIX + value: {{ .Values.pinnipedProxy.defaultPinnipedAPISuffix | quote }} + - name: RUST_LOG + # Use info,pinniped_proxy::pinniped=debug for module control. + value: info + {{- if .Values.pinnipedProxy.extraEnvVars }} + {{- include "common.tplvalues.render" (dict "value" .Values.pinnipedProxy.extraEnvVars "context" $) | nindent 12 }} + {{- end }} + envFrom: + {{- if .Values.pinnipedProxy.extraEnvVarsCM }} + - configMapRef: + name: {{ include "common.tplvalues.render" (dict "value" .Values.pinnipedProxy.extraEnvVarsCM "context" $) }} + {{- end }} + {{- if .Values.pinnipedProxy.extraEnvVarsSecret }} + - secretRef: + name: {{ include "common.tplvalues.render" (dict "value" .Values.pinnipedProxy.extraEnvVarsSecret "context" $) }} + {{- end }} + ports: + - name: pinniped-proxy + containerPort: {{ .Values.pinnipedProxy.containerPorts.pinnipedProxy }} + {{- if .Values.pinnipedProxy.resources }} + resources: {{- toYaml .Values.pinnipedProxy.resources | nindent 12 }} + {{- end }} + volumeMounts: + {{- if .Values.pinnipedProxy.tls.existingSecret }} + - name: pinniped-tls-secret + mountPath: "/etc/pinniped-tls" + readOnly: true + {{- end }} + {{- if .Values.pinnipedProxy.extraVolumeMounts }} + {{- include "common.tplvalues.render" (dict "value" .Values.pinnipedProxy.extraVolumeMounts "context" $) | nindent 12 }} + {{- end }} + {{- end }} + {{- if .Values.frontend.sidecars }} + {{- include "common.tplvalues.render" (dict "value" .Values.frontend.sidecars "context" $) | nindent 8 }} + {{- end }} + volumes: + - name: vhost + configMap: + name: {{ template "kubeapps.frontend-config.fullname" . }} + {{- if .Values.pinnipedProxy.tls.existingSecret }} + - name: pinniped-tls-secret + secret: + secretName: {{ .Values.pinnipedProxy.tls.existingSecret }} + {{- end }} + {{- if .Values.frontend.extraVolumes }} + {{- include "common.tplvalues.render" (dict "value" .Values.frontend.extraVolumes "context" $) | nindent 8 }} + {{- end }} diff --git a/packages/system/dashboard/charts/kubeapps/templates/frontend/oauth2-secret.yaml b/packages/system/dashboard/charts/kubeapps/templates/frontend/oauth2-secret.yaml new file mode 100644 index 00000000..6db0517e --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/templates/frontend/oauth2-secret.yaml @@ -0,0 +1,23 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.authProxy.enabled (not .Values.authProxy.external) (not .Values.authProxy.existingOauth2Secret) }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ template "kubeapps.oauth2_proxy-secret.name" . }} + namespace: {{ .Release.Namespace | quote }} + {{- $versionLabel := dict "app.kubernetes.io/version" ( include "common.images.version" ( dict "imageRoot" .Values.frontend.image "chart" .Chart ) ) }} + {{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.commonLabels $versionLabel ) "context" . ) }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: frontend + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +data: + clientID: {{ required "You must fill \".Values.authProxy.clientID\" with the Client ID of the provider" .Values.authProxy.clientID | b64enc }} + clientSecret: {{ required "You must fill \".Values.authProxy.clientSecret\" with the Client Secret of the provider" .Values.authProxy.clientSecret | b64enc }} + cookieSecret: {{ required "You must fill \".Values.authProxy.cookieSecret\". More info at https://oauth2-proxy.github.io/oauth2-proxy/docs/configuration/overview/#generating-a-cookie-secret" .Values.authProxy.cookieSecret | b64enc }} +{{- end }} diff --git a/packages/system/dashboard/charts/kubeapps/templates/frontend/service.yaml b/packages/system/dashboard/charts/kubeapps/templates/frontend/service.yaml new file mode 100644 index 00000000..13ce55b1 --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/templates/frontend/service.yaml @@ -0,0 +1,84 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +apiVersion: v1 +kind: Service +metadata: + name: {{ template "common.names.fullname" . }} + namespace: {{ .Release.Namespace | quote }} + {{- $versionLabel := dict "app.kubernetes.io/version" ( include "common.images.version" ( dict "imageRoot" .Values.frontend.image "chart" .Chart ) ) }} + {{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.commonLabels $versionLabel ) "context" . ) }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: frontend + {{- if or .Values.frontend.service.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.frontend.service.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + type: {{ .Values.frontend.service.type }} + {{- if and .Values.frontend.service.clusterIP (eq .Values.frontend.service.type "ClusterIP") }} + clusterIP: {{ .Values.frontend.service.clusterIP }} + {{- end }} + {{- if or (eq .Values.frontend.service.type "LoadBalancer") (eq .Values.frontend.service.type "NodePort") }} + externalTrafficPolicy: {{ .Values.frontend.service.externalTrafficPolicy | quote }} + {{- end }} + {{- if and (eq .Values.frontend.service.type "LoadBalancer") .Values.frontend.service.loadBalancerSourceRanges }} + loadBalancerSourceRanges: {{- toYaml .Values.frontend.service.loadBalancerSourceRanges | nindent 4 }} + {{- end }} + {{- if and (eq .Values.frontend.service.type "LoadBalancer") (not (empty .Values.frontend.service.loadBalancerIP)) }} + loadBalancerIP: {{ .Values.frontend.service.loadBalancerIP }} + {{- end }} + {{- if .Values.frontend.service.sessionAffinity }} + sessionAffinity: {{ .Values.frontend.service.sessionAffinity }} + {{- end }} + {{- if .Values.frontend.service.sessionAffinityConfig }} + sessionAffinityConfig: {{- include "common.tplvalues.render" (dict "value" .Values.frontend.service.sessionAffinityConfig "context" $) | nindent 4 }} + {{- end }} + ports: + - name: http + port: {{ .Values.frontend.service.ports.http }} + protocol: TCP + {{- if and .Values.authProxy.enabled (not .Values.authProxy.external) }} + targetPort: proxy + {{- else }} + targetPort: http + {{- end }} + {{- if and (or (eq .Values.frontend.service.type "NodePort") (eq .Values.frontend.service.type "LoadBalancer")) (not (empty .Values.frontend.service.nodePorts.http)) }} + nodePort: {{ .Values.frontend.service.nodePorts.http }} + {{- else if eq .Values.frontend.service.type "ClusterIP" }} + nodePort: null + {{- end }} + {{- if .Values.frontend.service.extraPorts }} + {{- include "common.tplvalues.render" (dict "value" .Values.frontend.service.extraPorts "context" $) | nindent 4 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.frontend.podLabels .Values.commonLabels ) "context" . ) }} + selector: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: frontend +{{- if .Values.pinnipedProxy.enabled }} +--- +# Include an additional ClusterIP service for the pinniped-proxy as some configurations +# require the normal frontend service to use NodePort. +apiVersion: v1 +kind: Service +metadata: + name: {{ template "kubeapps.pinniped-proxy.fullname" . }} + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: frontend + {{- if or .Values.pinnipedProxy.service.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.pinnipedProxy.service.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + type: ClusterIP + ports: + - port: {{ .Values.pinnipedProxy.service.ports.pinnipedProxy }} + targetPort: pinniped-proxy + protocol: TCP + name: pinniped-proxy + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.frontend.podLabels .Values.commonLabels ) "context" . ) }} + selector: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: frontend +{{- end }} diff --git a/packages/system/dashboard/charts/kubeapps/templates/ingress-api.yaml b/packages/system/dashboard/charts/kubeapps/templates/ingress-api.yaml new file mode 100644 index 00000000..54d02156 --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/templates/ingress-api.yaml @@ -0,0 +1,115 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.featureFlags.apiOnly.enabled (not .Values.ingress.enabled) -}} + {{ fail "Ingress must be enabled for the API mode to work. Please set \"ingress.enabled\" to true." }} +{{- end -}} +{{- if and .Values.ingress.enabled .Values.featureFlags.apiOnly.enabled -}} +{{- if and .Values.dashboard.enabled -}} + {{ fail "Dashboard is enabled but will NOT work with Ingress in API mode. Please set \"dashboard.enabled\" to false." }} +{{- end -}} +--- +apiVersion: {{ include "common.capabilities.ingress.apiVersion" . }} +kind: Ingress +metadata: + name: {{ template "common.names.fullname" . }}-http-api + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if or .Values.ingress.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.ingress.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + {{- if and .Values.ingress.ingressClassName (eq "true" (include "common.ingress.supportsIngressClassname" .)) }} + ingressClassName: {{ .Values.ingress.ingressClassName | quote }} + {{- end }} + rules: + {{- if .Values.ingress.hostname }} + - host: {{ .Values.ingress.hostname }} + http: + paths: + {{- if .Values.ingress.extraPaths }} + {{- toYaml .Values.ingress.extraPaths | nindent 10 }} + {{- end }} + - path: /apis + {{- if eq "true" (include "common.ingress.supportsPathType" $) }} + pathType: {{ $.Values.ingress.pathType }} + {{- end }} + backend: {{- include "common.ingress.backend" (dict "serviceName" (include "common.names.fullname" $) "servicePort" "http" "context" $) | nindent 14 }} + {{- if and .Values.ingress.path (ne (quote (trim .Values.ingress.path)) (quote "/")) }} + - path: {{ .Values.ingress.path }} + {{- if eq "true" (include "common.ingress.supportsPathType" $) }} + pathType: {{ $.Values.ingress.pathType }} + {{- end }} + backend: {{- include "common.ingress.backend" (dict "serviceName" (include "common.names.fullname" $) "servicePort" "http" "context" $) | nindent 14 }} + {{- end -}} + {{- end }} + {{- range .Values.ingress.extraHosts }} + - host: {{ .name }} + http: + paths: + - path: {{ default "/" .path }} + {{- if eq "true" (include "common.ingress.supportsPathType" $) }} + pathType: {{ $.Values.ingress.pathType }} + {{- end }} + backend: {{- include "common.ingress.backend" (dict "serviceName" (include "common.names.fullname" $) "servicePort" "http" "context" $) | nindent 14 }} + {{- end }} + {{- if .Values.ingress.extraRules }} + {{- include "common.tplvalues.render" (dict "value" .Values.ingress.extraRules "context" $) | nindent 4 }} + {{- end }} + {{- if or (and .Values.ingress.tls (or (include "common.ingress.certManagerRequest" ( dict "annotations" .Values.ingress.annotations )) .Values.ingress.selfSigned)) .Values.ingress.extraTls }} + tls: + {{- if and .Values.ingress.tls (or (include "common.ingress.certManagerRequest" ( dict "annotations" .Values.ingress.annotations )) .Values.ingress.selfSigned) }} + - hosts: + - {{ .Values.ingress.hostname | quote }} + secretName: {{ printf "%s-tls" .Values.ingress.hostname }} + {{- end }} + {{- if .Values.ingress.extraTls }} + {{- include "common.tplvalues.render" ( dict "value" .Values.ingress.extraTls "context" $ ) | nindent 4 }} + {{- end }} + {{- end }} +--- +apiVersion: {{ include "common.capabilities.ingress.apiVersion" . }} +kind: Ingress +metadata: + name: {{ template "common.names.fullname" . }} + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if or .Values.featureFlags.apiOnly.grpc.annotations .Values.ingress.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.featureFlags.apiOnly.grpc.annotations .Values.ingress.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + {{- if and .Values.ingress.ingressClassName (eq "true" (include "common.ingress.supportsIngressClassname" .)) }} + ingressClassName: {{ .Values.ingress.ingressClassName | quote }} + {{- end }} + rules: + {{- if .Values.ingress.hostname }} + - host: {{ .Values.ingress.hostname }} + http: + paths: + - path: / + {{- if eq "true" (include "common.ingress.supportsPathType" $) }} + pathType: {{ $.Values.ingress.pathType }} + {{- end }} + backend: + service: + name: {{ template "kubeapps.kubeappsapis.fullname" . }} + port: + name: grpc-http + {{- end }} + {{- if or (and .Values.ingress.tls (or (include "common.ingress.certManagerRequest" ( dict "annotations" .Values.ingress.annotations )) .Values.ingress.selfSigned)) .Values.ingress.extraTls }} + tls: + {{- if and .Values.ingress.tls (or (include "common.ingress.certManagerRequest" ( dict "annotations" .Values.ingress.annotations )) .Values.ingress.selfSigned) }} + - hosts: + - {{ .Values.ingress.hostname | quote }} + secretName: {{ printf "%s-tls" .Values.ingress.hostname }} + {{- end }} + {{- if .Values.ingress.extraTls }} + {{- include "common.tplvalues.render" ( dict "value" .Values.ingress.extraTls "context" $ ) | nindent 4 }} + {{- end }} + {{- end }} +--- +{{- end }} diff --git a/packages/system/dashboard/charts/kubeapps/templates/ingress.yaml b/packages/system/dashboard/charts/kubeapps/templates/ingress.yaml new file mode 100644 index 00000000..69f0c861 --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/templates/ingress.yaml @@ -0,0 +1,59 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.ingress.enabled (not .Values.featureFlags.apiOnly.enabled) -}} +apiVersion: {{ include "common.capabilities.ingress.apiVersion" . }} +kind: Ingress +metadata: + name: {{ template "common.names.fullname" . }} + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if or .Values.ingress.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.ingress.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + {{- if and .Values.ingress.ingressClassName (eq "true" (include "common.ingress.supportsIngressClassname" .)) }} + ingressClassName: {{ .Values.ingress.ingressClassName | quote }} + {{- end }} + rules: + {{- if .Values.ingress.hostname }} + - host: {{ .Values.ingress.hostname }} + http: + paths: + {{- if .Values.ingress.extraPaths }} + {{- toYaml .Values.ingress.extraPaths | nindent 10 }} + {{- end }} + - path: {{ .Values.ingress.path }} + {{- if eq "true" (include "common.ingress.supportsPathType" $) }} + pathType: {{ $.Values.ingress.pathType }} + {{- end }} + backend: {{- include "common.ingress.backend" (dict "serviceName" (include "common.names.fullname" $) "servicePort" "http" "context" $) | nindent 14 }} + {{- end }} + {{- range .Values.ingress.extraHosts }} + - host: {{ .name }} + http: + paths: + - path: {{ default "/" .path }} + {{- if eq "true" (include "common.ingress.supportsPathType" $) }} + pathType: {{ $.Values.ingress.pathType }} + {{- end }} + backend: {{- include "common.ingress.backend" (dict "serviceName" (include "common.names.fullname" $) "servicePort" "http" "context" $) | nindent 14 }} + {{- end }} + {{- if .Values.ingress.extraRules }} + {{- include "common.tplvalues.render" (dict "value" .Values.ingress.extraRules "context" $) | nindent 4 }} + {{- end }} + {{- if or (and .Values.ingress.tls (or (include "common.ingress.certManagerRequest" ( dict "annotations" .Values.ingress.annotations )) .Values.ingress.selfSigned)) .Values.ingress.extraTls }} + tls: + {{- if and .Values.ingress.tls (or (include "common.ingress.certManagerRequest" ( dict "annotations" .Values.ingress.annotations )) .Values.ingress.selfSigned) }} + - hosts: + - {{ .Values.ingress.hostname | quote }} + secretName: {{ printf "%s-tls" .Values.ingress.hostname }} + {{- end }} + {{- if .Values.ingress.extraTls }} + {{- include "common.tplvalues.render" ( dict "value" .Values.ingress.extraTls "context" $ ) | nindent 4 }} + {{- end }} + {{- end }} +{{- end }} diff --git a/packages/system/dashboard/charts/kubeapps/templates/kubeappsapis/configmap.yaml b/packages/system/dashboard/charts/kubeapps/templates/kubeappsapis/configmap.yaml new file mode 100644 index 00000000..2129cc8e --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/templates/kubeappsapis/configmap.yaml @@ -0,0 +1,21 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ printf "%s-configmap" (include "kubeapps.kubeappsapis.fullname" .) }} + namespace: {{ .Release.Namespace | quote }} + {{- $versionLabel := dict "app.kubernetes.io/version" ( include "common.images.version" ( dict "imageRoot" .Values.kubeappsapis.image "chart" .Chart ) ) }} + {{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.commonLabels $versionLabel ) "context" . ) }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +data: + plugins.conf: |- +{{- if .Values.kubeappsapis.pluginConfig }} +{{ .Values.kubeappsapis.pluginConfig | toPrettyJson | indent 4 }} +{{- end }} diff --git a/packages/system/dashboard/charts/kubeapps/templates/kubeappsapis/deployment.yaml b/packages/system/dashboard/charts/kubeapps/templates/kubeappsapis/deployment.yaml new file mode 100644 index 00000000..38e40ddb --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/templates/kubeappsapis/deployment.yaml @@ -0,0 +1,335 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +apiVersion: {{ include "common.capabilities.deployment.apiVersion" . }} +kind: Deployment +metadata: + name: {{ template "kubeapps.kubeappsapis.fullname" . }} + namespace: {{ .Release.Namespace | quote }} + {{- $versionLabel := dict "app.kubernetes.io/version" ( include "common.images.version" ( dict "imageRoot" .Values.kubeappsapis.image "chart" .Chart ) ) }} + {{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.commonLabels $versionLabel ) "context" . ) }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: kubeappsapis + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + replicas: {{ .Values.kubeappsapis.replicaCount }} + {{- if .Values.kubeappsapis.updateStrategy }} + strategy: {{- toYaml .Values.kubeappsapis.updateStrategy | nindent 4 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.kubeappsapis.podLabels .Values.commonLabels $versionLabel ) "context" . ) }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 6 }} + app.kubernetes.io/component: kubeappsapis + template: + metadata: + {{- if .Values.kubeappsapis.podAnnotations }} + annotations: {{- include "common.tplvalues.render" (dict "value" .Values.kubeappsapis.podAnnotations "context" $) | nindent 8 }} + {{- end }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $podLabels "context" $ ) | nindent 8 }} + app.kubernetes.io/component: kubeappsapis + spec: + {{- include "kubeapps.imagePullSecrets" . | indent 6 }} + serviceAccountName: {{ template "kubeapps.kubeappsapis.serviceAccountName" . }} + {{- if .Values.kubeappsapis.hostAliases }} + hostAliases: {{- include "common.tplvalues.render" (dict "value" .Values.kubeappsapis.hostAliases "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.kubeappsapis.affinity }} + affinity: {{- include "common.tplvalues.render" (dict "value" .Values.kubeappsapis.affinity "context" $) | nindent 8 }} + {{- else }} + affinity: + podAffinity: {{- include "common.affinities.pods" (dict "type" .Values.kubeappsapis.podAffinityPreset "component" "kubeappsapis" "customLabels" $podLabels "context" $) | nindent 10 }} + podAntiAffinity: {{- include "common.affinities.pods" (dict "type" .Values.kubeappsapis.podAntiAffinityPreset "component" "kubeappsapis" "customLabels" $podLabels "context" $) | nindent 10 }} + nodeAffinity: {{- include "common.affinities.nodes" (dict "type" .Values.kubeappsapis.nodeAffinityPreset.type "key" .Values.kubeappsapis.nodeAffinityPreset.key "values" .Values.kubeappsapis.nodeAffinityPreset.values) | nindent 10 }} + {{- end }} + {{- if .Values.kubeappsapis.schedulerName }} + schedulerName: {{ .Values.kubeappsapis.schedulerName }} + {{- end }} + {{- if .Values.kubeappsapis.topologySpreadConstraints }} + topologySpreadConstraints: {{- include "common.tplvalues.render" (dict "value" .Values.kubeappsapis.topologySpreadConstraints "context" .) | nindent 8 }} + {{- end }} + {{- if .Values.kubeappsapis.nodeSelector }} + nodeSelector: {{- include "common.tplvalues.render" (dict "value" .Values.kubeappsapis.nodeSelector "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.kubeappsapis.tolerations }} + tolerations: {{- include "common.tplvalues.render" (dict "value" .Values.kubeappsapis.tolerations "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.kubeappsapis.priorityClassName }} + priorityClassName: {{ .Values.kubeappsapis.priorityClassName | quote }} + {{- end }} + {{- if .Values.kubeappsapis.podSecurityContext.enabled }} + securityContext: {{- omit .Values.kubeappsapis.podSecurityContext "enabled" | toYaml | nindent 8 }} + {{- end }} + # Increase termination timeout to let remaining operations to finish before ending the pods + # This is because new releases/upgrades/deletions are synchronous operations + terminationGracePeriodSeconds: {{ .Values.kubeappsapis.terminationGracePeriodSeconds }} + {{- if .Values.kubeappsapis.initContainers }} + initContainers: {{- include "common.tplvalues.render" (dict "value" .Values.kubeappsapis.initContainers "context" $) | trim | nindent 8 }} + {{- end }} + containers: + - name: kubeappsapis + image: {{ include "kubeapps.kubeappsapis.image" . }} + imagePullPolicy: {{ .Values.kubeappsapis.image.pullPolicy | quote }} + {{- if .Values.kubeappsapis.containerSecurityContext.enabled }} + securityContext: {{- omit .Values.kubeappsapis.containerSecurityContext "enabled" | toYaml | nindent 12 }} + {{- end }} + {{- if .Values.kubeappsapis.lifecycleHooks }} + lifecycle: {{- include "common.tplvalues.render" (dict "value" .Values.kubeappsapis.lifecycleHooks "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 12 }} + {{- else if .Values.kubeappsapis.command }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.kubeappsapis.command "context" $) | nindent 12 }} + {{- else }} + command: + - /kubeapps-apis + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 12 }} + {{- else if .Values.kubeappsapis.args }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.kubeappsapis.args "context" $) | nindent 12 }} + {{- else }} + args: + {{- $enabledPlugins := include "kubeapps.kubeappsapis.enabledPlugins" . | fromJsonArray }} + {{- range $enabledPlugins }} + - --plugin-dir + - /plugins/{{ . }} + {{- end }} + {{- if .Values.clusters }} + - --clusters-config-path=/config/clusters.conf + {{- end }} + {{- if .Values.kubeappsapis.pluginConfig }} + - --plugin-config-path=/config/kubeapps-apis/plugins.conf + {{- end }} + {{- if .Values.pinnipedProxy.enabled }} + - --pinniped-proxy-url={{ printf "http%s://%s.%s:%d" (eq .Values.pinnipedProxy.tls.caCertificate "" | ternary "" "s") (include "kubeapps.pinniped-proxy.fullname" .) .Release.Namespace (int .Values.pinnipedProxy.service.ports.pinnipedProxy) }} + {{- if .Values.pinnipedProxy.tls.caCertificate }} + - --pinniped-proxy-ca-cert=/etc/pinniped-proxy-tls/ca.crt + {{- end }} + {{- end }} + - --global-repos-namespace={{ include "kubeapps.helmGlobalPackagingNamespace" . }} + {{- if .Values.kubeappsapis.qps }} + - --kube-api-qps={{ .Values.kubeappsapis.qps }} + {{- end }} + {{- if .Values.kubeappsapis.burst }} + - --kube-api-burst={{ .Values.kubeappsapis.burst }} + {{- end }} + {{- range .Values.kubeappsapis.extraFlags }} + - {{ . }} + {{- end }} + {{- end }} + env: + - name: GOGC + value: "50" # default is 100. 50 means increasing x2 the frequency of GC + - name: PORT + value: {{ .Values.kubeappsapis.containerPorts.http | quote }} + {{- if .Values.packaging.flux.enabled }} + # REDIS-* vars are required by the plugins for caching functionality + # TODO (gfichtenolt) this as required by the kubeapps apis service (which will + # longer-term pass something to the plugins so that the plugins won't need to + # know these details). Currently they're used directly by the flux plugin + - name: REDIS_ADDR + value: {{ printf "%s-master.%s.svc.cluster.local:6379" (include "kubeapps.redis.fullname" .) .Release.Namespace }} + - name: REDIS_PASSWORD + valueFrom: + secretKeyRef: + key: redis-password + name: {{ include "kubeapps.redis.secretName" . }} + - name: REDIS_DB + value: "0" + {{- end }} + # TODO(agamez): pass this configuration using a separated config file + # These env vars are currently (and temporarily) required by the 'helm' plugin + {{- if .Values.packaging.helm.enabled }} + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: ASSET_SYNCER_DB_URL + {{- if .Values.postgresql.enabled }} + value: {{ printf "%s-hl:%d" (include "kubeapps.postgresql.host" .) (int (include "kubeapps.postgresql.port" .)) }} + {{- else }} + value: {{ printf "%s:%d" (include "kubeapps.postgresql.host" .) (int (include "kubeapps.postgresql.port" .)) }} + {{- end }} + - name: ASSET_SYNCER_DB_NAME + value: {{ .Values.postgresql.auth.database | quote }} + - name: ASSET_SYNCER_DB_USERNAME + value: {{ .Values.postgresql.auth.username | quote }} + - name: ASSET_SYNCER_DB_USERPASSWORD + valueFrom: + secretKeyRef: + key: postgres-password + name: {{ include "kubeapps.postgresql.secretName" . }} + {{- if .Values.ociCatalog.enabled }} + - name: OCI_CATALOG_URL + value: {{ printf ":%d" (int .Values.ociCatalog.containerPorts.grpc) | quote }} + {{- end }} + {{- end }} + {{- if .Values.kubeappsapis.extraEnvVars }} + {{- include "common.tplvalues.render" (dict "value" .Values.kubeappsapis.extraEnvVars "context" $) | nindent 12 }} + {{- end }} + envFrom: + {{- if .Values.kubeappsapis.extraEnvVarsCM }} + - configMapRef: + name: {{ include "common.tplvalues.render" (dict "value" .Values.kubeappsapis.extraEnvVarsCM "context" $) }} + {{- end }} + {{- if .Values.kubeappsapis.extraEnvVarsSecret }} + - secretRef: + name: {{ include "common.tplvalues.render" (dict "value" .Values.kubeappsapis.extraEnvVarsSecret "context" $) }} + {{- end }} + ports: + - name: grpc-http + containerPort: {{ .Values.kubeappsapis.containerPorts.http }} + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.kubeappsapis.customLivenessProbe }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.kubeappsapis.customLivenessProbe "context" $) | nindent 12 }} + {{- else if .Values.kubeappsapis.livenessProbe.enabled }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.kubeappsapis.livenessProbe "enabled") "context" $) | nindent 12 }} + exec: + command: ["grpc_health_probe", "-addr=:{{ .Values.kubeappsapis.containerPorts.http }}"] + {{- end }} + {{- if .Values.kubeappsapis.customReadinessProbe }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.kubeappsapis.customReadinessProbe "context" $) | nindent 12 }} + {{- else if .Values.kubeappsapis.readinessProbe.enabled }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.kubeappsapis.readinessProbe "enabled") "context" $) | nindent 12 }} + exec: + command: ["grpc_health_probe", "-addr=:{{ .Values.kubeappsapis.containerPorts.http }}"] + {{- end }} + {{- if .Values.kubeappsapis.customStartupProbe }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" .Values.kubeappsapis.customStartupProbe "context" $) | nindent 12 }} + {{- else if .Values.kubeappsapis.startupProbe.enabled }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.kubeappsapis.startupProbe "enabled") "context" $) | nindent 12 }} + tcpSocket: + port: grpc-http + {{- end }} + {{- end }} + {{- if .Values.kubeappsapis.resources }} + resources: {{- toYaml .Values.kubeappsapis.resources | nindent 12 }} + {{- end }} + volumeMounts: + {{- if .Values.clusters }} + - name: clusters-config + mountPath: /config + - name: ca-certs + mountPath: /etc/additional-clusters-cafiles + {{- end }} + {{- if .Values.kubeappsapis.pluginConfig }} + - name: plugins-config + mountPath: /config/kubeapps-apis + {{- end }} + {{- if .Values.pinnipedProxy.tls.caCertificate }} + - name: pinniped-proxy-ca-cert + mountPath: /etc/pinniped-proxy-tls + {{- end }} + {{- if .Values.kubeappsapis.extraVolumeMounts }} + {{- include "common.tplvalues.render" (dict "value" .Values.kubeappsapis.extraVolumeMounts "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.ociCatalog.enabled }} + - name: oci-catalog + image: {{ include "kubeapps.ociCatalog.image" . }} + imagePullPolicy: {{ .Values.ociCatalog.image.pullPolicy | quote }} + {{- if .Values.ociCatalog.containerSecurityContext.enabled }} + securityContext: {{- omit .Values.ociCatalog.containerSecurityContext "enabled" | toYaml | nindent 12 }} + {{- end }} + {{- if .Values.kubeappsapis.lifecycleHooks }} + lifecycle: {{- include "common.tplvalues.render" (dict "value" .Values.kubeappsapis.lifecycleHooks "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 12 }} + {{- else if .Values.ociCatalog.command }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.ociCatalog.command "context" $) | nindent 12 }} + {{- else }} + command: + - /oci-catalog + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 12 }} + {{- else if .Values.ociCatalog.args }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.kubeappsapis.args "context" $) | nindent 12 }} + {{- else }} + args: + {{- range .Values.ociCatalog.extraFlags }} + - {{ . }} + {{- end }} + {{- end }} + env: + - name: OCI_CATALOG_PORT + value: {{ .Values.ociCatalog.containerPorts.grpc | quote }} + - name: RUST_LOG + # Use info,pinniped_proxy::pinniped=debug for module control. + value: info + {{- if .Values.ociCatalog.extraEnvVars }} + {{- include "common.tplvalues.render" (dict "value" .Values.ociCatalog.extraEnvVars "context" $) | nindent 12 }} + {{- end }} + {{- if or .Values.ociCatalog.extraEnvVarsCM .Values.ociCatalog.extraEnvVarsSecret }} + envFrom: + {{- if .Values.ociCatalog.extraEnvVarsCM }} + - configMapRef: + name: {{ include "common.tplvalues.render" (dict "value" .Values.ociCatalog.extraEnvVarsCM "context" $) }} + {{- end }} + {{- if .Values.ociCatalog.extraEnvVarsSecret }} + - secretRef: + name: {{ include "common.tplvalues.render" (dict "value" .Values.ociCatalog.extraEnvVarsSecret "context" $) }} + {{- end }} + {{- end }} + ports: + - name: grpc + containerPort: {{ .Values.ociCatalog.containerPorts.grpc }} + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.ociCatalog.customLivenessProbe }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.ociCatalog.customLivenessProbe "context" $) | nindent 12 }} + {{- else if .Values.ociCatalog.livenessProbe.enabled }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.kubeappsapis.livenessProbe "enabled") "context" $) | nindent 12 }} + exec: + command: ["grpc_health_probe", "-addr=:{{ .Values.ociCatalog.containerPorts.grpc }}"] + {{- end }} + {{- if .Values.ociCatalog.customReadinessProbe }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.ociCatalog.customReadinessProbe "context" $) | nindent 12 }} + {{- else if .Values.ociCatalog.readinessProbe.enabled }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.ociCatalog.readinessProbe "enabled") "context" $) | nindent 12 }} + exec: + command: ["grpc_health_probe", "-addr=:{{ .Values.ociCatalog.containerPorts.grpc }}"] + {{- end }} + {{- if .Values.ociCatalog.customStartupProbe }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" .Values.ociCatalog.customStartupProbe "context" $) | nindent 12 }} + {{- else if .Values.ociCatalog.startupProbe.enabled }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.ociCatalog.startupProbe "enabled") "context" $) | nindent 12 }} + tcpSocket: + port: grpc-http + {{- end }} + {{- end }} + {{- if .Values.ociCatalog.resources }} + resources: {{- toYaml .Values.ociCatalog.resources | nindent 12 }} + {{- end }} + volumeMounts: + {{- if .Values.ociCatalog.extraVolumeMounts }} + {{- include "common.tplvalues.render" (dict "value" .Values.ociCatalog.extraVolumeMounts "context" $) | nindent 12 }} + {{- end }} + {{- end }} + {{- if .Values.kubeappsapis.sidecars }} + {{- include "common.tplvalues.render" (dict "value" .Values.kubeappsapis.sidecars "context" $) | trim | nindent 8 }} + {{- end }} + volumes: + {{- if .Values.clusters }} + - name: clusters-config + configMap: + name: {{ template "kubeapps.clusters-config.fullname" . }} + - name: ca-certs + emptyDir: {} + {{- end }} + {{- if .Values.kubeappsapis.pluginConfig }} + - name: plugins-config + configMap: + name: {{ template "kubeapps.kubeappsapis.fullname" . }}-configmap + {{- end }} + {{- if .Values.pinnipedProxy.tls.caCertificate }} + - name: pinniped-proxy-ca-cert + configMap: + name: {{ .Values.pinnipedProxy.tls.caCertificate }} + {{- end }} + {{- if .Values.kubeappsapis.extraVolumes }} + {{- include "common.tplvalues.render" (dict "value" .Values.kubeappsapis.extraVolumes "context" $) | nindent 8 }} + {{- end }} diff --git a/packages/system/dashboard/charts/kubeapps/templates/kubeappsapis/rbac.yaml b/packages/system/dashboard/charts/kubeapps/templates/kubeappsapis/rbac.yaml new file mode 100644 index 00000000..d2290714 --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/templates/kubeappsapis/rbac.yaml @@ -0,0 +1,80 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.rbac.create -}} +{{- $versionLabel := dict "app.kubernetes.io/version" ( include "common.images.version" ( dict "imageRoot" .Values.kubeappsapis.image "chart" .Chart ) ) }} +{{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.commonLabels $versionLabel ) "context" . ) }} +apiVersion: {{ include "common.capabilities.rbac.apiVersion" . }} +kind: ClusterRole +metadata: + name: {{ printf "kubeapps:%s:kubeappsapis-ns-discovery" .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: kubeappsapis + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +rules: + - apiGroups: + - "" + resources: + - namespaces + verbs: + - list +--- +apiVersion: {{ include "common.capabilities.rbac.apiVersion" . }} +kind: ClusterRoleBinding +metadata: + name: {{ printf "kubeapps:%s:kubeappsapis-ns-discovery" .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: kubeappsapis + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ printf "kubeapps:%s:kubeappsapis-ns-discovery" .Release.Namespace | quote }} +subjects: + - kind: ServiceAccount + name: {{ template "kubeapps.kubeappsapis.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} +{{- if $.Values.featureFlags.operators }} +--- +apiVersion: {{ include "common.capabilities.rbac.apiVersion" . }} +kind: ClusterRole +metadata: + name: {{ printf "kubeapps:%s:kubeappsapis-operators" .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: kubeappsapis + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +rules: + - apiGroups: + - packages.operators.coreos.com + resources: + - packagemanifests/icon + verbs: + - get +--- +apiVersion: {{ include "common.capabilities.rbac.apiVersion" . }} +kind: ClusterRoleBinding +metadata: + name: {{ printf "kubeapps:%s:kubeappsapis-operators" .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: kubeappsapis + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ printf "kubeapps:%s:kubeappsapis-operators" .Release.Namespace | quote }} +subjects: + - kind: ServiceAccount + name: {{ template "kubeapps.kubeappsapis.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} +{{- end -}} +{{- end -}} diff --git a/packages/system/dashboard/charts/kubeapps/templates/kubeappsapis/rbac_fluxv2.yaml b/packages/system/dashboard/charts/kubeapps/templates/kubeappsapis/rbac_fluxv2.yaml new file mode 100644 index 00000000..1632da6f --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/templates/kubeappsapis/rbac_fluxv2.yaml @@ -0,0 +1,58 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.packaging.flux.enabled }} +{{- $versionLabel := dict "app.kubernetes.io/version" ( include "common.images.version" ( dict "imageRoot" .Values.kubeappsapis.image "chart" .Chart ) ) }} +{{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.commonLabels $versionLabel ) "context" . ) }} +{{- if .Values.rbac.create -}} +apiVersion: {{ include "common.capabilities.rbac.apiVersion" . }} +kind: ClusterRole +metadata: + name: "kubeapps:controller:kubeapps-apis-fluxv2-plugin" + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: kubeappsapis + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +rules: + - apiGroups: ["source.toolkit.fluxcd.io"] + resources: ["helmrepositories"] + verbs: ["get", "list", "watch"] + # needed by fluxv2 plug-in to check whether flux CRDs have been installed + - apiGroups: ["apiextensions.k8s.io"] + resources: ["customresourcedefinitions"] + verbs: ["get", "list"] + # Temp hack to avoid + # Failed to read secret for repo due to: rpc error: code = PermissionDenied desc = Forbidden + # to get the secret 'helm-podinfo' due to 'secrets "helm-podinfo" is forbidden: + # User "system:serviceaccount:kubeapps:kubeapps-internal-kubeappsapis" cannot get resource + # "secrets" in API group "" in the namespace "default"' + # see discussion in https://github.com/vmware-tanzu/kubeapps/pull/4932#issuecomment-1161243049 + - apiGroups: + - "" + resources: + - secrets + verbs: + - get +--- +apiVersion: {{ include "common.capabilities.rbac.apiVersion" . }} +kind: ClusterRoleBinding +metadata: + name: "kubeapps:controller:kubeapps-apis-fluxv2-plugin" + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: kubeappsapis + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: "kubeapps:controller:kubeapps-apis-fluxv2-plugin" +subjects: + - kind: ServiceAccount + name: {{ template "kubeapps.kubeappsapis.serviceAccountName" . }} + namespace: {{ .Release.Namespace | quote }} +{{- end }} +{{- end }} diff --git a/packages/system/dashboard/charts/kubeapps/templates/kubeappsapis/service.yaml b/packages/system/dashboard/charts/kubeapps/templates/kubeappsapis/service.yaml new file mode 100644 index 00000000..85c1a6dc --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/templates/kubeappsapis/service.yaml @@ -0,0 +1,34 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +apiVersion: v1 +kind: Service +metadata: + name: {{ template "kubeapps.kubeappsapis.fullname" . }} + namespace: {{ .Release.Namespace | quote }} + {{- $versionLabel := dict "app.kubernetes.io/version" ( include "common.images.version" ( dict "imageRoot" .Values.kubeappsapis.image "chart" .Chart ) ) }} + {{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.commonLabels $versionLabel ) "context" . ) }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: kubeappsapis + {{- if or .Values.kubeappsapis.service.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.kubeappsapis.service.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + type: ClusterIP + ports: + - port: {{ .Values.kubeappsapis.service.ports.http }} + targetPort: grpc-http + protocol: TCP + name: grpc-http + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.kubeappsapis.podLabels .Values.commonLabels ) "context" . ) }} + {{- if .Values.ociCatalog.enabled }} + - port: {{ .Values.ociCatalog.containerPorts.grpc }} + targetPort: grpc + protocol: TCP + name: grpc + {{- end }} + selector: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: kubeappsapis diff --git a/packages/system/dashboard/charts/kubeapps/templates/kubeappsapis/serviceaccount.yaml b/packages/system/dashboard/charts/kubeapps/templates/kubeappsapis/serviceaccount.yaml new file mode 100644 index 00000000..170724d0 --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/templates/kubeappsapis/serviceaccount.yaml @@ -0,0 +1,21 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.kubeappsapis.serviceAccount.create }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ template "kubeapps.kubeappsapis.serviceAccountName" . }} + namespace: {{ .Release.Namespace | quote }} + {{- $versionLabel := dict "app.kubernetes.io/version" ( include "common.images.version" ( dict "imageRoot" .Values.kubeappsapis.image "chart" .Chart ) ) }} + {{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.commonLabels $versionLabel ) "context" . ) }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: kubeappsapis + {{- if or .Values.kubeappsapis.serviceAccount.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.kubeappsapis.serviceAccount.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +automountServiceAccountToken: {{ .Values.kubeappsapis.serviceAccount.automountServiceAccountToken }} +{{- end }} diff --git a/packages/system/dashboard/charts/kubeapps/templates/shared/config.yaml b/packages/system/dashboard/charts/kubeapps/templates/shared/config.yaml new file mode 100644 index 00000000..7f633f1f --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/templates/shared/config.yaml @@ -0,0 +1,19 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if gt (len .Values.clusters) 0 }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ template "kubeapps.clusters-config.fullname" . }} + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +data: + clusters.conf: |- +{{ .Values.clusters | toPrettyJson | indent 4 }} +{{- end }} diff --git a/packages/system/dashboard/charts/kubeapps/templates/shared/helm-global-repos-namespace.yaml b/packages/system/dashboard/charts/kubeapps/templates/shared/helm-global-repos-namespace.yaml new file mode 100644 index 00000000..b58262c1 --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/templates/shared/helm-global-repos-namespace.yaml @@ -0,0 +1,11 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if or .Values.apprepository.globalReposNamespaceSuffix .Values.kubeappsapis.pluginConfig.helm.packages.v1alpha1.globalPackagingNamespace }} +apiVersion: v1 +kind: Namespace +metadata: + name: {{ include "kubeapps.helmGlobalPackagingNamespace" . | quote }} +{{- end }} diff --git a/packages/system/dashboard/charts/kubeapps/templates/tls-secrets.yaml b/packages/system/dashboard/charts/kubeapps/templates/tls-secrets.yaml new file mode 100644 index 00000000..1d3cbe8a --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/templates/tls-secrets.yaml @@ -0,0 +1,44 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.ingress.enabled }} +{{- if .Values.ingress.secrets }} +{{- range .Values.ingress.secrets }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ .name }} + namespace: {{ $.Release.Namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $.Values.commonLabels "context" $ ) | nindent 4 }} + {{- if $.Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $.Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +type: kubernetes.io/tls +data: + tls.crt: {{ .certificate | b64enc }} + tls.key: {{ .key | b64enc }} +--- +{{- end }} +{{- end }} +{{- if and .Values.ingress.tls .Values.ingress.selfSigned }} +{{- $secretName := printf "%s-tls" .Values.ingress.hostname }} +{{- $ca := genCA "kubeapps-ca" 365 }} +{{- $cert := genSignedCert .Values.ingress.hostname nil (list .Values.ingress.hostname) 365 $ca }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ $secretName }} + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +type: kubernetes.io/tls +data: + tls.crt: {{ include "common.secrets.lookup" (dict "secret" $secretName "key" "tls.crt" "defaultValue" $cert.Cert "context" $) }} + tls.key: {{ include "common.secrets.lookup" (dict "secret" $secretName "key" "tls.key" "defaultValue" $cert.Key "context" $) }} + ca.crt: {{ include "common.secrets.lookup" (dict "secret" $secretName "key" "ca.crt" "defaultValue" $ca.Cert "context" $) }} +{{- end }} +{{- end }} diff --git a/packages/system/dashboard/charts/kubeapps/values.schema.json b/packages/system/dashboard/charts/kubeapps/values.schema.json new file mode 100644 index 00000000..913528b8 --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/values.schema.json @@ -0,0 +1,125 @@ +{ + "$schema": "http://json-schema.org/schema#", + "type": "object", + "properties": { + "frontend": { + "type": "object", + "title": "Frontend configuration", + "form": true, + "properties": { + "replicaCount": { + "type": "integer", + "title": "Number of replicas", + "form": true + } + } + }, + "dashboard": { + "type": "object", + "title": "Dashboard configuration", + "form": true, + "properties": { + "replicaCount": { + "type": "integer", + "title": "Number of replicas", + "form": true + } + } + }, + "kubeappsapis": { + "type": "object", + "title": "kubeappsapis configuration", + "form": true, + "properties": { + "replicaCount": { + "type": "integer", + "title": "Number of replicas", + "form": true + } + } + }, + "ingress": { + "type": "object", + "form": true, + "title": "Ingress configuration", + "properties": { + "enabled": { + "type": "boolean", + "form": true, + "title": "Use a custom hostname", + "description": "Enable the ingress resource that allows you to access the Kubeapps dashboard." + }, + "hostname": { + "type": "string", + "form": true, + "title": "Hostname", + "hidden": { + "value": false, + "path": "ingress/enabled" + } + }, + "tls": { + "type": "boolean", + "form": true, + "title": "Enable TLS configuration", + "hidden": { + "value": false, + "path": "ingress/enabled" + } + } + } + }, + "authProxy": { + "type": "object", + "title": "OIDC Proxy configuration", + "properties": { + "enabled": { + "type": "boolean", + "form": true, + "title": "Enable OIDC proxy", + "description": "Use an OIDC provider in order to manage accounts, groups and roles with a single application" + }, + "provider": { + "type": "string", + "form": true, + "title": "Identity Provider name", + "description": "See https://oauth2-proxy.github.io/oauth2-proxy/docs/configuration/overview#generating-a-cookie-secret to find available providers", + "hidden": { + "value": false, + "path": "authProxy/enabled" + } + }, + "clientID": { + "type": "string", + "form": true, + "title": "Client ID:", + "description": "Client ID of the Identity Provider", + "hidden": { + "value": false, + "path": "authProxy/enabled" + } + }, + "clientSecret": { + "type": "string", + "form": true, + "title": "Client Secret", + "description": "Secret used to validate the Client ID", + "hidden": { + "value": false, + "path": "authProxy/enabled" + } + }, + "cookieSecret": { + "type": "string", + "form": true, + "title": "Cookie Secret", + "description": "Used by OAuth2 Proxy to encrypt any credentials", + "hidden": { + "value": false, + "path": "authProxy/enabled" + } + } + } + } + } +} diff --git a/packages/system/dashboard/charts/kubeapps/values.yaml b/packages/system/dashboard/charts/kubeapps/values.yaml new file mode 100644 index 00000000..6b4dae2d --- /dev/null +++ b/packages/system/dashboard/charts/kubeapps/values.yaml @@ -0,0 +1,2150 @@ +# Copyright VMware, Inc. +# SPDX-License-Identifier: APACHE-2.0 + +## @section Global parameters +## Global Docker image parameters +## Please, note that this will override the image parameters, including dependencies, configured to use the global value +## Current available global Docker image parameters: imageRegistry, imagePullSecrets and storageClass + +## @param global.imageRegistry Global Docker image registry +## @param global.imagePullSecrets Global Docker registry secret names as an array +## @param global.storageClass Global StorageClass for Persistent Volume(s) +## +global: + imageRegistry: "" + ## E.g. + ## imagePullSecrets: + ## - myRegistryKeySecretName + ## + imagePullSecrets: [] + storageClass: "" + +## @section Common parameters + +## @param kubeVersion Override Kubernetes version +## +kubeVersion: "" +## @param nameOverride String to partially override common.names.fullname +## +nameOverride: "" +## @param fullnameOverride String to fully override common.names.fullname +## +fullnameOverride: "" +## @param commonLabels Labels to add to all deployed objects +## +commonLabels: {} +## @param commonAnnotations Annotations to add to all deployed objects +## +commonAnnotations: {} +## @param extraDeploy Array of extra objects to deploy with the release +## +extraDeploy: [] +## @param enableIPv6 Enable IPv6 configuration +## +enableIPv6: false + +## Enable diagnostic mode in the deployment +## +diagnosticMode: + ## @param diagnosticMode.enabled Enable diagnostic mode (all probes will be disabled and the command will be overridden) + ## + enabled: false + ## @param diagnosticMode.command Command to override all containers in the deployment + ## + command: + - sleep + ## @param diagnosticMode.args Args to override all containers in the deployment + ## + args: + - infinity + +## @section Traffic Exposure Parameters + +## Configure the ingress resource that allows you to access the Kubeapps installation +## ref: https://kubernetes.io/docs/concepts/services-networking/ingress/ +## +ingress: + ## @param ingress.enabled Enable ingress record generation for Kubeapps + ## + enabled: false + ## @param ingress.apiVersion Force Ingress API version (automatically detected if not set) + ## + apiVersion: "" + ## @param ingress.hostname Default host for the ingress record + ## + hostname: kubeapps.local + ## @param ingress.path Default path for the ingress record + ## NOTE: You may need to set this to '/*' in order to use this with ALB ingress controllers + ## + path: / + ## @param ingress.pathType Ingress path type + ## + pathType: ImplementationSpecific + ## @param ingress.annotations [object] Additional annotations for the Ingress resource. To enable certificate autogeneration, place here your cert-manager annotations. + ## For a full list of possible ingress annotations, please see + ## ref: https://github.com/kubernetes/ingress-nginx/blob/main/docs/user-guide/nginx-configuration/annotations.md + ## Use this parameter to set the required annotations for cert-manager, see + ## ref: https://cert-manager.io/docs/usage/ingress/#supported-annotations + ## + ## e.g: + ## annotations: + ## kubernetes.io/ingress.class: nginx + ## cert-manager.io/cluster-issuer: cluster-issuer-name + ## + annotations: + nginx.ingress.kubernetes.io/proxy-read-timeout: "600" + ## @param ingress.tls Enable TLS configuration for the host defined at `ingress.hostname` parameter + ## TLS certificates will be retrieved from a TLS secret with name: `{{- printf "%s-tls" .Values.ingress.hostname }}` + ## You can: + ## - Use the `ingress.secrets` parameter to create this TLS secret + ## - Rely on cert-manager to create it by setting the corresponding annotations + ## - Rely on Helm to create self-signed certificates by setting `ingress.selfSigned=true` + ## + tls: false + + ## @param ingress.selfSigned Create a TLS secret for this ingress record using self-signed certificates generated by Helm + ## + selfSigned: false + ## @param ingress.extraHosts An array with additional hostname(s) to be covered with the ingress record + ## e.g: + ## extraHosts: + ## - name: kubeapps.local + ## path: / + ## + extraHosts: [] + ## @param ingress.extraPaths An array with additional arbitrary paths that may need to be added to the ingress under the main host + ## e.g: + ## extraPaths: + ## - path: /* + ## backend: + ## serviceName: ssl-redirect + ## servicePort: use-annotation + ## + extraPaths: [] + ## @param ingress.extraTls TLS configuration for additional hostname(s) to be covered with this ingress record + ## ref: https://kubernetes.io/docs/concepts/services-networking/ingress/#tls + ## e.g: + ## extraTls: + ## - hosts: + ## - kubeapps.local + ## secretName: kubeapps.local-tls + ## + extraTls: [] + ## @param ingress.secrets Custom TLS certificates as secrets + ## NOTE: 'key' and 'certificate' are expected in PEM format + ## NOTE: 'name' should line up with a 'secretName' set further up + ## If it is not set and you're using cert-manager, this is unneeded, as it will create a secret for you with valid certificates + ## If it is not set and you're NOT using cert-manager either, self-signed certificates will be created valid for 365 days + ## It is also possible to create and manage the certificates outside of this helm chart + ## Please see README.md for more information + ## e.g: + ## secrets: + ## - name: kubeapps.local-tls + ## key: |- + ## -----BEGIN RSA PRIVATE KEY----- + ## ... + ## -----END RSA PRIVATE KEY----- + ## certificate: |- + ## -----BEGIN CERTIFICATE----- + ## ... + ## -----END CERTIFICATE----- + ## + secrets: [] + ## @param ingress.ingressClassName IngressClass that will be be used to implement the Ingress (Kubernetes 1.18+) + ## This is supported in Kubernetes 1.18+ and required if you have more than one IngressClass marked as the default for your cluster . + ## ref: https://kubernetes.io/blog/2020/04/02/improvements-to-the-ingress-api-in-kubernetes-1.18/ + ## + ingressClassName: "" + ## @param ingress.extraRules Additional rules to be covered with this ingress record + ## ref: https://kubernetes.io/docs/concepts/services-networking/ingress/#ingress-rules + ## e.g: + ## extraRules: + ## - host: example.local + ## http: + ## path: / + ## backend: + ## service: + ## name: example-svc + ## port: + ## name: http + ## + extraRules: [] + +## @section Kubeapps packaging options +## Note: the helm and flux plugins are mutually exclusive, you can only +## enable one or the other since they both operate on Helm release objects. +## Enabling carvel or flux does *not* install the required related Carvel or +## Flux controllers on your cluster. Please read the documentation for running +## Kubeapps with Carvel or Flux support. +packaging: + ## Default helm packaging + ## @param packaging.helm.enabled Enable the standard Helm packaging. + helm: + enabled: true + ## Carvel packaging + ## @param packaging.carvel.enabled Enable support for the Carvel (kapp-controller) packaging. + carvel: + enabled: false + ## Flux (v2) packaging + ## @param packaging.flux.enabled Enable support for Flux (v2) packaging. + flux: + enabled: false + +## @section Frontend parameters + +## Frontend parameters +## +frontend: + ## Bitnami NGINX image + ## ref: https://hub.docker.com/r/bitnami/nginx/tags/ + ## @param frontend.image.registry [default: REGISTRY_NAME] NGINX image registry + ## @param frontend.image.repository [default: REPOSITORY_NAME/nginx] NGINX image repository + ## @skip frontend.image.tag NGINX image tag (immutable tags are recommended) + ## @param frontend.image.digest NGINX image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag + ## @param frontend.image.pullPolicy NGINX image pull policy + ## @param frontend.image.pullSecrets NGINX image pull secrets + ## @param frontend.image.debug Enable image debug mode + ## + image: + registry: docker.io + repository: bitnami/nginx + tag: 1.25.3-debian-11-r1 + digest: "" + ## Specify a imagePullPolicy + ## Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent' + ## ref: https://kubernetes.io/docs/user-guide/images/#pre-pulling-images + ## + pullPolicy: IfNotPresent + ## Optionally specify an array of imagePullSecrets. + ## Secrets must be manually created in the namespace. + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ + ## e.g: + ## pullSecrets: + ## - myRegistryKeySecretName + ## + pullSecrets: [] + ## Enable debug mode + ## + debug: false + ## @param frontend.proxypassAccessTokenAsBearer Use access_token as the Bearer when talking to the k8s api server + ## NOTE: Some K8s distributions such as GKE requires it + ## + proxypassAccessTokenAsBearer: false + ## @param frontend.proxypassExtraSetHeader Set an additional proxy header for all requests proxied via NGINX + ## e.g: + ## proxypassExtraSetHeader: Authorization "Bearer $cookie_sessionid"; + ## + proxypassExtraSetHeader: "" + ## @param frontend.largeClientHeaderBuffers Set large_client_header_buffers in NGINX config + ## NOTE: Can be required when using OIDC or LDAP due to large cookies + ## + largeClientHeaderBuffers: "4 32k" + ## @param frontend.replicaCount Number of frontend replicas to deploy + ## + replicaCount: 2 + ## @param frontend.updateStrategy.type Frontend deployment strategy type. + ## ref: https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#strategy + ## e.g: + ## updateStrategy: + ## type: RollingUpdate + ## rollingUpdate: + ## maxSurge: 25% + ## maxUnavailable: 25% + ## + updateStrategy: + type: RollingUpdate + ## Frontend containers' resource requests and limits + ## ref: https://kubernetes.io/docs/user-guide/compute-resources/ + ## @param frontend.resources.limits.cpu The CPU limits for the NGINX container + ## @param frontend.resources.limits.memory The memory limits for the NGINX container + ## @param frontend.resources.requests.cpu The requested CPU for the NGINX container + ## @param frontend.resources.requests.memory The requested memory for the NGINX container + ## + resources: + limits: + cpu: 250m + memory: 128Mi + requests: + cpu: 25m + memory: 32Mi + ## @param frontend.extraEnvVars Array with extra environment variables to add to the NGINX container + ## e.g: + ## extraEnvVars: + ## - name: FOO + ## value: "bar" + ## + extraEnvVars: [] + ## @param frontend.extraEnvVarsCM Name of existing ConfigMap containing extra env vars for the NGINX container + ## + extraEnvVarsCM: "" + ## @param frontend.extraEnvVarsSecret Name of existing Secret containing extra env vars for the NGINX container + ## + extraEnvVarsSecret: "" + ## @param frontend.containerPorts.http NGINX HTTP container port + ## + containerPorts: + http: 8080 + ## Configure Pods Security Context + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod + ## @param frontend.podSecurityContext.enabled Enabled frontend pods' Security Context + ## @param frontend.podSecurityContext.fsGroup Set frontend pod's Security Context fsGroup + ## + podSecurityContext: + enabled: true + fsGroup: 1001 + ## Configure Container Security Context for NGINX + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container + ## @param frontend.containerSecurityContext.enabled Enabled containers' Security Context + ## @param frontend.containerSecurityContext.runAsUser Set containers' Security Context runAsUser + ## @param frontend.containerSecurityContext.runAsNonRoot Set container's Security Context runAsNonRoot + ## @param frontend.containerSecurityContext.privileged Set container's Security Context privileged + ## @param frontend.containerSecurityContext.readOnlyRootFilesystem Set container's Security Context readOnlyRootFilesystem + ## @param frontend.containerSecurityContext.allowPrivilegeEscalation Set container's Security Context allowPrivilegeEscalation + ## @param frontend.containerSecurityContext.capabilities.drop List of capabilities to be dropped + ## @param frontend.containerSecurityContext.seccompProfile.type Set container's Security Context seccomp profile + ## + containerSecurityContext: + enabled: true + runAsUser: 1001 + runAsNonRoot: true + privileged: false + readOnlyRootFilesystem: false + allowPrivilegeEscalation: false + capabilities: + drop: ["ALL"] + seccompProfile: + type: "RuntimeDefault" + ## Configure extra options for frontend containers' liveness and readiness probes + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/#configure-probes + ## @param frontend.livenessProbe.enabled Enable livenessProbe + ## @param frontend.livenessProbe.initialDelaySeconds Initial delay seconds for livenessProbe + ## @param frontend.livenessProbe.periodSeconds Period seconds for livenessProbe + ## @param frontend.livenessProbe.timeoutSeconds Timeout seconds for livenessProbe + ## @param frontend.livenessProbe.failureThreshold Failure threshold for livenessProbe + ## @param frontend.livenessProbe.successThreshold Success threshold for livenessProbe + ## + livenessProbe: + enabled: true + initialDelaySeconds: 60 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 6 + successThreshold: 1 + ## @param frontend.readinessProbe.enabled Enable readinessProbe + ## @param frontend.readinessProbe.initialDelaySeconds Initial delay seconds for readinessProbe + ## @param frontend.readinessProbe.periodSeconds Period seconds for readinessProbe + ## @param frontend.readinessProbe.timeoutSeconds Timeout seconds for readinessProbe + ## @param frontend.readinessProbe.failureThreshold Failure threshold for readinessProbe + ## @param frontend.readinessProbe.successThreshold Success threshold for readinessProbe + ## + readinessProbe: + enabled: true + initialDelaySeconds: 0 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 6 + successThreshold: 1 + ## @param frontend.startupProbe.enabled Enable startupProbe + ## @param frontend.startupProbe.initialDelaySeconds Initial delay seconds for startupProbe + ## @param frontend.startupProbe.periodSeconds Period seconds for startupProbe + ## @param frontend.startupProbe.timeoutSeconds Timeout seconds for startupProbe + ## @param frontend.startupProbe.failureThreshold Failure threshold for startupProbe + ## @param frontend.startupProbe.successThreshold Success threshold for startupProbe + ## + startupProbe: + enabled: false + initialDelaySeconds: 0 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 6 + successThreshold: 1 + ## @param frontend.customLivenessProbe Custom livenessProbe that overrides the default one + ## + customLivenessProbe: {} + ## @param frontend.customReadinessProbe Custom readinessProbe that overrides the default one + ## + customReadinessProbe: {} + ## @param frontend.customStartupProbe Custom startupProbe that overrides the default one + ## + customStartupProbe: {} + ## @param frontend.lifecycleHooks Custom lifecycle hooks for frontend containers + ## + lifecycleHooks: {} + ## @param frontend.command Override default container command (useful when using custom images) + ## + command: [] + ## @param frontend.args Override default container args (useful when using custom images) + ## + args: [] + ## @param frontend.podLabels Extra labels for frontend pods + ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ + ## + podLabels: {} + ## @param frontend.podAnnotations Annotations for frontend pods + ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ + ## + podAnnotations: {} + ## @param frontend.podAffinityPreset Pod affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity + ## + podAffinityPreset: "" + ## @param frontend.podAntiAffinityPreset Pod anti-affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` + ## Ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity + ## + podAntiAffinityPreset: soft + ## nodeAffinityPreset Node affinity preset + ## Ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#node-affinity + ## + nodeAffinityPreset: + ## @param frontend.nodeAffinityPreset.type Node affinity preset type. Ignored if `affinity` is set. Allowed values: `soft` or `hard` + ## + type: "" + ## @param frontend.nodeAffinityPreset.key Node label key to match. Ignored if `affinity` is set + ## + key: "" + ## @param frontend.nodeAffinityPreset.values Node label values to match. Ignored if `affinity` is set + ## E.g. + ## values: + ## - e2e-az1 + ## - e2e-az2 + ## + values: [] + ## @param frontend.affinity Affinity for pod assignment + ## Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity + ## NOTE: frontend.podAffinityPreset, frontend.podAntiAffinityPreset, and frontend.nodeAffinityPreset will be ignored when it's set + ## + affinity: {} + ## @param frontend.nodeSelector Node labels for pod assignment + ## ref: https://kubernetes.io/docs/user-guide/node-selection/ + ## + nodeSelector: {} + ## @param frontend.tolerations Tolerations for pod assignment + ## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ + ## + tolerations: [] + ## @param frontend.priorityClassName Priority class name for frontend pods + ## + priorityClassName: "" + ## @param frontend.schedulerName Name of the k8s scheduler (other than default) + ## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ + ## + schedulerName: "" + ## @param frontend.topologySpreadConstraints Topology Spread Constraints for pod assignment + ## https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/ + ## The value is evaluated as a template + ## + topologySpreadConstraints: [] + ## @param frontend.hostAliases Custom host aliases for frontend pods + ## https://kubernetes.io/docs/concepts/services-networking/add-entries-to-pod-etc-hosts-with-host-aliases/ + ## + hostAliases: [] + ## @param frontend.extraVolumes Optionally specify extra list of additional volumes for frontend pods + ## + extraVolumes: [] + ## @param frontend.extraVolumeMounts Optionally specify extra list of additional volumeMounts for frontend container(s) + ## + extraVolumeMounts: [] + ## @param frontend.sidecars Add additional sidecar containers to the frontend pod + ## e.g: + ## sidecars: + ## - name: your-image-name + ## image: your-image + ## imagePullPolicy: Always + ## ports: + ## - name: portname + ## containerPort: 1234 + ## + sidecars: [] + ## @param frontend.initContainers Add additional init containers to the frontend pods + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/init-containers/ + ## e.g: + ## initContainers: + ## - name: your-image-name + ## image: your-image + ## imagePullPolicy: Always + ## command: ['sh', '-c', 'echo "hello world"'] + ## + initContainers: [] + ## Frontend service parameters + ## + service: + ## @param frontend.service.type Frontend service type + ## + type: ClusterIP + ## @param frontend.service.ports.http Frontend service HTTP port + ## + ports: + http: 80 + ## @param frontend.service.nodePorts.http Node port for HTTP + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#nodeport + ## + nodePorts: + http: "" + ## @param frontend.service.clusterIP Frontend service Cluster IP + ## e.g.: + ## clusterIP: None + ## + clusterIP: "" + ## @param frontend.service.loadBalancerIP Frontend service Load Balancer IP + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#type-loadbalancer + ## + loadBalancerIP: "" + ## @param frontend.service.loadBalancerSourceRanges Frontend service Load Balancer sources + ## ref: https://v1-17.docs.kubernetes.io/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/#restrict-access-for-loadbalancer-service + ## e.g: + ## loadBalancerSourceRanges: + ## - 10.10.10.0/24 + ## + loadBalancerSourceRanges: [] + ## @param frontend.service.externalTrafficPolicy Frontend service external traffic policy + ## ref https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip + ## + externalTrafficPolicy: Cluster + ## @param frontend.service.extraPorts Extra ports to expose (normally used with the `sidecar` value) + ## + extraPorts: [] + ## @param frontend.service.annotations Additional custom annotations for frontend service + ## + annotations: {} + ## @param frontend.service.sessionAffinity Session Affinity for Kubernetes service, can be "None" or "ClientIP" + ## If "ClientIP", consecutive client requests will be directed to the same Pod + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#virtual-ips-and-service-proxies + ## + sessionAffinity: None + ## @param frontend.service.sessionAffinityConfig Additional settings for the sessionAffinity + ## sessionAffinityConfig: + ## clientIP: + ## timeoutSeconds: 300 + ## + sessionAffinityConfig: {} + +## @section Dashboard parameters + +## Dashboard parameters +## +dashboard: + ## @param dashboard.enabled Specifies whether Kubeapps Dashboard should be deployed or not + ## + enabled: true + ## Bitnami Kubeapps Dashboard image + ## ref: https://hub.docker.com/r/bitnami/kubeapps-dashboard/ + ## @param dashboard.image.registry [default: REGISTRY_NAME] Dashboard image registry + ## @param dashboard.image.repository [default: REPOSITORY_NAME/kubeapps-dashboard] Dashboard image repository + ## @skip dashboard.image.tag Dashboard image tag (immutable tags are recommended) + ## @param dashboard.image.digest Dashboard image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag + ## @param dashboard.image.pullPolicy Dashboard image pull policy + ## @param dashboard.image.pullSecrets Dashboard image pull secrets + ## @param dashboard.image.debug Enable image debug mode + ## + image: + registry: docker.io + repository: bitnami/kubeapps-dashboard + tag: 2.9.0-debian-11-r16 + digest: "" + ## Specify a imagePullPolicy + ## Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent' + ## ref: https://kubernetes.io/docs/user-guide/images/#pre-pulling-images + ## + pullPolicy: IfNotPresent + ## Optionally specify an array of imagePullSecrets. + ## Secrets must be manually created in the namespace. + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ + ## e.g: + ## pullSecrets: + ## - myRegistryKeySecretName + ## + pullSecrets: [] + ## Enable debug mode + ## + debug: false + ## @param dashboard.customStyle Custom CSS injected to the Dashboard to customize Kubeapps look and feel + ## e.g: + ## customStyle: |- + ## .header.header-7 { + ## background-color: #991700; + ## } + ## + customStyle: "" + ## @param dashboard.customAppViews Package names to signal a custom app view + ## ref: https://github.com/vmware-tanzu/kubeapps/blob/main/site/content/docs/latest/howto/custom-app-view-support.md + ## e.g: + ## customAppViews: + ## - plugin: helm + ## name: helm-chart + ## repository: bitnami + customAppViews: [] + ## @param dashboard.customComponents Custom Form components injected into the BasicDeploymentForm + ## ref: https://github.com/vmware-tanzu/kubeapps/blob/main/site/content/docs/latest/howto/custom-form-component-support.md + ## + customComponents: "" + ## @param dashboard.remoteComponentsUrl Remote URL that can be used to load custom components vs loading from the local filesystem + ## + remoteComponentsUrl: "" + ## @param dashboard.skipAvailablePackageDetails Skip the package details view and go straight to the installation view of the latest version + ## + skipAvailablePackageDetails: false + ## @param dashboard.customLocale Custom translations injected to the Dashboard to customize the strings used in Kubeapps + ## ref: https://github.com/vmware-tanzu/kubeapps/blob/main/site/content/docs/latest/reference/translations/translate-kubeapps.md + ## e.g: + ## customLocale: + ## "Kubeapps": "My Dashboard" + ## "login-oidc": "Login with my company SSO" + ## + customLocale: "" + ## @param dashboard.defaultTheme Default theme used in the Dashboard if the user has not selected any theme yet. + ## enum: [ "light", "dark" ] + ## e.g: + ## defaultTheme: dark + ## + defaultTheme: "" + ## @param dashboard.replicaCount Number of Dashboard replicas to deploy + ## + ## @param dashboard.createNamespaceLabels Labels added to newly created namespaces + ## e.g: + # createNamespaceLabels: + # "managed-by": "kubeapps" + createNamespaceLabels: {} + replicaCount: 2 + ## @param dashboard.updateStrategy.type Dashboard deployment strategy type. + ## ref: https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#strategy + ## e.g: + ## updateStrategy: + ## type: RollingUpdate + ## rollingUpdate: + ## maxSurge: 25% + ## maxUnavailable: 25% + ## + updateStrategy: + type: RollingUpdate + ## @param dashboard.extraEnvVars Array with extra environment variables to add to the Dashboard container + ## e.g: + ## extraEnvVars: + ## - name: FOO + ## value: "bar" + ## + extraEnvVars: [] + ## @param dashboard.extraEnvVarsCM Name of existing ConfigMap containing extra env vars for the Dashboard container + ## + extraEnvVarsCM: "" + ## @param dashboard.extraEnvVarsSecret Name of existing Secret containing extra env vars for the Dashboard container + ## + extraEnvVarsSecret: "" + ## @param dashboard.containerPorts.http Dashboard HTTP container port + ## + containerPorts: + http: 8080 + ## Dashboard containers' resource requests and limits + ## ref: https://kubernetes.io/docs/user-guide/compute-resources/ + ## @param dashboard.resources.limits.cpu The CPU limits for the Dashboard container + ## @param dashboard.resources.limits.memory The memory limits for the Dashboard container + ## @param dashboard.resources.requests.cpu The requested CPU for the Dashboard container + ## @param dashboard.resources.requests.memory The requested memory for the Dashboard container + ## + resources: + limits: + cpu: 250m + memory: 128Mi + requests: + cpu: 25m + memory: 32Mi + ## Configure Pods Security Context + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod + ## @param dashboard.podSecurityContext.enabled Enabled Dashboard pods' Security Context + ## @param dashboard.podSecurityContext.fsGroup Set Dashboard pod's Security Context fsGroup + ## + podSecurityContext: + enabled: true + fsGroup: 1001 + ## Configure Container Security Context for Dashboard + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container + ## @param dashboard.containerSecurityContext.enabled Enabled containers' Security Context + ## @param dashboard.containerSecurityContext.runAsUser Set containers' Security Context runAsUser + ## @param dashboard.containerSecurityContext.runAsNonRoot Set container's Security Context runAsNonRoot + ## @param dashboard.containerSecurityContext.privileged Set container's Security Context privileged + ## @param dashboard.containerSecurityContext.readOnlyRootFilesystem Set container's Security Context readOnlyRootFilesystem + ## @param dashboard.containerSecurityContext.allowPrivilegeEscalation Set container's Security Context allowPrivilegeEscalation + ## @param dashboard.containerSecurityContext.capabilities.drop List of capabilities to be dropped + ## @param dashboard.containerSecurityContext.seccompProfile.type Set container's Security Context seccomp profile + ## + containerSecurityContext: + enabled: true + runAsUser: 1001 + runAsNonRoot: true + privileged: false + readOnlyRootFilesystem: false + allowPrivilegeEscalation: false + capabilities: + drop: ["ALL"] + seccompProfile: + type: "RuntimeDefault" + ## Configure extra options for Dashboard containers' liveness and readiness probes + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/#configure-probes + ## @param dashboard.livenessProbe.enabled Enable livenessProbe + ## @param dashboard.livenessProbe.initialDelaySeconds Initial delay seconds for livenessProbe + ## @param dashboard.livenessProbe.periodSeconds Period seconds for livenessProbe + ## @param dashboard.livenessProbe.timeoutSeconds Timeout seconds for livenessProbe + ## @param dashboard.livenessProbe.failureThreshold Failure threshold for livenessProbe + ## @param dashboard.livenessProbe.successThreshold Success threshold for livenessProbe + ## Dashboard containers' liveness and readiness probes + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes + ## + livenessProbe: + enabled: true + initialDelaySeconds: 60 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 6 + successThreshold: 1 + ## @param dashboard.readinessProbe.enabled Enable readinessProbe + ## @param dashboard.readinessProbe.initialDelaySeconds Initial delay seconds for readinessProbe + ## @param dashboard.readinessProbe.periodSeconds Period seconds for readinessProbe + ## @param dashboard.readinessProbe.timeoutSeconds Timeout seconds for readinessProbe + ## @param dashboard.readinessProbe.failureThreshold Failure threshold for readinessProbe + ## @param dashboard.readinessProbe.successThreshold Success threshold for readinessProbe + ## + readinessProbe: + enabled: true + initialDelaySeconds: 0 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 6 + successThreshold: 1 + ## @param dashboard.startupProbe.enabled Enable startupProbe + ## @param dashboard.startupProbe.initialDelaySeconds Initial delay seconds for startupProbe + ## @param dashboard.startupProbe.periodSeconds Period seconds for startupProbe + ## @param dashboard.startupProbe.timeoutSeconds Timeout seconds for startupProbe + ## @param dashboard.startupProbe.failureThreshold Failure threshold for startupProbe + ## @param dashboard.startupProbe.successThreshold Success threshold for startupProbe + ## + startupProbe: + enabled: true + initialDelaySeconds: 0 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 6 + successThreshold: 1 + ## @param dashboard.customLivenessProbe Custom livenessProbe that overrides the default one + ## + customLivenessProbe: {} + ## @param dashboard.customReadinessProbe Custom readinessProbe that overrides the default one + ## + customReadinessProbe: {} + ## @param dashboard.customStartupProbe Custom startupProbe that overrides the default one + ## + customStartupProbe: {} + ## @param dashboard.lifecycleHooks Custom lifecycle hooks for Dashboard containers + ## + lifecycleHooks: {} + ## @param dashboard.command Override default container command (useful when using custom images) + ## + command: [] + ## @param dashboard.args Override default container args (useful when using custom images) + ## + args: [] + ## @param dashboard.podLabels Extra labels for Dashboard pods + ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ + ## + podLabels: {} + ## @param dashboard.podAnnotations Annotations for Dashboard pods + ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ + ## + podAnnotations: {} + ## @param dashboard.podAffinityPreset Pod affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity + ## + podAffinityPreset: "" + ## @param dashboard.podAntiAffinityPreset Pod anti-affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` + ## Ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity + ## + podAntiAffinityPreset: soft + ## Node affinity preset + ## Ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#node-affinity + ## + nodeAffinityPreset: + ## @param dashboard.nodeAffinityPreset.type Node affinity preset type. Ignored if `affinity` is set. Allowed values: `soft` or `hard` + ## + type: "" + ## @param dashboard.nodeAffinityPreset.key Node label key to match. Ignored if `affinity` is set + ## + key: "" + ## @param dashboard.nodeAffinityPreset.values Node label values to match. Ignored if `affinity` is set + ## E.g. + ## values: + ## - e2e-az1 + ## - e2e-az2 + ## + values: [] + ## @param dashboard.affinity Affinity for pod assignment + ## Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity + ## NOTE: dashboard.podAffinityPreset, dashboard.podAntiAffinityPreset, and dashboard.nodeAffinityPreset will be ignored when it's set + ## + affinity: {} + ## @param dashboard.nodeSelector Node labels for pod assignment + ## ref: https://kubernetes.io/docs/user-guide/node-selection/ + ## + nodeSelector: {} + ## @param dashboard.tolerations Tolerations for pod assignment + ## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ + ## + tolerations: [] + ## @param dashboard.priorityClassName Priority class name for Dashboard pods + ## + priorityClassName: "" + ## @param dashboard.schedulerName Name of the k8s scheduler (other than default) + ## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ + ## + schedulerName: "" + ## @param dashboard.topologySpreadConstraints Topology Spread Constraints for pod assignment + ## https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/ + ## The value is evaluated as a template + ## + topologySpreadConstraints: [] + ## @param dashboard.hostAliases Custom host aliases for Dashboard pods + ## https://kubernetes.io/docs/concepts/services-networking/add-entries-to-pod-etc-hosts-with-host-aliases/ + ## + hostAliases: [] + ## @param dashboard.extraVolumes Optionally specify extra list of additional volumes for Dashboard pods + ## + extraVolumes: [] + ## @param dashboard.extraVolumeMounts Optionally specify extra list of additional volumeMounts for Dashboard container(s) + ## + extraVolumeMounts: [] + ## @param dashboard.sidecars Add additional sidecar containers to the Dashboard pod + ## e.g: + ## sidecars: + ## - name: your-image-name + ## image: your-image + ## imagePullPolicy: Always + ## ports: + ## - name: portname + ## containerPort: 1234 + ## + sidecars: [] + ## @param dashboard.initContainers Add additional init containers to the Dashboard pods + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/init-containers/ + ## e.g: + ## initContainers: + ## - name: your-image-name + ## image: your-image + ## imagePullPolicy: Always + ## command: ['sh', '-c', 'echo "hello world"'] + ## + initContainers: [] + ## Dashboard service parameters + ## + service: + ## @param dashboard.service.ports.http Dashboard service HTTP port + ## + ports: + http: 8080 + ## @param dashboard.service.annotations Additional custom annotations for Dashboard service + ## + annotations: {} + +## @section AppRepository Controller parameters + +## AppRepository Controller parameters +## +apprepository: + ## Bitnami Kubeapps AppRepository Controller image + ## ref: https://hub.docker.com/r/bitnami/kubeapps-apprepository-controller/tags/ + ## @param apprepository.image.registry [default: REGISTRY_NAME] Kubeapps AppRepository Controller image registry + ## @param apprepository.image.repository [default: REPOSITORY_NAME/kubeapps-apprepository-controller] Kubeapps AppRepository Controller image repository + ## @skip apprepository.image.tag Kubeapps AppRepository Controller image tag (immutable tags are recommended) + ## @param apprepository.image.digest Kubeapps AppRepository Controller image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag + ## @param apprepository.image.pullPolicy Kubeapps AppRepository Controller image pull policy + ## @param apprepository.image.pullSecrets Kubeapps AppRepository Controller image pull secrets + ## + image: + registry: docker.io + repository: bitnami/kubeapps-apprepository-controller + tag: 2.9.0-debian-11-r12 + digest: "" + ## Specify a imagePullPolicy + ## Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent' + ## ref: https://kubernetes.io/docs/user-guide/images/#pre-pulling-images + ## + pullPolicy: IfNotPresent + ## Optionally specify an array of imagePullSecrets. + ## Secrets must be manually created in the namespace. + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ + ## e.g: + ## pullSecrets: + ## - myRegistryKeySecretName + ## + pullSecrets: [] + ## Bitnami Kubeapps Asset Syncer image + ## ref: https://hub.docker.com/r/bitnami/kubeapps-asset-syncer/tags/ + ## @param apprepository.syncImage.registry [default: REGISTRY_NAME] Kubeapps Asset Syncer image registry + ## @param apprepository.syncImage.repository [default: REPOSITORY_NAME/kubeapps-asset-syncer] Kubeapps Asset Syncer image repository + ## @skip apprepository.syncImage.tag Kubeapps Asset Syncer image tag (immutable tags are recommended) + ## @param apprepository.syncImage.digest Kubeapps Asset Syncer image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag + ## @param apprepository.syncImage.pullPolicy Kubeapps Asset Syncer image pull policy + ## @param apprepository.syncImage.pullSecrets Kubeapps Asset Syncer image pull secrets + ## + syncImage: + registry: docker.io + repository: bitnami/kubeapps-asset-syncer + tag: 2.9.0-debian-11-r13 + digest: "" + ## Specify a imagePullPolicy + ## Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent' + ## ref: https://kubernetes.io/docs/user-guide/images/#pre-pulling-images + ## + pullPolicy: IfNotPresent + ## Optionally specify an array of imagePullSecrets. + ## Secrets must be manually created in the namespace. + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ + ## e.g: + ## pullSecrets: + ## - myRegistryKeySecretName + ## + pullSecrets: [] + ## @param apprepository.globalReposNamespaceSuffix Suffix for the namespace of global repos in the Helm plugin. Defaults to empty for backwards compatibility. Ignored if kubeappsapis.pluginConfig.helm.packages.v1alpha1.globalPackagingNamespace is set. + ## + globalReposNamespaceSuffix: "" + ## @param apprepository.initialRepos [array] Initial chart repositories to configure + ## e.g: + ## initialRepos: + ## - name: chartmuseum + ## url: https://chartmuseum.default:8080 + ## # Specify nodeSelector and tolerations: + ## nodeSelector: + ## somelabel: somevalue + ## tolerations: + ## - key: "cattle.io/os" + ## operator: "Equal" + ## value: "linux" + ## effect: "NoSchedule" + ## # Specify an Authorization Header if you are using an authentication method: + ## authorizationHeader: "Bearer xrxNC..." + ## # Specify the credentials if you are using a basic authentication method: + ## basicAuth: + ## user: + ## password: + ## # If you're providing your own certificates, please use this to add the certificates as secrets. + ## # It should start with -----BEGIN CERTIFICATE----- or + ## # -----BEGIN RSA PRIVATE KEY----- + ## caCert: + ## # Create this apprepository in a custom namespace + ## namespace: + ## # In case of an OCI registry, specify the type + ## type: oci + ## # And specify the list of repositories + ## ociRepositories: + ## - nginx + ## - jenkins + ## # Optionally filter out some charts. + ## # The jq query format is not exposed in the UI, so care needs to be taken to use the format which the UI expects to parse, + ## # which is why variables are used in the example below. + ## filterRule: + ## jq: .name == $var0 or .name == $var1 + ## variables: + ## $var0: nginx + ## $var1: jenkins + ## + initialRepos: + - name: bitnami + url: https://charts.bitnami.com/bitnami + ## @param apprepository.customAnnotations Custom annotations be added to each AppRepository-generated CronJob, Job and Pod + ## + customAnnotations: {} + ## @param apprepository.customLabels Custom labels be added to each AppRepository-generated CronJob, Job and Pod + ## + customLabels: {} + ## Proxy configuration to access chart repositories + ## + ## @param apprepository.initialReposProxy.enabled Enables the proxy + ## @param apprepository.initialReposProxy.httpProxy URL for the http proxy + ## @param apprepository.initialReposProxy.httpsProxy URL for the https proxy + ## @param apprepository.initialReposProxy.noProxy URL to exclude from using the proxy + ## + initialReposProxy: + enabled: false + httpProxy: "" + httpsProxy: "" + noProxy: "" + ## @param apprepository.crontab Default schedule for syncing App repositories (defaults to every 10 minutes) + ## e.g: + ## crontab: "*/10 * * * *" + ## + crontab: "" + ## @param apprepository.watchAllNamespaces Watch all namespaces to support separate AppRepositories per namespace + ## Switch this off only if you require running multiple instances of Kubeapps in different namespaces + ## without each instance watching AppRepositories of each other + ## + watchAllNamespaces: true + ## @param apprepository.extraFlags Additional command line flags for AppRepository Controller + ## + extraFlags: [] + ## @param apprepository.replicaCount Number of AppRepository Controller replicas to deploy + ## Running a single controller replica to avoid sync job duplication + ## + replicaCount: 1 + ## @param apprepository.updateStrategy.type AppRepository Controller deployment strategy type. + ## ref: https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#strategy + ## e.g: + ## updateStrategy: + ## type: RollingUpdate + ## rollingUpdate: + ## maxSurge: 25% + ## maxUnavailable: 25% + ## + updateStrategy: + type: RollingUpdate + ## AppRepository Controller containers' resource requests and limits + ## ref: https://kubernetes.io/docs/user-guide/compute-resources/ + ## @param apprepository.resources.limits.cpu The CPU limits for the AppRepository Controller container + ## @param apprepository.resources.limits.memory The memory limits for the AppRepository Controller container + ## @param apprepository.resources.requests.cpu The requested CPU for the AppRepository Controller container + ## @param apprepository.resources.requests.memory The requested memory for the AppRepository Controller container + ## + resources: + limits: + cpu: 250m + memory: 128Mi + requests: + cpu: 25m + memory: 32Mi + ## Configure Pods Security Context + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod + ## @param apprepository.podSecurityContext.enabled Enabled AppRepository Controller pods' Security Context + ## @param apprepository.podSecurityContext.fsGroup Set AppRepository Controller pod's Security Context fsGroup + ## + podSecurityContext: + enabled: true + fsGroup: 1001 + ## Configure Container Security Context for App Repository jobs + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container + ## @param apprepository.containerSecurityContext.enabled Enabled containers' Security Context + ## @param apprepository.containerSecurityContext.runAsUser Set containers' Security Context runAsUser + ## @param apprepository.containerSecurityContext.runAsNonRoot Set container's Security Context runAsNonRoot + ## @param apprepository.containerSecurityContext.privileged Set container's Security Context privileged + ## @param apprepository.containerSecurityContext.readOnlyRootFilesystem Set container's Security Context readOnlyRootFilesystem + ## @param apprepository.containerSecurityContext.allowPrivilegeEscalation Set container's Security Context allowPrivilegeEscalation + ## @param apprepository.containerSecurityContext.capabilities.drop List of capabilities to be dropped + ## @param apprepository.containerSecurityContext.seccompProfile.type Set container's Security Context seccomp profile + ## + containerSecurityContext: + enabled: true + runAsUser: 1001 + runAsNonRoot: true + privileged: false + readOnlyRootFilesystem: false + allowPrivilegeEscalation: false + capabilities: + drop: ["ALL"] + seccompProfile: + type: "RuntimeDefault" + ## @param apprepository.lifecycleHooks Custom lifecycle hooks for AppRepository Controller containers + ## + lifecycleHooks: {} + ## @param apprepository.command Override default container command (useful when using custom images) + ## + command: [] + ## @param apprepository.args Override default container args (useful when using custom images) + ## + args: [] + ## @param apprepository.extraEnvVars Array with extra environment variables to add to AppRepository Controller pod(s) + ## e.g: + ## extraEnvVars: + ## - name: FOO + ## value: "bar" + ## + extraEnvVars: [] + ## @param apprepository.extraEnvVarsCM Name of existing ConfigMap containing extra env vars for AppRepository Controller pod(s) + ## + extraEnvVarsCM: "" + ## @param apprepository.extraEnvVarsSecret Name of existing Secret containing extra env vars for AppRepository Controller pod(s) + ## + extraEnvVarsSecret: "" + ## @param apprepository.extraVolumes Optionally specify extra list of additional volumes for the AppRepository Controller pod(s) + ## + extraVolumes: [] + ## @param apprepository.extraVolumeMounts Optionally specify extra list of additional volumeMounts for the AppRepository Controller container(s) + ## + extraVolumeMounts: [] + ## @param apprepository.podLabels Extra labels for AppRepository Controller pods + ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ + ## + podLabels: {} + ## @param apprepository.podAnnotations Annotations for AppRepository Controller pods + ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ + ## + podAnnotations: {} + ## @param apprepository.podAffinityPreset Pod affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity + ## + podAffinityPreset: "" + ## @param apprepository.podAntiAffinityPreset Pod anti-affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` + ## Ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity + ## + podAntiAffinityPreset: soft + ## nodeAffinityPreset Node affinity preset + ## Ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#node-affinity + ## + nodeAffinityPreset: + ## @param apprepository.nodeAffinityPreset.type Node affinity preset type. Ignored if `affinity` is set. Allowed values: `soft` or `hard` + ## + type: "" + ## @param apprepository.nodeAffinityPreset.key Node label key to match. Ignored if `affinity` is set + ## + key: "" + ## @param apprepository.nodeAffinityPreset.values Node label values to match. Ignored if `affinity` is set + ## E.g. + ## values: + ## - e2e-az1 + ## - e2e-az2 + ## + values: [] + ## @param apprepository.affinity Affinity for pod assignment + ## Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity + ## NOTE: apprepository.podAffinityPreset, apprepository.podAntiAffinityPreset, and apprepository.nodeAffinityPreset will be ignored when it's set + ## + affinity: {} + ## @param apprepository.nodeSelector Node labels for pod assignment + ## ref: https://kubernetes.io/docs/user-guide/node-selection/ + ## + nodeSelector: {} + ## @param apprepository.tolerations Tolerations for pod assignment + ## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ + ## + tolerations: [] + ## @param apprepository.priorityClassName Priority class name for AppRepository Controller pods + ## + priorityClassName: "" + ## @param apprepository.schedulerName Name of the k8s scheduler (other than default) + ## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ + ## + schedulerName: "" + ## @param apprepository.topologySpreadConstraints Topology Spread Constraints for pod assignment + ## https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/ + ## The value is evaluated as a template + ## + topologySpreadConstraints: [] + ## @param apprepository.hostAliases Custom host aliases for AppRepository Controller pods + ## https://kubernetes.io/docs/concepts/services-networking/add-entries-to-pod-etc-hosts-with-host-aliases/ + ## + hostAliases: [] + ## @param apprepository.sidecars Add additional sidecar containers to the AppRepository Controller pod(s) + ## e.g: + ## sidecars: + ## - name: your-image-name + ## image: your-image + ## imagePullPolicy: Always + ## ports: + ## - name: portname + ## containerPort: 1234 + ## + sidecars: [] + ## @param apprepository.initContainers Add additional init containers to the AppRepository Controller pod(s) + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/init-containers/ + ## e.g: + ## initContainers: + ## - name: your-image-name + ## image: your-image + ## imagePullPolicy: Always + ## command: ['sh', '-c', 'echo "hello world"'] + ## + initContainers: [] + ## AppRepository Controller Service Account + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/ + ## @param apprepository.serviceAccount.create Specifies whether a ServiceAccount should be created + ## @param apprepository.serviceAccount.name Name of the service account to use. If not set and create is true, a name is generated using the fullname template. + ## @param apprepository.serviceAccount.automountServiceAccountToken Automount service account token for the server service account + ## @param apprepository.serviceAccount.annotations Annotations for service account. Evaluated as a template. Only used if `create` is `true`. + ## + serviceAccount: + create: true + name: "" + automountServiceAccountToken: true + annotations: {} + +## @section Auth Proxy parameters + +## Auth Proxy configuration for OIDC support +## ref: https://github.com/vmware-tanzu/kubeapps/blob/main/site/content/docs/latest/tutorials/using-an-OIDC-provider.md +## +authProxy: + ## @param authProxy.enabled Specifies whether Kubeapps should configure OAuth login/logout + ## + enabled: false + ## Bitnami OAuth2 Proxy image + ## ref: https://hub.docker.com/r/bitnami/oauth2-proxy/tags/ + ## @param authProxy.image.registry [default: REGISTRY_NAME] OAuth2 Proxy image registry + ## @param authProxy.image.repository [default: REPOSITORY_NAME/oauth2-proxy] OAuth2 Proxy image repository + ## @skip authProxy.image.tag OAuth2 Proxy image tag (immutable tags are recommended) + ## @param authProxy.image.digest OAuth2 Proxy image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag + ## @param authProxy.image.pullPolicy OAuth2 Proxy image pull policy + ## @param authProxy.image.pullSecrets OAuth2 Proxy image pull secrets + ## + image: + registry: docker.io + repository: bitnami/oauth2-proxy + tag: 7.5.1-debian-11-r11 + digest: "" + ## Specify a imagePullPolicy + ## Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent' + ## ref: https://kubernetes.io/docs/user-guide/images/#pre-pulling-images + ## + pullPolicy: IfNotPresent + ## Optionally specify an array of imagePullSecrets. + ## Secrets must be manually created in the namespace. + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ + ## e.g: + ## pullSecrets: + ## - myRegistryKeySecretName + ## + pullSecrets: [] + ## @param authProxy.external Use an external Auth Proxy instead of deploying its own one + ## + external: false + ## @param authProxy.oauthLoginURI OAuth Login URI to which the Kubeapps frontend redirects for authn + ## @param authProxy.oauthLogoutURI OAuth Logout URI to which the Kubeapps frontend redirects for authn + ## + oauthLoginURI: /oauth2/start + oauthLogoutURI: /oauth2/sign_out + ## @param authProxy.skipKubeappsLoginPage Skip the Kubeapps login page when using OIDC and directly redirect to the IdP + ## + skipKubeappsLoginPage: false + ## @param authProxy.provider OAuth provider + ## @param authProxy.clientID OAuth Client ID + ## @param authProxy.clientSecret OAuth Client secret + ## NOTE: Mandatory parameters for the internal auth-proxy + ## + provider: "" + clientID: "" + clientSecret: "" + ## @param authProxy.cookieSecret Secret used by oauth2-proxy to encrypt any credentials + ## NOTE: It must be a particular number of bytes. It's recommended using the following + ## script to generate a cookieSecret: + ## python -c 'import os,base64; print base64.urlsafe_b64encode(os.urandom(16))' + ## ref: https://oauth2-proxy.github.io/oauth2-proxy/docs/configuration/overview#generating-a-cookie-secret + ## + cookieSecret: "" + ## @param authProxy.existingOauth2Secret Name of an existing secret containing the OAuth client secrets, it should contain the keys clientID, clientSecret, and cookieSecret + ## If set, the values `authProxy.provider`, `authProxy.clientID`, `authProxy.clientSecret` will be ignored + ## + existingOauth2Secret: "" + ## @param authProxy.cookieRefresh Duration after which to refresh the cookie + ## + cookieRefresh: 2m + ## @param authProxy.scope OAuth scope specification + ## + scope: "openid email groups" + ## @param authProxy.emailDomain Allowed email domains + ## Use "example.com" to restrict logins to emails from example.com + ## + emailDomain: "*" + ## @param authProxy.extraFlags Additional command line flags for oauth2-proxy + ## ref: https://oauth2-proxy.github.io/oauth2-proxy/docs/configuration/overview + ## e.g: + ## extraFlags: + ## - --ssl-insecure-skip-verify + ## - --cookie-secure=false + ## - --oidc-issuer-url=https://accounts.google.com # Only needed if provider is oidc + ## + extraFlags: [] + ## @param authProxy.lifecycleHooks for the Auth Proxy container(s) to automate configuration before or after startup + ## + lifecycleHooks: {} + ## @param authProxy.command Override default container command (useful when using custom images) + ## + command: [] + ## @param authProxy.args Override default container args (useful when using custom images) + ## + args: [] + ## @param authProxy.extraEnvVars Array with extra environment variables to add to the Auth Proxy container + ## e.g: + ## extraEnvVars: + ## - name: FOO + ## value: "bar" + ## + extraEnvVars: [] + ## @param authProxy.extraEnvVarsCM Name of existing ConfigMap containing extra env vars for Auth Proxy containers(s) + ## + extraEnvVarsCM: "" + ## @param authProxy.extraEnvVarsSecret Name of existing Secret containing extra env vars for Auth Proxy containers(s) + ## + extraEnvVarsSecret: "" + ## @param authProxy.extraVolumeMounts Optionally specify extra list of additional volumeMounts for the Auth Proxy container(s) + ## + extraVolumeMounts: [] + ## @param authProxy.containerPorts.proxy Auth Proxy HTTP container port + ## + containerPorts: + proxy: 3000 + ## Configure Container Security Context for Auth Proxy + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container + ## @param authProxy.containerSecurityContext.enabled Enabled containers' Security Context + ## @param authProxy.containerSecurityContext.runAsUser Set containers' Security Context runAsUser + ## @param authProxy.containerSecurityContext.runAsNonRoot Set container's Security Context runAsNonRoot + ## @param authProxy.containerSecurityContext.privileged Set container's Security Context privileged + ## @param authProxy.containerSecurityContext.readOnlyRootFilesystem Set container's Security Context readOnlyRootFilesystem + ## @param authProxy.containerSecurityContext.allowPrivilegeEscalation Set container's Security Context allowPrivilegeEscalation + ## @param authProxy.containerSecurityContext.capabilities.drop List of capabilities to be dropped + ## @param authProxy.containerSecurityContext.seccompProfile.type Set container's Security Context seccomp profile + ## + containerSecurityContext: + enabled: true + runAsUser: 1001 + runAsNonRoot: true + privileged: false + readOnlyRootFilesystem: false + allowPrivilegeEscalation: false + capabilities: + drop: ["ALL"] + seccompProfile: + type: "RuntimeDefault" + ## OAuth2 Proxy containers' resource requests and limits + ## ref: https://kubernetes.io/docs/user-guide/compute-resources/ + ## @param authProxy.resources.limits.cpu The CPU limits for the OAuth2 Proxy container + ## @param authProxy.resources.limits.memory The memory limits for the OAuth2 Proxy container + ## @param authProxy.resources.requests.cpu The requested CPU for the OAuth2 Proxy container + ## @param authProxy.resources.requests.memory The requested memory for the OAuth2 Proxy container + ## + resources: + limits: + cpu: 250m + memory: 128Mi + requests: + cpu: 25m + memory: 32Mi + +## @section Pinniped Proxy parameters + +## Pinniped Proxy configuration for converting user OIDC tokens to k8s client authorization certs +## +pinnipedProxy: + ## @param pinnipedProxy.enabled Specifies whether Kubeapps should configure Pinniped Proxy + ## + enabled: false + ## Bitnami Pinniped Proxy image + ## ref: https://hub.docker.com/r/bitnami/kubeapps-pinniped-proxy/tags/ + ## @param pinnipedProxy.image.registry [default: REGISTRY_NAME] Pinniped Proxy image registry + ## @param pinnipedProxy.image.repository [default: REPOSITORY_NAME/kubeapps-pinniped-proxy] Pinniped Proxy image repository + ## @skip pinnipedProxy.image.tag Pinniped Proxy image tag (immutable tags are recommended) + ## @param pinnipedProxy.image.digest Pinniped Proxy image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag + ## @param pinnipedProxy.image.pullPolicy Pinniped Proxy image pull policy + ## @param pinnipedProxy.image.pullSecrets Pinniped Proxy image pull secrets + ## + image: + registry: docker.io + repository: bitnami/kubeapps-pinniped-proxy + tag: 2.9.0-debian-11-r10 + digest: "" + ## Specify a imagePullPolicy + ## Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent' + ## ref: https://kubernetes.io/docs/user-guide/images/#pre-pulling-images + ## + pullPolicy: IfNotPresent + ## Optionally specify an array of imagePullSecrets. + ## Secrets must be manually created in the namespace. + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ + ## e.g: + ## pullSecrets: + ## - myRegistryKeySecretName + ## + pullSecrets: [] + ## @param pinnipedProxy.defaultPinnipedNamespace Namespace in which pinniped concierge is installed + ## + defaultPinnipedNamespace: pinniped-concierge + ## @param pinnipedProxy.defaultAuthenticatorType Authenticator type + ## + defaultAuthenticatorType: JWTAuthenticator + ## @param pinnipedProxy.defaultAuthenticatorName Authenticator name + ## + defaultAuthenticatorName: jwt-authenticator + ## @param pinnipedProxy.defaultPinnipedAPISuffix API suffix + ## + defaultPinnipedAPISuffix: pinniped.dev + ## TLS settings for Pinniped Proxy + ## ref: https://kubeapps.dev/docs/latest/howto/oidc/using-an-oidc-provider-with-pinniped/#running-the-pinniped-proxy-service-over-tls + ## + tls: + ## @param pinnipedProxy.tls.existingSecret TLS secret with which to proxy requests + ## + existingSecret: "" + ## @param pinnipedProxy.tls.caCertificate TLS CA cert config map which clients of pinniped proxy should use with TLS requests + ## This config map must contain a ca.crt key with the CA cert content as the value. + ## + caCertificate: "" + ## @param pinnipedProxy.lifecycleHooks For the Pinniped Proxy container(s) to automate configuration before or after startup + ## + lifecycleHooks: {} + ## @param pinnipedProxy.command Override default container command (useful when using custom images) + ## + command: [] + ## @param pinnipedProxy.args Override default container args (useful when using custom images) + ## + args: [] + ## @param pinnipedProxy.extraEnvVars Array with extra environment variables to add to Pinniped Proxy container(s) + ## e.g: + ## extraEnvVars: + ## - name: FOO + ## value: "bar" + ## + extraEnvVars: [] + ## @param pinnipedProxy.extraEnvVarsCM Name of existing ConfigMap containing extra env vars for Pinniped Proxy container(s) + ## + extraEnvVarsCM: "" + ## @param pinnipedProxy.extraEnvVarsSecret Name of existing Secret containing extra env vars for Pinniped Proxy container(s) + ## + extraEnvVarsSecret: "" + ## @param pinnipedProxy.extraVolumeMounts Optionally specify extra list of additional volumeMounts for the Pinniped Proxy container(s) + ## + extraVolumeMounts: [] + ## @param pinnipedProxy.containerPorts.pinnipedProxy Pinniped Proxy container port + ## + containerPorts: + pinnipedProxy: 3333 + ## Configure Container Security Context for Pinniped Proxy + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container + ## @param pinnipedProxy.containerSecurityContext.enabled Enabled containers' Security Context + ## @param pinnipedProxy.containerSecurityContext.runAsUser Set containers' Security Context runAsUser + ## @param pinnipedProxy.containerSecurityContext.runAsNonRoot Set container's Security Context runAsNonRoot + ## @param pinnipedProxy.containerSecurityContext.privileged Set container's Security Context privileged + ## @param pinnipedProxy.containerSecurityContext.readOnlyRootFilesystem Set container's Security Context readOnlyRootFilesystem + ## @param pinnipedProxy.containerSecurityContext.allowPrivilegeEscalation Set container's Security Context allowPrivilegeEscalation + ## @param pinnipedProxy.containerSecurityContext.capabilities.drop List of capabilities to be dropped + ## @param pinnipedProxy.containerSecurityContext.seccompProfile.type Set container's Security Context seccomp profile + ## + containerSecurityContext: + enabled: true + runAsUser: 1001 + runAsNonRoot: true + privileged: false + readOnlyRootFilesystem: false + allowPrivilegeEscalation: false + capabilities: + drop: ["ALL"] + seccompProfile: + type: "RuntimeDefault" + ## Pinniped Proxy containers' resource requests and limits + ## ref: https://kubernetes.io/docs/user-guide/compute-resources/ + ## @param pinnipedProxy.resources.limits.cpu The CPU limits for the Pinniped Proxy container + ## @param pinnipedProxy.resources.limits.memory The memory limits for the Pinniped Proxy container + ## @param pinnipedProxy.resources.requests.cpu The requested CPU for the Pinniped Proxy container + ## @param pinnipedProxy.resources.requests.memory The requested memory for the Pinniped Proxy container + ## + resources: + limits: + cpu: 250m + memory: 128Mi + requests: + cpu: 25m + memory: 32Mi + ## Pinniped Proxy service parameters + ## + service: + ## @param pinnipedProxy.service.ports.pinnipedProxy Pinniped Proxy service port + ## + ports: + pinnipedProxy: 3333 + ## @param pinnipedProxy.service.annotations Additional custom annotations for Pinniped Proxy service + ## + annotations: {} +## @section Other Parameters + +## @param clusters [array] List of clusters that Kubeapps can target for deployments +## When populated with a single cluster (as it is by default), Kubeapps will not allow users to +## change the target cluster. When populated with multiple clusters, Kubeapps will present the clusters to +## the user as potential targets for install or browsing. +## - Note that you can define a single cluster without an apiServiceURL and the chart will assume this is +## the name you are assigning to the cluster on which Kubeapps is itself installed. Specifying more than +## one cluster without an apiServiceURL will cause the chart display an error. +## - The base64-encoded certificateAuthorityData can be obtained from the additional cluster's kube config +## file, for example, to get the ca data for the 0th cluster in your config (adjust the index 0 as necessary): +## kubectl --kubeconfig ~/.kube/kind-config-kubeapps-additional config view --raw -o jsonpath='{.clusters[0].cluster.certificate-authority-data}' +## - serviceToken is an optional token configured to allow LIST namespaces and package manifests (operators) only on the additional cluster +## so that the UI can present a list of (only) those namespaces to which the user has access and the available operators. +## - isKubeappsCluster is an optional parameter that allows defining the cluster in which Kubeapps is installed; +## this param is useful when every cluster is using an apiServiceURL (e.g., when using the Pinniped Impersonation Proxy) +## as the chart cannot infer the cluster on which Kubeapps is installed in that case. +## - pinnipedConfig is an optional parameter that contains configuration options specific to a cluster running the pinniped concierge service. +## e.g.: +## clusters: +## - name: default +## domain: cluster.local +## - name: second-cluster +## domain: cluster.local +## apiServiceURL: https://second-cluster:6443 +## certificateAuthorityData: LS0tLS1CRUdJ... +## serviceToken: ... +## isKubeappsCluster: true +## pinnipedConfig: +## enabled: true + +## +clusters: + - name: default + domain: cluster.local + +## RBAC configuration +## +rbac: + ## @param rbac.create Specifies whether RBAC resources should be created + ## + create: true + +## @section Feature flags +## +## Opt-in features intended for development and advanced use cases. +## They might be removed in future releases without prior notice. +featureFlags: + ## For a full list of possible ingress annotations, please see + apiOnly: + ## @param featureFlags.apiOnly.enabled Enable ingress for API operations only. Access to "/" will not be possible, so Dashboard will be unusable. + ## + enabled: false + grpc: + ## @param featureFlags.apiOnly.grpc.annotations [object] Specific annotations for the GRPC ingress in API-only mode + ## ref: https://github.com/kubernetes/ingress-nginx/blob/main/docs/user-guide/nginx-configuration/annotations.md + ## + annotations: + nginx.ingress.kubernetes.io/backend-protocol: GRPC + ## @param featureFlags.operators Enable support for Operators in Kubeapps + ## + operators: false + schemaEditor: + ## @param featureFlags.schemaEditor.enabled Enable a visual editor for customizing the package schemas + ## + enabled: false + +## @section Database Parameters + +## PostgreSQL chart configuration +## ref: https://github.com/bitnami/charts/blob/main/bitnami/postgresql/values.yaml +## @param postgresql.enabled Deploy a PostgreSQL server to satisfy the applications database requirements +## @param postgresql.auth.username Username for PostgreSQL server +## @param postgresql.auth.postgresPassword Password for 'postgres' user +## ref: https://github.com/bitnami/containers/tree/main/bitnami/postgresql#setting-the-root-password-on-first-run +## @param postgresql.auth.database Name for a custom database to create +## @param postgresql.auth.existingSecret Name of existing secret to use for PostgreSQL credentials +## +postgresql: + enabled: true + auth: + username: "postgres" + postgresPassword: "" + database: assets + existingSecret: "" + ## PostgreSQL Primary persistence configuration + ## @param postgresql.primary.persistence.enabled Enable PostgreSQL Primary data persistence using PVC + primary: + persistence: + enabled: false + ## @param postgresql.architecture PostgreSQL architecture (`standalone` or `replication`) + ## + architecture: standalone + ## @param postgresql.securityContext.enabled Enabled PostgreSQL replicas pods' Security Context + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ + ## + securityContext: + enabled: false + ## PostgreSQL containers' resource requests and limits + ## ref: https://kubernetes.io/docs/user-guide/compute-resources/ + ## @param postgresql.resources.limits The resources limits for the PostgreSQL container + ## @param postgresql.resources.requests.cpu The requested CPU for the PostgreSQL container + ## @param postgresql.resources.requests.memory The requested memory for the PostgreSQL container + ## + resources: + limits: {} + requests: + memory: 256Mi + cpu: 250m + +## @section kubeappsapis parameters +kubeappsapis: + ## @param kubeappsapis.enabledPlugins Manually override which plugins are enabled for the Kubeapps-APIs service + ## + ## NOTE: normally this should remain blank, with the top-level `packaging` + ## value automatically determining which plugins should be enabled. Only + ## set this value if you want to manually override the list of plugins + ## enabled for the service. + ## + enabledPlugins: [] + pluginConfig: + core: + packages: + v1alpha1: + versionsInSummary: + ## @param kubeappsapis.pluginConfig.core.packages.v1alpha1.versionsInSummary.major Number of major versions to display in the summary + major: 3 + ## @param kubeappsapis.pluginConfig.core.packages.v1alpha1.versionsInSummary.minor Number of minor versions to display in the summary + minor: 3 + ## @param kubeappsapis.pluginConfig.core.packages.v1alpha1.versionsInSummary.patch Number of patch versions to display in the summary + patch: 3 + ## @param kubeappsapis.pluginConfig.core.packages.v1alpha1.timeoutSeconds Value to wait for Kubernetes commands to complete + timeoutSeconds: 300 + helm: + packages: + v1alpha1: + ## @param kubeappsapis.pluginConfig.helm.packages.v1alpha1.globalPackagingNamespace Custom global packaging namespace. Using this value will override the current "kubeapps release namespace + suffix" pattern and will create a new namespace if not exists. + globalPackagingNamespace: "" + kappController: + packages: + v1alpha1: + ## @param kubeappsapis.pluginConfig.kappController.packages.v1alpha1.defaultUpgradePolicy Default upgrade policy generating version constraints + ## enum: [ "major", "minor", "patch", "none" ] + defaultUpgradePolicy: none + ## @param kubeappsapis.pluginConfig.kappController.packages.v1alpha1.defaultPrereleasesVersionSelection [array,nullable] Default policy for allowing prereleases containing one of the identifiers + ## ref: https://carvel.dev/kapp-controller/docs/latest/package-consumer-concepts/#prereleases + ## e.g: + # defaultPrereleasesVersionSelection: + # - rc + defaultPrereleasesVersionSelection: null + ## @param kubeappsapis.pluginConfig.kappController.packages.v1alpha1.defaultAllowDowngrades Default policy for allowing applications to be downgraded to previous versions + ## ref: https://carvel.dev/kapp-controller/docs/latest/package-consumer-concepts/#downgrading + defaultAllowDowngrades: false + ## @param kubeappsapis.pluginConfig.kappController.packages.v1alpha1.globalPackagingNamespace Default global packaging namespace + ## ref: https://carvel.dev/kapp-controller/docs/latest/package-consumer-concepts/#namespacing + globalPackagingNamespace: kapp-controller-packaging-global + flux: + packages: + v1alpha1: + ## @param kubeappsapis.pluginConfig.flux.packages.v1alpha1.defaultUpgradePolicy Default upgrade policy generating version constraints + ## enum: [ "major", "minor", "patch", "none" ] + defaultUpgradePolicy: none + ## @param kubeappsapis.pluginConfig.flux.packages.v1alpha1.noCrossNamespaceRefs Enable this flag to disallow cross-namespace references, useful when running Flux on multi-tenant clusters + noCrossNamespaceRefs: false + resources: + packages: + v1alpha1: + ## Trusted namespaces parameters + ## + trustedNamespaces: + ## @param kubeappsapis.pluginConfig.resources.packages.v1alpha1.trustedNamespaces.headerName Optional header name for trusted namespaces + ## e.g: + ## headerName: X-Consumer-Groups + ## + headerName: "" + ## @param kubeappsapis.pluginConfig.resources.packages.v1alpha1.trustedNamespaces.headerPattern Optional header pattern for trusted namespaces + ## e.g: + ## headerPattern: namespace:^([\w-]+):\w+$ + ## + headerPattern: "" + ## Bitnami Kubeapps-APIs image + ## ref: https://hub.docker.com/r/bitnami/kubeapps-apis/tags/ + ## @param kubeappsapis.image.registry [default: REGISTRY_NAME] Kubeapps-APIs image registry + ## @param kubeappsapis.image.repository [default: REPOSITORY_NAME/kubeapps-apis] Kubeapps-APIs image repository + ## @skip kubeappsapis.image.tag Kubeapps-APIs image tag (immutable tags are recommended) + ## @param kubeappsapis.image.digest Kubeapps-APIs image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag + ## @param kubeappsapis.image.pullPolicy Kubeapps-APIs image pull policy + ## @param kubeappsapis.image.pullSecrets Kubeapps-APIs image pull secrets + ## + image: + registry: docker.io + repository: bitnami/kubeapps-apis + tag: 2.9.0-debian-11-r13 + digest: "" + ## Specify a imagePullPolicy + ## Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent' + ## ref: https://kubernetes.io/docs/user-guide/images/#pre-pulling-images + ## + pullPolicy: IfNotPresent + ## Optionally specify an array of imagePullSecrets. + ## Secrets must be manually created in the namespace. + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ + ## e.g: + ## pullSecrets: + ## - myRegistryKeySecretName + ## + pullSecrets: [] + ## @param kubeappsapis.replicaCount Number of frontend replicas to deploy + ## + replicaCount: 2 + ## @param kubeappsapis.updateStrategy.type KubeappsAPIs deployment strategy type. + ## ref: https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#strategy + ## e.g: + ## updateStrategy: + ## type: RollingUpdate + ## rollingUpdate: + ## maxSurge: 25% + ## maxUnavailable: 25% + ## + updateStrategy: + type: RollingUpdate + ## @param kubeappsapis.extraFlags Additional command line flags for KubeappsAPIs + ## + extraFlags: [] + ## @param kubeappsapis.qps KubeappsAPIs Kubernetes API client QPS limit + ## + qps: "50.0" + ## @param kubeappsapis.burst KubeappsAPIs Kubernetes API client Burst limit + ## + burst: "100" + ## @param kubeappsapis.terminationGracePeriodSeconds The grace time period for sig term + ## ref: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#hook-handler-execution + ## + terminationGracePeriodSeconds: 300 + ## @param kubeappsapis.extraEnvVars Array with extra environment variables to add to the KubeappsAPIs container + ## e.g: + ## extraEnvVars: + ## - name: FOO + ## value: "bar" + ## + extraEnvVars: [] + ## @param kubeappsapis.extraEnvVarsCM Name of existing ConfigMap containing extra env vars for the KubeappsAPIs container + ## + extraEnvVarsCM: "" + ## @param kubeappsapis.extraEnvVarsSecret Name of existing Secret containing extra env vars for the KubeappsAPIs container + ## + extraEnvVarsSecret: "" + ## @param kubeappsapis.containerPorts.http KubeappsAPIs HTTP container port + ## + containerPorts: + http: 50051 + ## KubeappsAPIs containers' resource requests and limits + ## ref: https://kubernetes.io/docs/user-guide/compute-resources/ + ## @param kubeappsapis.resources.limits.cpu The CPU limits for the KubeappsAPIs container + ## @param kubeappsapis.resources.limits.memory The memory limits for the KubeappsAPIs container + ## @param kubeappsapis.resources.requests.cpu The requested CPU for the KubeappsAPIs container + ## @param kubeappsapis.resources.requests.memory The requested memory for the KubeappsAPIs container + ## + resources: + limits: + cpu: 250m + memory: 256Mi + requests: + cpu: 25m + memory: 32Mi + ## Configure Pods Security Context + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod + ## @param kubeappsapis.podSecurityContext.enabled Enabled KubeappsAPIs pods' Security Context + ## @param kubeappsapis.podSecurityContext.fsGroup Set KubeappsAPIs pod's Security Context fsGroup + ## + podSecurityContext: + enabled: true + fsGroup: 1001 + ## Configure Container Security Context for Kubeapps APIs + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container + ## @param kubeappsapis.containerSecurityContext.enabled Enabled containers' Security Context + ## @param kubeappsapis.containerSecurityContext.runAsUser Set containers' Security Context runAsUser + ## @param kubeappsapis.containerSecurityContext.runAsNonRoot Set container's Security Context runAsNonRoot + ## @param kubeappsapis.containerSecurityContext.privileged Set container's Security Context privileged + ## @param kubeappsapis.containerSecurityContext.readOnlyRootFilesystem Set container's Security Context readOnlyRootFilesystem + ## @param kubeappsapis.containerSecurityContext.allowPrivilegeEscalation Set container's Security Context allowPrivilegeEscalation + ## @param kubeappsapis.containerSecurityContext.capabilities.drop List of capabilities to be dropped + ## @param kubeappsapis.containerSecurityContext.seccompProfile.type Set container's Security Context seccomp profile + ## + containerSecurityContext: + enabled: true + runAsUser: 1001 + runAsNonRoot: true + privileged: false + readOnlyRootFilesystem: false + allowPrivilegeEscalation: false + capabilities: + drop: ["ALL"] + seccompProfile: + type: "RuntimeDefault" + ## Configure extra options for KubeappsAPIs containers' liveness and readiness probes + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/#configure-probes + ## @param kubeappsapis.livenessProbe.enabled Enable livenessProbe + ## @param kubeappsapis.livenessProbe.initialDelaySeconds Initial delay seconds for livenessProbe + ## @param kubeappsapis.livenessProbe.periodSeconds Period seconds for livenessProbe + ## @param kubeappsapis.livenessProbe.timeoutSeconds Timeout seconds for livenessProbe + ## @param kubeappsapis.livenessProbe.failureThreshold Failure threshold for livenessProbe + ## @param kubeappsapis.livenessProbe.successThreshold Success threshold for livenessProbe + ## KubeappsAPIs containers' liveness and readiness probes + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes + ## + livenessProbe: + enabled: true + initialDelaySeconds: 60 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 6 + successThreshold: 1 + ## @param kubeappsapis.readinessProbe.enabled Enable readinessProbe + ## @param kubeappsapis.readinessProbe.initialDelaySeconds Initial delay seconds for readinessProbe + ## @param kubeappsapis.readinessProbe.periodSeconds Period seconds for readinessProbe + ## @param kubeappsapis.readinessProbe.timeoutSeconds Timeout seconds for readinessProbe + ## @param kubeappsapis.readinessProbe.failureThreshold Failure threshold for readinessProbe + ## @param kubeappsapis.readinessProbe.successThreshold Success threshold for readinessProbe + ## + readinessProbe: + enabled: true + initialDelaySeconds: 0 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 6 + successThreshold: 1 + ## @param kubeappsapis.startupProbe.enabled Enable startupProbe + ## @param kubeappsapis.startupProbe.initialDelaySeconds Initial delay seconds for startupProbe + ## @param kubeappsapis.startupProbe.periodSeconds Period seconds for startupProbe + ## @param kubeappsapis.startupProbe.timeoutSeconds Timeout seconds for startupProbe + ## @param kubeappsapis.startupProbe.failureThreshold Failure threshold for startupProbe + ## @param kubeappsapis.startupProbe.successThreshold Success threshold for startupProbe + ## + startupProbe: + enabled: false + initialDelaySeconds: 0 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 6 + successThreshold: 1 + ## @param kubeappsapis.customLivenessProbe Custom livenessProbe that overrides the default one + ## + customLivenessProbe: {} + ## @param kubeappsapis.customReadinessProbe Custom readinessProbe that overrides the default one + ## + customReadinessProbe: {} + ## @param kubeappsapis.customStartupProbe Custom startupProbe that overrides the default one + ## + customStartupProbe: {} + ## @param kubeappsapis.lifecycleHooks Custom lifecycle hooks for KubeappsAPIs containers + ## + lifecycleHooks: {} + ## @param kubeappsapis.command Override default container command (useful when using custom images) + ## + command: [] + ## @param kubeappsapis.args Override default container args (useful when using custom images) + ## + args: [] + ## @param kubeappsapis.extraVolumes Optionally specify extra list of additional volumes for the KubeappsAPIs pod(s) + ## + extraVolumes: [] + ## @param kubeappsapis.extraVolumeMounts Optionally specify extra list of additional volumeMounts for the KubeappsAPIs container(s) + ## + extraVolumeMounts: [] + ## @param kubeappsapis.podLabels Extra labels for KubeappsAPIs pods + ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ + ## + podLabels: {} + ## @param kubeappsapis.podAnnotations Annotations for KubeappsAPIs pods + ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ + ## + podAnnotations: {} + ## @param kubeappsapis.podAffinityPreset Pod affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity + ## + podAffinityPreset: "" + ## @param kubeappsapis.podAntiAffinityPreset Pod anti-affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` + ## Ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity + ## + podAntiAffinityPreset: soft + ## nodeAffinityPreset Node affinity preset + ## Ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#node-affinity + ## + nodeAffinityPreset: + ## @param kubeappsapis.nodeAffinityPreset.type Node affinity preset type. Ignored if `affinity` is set. Allowed values: `soft` or `hard` + ## + type: "" + ## @param kubeappsapis.nodeAffinityPreset.key Node label key to match. Ignored if `affinity` is set + ## + key: "" + ## @param kubeappsapis.nodeAffinityPreset.values Node label values to match. Ignored if `affinity` is set + ## E.g. + ## values: + ## - e2e-az1 + ## - e2e-az2 + ## + values: [] + ## @param kubeappsapis.affinity Affinity for pod assignment + ## Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity + ## NOTE: kubeappsapis.podAffinityPreset, kubeappsapis.podAntiAffinityPreset, and kubeappsapis.nodeAffinityPreset will be ignored when it's set + ## + affinity: {} + ## @param kubeappsapis.nodeSelector Node labels for pod assignment + ## ref: https://kubernetes.io/docs/user-guide/node-selection/ + ## + nodeSelector: {} + ## @param kubeappsapis.tolerations Tolerations for pod assignment + ## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ + ## + tolerations: [] + ## @param kubeappsapis.priorityClassName Priority class name for KubeappsAPIs pods + ## + priorityClassName: "" + ## @param kubeappsapis.schedulerName Name of the k8s scheduler (other than default) + ## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ + ## + schedulerName: "" + ## @param kubeappsapis.topologySpreadConstraints Topology Spread Constraints for pod assignment + ## https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/ + ## The value is evaluated as a template + ## + topologySpreadConstraints: [] + ## @param kubeappsapis.hostAliases Custom host aliases for KubeappsAPIs pods + ## https://kubernetes.io/docs/concepts/services-networking/add-entries-to-pod-etc-hosts-with-host-aliases/ + ## + hostAliases: [] + ## @param kubeappsapis.sidecars Add additional sidecar containers to the KubeappsAPIs pod(s) + ## e.g: + ## sidecars: + ## - name: your-image-name + ## image: your-image + ## imagePullPolicy: Always + ## ports: + ## - name: portname + ## containerPort: 1234 + ## + sidecars: [] + ## @param kubeappsapis.initContainers Add additional init containers to the KubeappsAPIs pod(s) + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/init-containers/ + ## e.g: + ## initContainers: + ## - name: your-image-name + ## image: your-image + ## imagePullPolicy: Always + ## command: ['sh', '-c', 'echo "hello world"'] + ## + initContainers: [] + ## kubeappsapis service parameters + ## + service: + ## @param kubeappsapis.service.ports.http KubeappsAPIs service HTTP port + ## + ports: + http: 8080 + ## @param kubeappsapis.service.annotations Additional custom annotations for KubeappsAPIs service + ## + annotations: {} + ## kubeappsapis Service Account + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/ + ## @param kubeappsapis.serviceAccount.create Specifies whether a ServiceAccount should be created + ## @param kubeappsapis.serviceAccount.name Name of the service account to use. If not set and create is true, a name is generated using the fullname template. + ## @param kubeappsapis.serviceAccount.automountServiceAccountToken Automount service account token for the server service account + ## @param kubeappsapis.serviceAccount.annotations Annotations for service account. Evaluated as a template. Only used if `create` is `true`. + ## + serviceAccount: + create: true + name: "" + automountServiceAccountToken: true + annotations: {} + +## @section OCI Catalog chart configuration +ociCatalog: + ## @param ociCatalog.enabled Enable the OCI catalog gRPC service for cataloging + ## OCI repositories + enabled: false + ## Bitnami Kubeapps OCI Catalog image + ## ref: https://hub.docker.com/r/bitnami/kubeapps-ocicatalog/ + ## @param ociCatalog.image.registry [default: REGISTRY_NAME] OCI Catalog image registry + ## @param ociCatalog.image.repository [default: REPOSITORY_NAME/kubeapps-oci-catalog] OCI Catalog image repository + ## @skip ociCatalog.image.tag OCI Catalog image tag (immutable tags are recommended) + ## @param ociCatalog.image.digest OCI Catalog image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag + ## @param ociCatalog.image.pullPolicy OCI Catalog image pull policy + ## @param ociCatalog.image.pullSecrets OCI Catalog image pull secrets + ## @param ociCatalog.image.debug Enable image debug mode + ## + image: + registry: docker.io + repository: bitnami/kubeapps-oci-catalog + tag: 2.9.0-debian-11-r6 + digest: "" + ## Specify a imagePullPolicy + ## Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent' + ## ref: https://kubernetes.io/docs/user-guide/images/#pre-pulling-images + ## + pullPolicy: IfNotPresent + ## Optionally specify an array of imagePullSecrets. + ## Secrets must be manually created in the namespace. + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ + ## e.g: + ## pullSecrets: + ## - myRegistryKeySecretName + ## + pullSecrets: [] + ## Enable debug mode + ## + debug: false + ## @param ociCatalog.extraFlags Additional command line flags for OCI Catalog + ## + extraFlags: [] + ## @param ociCatalog.extraEnvVars Array with extra environment variables to add to the oci-catalog container + ## e.g: + ## extraEnvVars: + ## - name: FOO + ## value: "bar" + ## + extraEnvVars: [] + ## @param ociCatalog.extraEnvVarsCM Name of existing ConfigMap containing extra env vars for the OCI Catalog container + ## + extraEnvVarsCM: "" + ## @param ociCatalog.extraEnvVarsSecret Name of existing Secret containing extra env vars for the OCI Catalog container + ## + extraEnvVarsSecret: "" + ## @param ociCatalog.containerPorts.grpc OCI Catalog gRPC container port + ## + containerPorts: + grpc: 50061 + ## OCI Catalog containers' resource requests and limits + ## ref: https://kubernetes.io/docs/user-guide/compute-resources/ + ## @param ociCatalog.resources.limits.cpu The CPU limits for the OCI Catalog container + ## @param ociCatalog.resources.limits.memory The memory limits for the OCI Catalog container + ## @param ociCatalog.resources.requests.cpu The requested CPU for the OCI Catalog container + ## @param ociCatalog.resources.requests.memory The requested memory for the OCI Catalog container + ## + resources: + limits: + cpu: 250m + memory: 256Mi + requests: + cpu: 25m + memory: 32Mi + ## Configure Container Security Context (only main container) + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container + ## @param ociCatalog.containerSecurityContext.enabled Enabled containers' Security Context + ## @param ociCatalog.containerSecurityContext.runAsUser Set containers' Security Context runAsUser + ## @param ociCatalog.containerSecurityContext.runAsNonRoot Set container's Security Context runAsNonRoot + ## @param ociCatalog.containerSecurityContext.privileged Set container's Security Context privileged + ## @param ociCatalog.containerSecurityContext.readOnlyRootFilesystem Set container's Security Context readOnlyRootFilesystem + ## @param ociCatalog.containerSecurityContext.allowPrivilegeEscalation Set container's Security Context allowPrivilegeEscalation + ## @param ociCatalog.containerSecurityContext.capabilities.drop List of capabilities to be dropped + ## @param ociCatalog.containerSecurityContext.seccompProfile.type Set container's Security Context seccomp profile + ## + containerSecurityContext: + enabled: true + runAsUser: 1001 + runAsNonRoot: true + privileged: false + readOnlyRootFilesystem: false + allowPrivilegeEscalation: false + capabilities: + drop: ["ALL"] + seccompProfile: + type: "RuntimeDefault" + ## Configure extra options for OCI Catalog containers' liveness and readiness probes + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/#configure-probes + ## @param ociCatalog.livenessProbe.enabled Enable livenessProbe + ## @param ociCatalog.livenessProbe.initialDelaySeconds Initial delay seconds for livenessProbe + ## @param ociCatalog.livenessProbe.periodSeconds Period seconds for livenessProbe + ## @param ociCatalog.livenessProbe.timeoutSeconds Timeout seconds for livenessProbe + ## @param ociCatalog.livenessProbe.failureThreshold Failure threshold for livenessProbe + ## @param ociCatalog.livenessProbe.successThreshold Success threshold for livenessProbe + ## OCI Catalog containers' liveness and readiness probes + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes + ## + livenessProbe: + enabled: true + initialDelaySeconds: 60 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 6 + successThreshold: 1 + ## @param ociCatalog.readinessProbe.enabled Enable readinessProbe + ## @param ociCatalog.readinessProbe.initialDelaySeconds Initial delay seconds for readinessProbe + ## @param ociCatalog.readinessProbe.periodSeconds Period seconds for readinessProbe + ## @param ociCatalog.readinessProbe.timeoutSeconds Timeout seconds for readinessProbe + ## @param ociCatalog.readinessProbe.failureThreshold Failure threshold for readinessProbe + ## @param ociCatalog.readinessProbe.successThreshold Success threshold for readinessProbe + ## + readinessProbe: + enabled: true + initialDelaySeconds: 0 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 6 + successThreshold: 1 + ## @param ociCatalog.startupProbe.enabled Enable startupProbe + ## @param ociCatalog.startupProbe.initialDelaySeconds Initial delay seconds for startupProbe + ## @param ociCatalog.startupProbe.periodSeconds Period seconds for startupProbe + ## @param ociCatalog.startupProbe.timeoutSeconds Timeout seconds for startupProbe + ## @param ociCatalog.startupProbe.failureThreshold Failure threshold for startupProbe + ## @param ociCatalog.startupProbe.successThreshold Success threshold for startupProbe + ## + startupProbe: + enabled: false + initialDelaySeconds: 0 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 6 + successThreshold: 1 + ## @param ociCatalog.customLivenessProbe Custom livenessProbe that overrides the default one + ## + customLivenessProbe: {} + ## @param ociCatalog.customReadinessProbe Custom readinessProbe that overrides the default one + ## + customReadinessProbe: {} + ## @param ociCatalog.customStartupProbe Custom startupProbe that overrides the default one + ## + customStartupProbe: {} + ## @param ociCatalog.lifecycleHooks Custom lifecycle hooks for OCI Catalog containers + ## + lifecycleHooks: {} + ## @param ociCatalog.command Override default container command (useful when using custom images) + ## + command: [] + ## @param ociCatalog.args Override default container args (useful when using custom images) + ## + args: [] + ## @param ociCatalog.extraVolumes Optionally specify extra list of additional volumes for the OCI Catalog pod(s) + ## + extraVolumes: [] + ## @param ociCatalog.extraVolumeMounts Optionally specify extra list of additional volumeMounts for the OCI Catalog container(s) + ## + extraVolumeMounts: [] + +## @section Redis® chart configuration +## ref: https://github.com/bitnami/charts/blob/main/bitnami/redis/values.yaml +## +## Redis(R) will be enabled and installed if `packages.flux.enabled` is true. +redis: + ## @param redis.auth.enabled Enable password authentication + ## @param redis.auth.password Redis® password + ## @param redis.auth.existingSecret The name of an existing secret with Redis® credentials + ## + auth: + enabled: true + password: "" + existingSecret: "" + ## @param redis.architecture Redis(R) architecture (`standalone` or `replication`) + ## + architecture: standalone + master: + ## @param redis.master.extraFlags Array with additional command line flags for Redis® master + ## + extraFlags: + ## The maxmemory configuration directive is used in order to configure Redis(R) to use a specified + ## amount of memory for the data set. Setting maxmemory to zero results into no memory limits + ## see https://redis.io/topics/lru-cache for more details + ## + - "--maxmemory 200mb" + ## The exact behavior Redis(R) follows when the maxmemory limit is reached is configured using the + ## maxmemory-policy configuration directive + ## allkeys-lru: evict keys by trying to remove the less recently used (LRU) keys first, in order + ## to make space for the new data added + ## + - "--maxmemory-policy allkeys-lru" + ## ref https://stackoverflow.com/questions/22815364/flushall-and-flushdb-commands-on-redis-return-unk-command + ## Redis official Helm chart by default disables FLUSHDB and FLUSHALL commands + ## + ## @param redis.master.disableCommands Array with commands to deactivate on Redis® + disableCommands: [] + ## Redis(R) Master persistence configuration + # + persistence: + ## @param redis.master.persistence.enabled Enable Redis® master data persistence using PVC + ## + enabled: false + replica: + ## @param redis.replica.replicaCount Number of Redis® replicas to deploy + ## + replicaCount: 1 + ## @param redis.replica.extraFlags Array with additional command line flags for Redis® replicas + ## + extraFlags: + ## The maxmemory configuration directive is used in order to configure Redis(R) to use a specified + ## amount of memory for the data set. Setting maxmemory to zero results into no memory limits + ## + - "--maxmemory 200mb" + ## The exact behavior Redis(R) follows when the maxmemory limit is reached is configured using the + ## maxmemory-policy configuration directive + ## allkeys-lru: evict keys by trying to remove the less recently used (LRU) keys first, in order + ## to make space for the new data added + ## + - "--maxmemory-policy allkeys-lru" + ## ref https://stackoverflow.com/questions/22815364/flushall-and-flushdb-commands-on-redis-return-unk-command + ## Redis(R) official Helm chart by default disables FLUSHDB and FLUSHALL commands + ## @param redis.replica.disableCommands Array with commands to deactivate on Redis® + ## + disableCommands: [] + ## Redis(R) Replica persistence configuration + ## + persistence: + ## @param redis.replica.persistence.enabled Enable Redis® replica data persistence using PVC + ## + enabled: false diff --git a/packages/system/dashboard/images/dashboard.json b/packages/system/dashboard/images/dashboard.json new file mode 100644 index 00000000..448617b9 --- /dev/null +++ b/packages/system/dashboard/images/dashboard.json @@ -0,0 +1,4 @@ +{ + "containerimage.config.digest": "sha256:f5a26c90226016af3a23d5fdb8b23d36b0aca97b1b2a8a1de2e37cc9d5dfeb04", + "containerimage.digest": "sha256:c71ed8953381d8fba2aebd79d538bfc0a6933910ed626afc850c4dbef4a15182" +} \ No newline at end of file diff --git a/packages/system/dashboard/images/dashboard.tag b/packages/system/dashboard/images/dashboard.tag new file mode 100644 index 00000000..1b11f26f --- /dev/null +++ b/packages/system/dashboard/images/dashboard.tag @@ -0,0 +1 @@ +ghcr.io/aenix-io/cozystack/dashboard:v0.0.1 diff --git a/packages/system/dashboard/images/dashboard/Dockerfile b/packages/system/dashboard/images/dashboard/Dockerfile new file mode 100644 index 00000000..243d6dd6 --- /dev/null +++ b/packages/system/dashboard/images/dashboard/Dockerfile @@ -0,0 +1,33 @@ +# Copyright 2018-2023 the Kubeapps contributors. +# SPDX-License-Identifier: Apache-2.0 + +FROM bitnami/node:18.18.0 AS build +WORKDIR /app + +ARG VERSION=2.9.0 +RUN wget -O- https://github.com/vmware-tanzu/kubeapps/archive/refs/tags/v${VERSION}.tar.gz | tar xzf - --strip-components=2 kubeapps-${VERSION}/dashboard + +COPY apple-touch-icon.png favicon-16x16.png favicon-32x32.png favicon.ico mstile-144x144.png mstile-150x150.png mstile-310x150.png mstile-310x310.png mstile-70x70.png safari-pinned-tab.svg public/ + +RUN sed -i 's/opacity: 0.05;/display: none;/g' src/components/InfoCard/InfoCard.scss +RUN sed -i 's/"Kubeapps",/"Cozystack",/' lang/en.json +RUN sed -i 's/Kubeapps/Cozystack/g' public/site.webmanifest +RUN sed -i 's/Welcome To Kubeapps/Welcome To Cozystack/g' ./src/components/LoginForm/LoginForm.tsx ./src/components/AppList/AppListGrid.tsx ./src/components/AppList/AppList.test.tsx +RUN sed -i src/components/DeploymentForm/DeploymentForm.tsx \ + -e '/const handleDeploy/i \ const packageName = packageId ? packageId.split("/").pop() : "";' \ + -e '/releaseName,$/ s|releaseName,|packageName + "-" + releaseName,|' +RUN sed -i '/by VMware/,/ \.$/d' src/components/Header/Menu.tsx +RUN sed -i '/height: 4em;/ s/4em/4.5em/' src/components/Header/Header.scss +RUN sed -i '/background-image/ s|base64,[^"]\+|base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjxzdmcKICAgd2lkdGg9IjUyMSIKICAgaGVpZ2h0PSIxODUiCiAgIHZpZXdCb3g9IjAgMCA1MjEgMTg1IgogICBmaWxsPSJub25lIgogICB2ZXJzaW9uPSIxLjEiCiAgIGlkPSJzdmc5NTgiCiAgIHNvZGlwb2RpOmRvY25hbWU9IkNPWllTVEFDSy5zdmciCiAgIGlua3NjYXBlOnZlcnNpb249IjEuMS4xIChjMzA4NGVmLCAyMDIxLTA5LTIyKSIKICAgeG1sbnM6aW5rc2NhcGU9Imh0dHA6Ly93d3cuaW5rc2NhcGUub3JnL25hbWVzcGFjZXMvaW5rc2NhcGUiCiAgIHhtbG5zOnNvZGlwb2RpPSJodHRwOi8vc29kaXBvZGkuc291cmNlZm9yZ2UubmV0L0RURC9zb2RpcG9kaS0wLmR0ZCIKICAgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIgogICB4bWxuczpzdmc9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZGVmcwogICAgIGlkPSJkZWZzOTYyIiAvPgogIDxzb2RpcG9kaTpuYW1lZHZpZXcKICAgICBpZD0ibmFtZWR2aWV3OTYwIgogICAgIHBhZ2Vjb2xvcj0iI2ZmZmZmZiIKICAgICBib3JkZXJjb2xvcj0iIzY2NjY2NiIKICAgICBib3JkZXJvcGFjaXR5PSIxLjAiCiAgICAgaW5rc2NhcGU6cGFnZXNoYWRvdz0iMiIKICAgICBpbmtzY2FwZTpwYWdlb3BhY2l0eT0iMC4wIgogICAgIGlua3NjYXBlOnBhZ2VjaGVja2VyYm9hcmQ9IjAiCiAgICAgc2hvd2dyaWQ9ImZhbHNlIgogICAgIHNob3dndWlkZXM9InRydWUiCiAgICAgaW5rc2NhcGU6Z3VpZGUtYmJveD0idHJ1ZSIKICAgICBpbmtzY2FwZTp6b29tPSIwLjU2NjEwNjA5IgogICAgIGlua3NjYXBlOmN4PSIxNTEuMDMxNzYiCiAgICAgaW5rc2NhcGU6Y3k9IjMxNy4wNzgzNyIKICAgICBpbmtzY2FwZTp3aW5kb3ctd2lkdGg9IjEyOTYiCiAgICAgaW5rc2NhcGU6d2luZG93LWhlaWdodD0iOTY5IgogICAgIGlua3NjYXBlOndpbmRvdy14PSIwIgogICAgIGlua3NjYXBlOndpbmRvdy15PSIyNSIKICAgICBpbmtzY2FwZTp3aW5kb3ctbWF4aW1pemVkPSIwIgogICAgIGlua3NjYXBlOmN1cnJlbnQtbGF5ZXI9InN2Zzk1OCIgLz4KICA8cGF0aAogICAgIGQ9Ik0gNDcyLjk5MzQ1LDEyMC44NjMxMiBWIDU3LjQwODc3OSBoIDcuMzggViA4Ni4yMTA3MiBoIDAuMTggbCAzMC43ODIsLTI4LjgwMTk0MSBoIDkuNDUxIGwgLTM1LjI4MywzMi44NTIyNDEgMC4wOSwtMy45NjAyIDM3LjE3MywzNC41NjIzIGggLTkuNzIxIGwgLTMyLjQ5MiwtMjkuODgyIGggLTAuMTggdiAyOS44ODIgeiIKICAgICBmaWxsPSIjZmZmZmZmIgogICAgIGlkPSJwYXRoOTQwIiAvPgogIDxwYXRoCiAgICAgZD0ibSA0MzkuODg0NDUsMTIxLjY3MzIyIGMgLTYuMjQxLDAgLTExLjU4MSwtMS4zMjAxIC0xNi4wMjEsLTMuOTYwMyAtNC40NDEsLTIuNjQwMiAtNy44NjEsLTYuMzkwNCAtMTAuMjYxLC0xMS4yNTA4IC0yLjM0LC00Ljg2MDMgLTMuNTEsLTEwLjY1MDcgLTMuNTEsLTE3LjM3MTIgMCwtNi43MjA0IDEuMTcsLTEyLjQ4MDggMy41MSwtMTcuMjgxMSAyLjQsLTQuODYwNCA1LjgyLC04LjYxMDY0IDEwLjI2MSwtMTEuMjUwODIgNC40NCwtMi42NDAxOSA5Ljc4LC0zLjk2MDI4IDE2LjAyMSwtMy45NjAyOCA0LjM4LDAgOC40MywwLjY5MDA0OCAxMi4xNTEsMi4wNzAxNCAzLjcyLDEuMzgwMSA2Ljg0LDMuMzkwMjQgOS4zNiw2LjAzMDQyIGwgLTIuODgsNi4wMzA0NCBjIC0yLjc2LC0yLjU4MDIgLTUuNjQsLTQuNDQwMzMgLTguNjQxLC01LjU4MDQxIC0yLjk0LC0xLjIwMDA4IC02LjIxLC0xLjgwMDEyIC05LjgxLC0xLjgwMDEyIC03LjE0MSwwIC0xMi42MDEsMi4yNTAxNSAtMTYuMzgxLDYuNzUwNDMgLTMuNzgxLDQuNTAwMyAtNS42NzEsMTAuODMwOCAtNS42NzEsMTguOTkxMyAwLDguMTYwNiAxLjg5LDE0LjUyMSA1LjY3MSwxOS4wODE0IDMuNzgsNC41MDAzIDkuMjQsNi43NTA0IDE2LjM4MSw2Ljc1MDQgMy42LDAgNi44NywtMC41NyA5LjgxLC0xLjcxMDEgMy4wMDEsLTEuMjAwMSA1Ljg4MSwtMy4wOTAyIDguNjQxLC01LjY3MDQgbCAyLjg4LDYuMDMwNCBjIC0yLjUyLDIuNTgwMiAtNS42NCw0LjU5MDQgLTkuMzYsNi4wMzA1IC0zLjcyMSwxLjM4IC03Ljc3MSwyLjA3MDEgLTEyLjE1MSwyLjA3MDEgeiIKICAgICBmaWxsPSIjZmZmZmZmIgogICAgIGlkPSJwYXRoOTQyIiAvPgogIDxwYXRoCiAgICAgZD0ibSAzNDEuNzk1NDUsMTIwLjg2MzEyIDI3Ljk5MiwtNjMuNDU0MzQxIGggNi4zIGwgMjcuOTkyLDYzLjQ1NDM0MSBoIC03LjY1IGwgLTcuODMxLC0xOC4wOTEyIDMuNiwxLjg5MDEgaCAtMzguNzAyIGwgMy42OSwtMS44OTAxIC03Ljc0MSwxOC4wOTEyIHogbSAzMS4wNTIsLTU0LjgxMzc0IC0xNC40OTEsMzQuMTEyMzQgLTIuMTYsLTEuNzEwMSBoIDMzLjMwMiBsIC0xLjk4LDEuNzEwMSAtMTQuNDkxLC0zNC4xMTIzNCB6IgogICAgIGZpbGw9IiNmZmZmZmYiCiAgICAgaWQ9InBhdGg5NDQiIC8+CiAgPHBhdGgKICAgICBkPSJtIDMxNi4xOTk0NSwxMjAuODYzMTIgdiAtNTcuMDYzOSBoIC0yMy4wNDIgdiAtNi4zOTA0NDEgaCA1My41NTQgdiA2LjM5MDQ0MSBoIC0yMy4wNDIgdiA1Ny4wNjM5IHoiCiAgICAgZmlsbD0iI2ZmZmZmZiIKICAgICBpZD0icGF0aDk0NiIgLz4KICA8cGF0aAogICAgIGZpbGwtcnVsZT0iZXZlbm9kZCIKICAgICBjbGlwLXJ1bGU9ImV2ZW5vZGQiCiAgICAgZD0ibSAyMzYuNjQ1NDUsNTcuMzI5MzExIGggNTAuODI3IHYgNi4zNTMzNzkgaCAtNTAuODI3IHogbSAwLDU3LjE4MDQwOSBoIDUwLjgyNyB2IDYuMzUzNCBoIC01MC44MjcgeiBtIDUwLjgyNywtMjguNTkwMiBoIC01MC44MjcgdiA2LjM1MzQgaCA1MC44MjcgeiIKICAgICBmaWxsPSIjZmZmZmZmIgogICAgIGlkPSJwYXRoOTQ4IiAvPgogIDxwYXRoCiAgICAgZD0ibSAxOTkuODYzNDUsMTIwLjg2MzEyIHYgLTMyLjg1MjIgbCAxLjYyLDUuMTMwMyAtMjUuOTIyLC0zNS43MzI0NDEgaCA4LjY0MSBsIDIwLjQzMSwyOC4yNjE5NDEgaCAtMS44OSBsIDIwLjQzMiwtMjguMjYxOTQxIGggOC4zNyBsIC0yNS44MzIsMzUuNzMyNDQxIDEuNTMxLC01LjEzMDMgdiAzMi44NTIyIHoiCiAgICAgZmlsbD0iI2ZmZmZmZiIKICAgICBpZD0icGF0aDk1MCIgLz4KICA8cGF0aAogICAgIGQ9Im0gMTI2Ljk5MTQ1LDEyMC44NjMxMiB2IC01LjQ5MDMgbCAzOC41MjMsLTU0LjQ1MzggdiAyLjg4MDIgaCAtMzguNTIzIHYgLTYuMzkwNDQxIGggNDUuNDUzIHYgNS40OTAzODEgbCAtMzguNTIyLDU0LjM2Mzc2IHYgLTIuNzkwMiBoIDM5Ljc4MyB2IDYuMzkwNCB6IgogICAgIGZpbGw9IiNmZmZmZmYiCiAgICAgaWQ9InBhdGg5NTIiIC8+CiAgPHBhdGgKICAgICBkPSJtIDg5LjQ2MzU1MywxMjEuNjczMjIgYyAtNC4zODAzLDAgLTguMzcwNiwtMC43NTAxIC0xMS45NzA4LC0yLjI1MDIgLTMuNjAwMywtMS41NjAxIC02LjY2MDUsLTMuNzUwMiAtOS4xODA3LC02LjU3MDQgLTIuNTIwMSwtMi44MjAyIC00LjQ3MDMsLTYuMjQwNCAtNS44NTA0LC0xMC4yNjA3IC0xLjMyMDEsLTQuMDIwMyAtMS45ODAxLC04LjUyMDYgLTEuOTgwMSwtMTMuNTAxIDAsLTUuMDQwMyAwLjY2LC05LjU0MDYgMS45ODAxLC0xMy41MDA5IDEuMzgwMSwtNC4wMjAzIDMuMzMwMywtNy40MTA1IDUuODUwNCwtMTAuMTcwNjkgMi41MjAyLC0yLjgyMDIgNS41NTA0LC00Ljk4MDM0IDkuMDkwNywtNi40ODA0NSAzLjYwMDIsLTEuNTYwMTA0IDcuNjIwNSwtMi4zNDAxNiAxMi4wNjA4LC0yLjM0MDE2IDQuNTAwMywwIDguNTIwNiwwLjc1MDA1NCAxMi4wNjA3OTcsMi4yNTAxNiAzLjYwMDEsMS41MDAxIDYuNjYwMSwzLjY2MDI1IDkuMTgxMSw2LjQ4MDQ0IDIuNTgsMi44MjAyIDQuNTMsNi4yNDA0IDUuODUsMTAuMjYwNyAxLjM4LDMuOTYwMyAyLjA3LDguNDMwNiAyLjA3LDEzLjQxMDkgMCw1LjA0MDQgLTAuNjksOS41NzA3IC0yLjA3LDEzLjU5MSAtMS4zOCw0LjAyMDMgLTMuMzMsNy40NDA1IC01Ljg1LDEwLjI2MDcgLTIuNTIxLDIuODIwMiAtNS41ODEsNS4wMTAzIC05LjE4MTEsNi41NzA0IC0zLjU0MDE5NywxLjUwMDEgLTcuNTYwNDk3LDIuMjUwMiAtMTIuMDYwNzk3LDIuMjUwMiB6IG0gMCwtNi41NzA1IGMgNC41NjAzLDAgOC40MDA2LC0xLjAyIDExLjUyMDc5NywtMy4wNjAyIDMuMTgwMSwtMi4wNDAxIDUuNjEwMSwtNS4wMTAzIDcuMjkwMSwtOC45MTA2IDEuNjgxLC0zLjkwMDMgMi41MjEsLTguNTgwNiAyLjUyMSwtMTQuMDQxIDAsLTUuNTIwMyAtMC44NCwtMTAuMjAwNyAtMi41MjEsLTE0LjA0MDkgLTEuNjgsLTMuODQwMyAtNC4xMSwtNi43ODA1IC03LjI5MDEsLTguODIwNjQgLTMuMTIwMTk3LC0yLjA0MDE0IC02Ljk2MDQ5NywtMy4wNjAyIC0xMS41MjA3OTcsLTMuMDYwMiAtNC40NDAzLDAgLTguMjUwNiwxLjAyMDA2IC0xMS40MzA4LDMuMDYwMiAtMy4xMjAyLDIuMDQwMTQgLTUuNTIwNCw1LjAxMDM0IC03LjIwMDUsOC45MTA2NCAtMS42ODAxLDMuODQwMiAtMi41MjAyLDguNDkwNiAtMi41MjAyLDEzLjk1MDkgMCw1LjQ2MDQgMC44NDAxLDEwLjE0MDcgMi41MjAyLDE0LjA0MSAxLjY4MDEsMy44NDAzIDQuMDgwMyw2LjgxMDUgNy4yMDA1LDguOTEwNiAzLjE4MDIsMi4wNDAyIDYuOTkwNSwzLjA2MDIgMTEuNDMwOCwzLjA2MDIgeiIKICAgICBmaWxsPSIjZmZmZmZmIgogICAgIGlkPSJwYXRoOTU0IiAvPgogIDxwYXRoCiAgICAgZD0ibSAzMS41NTg1NTMsMTIxLjY3MzIyIGMgLTYuMjQwNSwwIC0xMS41ODA4LC0xLjMyMDEgLTE2LjAyMTIsLTMuOTYwMyAtNC40NDAyNiwtMi42NDAyIC03Ljg2MDQ4OTcsLTYuMzkwNCAtMTAuMjYwNjU5NywtMTEuMjUwOCAtMi4zNDAxNiwtNC44NjAzIC0zLjUxMDI0LC0xMC42NTA3IC0zLjUxMDI0LC0xNy4zNzEyIDAsLTYuNzIwNCAxLjE3MDA4LC0xMi40ODA4IDMuNTEwMjQsLTE3LjI4MTEgMi40MDAxNywtNC44NjA0IDUuODIwMzk5NywtOC42MTA2NCAxMC4yNjA2NTk3LC0xMS4yNTA4MiA0LjQ0MDQsLTIuNjQwMTkgOS43ODA3LC0zLjk2MDI4IDE2LjAyMTIsLTMuOTYwMjggNC4zODAzLDAgOC40MzA1LDAuNjkwMDQ4IDEyLjE1MDgsMi4wNzAxNCAzLjcyMDMsMS4zODAxIDYuODQwNSwzLjM5MDI0IDkuMzYwNiw2LjAzMDQyIGwgLTIuODgwMiw2LjAzMDQ0IGMgLTIuNzYwMSwtMi41ODAyIC01LjY0MDMsLTQuNDQwMzMgLTguNjQwNiwtNS41ODA0MSAtMi45NDAyLC0xLjIwMDA4IC02LjIxMDQsLTEuODAwMTIgLTkuODEwNiwtMS44MDAxMiAtNy4xNDA1LDAgLTEyLjYwMDksMi4yNTAxNSAtMTYuMzgxMiw2Ljc1MDQzIC0zLjc4MDIyLDQuNTAwMyAtNS42NzAzNDk3LDEwLjgzMDggLTUuNjcwMzQ5NywxOC45OTEzIDAsOC4xNjA2IDEuODkwMTI5NywxNC41MjEgNS42NzAzNDk3LDE5LjA4MTQgMy43ODAzLDQuNTAwMyA5LjI0MDcsNi43NTA0IDE2LjM4MTIsNi43NTA0IDMuNjAwMiwwIDYuODcwNCwtMC41NyA5LjgxMDYsLTEuNzEwMSAzLjAwMDMsLTEuMjAwMSA1Ljg4MDUsLTMuMDkwMiA4LjY0MDYsLTUuNjcwNCBsIDIuODgwMiw2LjAzMDQgYyAtMi41MjAxLDIuNTgwMiAtNS42NDAzLDQuNTkwNCAtOS4zNjA2LDYuMDMwNSAtMy43MjAzLDEuMzggLTcuNzcwNSwyLjA3MDEgLTEyLjE1MDgsMi4wNzAxIHoiCiAgICAgZmlsbD0iI2ZmZmZmZiIKICAgICBpZD0icGF0aDk1NiIgLz4KPC9zdmc+Cg==|' src/components/Header/Header.scss +RUN sed -i '/background-image/a \ background-size: 85%;' src/components/Header/Header.scss + +RUN yarn install --frozen-lockfile + +RUN yarn run prettier-check && yarn run ts-compile-check +RUN yarn run build + +RUN sed -i 's/hsl(206, 25%, 25%)/hsl(225, 6%, 13%)/g' $(grep -rl 'hsl(206, 25\%, 25\%)') +RUN sed -i 's/#304250/#202124/g' $(grep -rl "#304250") + +FROM bitnami/nginx:1.25.2 +COPY --from=build /app/build /app diff --git a/packages/system/dashboard/images/dashboard/apple-touch-icon.png b/packages/system/dashboard/images/dashboard/apple-touch-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..39c1ff6ea0b46f798eb49f034c34a39c57d24d46 GIT binary patch literal 7584 zcmeHMcTkgCun)a>DIyj?AO;)6kV0soS1C6VilPW;NCF9x1d>pdB1O71Q7IyzB25IO zh!jOcP>_xaC?G`;EOZeC-xn;`JMX?Xb6@$-%;d{=_U!)7?r(R`oHL2U9oR1c~< ztQy*X2iE#=!|FqDxkzZ2a`s_#cvuh_~7xbpDUFNp&u zOLSIY9T{6@UY(1Hlq+gg<#-;r-RJm@OVH5!%9lT%IWbbb6W6SyrKK$`M%}8c^Kzk0 zAx^_jTUOf+dVOHaTISfww##jN3bI?4>-W@-rw_bSti60;`@6)+kfqhi$_oEM2|AJy zmOuUO+WVV~_r>(!uv;{a?B2c0o8#l>-z}^7ECxf#_8ueExz@o|DkLk(vPW&V$$Agc z_wB65nn7n%-1g;NZ@jQNbL~>72K4PkAL&~z2Skoc7QgcdYq)XxmRQAZPNa7@J+Q%B z_W6Lp>Ae-nB!(YbL4?VRR+mgnOU z-{gZA3M*D5Q_pQ)&N^t6<|S>+Yg_8pm>;P;t)gO2Wj^=4;86Lt;!(;x)Kf#1{j#&%Br>~e73V|b(a~`ND`^onu9+{%s=#M zL|~y`g5`a2NLD`H;=GrQLtXJ`De9i?sDx<9=RccN_`ZrYK}(oi6ydB@%k*%>+3R;7 zM9zvew-m=gc;2q3 zPc`*--3U^Lx0a6J>i8HQ8C*dr#EXoJPCf?Hd>H_ zGGCkwJvn``7k3TmndZ>hg%&kb+X!Oawp|ix6T9OPcZ*>!Adi6BMZAP6Bn#?nn%UXC z>z2u}#BvhGG(*gijy_K<+HOBb3zGLyeS9j&@_cQ6$TlV2 z)~A>{N5P}^8BuDoI$MXZT!=YTWVF7|r3XekY7UHKi#qP{u;jm)bbD_oJYILUCca#* z)EOSoV>v1lV^8Q-f(l)8!au=oZXGu75}cEoQa&*$I2HWi>iB!(gC{4>h_`78_(kP) zE!18>GMP`1xtTZMzNUVyaTyva| zSGPG2PRU*}grYjF4HtIz^bGVB@3W+pnWyJ!reZMgwi`0`XFiWc7Tm59l`1_hS<9cD zYat@Q(&ZTz>E+C>Jzi@4xbUsyl3alyf2H*;OMTu->qOrw&$ryo;VJo!rrAxI<2~Bs zuSKSGvo<+eRW;cW>X7XathEukz3RZ~qH%HBVb!dFNJHEDMZKL{O}M!4L^DHYB|qLk z9P71K<6Py{3X^+A@38iH{vk3$ELyLk1d~d6#J`!l6Fod!6f+6RrA_6|I(H72+@6ZK zG=YdOl6!XE(mxxndT$c-(YWVqbB|GsQP|eh$uke^<6B{>JRii)%O(kr(RI?qjRKD8 zxIVwXjJ-6Z6Y2;-w=8Wp_r0H>3NCBl!6oIjI(BE~y$HI;bh z8t#(hTCNUic%SQkz3=6fTYkLHJtZWi;&jX{kCk5=II}mwVLGy+w&QhrO!moipEyFhd_^u~pXjwtF7il%h1>mO^Pezj zGtW-dwe7B%!_fOeZ5=0IX)}+fYe<_MeJ@qI-G|oxO6KfBbbgU%z5XjoyLl{ZE8%Hw&0cqy_asqrLl>nSxuy zx2G|)#eEl|qKTvDyvrTGxV@r7&(9Qw?m*j)2toS&;tg>?}oPmj{c;pEb@ksqWsLOv`FG8S)+#}&v<*5D285&L-M(&mUODor_CBwUw13%2L!h?GIdYvs$b-;-K`?@z@|JDWL9-_c0MAg?~}%z z(fB~?v{jw`{Ed@OW!AWax2ahSCx7+@PB|X`c)X#wvk2_tjh4Bda1esOdS37{sEjtR z-twY8jqj_h1oC`GS;u2f9fJx(OT8=e!+9~EILfmeUnf@IDprh>tZT?Bnc2i^aYo3p zJ?FH9be2m^gv^U#*VY;Dgsoi_(lmkCEd?MDM<~U>0B34o@Z)R+ESc_~pk>mayY0+S zj+v1i=DFU39R{AIV1<#~gM0PEaL}@;>JOl-Bc#+`C1LU%sWT^p&FYQjR=K z-+AqoM&0|3!=D|3T|PZqRfo9NJL&4~%pjeiY@&-=(EE8O{71GyTNGy1XD^y=-5D@; zXJl4tBC&f zxHp`%Bdrw5LlJ0%%mf$@o#W%BonBMENq@&o*9IM#I=I5Crp9e-ey;ZY{QJ81b*o3a z-w%nPu#DKQx|Vj}47{BJoOKUl|HKgJR7E_I?nF}bp}GTA0s?93__*TPBN? ze6%3zxESD_ErvtD>nf}hT9Ct79N2))Ac4_}Xhj6f$cN&Ef@lkZH5o)_jFqABcL-pl z1tGIo?ie`S+uK{wTS<}5aDgM$)z#q$6dZ+u0U9u-FO7xwfzg<9Y>00dh9o9|0hBg{ zP6M+s@lJG4mKFp8%!7aUM|Hy5b9r{NL zrVVgqfLoE6bWa9>WaLGnvE+V*AQFDsyL&R+*25tZ;3PK^6;NdYt0MolvfVQ^)Pk_r z#}MfR3K6sZN>WotqLD-r%t;M+ph-k0n7T3w2}7!>sHqW1coe}I`3saOjmg5(2qZQX z0Io;@aPUe*WhD{;1w)dY5HK_ziGrykP);x>6(kWr$0ME8Nxwi?FepG(;@y7riVZ~s zpwv{ANY2iH530@xB^a9M#D;Q4!cMnTD4|u< zP=6^MA~BdiDY8M42t}oD!0fzWfM@__@$5nc0M;#lU@!&@5}rk8*wE>2S`fBRV7BFY zeSWyOTT1T=ivCI7wXtw|o=M&EkCjj}!k2CvsG22c352ovu`BCan4*nOKKknuDZ z642n^E9!@w@(_g_kQD2{_oCslSyo%5GW-WPzgvS8zdToRKuXqPy`Z#KtSN%BZjm4 z`bWr`@c%@L=DNZ!8v$VVO$KZ*zoK&k2503jdC6l=sc@rRI**tR5#_IMD8N5a%l&j$G0;KdU& zDeAWH*{@>;5nBo>(r~++TwiVpeJ)x}1{)dX9==1~u&DVqJJ?5%$2xZedAlQOMBk1O zyj)dg#h;)*wO=3QDllI(rghrmVUwfI#no8mr`FNhj>Iwk+j5*=_;ou#dR*K>qG*0e zFgYlbBbb+8l0Ez`XAi&2zp1h1A>Y)%_N#P>AA!a+pqMAlsX|&hWJ7ZH*X4kAt zr>Cd$pG`k}^5Nq0spXk^`7P1Hv;#K|F>|h8zm$`+JEgTxH&=?Zhk$KwM`o~93k;R3Dz1xLPkVxZC+g%?Oe;vMCQj&H0G>5|cMe0D5@fD1Yj!Vm{ z^Wh@03JE5-3nGw&2*(CRUav8GEKKVAbr1_VVm#_|nIZ^wso-RQ2~mcW>G&UazauR+u-bb+lDT?pj(> z*;6*q*501{h*(x$ZbXq;Uj1BoCOkYgqOW<=iXCEG&p;(z8H33m9CUnH?H#vb&+zrl zb1KQD57o)1J;}Gq+on`qqQ~Vu@|fd)#`Di~{1@i2fd#QQh2{E2yKdz5hHlSbK8f%gSO){gXT!g|@M=tDA(wv91j@7j^ts45>19_V(!A zQ<+yyleG637#OU~jYscm8KDg)G{wn6Mfu5|o{K;(9Avw5me*FR6CdqN_APY036+cm z0xTYPZwcWOS$Ny0G&QHkWZvp}gFd05>gnah=$*0Lw?&Su+Uu&EKWABPw~MSQEiIjA zuV{VVV(ycsUUgn4nM|XdEj<P+rZP|;mnGP z3bm}4US3`~7vRTSU0lMuG;xX-lu;-r!&c*rj%WH=@q>2*Z!wYcdR}LRh4B!wh0RjYZ8b$Ujuzrv9RYm~U=u49n07 z1jhFS-ct`#byW+>;#M z5E;*=#**XD4hDBC{W48dSNOHU4sK!c$qtPGKg#PKi|T_c0Buu3e# zU{u$83ghzU&$GxHKC*tk(GA-c#9>x&V!{0fPr6$Jxl#9Dv~)Xdl$4DzugvI=sf@ic z{7Ui5BH5wc-RWO`$MD_Ye6OIkl%E;}-@kXVsV%P|tn+ByS~FpN>6VnZ{@jM6o4?-8 zHl?N53!kGa`W7PeS1+*Wmz%_s$}i;eJiJcSW#qH2H9sXqCf8-|>pOfioIm&=yrKs} zik{#0n4_w4)J@X4%$Zetmc-I=i>IJZnxH99s~=5!Y5h}AK}_oLsA<-D;#d{4+ivUH zypm&eeqW`vS*?*F|0(3&uzRR*YJM&iO-PLWTjT!hd*rot@R_Uckwcer!?sx6ex$Ni zMmFt*ImJDJQtIH-NGMU4OhU^2juiB(p5gs_6C;1gY{Mp6M`WclK)1 zSGKfYBMLSZG1O^e^X`VOoS>=rH4d3-b@Ac-S|9SvwFx-^4|i;4S+CZzd};@<6^SNY zxWEHMwTTHUkL|dL+mbUjpNerJ{y6uEsqxMxOJBq)CtBdP`;2|gWnQ@N5$}Z)C7TPLUKp|sfG_Wg4gTPzjiI<|Trn#0k~4I)(t9e4Bj+KWHUr8I|= zW3**^7`iR^2P@2V^LZ|+{;7J~|&;y5d#nP@^_=R)w<#~R< zZ(m6&Li`+_|9lH<=inpu^Wa(fFq`A*1w1F}1@I@O=REBDT`*~1{-+*3xYC^Gr& zE_)sYBd{5Js-6AKH@b5zGqM^tcL>!zc`M5-?3Ls=YED{o_bF!gnb!Ut|hRQ*YV#d4uZd#C78zm;bCfe>n2)`XxVpeIxZ?;89(eQu}zuD&Ka$TTjCWH;l7f zmnzM|sSI=Q%HlcKJc>phenA!c2d|iEdL=z$(RX2HHZd#hR+xG|F*|kXH0Qj};=f%S zYqI@2M7!;~$Dw_l=6SbaP}6wDzNMosmu8f))GS?{@R`I+K56}J~^dM9-a zu1t@4d1Z)!i`DX3tT`pHT0B{5#g$$k^C0Dpt#h+eKcoK#j?J9Zd&lqe&v>w@*|;rt z+qD)qd2Ymf<)I6w_s7Sc3OOYYYj=z~yJkPqd1rsvANy0duTRK4qn7KK2cVtR*>nA^ z%1ZOi_f~H#T{-Wxm%4Sc$LrZw2pa=tFEh=ZIlj^}$Px_3ZIMa_3F2TB%ZFpc5_eo*T>}m)7P{k> z(SnFUGH-ab*gqM8Lz0(-3Xn%lKEY*eTLd5&1#EE2_hdI^_5sH|>Y~N7|@aB$NjiNFpfsmAxh!5`)1Y5Xl5G84nP6#Tp3;sqhkoy`Ex(gAFSL2uN+QRD#uWLVT$bb;sdAKlaV| z5@bO^Z|Nn9Q5Aq51QjGBkX(p_gapF-77ElS5s-`y=pQWR3Z(+EkZE|N^64<0M&{#5#03lR zR1%4VXDpzL@FXE!BoYWj5SdDUkBTEvppZlW>!|>_ix}`w=zNI6fN6M$NC6Z=z6ehj zl7)B?jZ7Bt1wtA_2)#$aMZ_R0q4@VlrKb`CDwyvILwqU~4+|hyJe4dW;UNau6;BqB z1tbxfOeMm61C>y~^pzqB5SUJJ0u%!iWRe&|hhA`|Cy(QfBfAjaweaF0R0Is%aY2v( z%ME$g6Dm%CLr_RBC&`sarn*vSRMG+p&6Vi-4ipX}3XqC=QWDXHGD57M7bb`XC=2Nm z6%ZIKKrl>i1cp#45-OF(yW{j@!s;yz`HgiOnH7Jr0wC7tQ+_n*Lty#H+sGP-7aO{; zSVP`2A;E|f1(XO24UT}_NS9zWB#D8+0w2w&H|^qom@O)m1PMh%2rs13`FJWFOg){p zfQ}c5V2CcHkZClc=tFjeRD>o$2<#aHA_dWa3^GK6br{jo@k4mhYFIB6kxapp$aoSZ zltg8c7)&C`nMh(1i8#V"ieiO1A;eSMNGXUNz1i)^j4HOtquLy4o)~IND9sk8+ zbTa-$4}kiUlaJE(lU$$V`X~iH3j8U%KFRe_3Vam!Q+EB|2IWHPi-qa7X| z{`2pl`bMo>E(g!W+e-juU|=9CD+iFsrOL9hod8*0R#947j>r`1tZy^Y)d28f=(Sv` z&}bSp^^L$pB0&*}o*$5$)(tdu58Qq_7+Q0GSY$o6>eRFbyShb!6uCM(qvi1jHJ3-{jbhG z7~medYZFpr9bJTJyg06?!6u}5@qwP7 MX9@eDS9JP+0qfExWB>pF literal 0 HcmV?d00001 diff --git a/packages/system/dashboard/images/dashboard/favicon-32x32.png b/packages/system/dashboard/images/dashboard/favicon-32x32.png new file mode 100644 index 0000000000000000000000000000000000000000..b149bda6e4c9b916e023376c7b1e409faf2aeafa GIT binary patch literal 5269 zcmeHLX;c$u7an#*aHWDMIs`-!CwmBq2?!)YzyPupEU1%Y0;6Oh3q&j`3JS%-hpa|i zP>U2<#DZIQWOQCnQ7@=XG6=j$KO`TEbCGntwD-uv8ppL^dsnPi6s z``cJKSOEZF!wcYqVP{Z(Sej$s%GA_90l;K1H6mIS2B&~>g-nblBA{x8903sxDh2?} zmEJFxZ|d=|d{Y!t(J$F}pr1U@Ccm0x6D&kX97Jv2q?q$8pOeUDOZrH~>efUl6 zt+BDTN-N%Pijyx}iUMax9O+70toH8CA5bn)@qJd=k9|Js=(u%H-4-?fDeHbBz3K8r z*&(9nwKgGd;*7X~-lFpM@hdsg+J3SwY9DujF`i)ZS8Qi~&i(co4J$g5zRKQuc;Ds$ z`+?;QxBYa}Riz1v9+Qwe?!drwi`vp1uQ{QbieK$mnSYVjXRz8Yyq=wvu%hz*_Z=p) zQ}ABX$JU(>RDIvS*X8cqH0HFOEPrIro6Nf+JO8|Hmkry-H=Sx8>U20TpsoK#OAgyw z$Njx{KjWTJaZfD-Hdt?&OcU)`Wp{0TRo|@4B-PTcmXd%q%iC=ItCQM(M)MqC`9 z??`1gd5!InMzHk6JfMurU^=OkNJHLbqUw1TrzI0 zNup9fr?QxIo8-wYfxJ*}tu-wob4GT+q%R6^G-Ys%;*7S*EehfLaDS-MPO3RpykO22 zZA|^5N}{%+Ft#Du?YpQK)%#+fBxm~8eCzPzZ!Qhj8e-gQk_$sZ;!^vr)RZi?u$gvm zy7O2^k5iSD;KGgt;o@yfNpXx_pd=|8J$Wjqq-OsE$Hvi}^yf1}bL^HiAUa_z@0plqtv=*xA+WuNUB`k{Q& z`BN=mxw`NHW6FukRSl6xcfC-%9okyvOy9dbZmGQD;-Wo0qi^J5nu6dm^_isfbS4Nct zT|T#Zfz|Y=qV^4goWGVIiFw@RByo_Qo*QwC%dAAD{%t?+@2hz!bhsY=VixAWZi>Sj@5a19$(dcbf85iiT)7xkIuQ2v zLECAq9UWdsd0lO5Lgho(#;CG_dxP71``w!dha&w(@1YL;@|s?;?Umwb(C%~CG*JBG7(nGJp?(aogX(Qs zh?ZA>-Z>L+E%9N^1c=hWW8{yWLHsEyJB=#E8nSz|4fv#9X^d(jIc zv*W%qO|{lZf?q?@k&AwHS=P=!S=cqqS#6hUbivgzxw_1a002fAsGnab&(H7e5W;+x zrRB2&bo1=j->3-WE@F21v^x2z_k*)xQn2#cL+c4_T8@0>^r zyZAWASTmn~i`I*6yz|_^zwvGjSx<7ir(GYsUh>OhpgacAUZjjkI4BW^@kk|0zVNHF zboQluJLerPmDHvLk|d^IWze>(Pm_aUrrR=6BO>+q<{V ze!_TC%CmD>)pPLnlPPyMwHu$^xcTyFR?^1kIqLe3w(7)Xt>LXnkr&*SoLEtsijtt#Qk=5Mp$tbZ6Hf|#1J|h`tB&SE|lA7}z_o$6cx2L-|b=T3-H-~ggafDWx za(+zDd6--A$f#s)%gq9(E&JWg&{1u;{#EmD6k3=|)8EkQWWCBVFCgYY@5Wd%U-4~6bNgBBVKEiO9tzR?1x%q#f`>&i0fN^^k0Lxn= zhlR@#6(~UBQ7Ieu_?N>t5EZd;U()zQzT6K+gfMlvkRif(ds(qGObkGR zs9;bdNt7y?8aB>=%fznrVge2{sHm2+anbxx&`+j7Kq{V!Cqi5enoP!dS%EBtNX!i5 z%pZZk?%22ll}gSe5K>Z7@F^6$Oc75YF&GR2kxU?yAxr~Ou8^u=4J1`M>mi0QIEYfH zzH_G~4DAxfEAAw;;zh*ahLA%sZy&R(uoBpT8Y2?9U=d6cQz2O7Nrk8sF#{5i=wyf@LWmv+0wZKH@dGHHRH=fcLPQURf#XpO zheT(PsWhq(q7$hkh)N^VAy`21fMA3|6;lufCWSwM2vML|SHg)OMx}=mVNjl)6q1K0 znFf()bP+^Fs0hR$)9DbylOzx@L?ki;78syJLgsv#LIPvuL?v)MLXb=24GVh0nLeRB zHja!R4%{FKO@viq%z%yK!$L45{Jm}jDnY_ku%1p5ok*tADKrM%lR_tX(%&mZAqpkd zih58I5ll+mVFj!#8F#Qw=tdc1rWU@pyP9FiNw>0!O$QrIn0II|^ zR_I%Pr0K(vq~W{aJ&=eRmO#+Zw@g?#>_iDCBO-$%%x-u|m;g)T5p08xbktip`VZ9- zQK%%cSSWzR9wZNlN+e+g7sDb*L}ds?6s(dW`f%d!(3LW=Dg{;`KJi$lST5Q!2&qB2PgCXMb+Br%CZ9APA5f_`7WO_@dbA5vHbg%1V+ zW;ZOu1`IZ@2=4~g2x)pA|HaQpG5$pl81!c+pTzHHx<1qONeq0F^5^dQOxGtd@JY&_ zyX*f(m(}}M9z=@$3`)UXXzI>KS7R?j=7J!94lo3?0l;p*S<#qelsq6t2>_-+`ol;@ z8qojwW})KoxfXY=ZEPkojZ77%qNkRb^M9t zfo&}&Sxe)gN!wZ$&oRrp6*6EtcXYknZbASJe!A)Qud{#*3tfxO3CJ@!q}mYZ*0W;F z*=Jog2Wxdy{uPH;g{ZdUcl+b{Dt5z^=wdVOLeSE<^G{C30ZAh*kOcz9{TE!R{E6x~ z=UiduAIFn+RL!RHbrg7$%a8o7=S`g%OSpx|u}dB@af3OvzDw8s7q@WttN;K2 literal 0 HcmV?d00001 diff --git a/packages/system/dashboard/images/dashboard/favicon.ico b/packages/system/dashboard/images/dashboard/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..fc042661f44d8af48e7b978dc3f6b20d637b0183 GIT binary patch literal 7406 zcmeHMJx?M*7=9L5`Thn$5rjSN;5dRB<0ZsMj)eFp49OLu*J)!61(v6kg_YJ)9Q*+T zgo;K36^Vs~r$4~P#)L$|%`Ti_$*du{#*=xH37MJaoycUl!mi zfM9UY*8#uDn9bJj|KNe29w16MBn00{6XRY3$8k`pR8Xtc&}cN!YPB$#OfZ|xuv)FK z+wE{T9Ps&k2m}HMg+dSn0pV~M(P$KjL;?#73s_rQLpq(t`uaLHH#f1hwT12NZS3vs zVSj%g`FtJ+2M0JgIYFgTLA6>%tyaU;)fL+9HmE70kSu+ev;fZapIG)a$X zuzXfHZ;>e)9WDiWJZ_@$RsQft8b0`_bT-Hom^=l6CFHz!wz zb56@)md~@Ef&yZmBA&G%Y2)N6qL(h_DWaDy<|;;`5iXYtVxAI-M6k59gk&;_)zwvG zG8t@aY#^7*NuK%c?ylsQA0HpTIIe`En5JDFOR79$UE&_H`5Rf8B zQJN^lD8&NOL`4x1E*1pQ?*#Q;{l5GDaINqCXVy9=lbOArz4tTE%$iv_Y-h7oN?cJK z0)a@8EKJGZ_YwXhCIY_4%%4_4AY!M(99+0$N-)%q!)7pj04O)q4}bz8Oa=rJ()Y%d zb*vw^Y=LLrAtM$8y*WBn=H*+`IwVR8>YEH&H}GoUQda!Qbb7p?5kWe{u5pexwB_@` z<<6T_6WlJIGu_MS)YjhVLNI)TBX_h;&-T1t6=|4wXg=wH>a8qZp3{|2*Zi+b;B2Lw z|1v+4^xAx1?e>{0izir~PMC9!c zo*!z4#NS#+ud!jG{hN<|!bB~kEYW>p(JEs;lIfqMgfmBEpm5LB3lsoNrB6lZIW7|&s^_h3O^eR2%7{pCz*XkKuHQ?sx+!`u z@o>ycwJ2$99Rv~M6^(8-f)vO|tc=e-wxZ#vNR*rY3i1eb$fj=fah+Ebgy~e*KahNNT8>lYBE=0 zoxdadiI#q`n{kqL-*{tDEj{gAyOTRhtw-n3$!il=1N*Pk3~aC26Y+6D$cuX_ec9Q) zrw6w;6^vU8h2mveC8N$ASsHiQBr3`#*%jNSr^iWlEzEtc-eBS1v0jgAghFn+`YP7l zV#Dd=C+v|`Si|A;`uLrGFAWYq34dZ>%nDnrC`uhea4(qOnrvDC;I1>&kCV!~24*Kd z*91y=S6&_=|x!o?G?HD6-O_2R$rTu)jlh` zQ_n4YrPy%dLNiR=s8d&AW@CX-|MZ>f)f3i9A5X_ukB>&B2EQ?qe@ARJjT*Ol(<1)bfEqG(Jqq>)X}c^s4DOG+vc67y(^~46ESPBL+Q%9iawQDE-QZU`SH3# z&fe>LJ|`7boXmTHl|R-g)EvC@I31ymj#=R)l2BmtY=1Ve4H!5hPgg#7M`eOiQJZla z!W7Vy`yB4SZ0*32rJ+oFrfinChnn{0x?*ALijw=gieS!avfO76;{{i)I%Xlvt4!^6 zTBRq-1W`s!(|8NL=+; zP&IS;Jb6-bjO zCjGFKsljZG1zdS})WzuFTEIJLDGr6=2smAu8(9m!`A81>68fxO!$@>Qat zWU~lUH<6Y(zs3mc-s$S#l!HivkCUZSEn|cFt0J4=%g>Bl;APD|5wKP>cUYRK6Y-{8fR9UGWJ$5~uyP@O-W6$Vt<(3OoMz^=ToRUes4K%lx zLjfjCQzAMkUE!SqK_w_fa&B4UFiFmp*Zt0O>z7^gR3)P^ePhnycUR@lk-<8D_88oJrTsiH`o_(s_$V%O9k` zSp6cp?_6XfcKS#pDSVJD%BdB2Gaj+8TtI}e3nNor<+Ubw*h{C)SlD-Co824tb!b{8 z!w)GG<}0C1xD|v|90{7P88eLe!j4%#SAomuJy7`kjnON33bx@>%{hS;MV>0{1{_C( zO`c*{SotdNN^(P+T%u$|i|46mrDbQ0bM9HayiZoOJd;6G-l8A3&HLsIh zdQCI7k##$1kI%}iuhIwa-Zne=O67E|-0TC0e|Q)7Rq3JWsZo*Z!jbU5JlYzIJ?B>f zBhKXuu6;K=nNO;)3G0w==cN|LdqT=zmcB{G+#~TaGYXVJ2K_CDUJ;;$nl_8-c}J-Y)>?z1B>vJSY9v3qFk)iRl~ib%CHtIf7TD4zs7 zA0(zP6*f^Q_wdhwx(S}Hy;ttslbWKXe)0 z({t>uZ-mRr72WGK9xSahn8PhOdgztby0~JOnKfU?6*V`OCJqcw0aoJjtG9Q}RHRhB zAm^A1%H^X~SAAq`W`>4s8@4UD)p@xT>&nbClH5lrrQY2tv)rWl#H&6nf|GJ=?)(uN zXZ_7*Uw7#iR!o0=#`ekz=^T-7F7xj(LZz_I}`t=r|KbuvYJ zpKx?UTmHhZSx&1+#bfJ+AP%t^)6nyz@#c#W^GMB@OiM4Z+Q%B%$IsVlZme}W*zl@D z-0i;SyH3)5TKtotrdW39=sa8Yz`eh|<}DxvV2V3&VdWdZLyOrKCTpIthqHjrD z7KIY4nGw%}lw%^2v$llH41ZNqyR{;Fm0R`Xg?6&oN+0edAx+OP|3NR!sv5ta6;}RE zR5@G1kTOMek$>-{=yE?d>{&vlu)5~y#v!v^UAt5m$FKAgAP|8AOcN73l8MQWlM)y) zC*r8SMU#<2?9lmbW^VXL#Aa2Kz^hP=rv;81jSt#smXGh@yjqK8T99`t3qOq6ZkW;QecCXel&+9A(nS{>Rz0#yu zOwCv;o|xr&D@Xm@$d>v^nc;c&7>`d67xZ9W4OAl|^;{s9Da)3&W%r4UMLbo|Y}c69 zo6aQ3t4BV&{&ZSt>{z=XFEQ(J2f;tlWpiL@S4*LfSF?Syzhn2N-M2#vIfG9N9bXql z*nVmBBkp#6fiI$*Es0xaA$=-8S^QGT(R}v}Eyl5Tj~jeZeTY12sp>48s4P)H+&?kb z@O3ztUG((Xfebkt!8&B}3|jC&P_$E%e|?I|g+M`}ylBn3(PHiBEZZ(66?mkO>9y#D z*U9H61TwbV96qjk;;N=Fb7>1~D$;x?RaC?``ipik`%OTO0mOCOaZUt>6Ee3o3*wH;Xv>ap2N$RR^=Yc0$WhQuXb+NX>)7UHoh0dk|h!B<^C=v*SU>M>@p?L#b zC>8Kv`s%~p*4%(WnRI=av$i$L+Rp^=WLkuA0Q)c-2U?gnO^*&UG!Q3*;6VTuz@AA}$_m^ShBS=%NYNTOa0PZ3i`Ba{wq7fkmL;W+BWV49q|rO5o5Lc(SSa zcL?y8KFpKL^}{2P!NI|ZU@ZijFFU+7$gP*2QA%ZZB1HQ8W@_`JY_#x2<6q3b4{_GLJH46ek zz9;mr9sv&E1pr9~0@#5Z8ekR#_;S^LhM?2__V)|q_$-z~ry&6!fCZWcfKk!EgxpH9 zw)@+IPk{%M<+tbslKqP%m&y2ttY32Dk1Uq+b0VPo-?+b6|EPV@7__ps#+$Nff&BDH zrur~`d_0{^W76@9O+6F_ho&&Fa2y6phhu440Gvt%P;iPKfTd!z0R|0&`U#5U8^ERb z(f~db2##QaI4CrRu0_*gz_BPT3>-_*qQLd2R9!d)r>n)F>oPDjtoBb3wj3s?N{Y|V zS@EIhAQT0stp(^|(QpPzn*wHo(ScKOSS>h%j-g|z0FI$c*Ik67)9~hO4vPX#CzD0- z0FZvZ9*YBf!tq2ql0FQB_?Gx$kDU*N%K#npVb&BH)YkqVTL&f!u;)_vbfR@p7_6?A zE>1^JPaB2%$=wOy1b|ZHgQ8Igt#2dzdBKC#fXq_(LInYSl!-Ut02D5p41F`i2s|&58vx0JI3@Oa8m)?E(L9zrL*jALil^6uPKeJcafxNB|`Wpf3gj{k{#+ zJSn~&0Jy-vE9yr-^Iv95M;C{p(9ybZEgA}(GCc+j4$c!Au7{%OXfpsRhQ^@&iXOmb zaDyovfan2M3RVLuXt5gT#&2A1`qezx6W|kt!f3(K7&uzX0gc6DwD2e$O%xiBLcx&V zD@O9y^^cMX$p1qMVbS2HjR5rf)(37d;C_Ytd&Bxp8lT7i;^+Hh{1+pD(0_vb7QcV! z`a{=mG4NZ)f7JDduHRzdw~YU&>;H`|@qey7fG>Cq3I;DU=?@%lfR`Z=s^wNw$X7@U z1aj77qYK!x)X%~-00NPa>LHKQg z%E=p8TwokG^L+Y9KOu`;zqTNP7J+s=F}LMdV$_Xy35Eh4TVZei-|#@pS?*+hHZiFogEzoE}JjixRK|6tjDW@8yvi0=wo1Hq;K!F z)hC=vU9c5yo%uCRmw}+5AS?XIN`N`6j3H8nzVyOflaQe{RBx1X|` zeH+f`RSom?O>VL=O&;|O3QFJMa^ch|)wVcFNJwTB-re1OyP0H0Mut$&tKs1&4Om!2 zMDNIm>ciQ)z1`ikeiC0R~zAl{fY_-sPORc^N)SVB>DGY1Dg>Dx3b;In$J0D%GZWtXVRp8lyW3uvxQEBGBlsW6Ye=r~<#OHxe)c+=plzz9( zV*T;#+}!lB&~54~CdmEm?FoB_oQs^w#%l`0)Jp9(W_ne$(c<#NVs85Q`er+5w5XjJ z(bmynC?<)dnU>VmSsRTwYNTycyHzO3o5@VO&y0-B-Op#l1-+yBQq zT2Y3nKi2*{l{fbMI^u>ii^t<#a?tS7Iq~6%NK2vQ=Ts9czoh?E-giy>qlO=hd{c&y zki}K5lR50@y`G*_0?%F}jhfMyo16P=z8--<6wVlnT(JQgAvt#c<3 z2$|2H0}Nmo?EvP7L2^Xl?x%6 L*_d82-V^gb2IF%Q literal 0 HcmV?d00001 diff --git a/packages/system/dashboard/images/dashboard/mstile-150x150.png b/packages/system/dashboard/images/dashboard/mstile-150x150.png new file mode 100644 index 0000000000000000000000000000000000000000..70d40bcdc253519a56d60226b9c914d3a392a761 GIT binary patch literal 6948 zcmeHLc{o(<-yenSDJ3MPkrc+5%`&#^OIbsxFlNp$7&B%@mMoPeMdPV#S=ucvh-?o@ zlqgvfA<9xB>!U15-ZN5<-uL-k*VA>qzyF%+nmOlum(Tb9e(uk??{nsqm4&e&p9CKS z0ueMdF|dI^IE2_=9&XSQkUyURfpB{V**Y+7@cvL5ok}8m15jol4S)gxWD*$CHRf=T zr6?z`=)T!;jfz<6+sXKXa7CS3yBAs|M{$2nN5}6fvl}_V;qA?G+2;`U<^DrzfX#Ku zg6sq*vq$H>a$hy)2WXGY**vSA4Q_vNt#*ob$+eJ|f|I+Q2Jd-Hjm=Gz2>NTS%+?Nr zu(a%X@6L;2Q=L1K>K3NmY!ODMnt02^3iszY+#HUR|L9k|Wie3T-Oax9W7eboVG0&h zz8TYJ3f8CRGMT)8d`Z&tOnx)Ke`T`aJzz7Iy#pM??V{fImi}pVsUZ75p7n;SL3J=lR-r9_0 zK5cne#)1cX@eAh|)L1^yi!15>6vDj^|9FE&uWo`Ejq((8qb1X?Fr3@q*}XLixM$(d zkshXh{$(N;8bH3AnL$-%{8{jl?91-M$9Hut z-iB_uE3NW~Huxn5*b_11mra+P9197R?BL|AvFtp2z29}=$yNRe!xKzM`W>t0i`phQ z1h*Q@8!jBRQ5fPGAHin`*ux~Rb6neGiltt*_AMQFx+6+;c2y)keIRZ z+KuPTY+U#6U+bXGKWcopDk^2i6PS%b&2=+{8-uWnO>n7AsXH5V4P$Pm*i#Y}Qyq}l zyPi38bDk8Ny)QhA+S~8AuN~qZiQ>xf8^1B6bR{XbCuofFAlOI>^|Tp(jinNpd1?+> z-$uUMSnN?1Z|_|2v=z9OTa5SAh)gdTE%58kE$^`|cMX{hU4t#N8d$sACELGE`DPG7 zSIXiMa;>W*io@5B$F+Gh+3;Fg=UK)xw@bn|{5jN2pcse2BUT>qhe9 zuN&vL`prqPet=q|G{rJk0xN6T^^ZLYFUomx7D87d_G5AwPm>0NGNqyKP zs#)Aso|_+ZkRNGcOu5#UgFW-dn>&Zk-r4@)ofOwxkms}b#J3rR#fohlaC_6uF9fs3 zMe`R%y&A6`&4Tk39rdx@hC7-{mQgBP2)sNhSw1uxMs?uEg@~gLykW*>`V2cL))bv*feX4>Vi5Lw^33w6>7YG3vZ&Tb@}+h9c* z60l!eH2olQr|pXZ^#&xKz^j|c-D){;h@k4EuTZ>U+vzXY66~Yqye>cHjLO+pDPQV) zS*!y0nzAGlOB7T))M}`q*d1eRw`qSJtwF$AK4DGAR;R>d!y86vM@<_NllbqJehBj6 zG%DM|TcB{-dWXXBVgV~SNc+o{SkD+w2^NZSz}izA4`tFz?hHIsg^WafFKKz1ev6xoixrxGNDB zfQoR8LB)w{IdD0IRVCC3*O>M4;=P%1QH7ah<>YxNw8v%h{o;(AR+@9^MY*Cs8C4f#B8yL?lr>dF z!z%`!HXh3A;H*opyX3dNNK4q}ef0b7Lc}$%xQerE!cShk*?y+<%whSjn5cDCTB@y| z9&mmz=+}yg(fV-KRw5V+MNb4wrfncEJ~;G6TA;T7fI!bapK^_I#?l{|x6M!bUXi#X zBMztSu0{0(bMnUe^W3eF7zyS+H}cqzbF;hTMfJ*df!i1Tj<&^CXLKH|a7JqYVPUx& zEh?09d~oR!J)fph=dZNfXtHq3k!xyx$)n)Zh{e20wrZbIDwXQnDZ2QXdvWpuJ`T+Ii@E}*K$2L+}=DaAl14fYb^{q_x^}la=V9B(Qvsxw(_lQNk&NMT0 z!oAdev|Zn?04m>~ZMRD=(n_Il#FaiQjUk)Z9FpYfI1#QBW4CUL`{8YexO6AiJ$g}N z+G1$-MQL|o^b~7As&}C`seA%*#Sut(ffn*8qmXP&kx4F__49aS^w6huFE~C<+mX?y zaesWnn}x$C+~+$M)nT4hZhQ9ZxClg%MX17-)GqF!kbW_Rdig2!sbteFJ3dCPhrajYwq^OP;k(*`XP)>uA<1rstnWG#@8V}x_ z-=12az(wY*flY=Qy^deU?Q{GqHjg^SNYjQmj@W(XR#W3N+8bXnK0SVa{Qly>=i{%} zqs-}NTJP64fe$B=Wbh%x!F(T%K&2?*iBva0DS$!)RRV!%>IBg61TTOIbpzbVK3cGe z@=6$#Ow@uMz?v(Y)ARukvPlpf*dJtJO9=8Js1sp2+I*S;I1qpWF!9g;ink8~7oY`O z#>Ii>Y%>A|T@GP-X~7)Kt)Ti;IsnBeVU(2Nh5_UwD3~@MRFh65;cN_yRv^GDEtm(B zNy8x!{{H?-{%9pC-5r5cS64?UqYx+*9E^Z70)3eH0JslBh7Iuz!vJ6q=%BR8R39iC z6Yoa#V`{-*pdb2ud=#3w`44y>#tI7{ABX@v4S`frMo=h-)fo(?;SmsIWkCO!!LS9N z4k4^&^8#fjgN( zTh0Q>{wb14CjCv;Ph(?ymfKl95HS4*?oZL*dtVL)qs+~522_F{dw8Y>S}=Bf9Fa;O z6LHI@%6OtOmZXMFM*9u*sk2tpB6 z+?3Un@dUUkia>y4kSYM&4UJTVV~GHX2&k*Nsj8?gLlFr$BPyMO2d9%v!Mg(pnveUk zgH1S2*UD52hEh`g+hXO7XOh4KEtol;0JYrzx5t)D0roTTY&wyu$|#H~S`Ez>sEYEc zbbEl#0Hw$VMJg+yzj@g6f&;q&nZ>h(3IZ&{g3aLc=>VQdrQ1@e-dZsBn4s*;Wqm_6 zzs-sXnE^%wvL(MF`u%|Kx2tdWfH!&B1%)o_7KbN%E5g7Z0f@_mz`SoRf(PEm9RP3e z6-9lwlmB71+z3cK3P7vC0X!BD$0(ywaCM?G07nvtDp++S2@haZenw|dNlbq{9nf_L zI|aJ|6|~$9bk{d7cmEvj?*XuhQU(QqM8T10TOZ5P*5#Y~TU|u2+a33)Tv0Y##rMpOwk@FIE7de;4^Bet*;To33AC;Fp4b ztLryizr?^V1^-sp{~KL=f4}koKHy`JKlnmpa1H+vd>P_)+iPq9S%TC+AlLPGIe->k znu#L=0^t{7e>os2X=0#p9n;j@aNUrApx_p?UPN^Q1j5B>YM^Ti{-4{Ezqc(+vUaK@ zsJZX*UeWk2;M(zcFWvXhNc|$rpi6V65=*yvM5+jraZO(^lCalyuM6$Yrt7h&RP zgG8)dIV@lQ2Xh~U?LC&Z`vO!aC@9Fy+gs7%k~SqaY;IwestAYI#B4!ab;^;5$TSPQ zmzkCId}iiIzpH|R!f?U;ma(yx zwGCaTtrPksTCu+W$$7c_`}ci>Q{=%>CzuUag|E9|e@j+q=0isw28lddvJg$f%%-HL z+lAxC#>O&QTCDp#&K94Dl2L6;Qx~bPueX+;Z*#~ip}u|$PELA;=;T|Em@{Y2oH7bm zI#ep0Ws#1Gplxb8B_bC~7@hyr{z2u)wcMJ#g^g!7~2|=dRAqskBeR+F@VQ za-Azi{3YRozTPZb`2;a(>A2or=fI_tJv}`RPEMyIBO~YLr?c)3*6^)sJU78s;}21? zPxe8+GyT7q{}1MBj&Jj_JVB6kpjhR&sMNTFB|bF`sjAoV@(^aSC8WyNm0`w-z|{Me zYXP4|5_COo#+Tf>bxQ%Rq_k5g%l=kIx&OqwF>RP+L&dvy@7gYNfEm4o|x*l4TF+HVzB^E%Fee_ zDapwuE|sC5Vm}ExSB9oHUecLZAvC`JZE5g4{p0Mcv9a;VM-$USO_%Bl6npOlitLtk ze-g7c7vJ5zCEyUtc8=N{ z003m|Y^_`X0EPkpF*#{TNKzn|DF6V8fC$$O0vAdcoXg`dSb-p1u!Rf4!EhD>0K(h* zJvQytUOspHwW5iI9ZXw8O2O*0q)Fw1vyq`b9UuA%ro0yJQaO=uqdDGgq|nr3OkCbK zb3MwxC7@!6e)o>7M)|<$qX!GNwvP;5{fr%BkiAEmK-<{;k=1XJJ;ce+ow{eTJbZL7 z4j+2MSxz=xc|Po~ph#4kQhyX#any3pkg>VEM8C;Hx2Nwv%p1G<^7$8a$;YcL_x0zu zEtzybp)B!5dPH$Pd?`X+oIa&(S2OFll1K1xDwdPH&(zwV!&mPPu~e zGUrn&vVYyfjtd7yFIaWNdilOM{e0)G^4VM3j{6Q~_SZRdq(qjx<@9QdeYx!Zh{UYd z-B=J)W+L~2+}%UbkURM4;lUGyK7aYf&M_{0P6+=Hv!a$zkQ%moL41Mr;W#y9#%ejW zRc7JK+y#fE8dde3Ll^T#wx=uQl_sc^F53Qazp=#GvZnf^Lk2hJF!ON8+v1)gWNG`};&*y^DDO*KOOzijE{+Pnc3sVQ!}FSE zpIr1gitC3naiJvLBY1^+-32PG4q}Tk44LW9cdj0OoavqVet9B=-j*rBuD`zdSS{GJ zue{dqsKc4KB@*>XuM~X^3=K1ykb_<_EFZZ{C?^u^Hb3o zpU;lVD~7mb-?SrMOgYPzwJ!Up&e9ZQ9$TwqGnRS*X#rJm2JDOP49x1GT5nx%XUGsGDYZoV@t) zWh?MuK{rbJV+8bw&?vXc_08fy7|TFbw$lc<-g~8Z$GNDG>?WI{Dpd9zx0tQ&Jo1zrGbx9wIC#>VZD zrpaLJC8)$gefS~zjwuT7R?r!21J{mov;wD;%ARBI+6%IBVG zigZj;AEh?8%=O9etJum&9?Gidd}wt&35DFPOLd{t>xELq;l2z6>UR0Jk7+3tIYP==?dAHpfhT9L^P9jZDujQtG(Z?G!6> z%TBv=DZ=Vh{ilz&jvtbK$xMuOQdp&ZIitOeFrw#O6_w-}mW>$L6Ed8BpslxZ_)1?{ z>J+1S1;N*o}J+bO<(T6j$Ia4KogE# zV|#PC7>soJ$eiOq@#FVI#z5!o_^Gs%l?U$?-@7$&)%%i_Tb1MMDtpxtaewcMRNdsF ziw?|$6 zj(o^t=C(b?wl!udNzYELvEE2}WL~Rj8FCS>*PZL8W0B~zqWJA*Ue6MJmaU7|B8k?x zc++GzDP^X&hL?o-kW_6;on4dlnsJnF@s8ot=ZibObflLL0$HA5MhjlfuZ+!bvBReO zF0?F^*0R9=Wq#PRK2tlVYgOgIyv{G)am>-y2_nM3ifU%2eGE)uE#N4u%EPzyD5j;{vijaY*-m`;eOq@K>ynHwZU!=bbW7ZImheh zKIhhZZri%aYOcAj=POb^CHwr2rM3!LCsOB}J-_FK_wqW6q&xdeCN*2pd+aqmBvKa1 z({UnHa}I>IW@sUuieLTIdeO>kwJ#_15)tmCmODxMb-Vh^voudacN znq_r4Hn}(TRG(P-s_UKmG>=?dA;FqmhZu^odA46lGAMSEP{`@$XPN+>Z{5Zujf`g5 z*zd0x7#XM>sGQjJVBncN&VjeySkePt~)q?K|{gOeufP78}j|N(Yfj5f^0~Y4|&D@ z!;X+C!%zI3pR2 zh%cZ7(Lf;-1dd`sI5-1C14EE#gv5eW0#cvBFhm*=2vj77&cNss4Dob*D)tA6bvzc- zm6X6AqY^^VAt*y4mSIRF5ReRgBOFqnh^HcnR16M@#S!Q<0|JJQCmM;M=rocIhsUNs zJILchttbS=Vo>;LU}0TIP&N>=6k(%603r)08ImOrqzE`XR}Lr8 z7$J-aF0>T&H=I0O6i~5#Cp-nsCQ$j(y$Pr{W zeMIx41TjJAg3ol+S2^onszt>RuvidpfW%^Hbfi9>K}1sNI06!DWC#-ISdc*gr_=a` z&gU=$VH6%{&V(|BvVl5Clnq>GnoHfEg9-Bkg+yU+c&KbhEZ!BXPr?yM7~BdBmW06| z&@&mMh4=bv%4GEaAcZVa_+b!0cGEIwz(Df~{cT{)kS65uzxbLd#(&WR1pUX!FY)__ zu0M4B5(B@a{HMGA(Dh3U{F3sY?)q(X&H4Vw0|r4qgTkN(8phH6LD0jHB-MVk6)*+V z0YJ8;&IU*_n``UI2LPD`!nYWZk*NX+r37{k)>5zM%F3$3cC`&^LWUl8R_3nIznM=i z*zXTs)G$2QX1+Qe<>}<=P1Z;Q0DXa_Ao7YvwL;9jDga7mB>W|kPPm~bat6i{CmA(~G9+1Z;T-}LwIs;a7b zbS?TCHma*3Z3z~SU$E}D$u66d6a|1}q1Vj}3|yI?pT9JU6BT80l*m8j$CL(+&O@C% zdD36|bV*5xpu2W<7i_636t7%*wGc2dG4WAJK>EI$EFKRhDJl7+&Iz~pPU3uZHMRLj zBq?mbtFNQtu>#yHCbXxw7jKc5?(3000j1afzNkE8R5!tFh%-P>P_MtZk*!*Sc&WiTa?s+*ocg`L(;y9mdvh^tR z`CyE4a`CB(AMbLpotT&i?zx|n+uG}#*OJ-1EH5u_59s;iTC}N8MZ`;#WEZSj;z`{Q zXG^_=kS8HQGt2K~{Tuc&QIUSA&gWHUm&NpVz3+JtJltIe1$u%1+A%)xUC)ElH!iMR zOb%B_PEM8-JE4{R_qMYw{$r$JIIDk^f$A1mbepnb0HSby5_N^%yRoGG)^z{p5v<3_=|7dIbW z<{Z})*5M-a?qaA86_KCR#1drgp*YVf2^PsNYldIlR<{&YX83tSlb`{EZT<_mLV)$Tetn5?f<<6(&VLjucBb5yj zYi_Lw-)-tO=ZsHbL!yjw_w`tD#~$U%=&8kcJbrkntLF3gXi>RJf{e5>SGnfeOVw|E zFD%RdrTzc6>Y9}v0=|}iMz3=)Hv_m-?SN&+XfFO($1Bow+W(gM)?^$*GHo^S8?{F_?+qY*mH$Djh!8*|u^YrxG8PHmwia4FN#I*j+n_Nxc z(MOkgrdnEBEEenLsymy8`r3*F<2hI7ocXNY4 zAU;bA6MGPdRh9YS;s8c2Sw)S4K%7P=99;tJF~ML8jqFAABY*=!C!b8gs6vQKYUkQTbs!7)LoJobL$=70foW1EbX zoiV0+_;}LlIVZRI%5FyJTGcI=&X1>-lD~wl&4(~ZcwIUJ;}*``^vVQ1d{y4whsd~d9R|CJSE;KcERprNy_BIV(V@nKEu>si*DGjJQ%#T z3Hx~jyO5KmsSufa_N_?xhIs@UwN$lV=?KrfI-!lF8vWE4ufweOh)gmhZ&kW3smBgAYsV)A=4FBIBI1>(Bh|NL|S>g$ds( zs<2N{p58Id;iBcsCs1hCkYcpIvtlg&wfY#hN~hMsl{>k-mHW<@*&n*_$<;eUpm-C*+tV2)T4_JDIbQrXW=g?W9!h)w&mbLp$P9&7+F?u^QN= z5GDDh^>(M9RJ=7&O_a%vc$}g95Xn)WBdkuwAX$aQC`jexS)^Fd5qXZ=GMB@5bVWxc zevEIBpH&3yiqJ5=WMT-)Qy6!2IG3fMAZE{E8~gUMm9!xkG0iSZm%aPYthBU6C9Si& zLp){MRk_P7+izL1`t1%3Kg|8;^i8ExdFoWm)RV?1NhfpNln2~$PuS1xw~zeUQP7Uq zbG}T;_pn{xtp{(+EHYjmPrp@of25%_iq`rJLd{RHP*-Z!P>YgZ)qkeJ_hJ##lojWuz=#PzMs zXJx@aO7^_{HLS|iaf@9DjU$lw?Dvkl>HO8*Izwl?pG_MD?~=lYdB9hjoZnt_Uk}LW)@tdVsjF% zndG$(=d-kcBNNY<*rmG6m~hJ*qi3(WEB91F17vW#4z*>R?%JUUiutq1n~qp%ae?Ws zbEqAViJSgtowb6nm+vxtS4+3GC0h=Pq*%7)IJG_*LZ|fnr0>v2gwG_4jQ!;J>ip;G z4KBV+*8D;Z&3&j>_NDtOmTWUb-E8^IG=_wacE-5RZcpX%zj(VN+K-ptYIv5)P3Ms~ zp*bjS%yazidNaO})uBRDTR;Sdi202y0bRvLTFmEWd)P=_96{i~aY_Ros z7JUoc?<5ptx+$?k_yF`Py>6{gIM@>xe42kqWKvLTPr><=ZK$T8;|WvebFKDs&^*V&={|b# z+LDo*pJ*o0BL&mBSGnkC3#(qUF*wr`Qz9PdB@Q<$z06u!H4(NoDRC2fkt|1juz%W` zwsPUnYBAj=EB5dy#L0IzRlhuKHJ{MT+EKNTnwoxtoVT*Dz5Z@bsi5?ER8riWn8Ot( zF?`4k;n}i-VWh(XG>=bR5kymevc+v=`9RBMJJqN)xYDi#oEawzzBk?&X(=(%G@oGg^@w0>)o1G^CeKF32=7qO~Bp z9;bO0+bHr}Fu|F~ZSyJ?KegUj%X>)Kk1sf*ZPnvqZM#dfbE=*_49O;z{Mke<4gPN5 zH`9BM`o0x43KwVdP~q$kWIF>*4bgrs;=drq3)49Dvks|Ejq1Sx^l>D6+|CaC>iX^0-4BP*bUYT1<(Q035TJ z>RB7@2#0gkEOTE2mAzQe_IlBf$@xu29C4wmtm{dj!O?P)!wmQ-hdD*Pk4hb3H(KCq>T9;_HnrMN-CK5cF?m9IWPRjf%?D79D=2{tkFRcPLHT{DN?rsS=p{ds63dsrx9`aP>+NZ zG>pxpA|hcn`PLlEMV*JQ(`7SDRM?5zn;{EfW~1jgIs79wHSUq$)3fwJt}}<%IJC6b z%&gBnm|vc+o3H!o-a9|auVzC_>Zxmg2HdzLiNMXu#pVDSM<%Ia@MJ7Ol|iBaUIGH? z8ZamroG&2&j3syz{q-OpYU&|iB3=*TtYHJUp%@c2mu%{gXHH=M>F&wTexW8H***U0dI)}`07DiY;3{CWEugCR7I-7p{5LCkQzjv z8>~yid!g-3%zi)sJw1p|KmY{|g9Qf%s|Ks9l4;&BgtoRe46X)KQ-cB$PG6IAoqI+JnmP0N+8W|Ydd%xjNnHg z0itxkD&h|&%`I(gf7M`8;7ue^wzL4U{~#Ga^!kmgKdg;8v$dVyF9cBk755L)zwCWW z7?85DL7R|qfz0Jun&?58_R)AUj)+HZ{Y1gF2uOmu7E~RHML?077&ug0T>}G!YpZKx z5eRjZ79R6EC`*5O0LC9jU_t@lszd+>uZcon2x>Se0f*FtBDKA6P%ST{22=~Ki9%{3 zHLwJN_U|AL(TIRoV*Gx;Dkc;jfYQKXP#7;P0ZP!st3#1kj0RMjpsoqUVKkBIC@(DV zrM?A)$Dz&0G!h0lP9h28O@LASy|*TqgrkjYE%hL3s_@@NZ2d3+UVwrg#0G-{A9DC@ z#*s)OI0RsrbRsn2YDi6WZFNm`goc`i)^9>i1R5Q1MJ6Z$uB!eWn0YQ}U^f7>7^b5F z09zWsX3)ko0w#b=b0m}f^dQVNfti|H{tedsekvA3Iv^3kbon1n??9k_?|qK}KjPLD z7`)}TXbkSV5jrM_fZs9%=zX8U`C$CL2|$4V@TgzLiGOlh7$iyqhtkjj4ock%iuBSz zLbXvyEvTlZCLX1M!r}>P$Umaf$zB1$7#hLI8`vqZ8^D9Mb^})W&gI@eiU<1;m_)(V z)S(D9C_>#4fkdlmpw%^1;0QDv4uSpHF^n14zie3-_8+9^ZVCJ@5deDM$AAO_( z3F`-GOdkKi=f`3EgBAeje~tVle*dNGU%LJh1Aj^QU+?;tuD`^vX1Sov$iCA!rE8qgRk=tl!SvejcY(LA6Z4HFIM{Sov>?{C63%yG;B-2xuP zsb|+@?l>yn&Clm+Jjch!*ZlCIAztlr+Z!4O%NT2~T&hJ=OOgccMLDUM_U1|6ojVBb z-dp$X!K$mP$6p1HCSAQM9re)V*&{_Ioy{wm*G&^dny>1e93P97L2*>{wY6E)E_dn_ z)2BNtLzZtDWf3X|8_zs;t)da;M(Yi{o?RvJa!;*)s88XOKs9xB{e<`~5$9Thx6IO_ zLcE@45O}%gUy$pQ`tqI4QJESsrHN-PGP37t@sV-)ckaZ=gssZj-#Ld+if?IYS)E8R z7#}RgwX}U8>^jFU6B|R-{kE~(JvivY6@R=nS<24SlguTc`jaOl^{l7|qd`FEDDdd6 z&y~gi$MOYwv>G|}G}D{QsxJ;ekB0;4q zduHRg$vZg#y}thb-4SW_&d%O!(Fxm+`CWv0qF5Ca(jSYljA2>DGDqWc&hhTpvBq%} zusu59dHQ`YR!KaTUk1g>CE7;z@lmQ8X8NRtcX|4sjAXGcm*vi zEWG>LxOUhEqpYkv5h6zOa z#M>N~`mj(W3e{2@vW%VTxEzCd6881uKpS3d5jcyMhA7U7C+Ahns29etaz{Yk;=yQ` zFw5T?8h;)Wjm`g0;}T9iuNeL~|L)y*VHGD62M33aD>|B9omoVoTYeM@TZ0XvB^7sS^UHLq1*6iI@!-LOV!xphF-b{eOewFZdnLTiQCV0N z=8;%kjmFs`Pkx?Hx_vEdSfEp_(b^PVbVVmPUL@Xsw!g5Lv4}Mer$lT3d4-ufVzS?+ zJ;v)Ucc^cLnck;C9QE_7V2Q}IpZ#B<<(QJvrxuLlY}GO{GOm}G_X}`|?s_=5d-v`{ zL(8fUb?b@Y6a-5m^x`thz73m5N`y{RuJy&l@On!DRf@OP$xj79i0bL-Q72mXzK5vJ zi4`ASety6LW#P5amIX62Gwf(xD6p22A-_|rW3e&e3mT8#wAHLD=H%qahHZZF9=&R9 z7rN4I-re1e;qn$AOXf+O?a8$Ux?{bPLN;VFxps9tAttq%kI@ZV@rPWR;7E}!{P5id)-#BB&nR|5rvEXP8 zYPW=h+<7ZgNGhD$;S*4B%oWq)0?<;iJEYqGYQ)j@0FCO1$`Ki0&=A$2RjwWpgv@B%A;6*iASz6 z3D6^#DgkMruoMTqcf;A*0w{~m9S)f~J6{9}+(vUIeay3VZ6^Qvnd^B41&N{SpPI*; z6Ovez@B39vsBM4x^eJ`b`JKGHu2rFDixaIka&w!RF(xG{HlT8^7UHH<%}gD>zWK6- zm4;!Z-p`WD%TYk}7=H00iCMFJNu(rZv9jISU*L*kW7azdhjbuBK98IvcU)F){T^O3 zv$IKtmP8*PI4h7X;pMXf_aq|HXzzzLjIa#jg)%;}R9~^!E1N zSZasGWaoLDe1E@^_9k8yyisSYz2t71UWR|1rbQh$>B!J%7ZZ9JJQ^yR?^GD?hw|m! z3dD{4-rI*-WB4Sn48|Z()>7rnvCC6Wud_$<9O%>>J+&)Ef6XULH>5}GWssbl+~QOw z+0571cjMCwGDk!`^vilHc!#8xKuz$6 z)e5@hTBG*3kfFf`|dR0l4TU%SZUSDrO)8@DH7FR_zvQsWB z*1y*K_4fDoUex~gB@n^#%PsN$x-9-@Mf~r+kNlxbdP#m$5#I#~*deEe3 I|FOvb0Wrw70{{R3 literal 0 HcmV?d00001 diff --git a/packages/system/dashboard/images/dashboard/mstile-70x70.png b/packages/system/dashboard/images/dashboard/mstile-70x70.png new file mode 100644 index 0000000000000000000000000000000000000000..f59b5aaf2111e88e160d0f3c697419d8b37f13fa GIT binary patch literal 7504 zcmeHMc{r5o`yacMEh<|YQyuG=#SCT`VXVoTU1Vm=Fc>pt218l1>rhFSqogRxR@veV z3Ux{%ODIJmBBGQc^?Rw)a{a#loa_32|2xlhy)*CoJoo*%@B8z7-e;cYniM-5b5RjF z5fBI@YH4BO0DQ-+UBZIEXR86B0|XLDjBs>iI}pOa3?`jI4J3ov;S4gE%%M_1AkL#% zH`CaRXKynaF!qr%&7ay`;uWWICYG_m&)36X0FvP`^;Y3sZ6?#;ev?J* ztHxskBbMGc@_`~5Wq~&zeru2huN*s{7+c?5DBUD=e`nUJC(PRWSXgL7GrSABAI&|z zIG(lQ#)*EyjZkk75aG&TMl$G?jV-UaSFOKPG1Ug#4mYK@V&%B5BL)Ffw?kcnrdF~S z?hjlD@)+{X8MqP;^;B@|@R}ziA6u>9Y%_TmGtehKvY=R)C>&OPEG}`YbIywH&6reG zn{5Khh;)k;qEZT44EwoNuS~_!^4V<*QX|g(&za5dul9@Axv0Ck@m;tDB5V~q7}Z$$ zwCYr`v2fEcO@K>8k?^8#^CL-e`kNn;9iIv|aStAR;Swh_R2Hb}Kp2cNVT(GEC3eW)&TSew>1XwP z>xM)AbuQ8S*Rr!-fBz9)!MkNVi-Ab5;LhWWO!wRCG+M9 z(;|y3=aQnEySJ$p_x1Rf@pq5sUG8%Tpos=(TLjfN5{v_Iq0^<;X0BVoxbL+k40eht zhX18(&)7WgD-u5#yvmgoxv z2i_?Wp76)(1Nw^SuGJGG`9;dj?XM&5=gu@uUGIuIG>NW3qH1s3Y|XRBDXqW_tkR0z zuB@=xd*nV$FTB<$L0)`{W0fHI`WdthOv3>M_2kRvhQbQ9M?14f<)^*-(3zDn3v#FW z^0$sfSdVFT7}859wOWP^*9neH*$|Pb_st8dZ;k<``C@uQ}5qd zBhF8ey7cen_U_1HQ7c1V3ejqr+5X*Qrq?@r;4>;hgs_R>BcbNk&p)!icdA=mIGU)n zz(LJu*Y@;@-(rl%ob2#(Cxa;nRM{}E`HcF;?ojjo2vv>KJTexXksPR5?i|4X4 zB4rgdo_-!uG-wfG%bf&&4|`vn=8;HM<=lIust~VJ%JlR(bH0PP&mZGB&OW;N$*Zw4 zD!NuXWNAf?5}Ef-``C3B!l>s@P54i2Ha5ymS5GVHg!t|2X861F8N@7LK|H1vOT`#t znHD1R{jpZZQ5LUeL;HE@CO@Ao`n+<8o=cR z^Ql74Mx(Y8^OmADvbAj&gUf~&FC;Wx4n7$p(%zHcx4b>CQ(B;Muktn5;#-ksDHjDI z-*`w0;ftlN1tM0EpLC~NUpZslPd%%vH4~P2cfR5@q*x~c&4=`pze)T|NxqF6TON8& z<`JD+9qoNTqF0!o|7T$LaMA{iNSM@cnBTN~_K4o$q1CrJkN+@#BA@SUWRp-)vP)8) zm!$UB!>m$cy_2S1()){Jv1yu|U^Bh^Nbsy@yQnJzlC*)@@WkFOLpn<(tLZ8@hDNJU zYL!7o&P45fFS&YFf={9%Vu{Q9@x_Pcofh5^X$P`>Gc7@|$}O{o<@0T?rY5j)v9hQe zXEwEHY(b>+jpEMNXK%9N^;BL~x~$s!3=aQ9nUY&TeMqW{9-fVweV-w@6i^p^v_9#v zeK&8;zN2|7pf6*WN|jC>8cV$A=YD6~{6}4PJ_24;PDO{W&9^;Hn%Zdpq5t{$vkALk z{Jh0aUgfO zTYr<D+_3(k=Rp!pU2PdL3ItQ+I?!Ub4~x z_ruffcW1i8T7=uu9WG^+?>_7xm{Qjp8@j46Q_eU*xbxw8!Df zqo!UDLoHa&P;C9t%@UuAN&<1V@y)mcekxIUF!!LuS*=Z;MHci{En)l+J$!Ti|4W^xn#5QF4Z17;Riur6y zYr`nyWUp8M?9}-l{rYR^SlC?!>$1{99r?zaGr2? zShQ=G9@12)r1R0+yeSF0D7KAKi<*YOp~B0CzGPwUjC+CnX&s;FrMeY9ouYeD+IIQ* zujtS!KlS+)xA@@ROCU~2lhUpme9~8p+hp>md0xe93g`DI-rZMp0tXSSc0o1gjmY+{ z-rH`$Ti|OB^S7njftd1{#JbSSiRkQAm!6wU!`53E1(_2STiT1e%-nb#WG5ntc!ZTU zT{0_&7x?WCO)+!>vjnK!eG_Mljr;EkUznb~@g{YPQh=gSEFa;%Gu$Ib8J#Df6Or26 zmmx}iq_JWz7}ghY^mnNtJ!?ah4LWX=dX7K^7R6QHBCs}*VM~nOPveJ!{oO6uZpGYH1njNts+e6ZkUwq`1 z&^*4bN$%u;!Skz`mg4dztl`<0JFAUxT`Jn%cIp$qxB97+z3hrIl=qUt8P`XKfvY(10R#2NU!FEsDy+Wccl-EY`twGf;%Ize_4Ec{V@msv zJ5nlxOtjSr1=ZVhhA*nTmDm%kuZo%_5J9h+<0 zBflLQ#cxsLev;T2D|Udw2v(jQmV1*jX^A@fmYBPWFfgJM6UE9tYWd;^f%w9~Sn zt}efs)k*H$+qtH>rd5yLxe;-sHS_nLrj9NUNDM>;jwY_w`>-TBO_Sh5Cz3TeGzOp$ z5J-Oyhe03(klA1&*_RrGgS>8RhJdL)IEV|{8g9+Nll`a`5lr&_2pdOIL;wln1KDFB zqR+ts05me20OrsFgIHJ&4ziAm1@70nVG!`T2|EA>akaJsL{Bcny<4q=&F^5C||1{yRS!!`k{gd=Tp!3jiN54uJtfXu@GM z8ti8e7TYuw0Qr{CfAnBE0w+9}1DQn+VUozEq2wU;&YvNCNZ|a4OwIDG774T)*?~R+ByW% zFA%m&DxgY2;LlmDLHPhsBs84pqfJ6U(Wo^j3IzZqXc3?oB8f;rz;!SvB4Rxo9}?D# z&ZH55>7>#KzGN69$aj5Ujc}}yoh1%})P(=&u?r-yDS!hGVoe}{ZTJ5eair47``Lsw zIuSZ>BuWQ`fMZZdZL|*hhmkXx$pWOf28w`dYJCM>n-?rl4Ztj6O{f6Cx(84U7SALT z*mR~NogRpTtmOn=^IX?ASpVy+SWsDjMfjTJzlnZ7Ir!_-*LNV0x;_L3uj>{|AbkzO zB7~BC)&l{4Ux!G3gdkrs@PdC+)ZhKo|1et=T^$69fW|;|e9#0aN?R8NP>j)mVvrc3 z4qA&$A!_UXiq4`_*kJ@F*~k~D6sQJJ(0Vmsm9Jc?{%RiPM_wZej?{u8kWhq{BLam* zBC#l>Ivjz8!y&N$eT`@e9OHvTk)S9dg#tzC0ySbVNCZ>|==DL6kvK^wCcnD-^714_-U~NxcS-#ETX`g4Ew$)eqCi2mtiI zLH-fH|I+m@UH^!Ie`Nfxy8fl>A2INcjQ>^Fe~m7YAICa!5U|w?0}gFTAP#UA1PKzY z%uPUFKQAR9#CGs4A3dWwzM`Cn%pERs<1us!q(#;5U;kS ziIF4lPu8%}UaY-B%fe)Vh6lg#<>V=T%VYcz>06;s>Sne=Z%VNRj540N6X55qV+YSA zq#clX9i4D4CmgnCM@~(b&WLQ{vx`bVgrC~6-`!0MtEwu9N=2+Ot>~w@=|`xHX|)9?Zc-}3j3?v%ZZf(Y0dLo{`r2A zzT)kZWdk!D4kyPGG-SY+f9A|@HD|b7E`!Y;SE|xDasyoYZr{aTJ89F zi4VSBT6GG{<+(?>HlAo~Yh$x1;S@PKde3zg^ zZG6)GlC8EwgsxRKdG=A+6?9j%|nF0PSkobpkJDy|7SkqJT)+VKw;C` OfTgL8Nrka@-2VYVtMbMG literal 0 HcmV?d00001 diff --git a/packages/system/dashboard/images/dashboard/safari-pinned-tab.svg b/packages/system/dashboard/images/dashboard/safari-pinned-tab.svg new file mode 100644 index 00000000..d72f1f44 --- /dev/null +++ b/packages/system/dashboard/images/dashboard/safari-pinned-tab.svg @@ -0,0 +1,49 @@ + + + + + + + diff --git a/packages/system/dashboard/images/kubeapps-apis.json b/packages/system/dashboard/images/kubeapps-apis.json new file mode 100644 index 00000000..ffaf0a3a --- /dev/null +++ b/packages/system/dashboard/images/kubeapps-apis.json @@ -0,0 +1,4 @@ +{ + "containerimage.config.digest": "sha256:87c3ac99ed10ee9cf29ca01ec3a00da11f336a614ea98c48da04cd7349e13454", + "containerimage.digest": "sha256:d286c9be6baba35fc4b5dacd8701999b490a82fef42a1c52d0d65ced8bb07b51" +} \ No newline at end of file diff --git a/packages/system/dashboard/images/kubeapps-apis.tag b/packages/system/dashboard/images/kubeapps-apis.tag new file mode 100644 index 00000000..af6d5e9a --- /dev/null +++ b/packages/system/dashboard/images/kubeapps-apis.tag @@ -0,0 +1 @@ +ghcr.io/aenix-io/cozystack/kubeapps-apis:v0.0.1 diff --git a/packages/system/dashboard/images/kubeapps-apis/Dockerfile b/packages/system/dashboard/images/kubeapps-apis/Dockerfile new file mode 100644 index 00000000..fdc110ea --- /dev/null +++ b/packages/system/dashboard/images/kubeapps-apis/Dockerfile @@ -0,0 +1,127 @@ +# Copyright 2021-2023 the Kubeapps contributors. +# SPDX-License-Identifier: Apache-2.0 + +# syntax = docker/dockerfile:1 + +FROM alpine as source +ARG VERSION=v2.9.0 +RUN apk add --no-cache patch +WORKDIR /source +RUN wget -O- https://github.com/vmware-tanzu/kubeapps/archive/refs/tags/${VERSION}.tar.gz | tar xzf - --strip-components=1 +COPY fix-flux.diff /patches/fix-flux.diff +COPY labels.diff /patches/labels.diff +COPY reconcile-strategy.diff /patches/reconcile-strategy.diff +RUN patch -p1 < /patches/fix-flux.diff +RUN patch -p1 < /patches/labels.diff +RUN patch -p1 < /patches/reconcile-strategy.diff + +FROM bitnami/golang:1.21.1 as builder +WORKDIR /go/src/github.com/vmware-tanzu/kubeapps +COPY --from=source /source/go.mod /source/go.sum ./ +ARG VERSION="devel" +ARG TARGETARCH + +# If true, run golangci-lint to detect issues +ARG lint + +# https://github.com/bufbuild/buf/releases/ +ARG BUF_VERSION="1.26.0" + +# https://github.com/golangci/golangci-lint/releases +ARG GOLANGCILINT_VERSION="1.53.3" + +# https://github.com/grpc-ecosystem/grpc-health-probe/releases/ +ARG GRPC_HEALTH_PROBE_VERSION="0.4.19" + +# Install lint tools +RUN if [ ! -z "$lint" ]; then \ + go install github.com/golangci/golangci-lint/cmd/golangci-lint@v$GOLANGCILINT_VERSION; \ + fi + +RUN curl -sSL "https://github.com/bufbuild/buf/releases/download/v$BUF_VERSION/buf-Linux-x86_64" -o "/tmp/buf" && chmod +x "/tmp/buf" + +# TODO: Remove and instead use built-in gRPC container probes once we're supporting >= 1.24 only. https://kubernetes.io/blog/2022/05/13/grpc-probes-now-in-beta/ +RUN curl -sSL "https://github.com/grpc-ecosystem/grpc-health-probe/releases/download/v${GRPC_HEALTH_PROBE_VERSION}/grpc_health_probe-linux-${TARGETARCH}" -o "/bin/grpc_health_probe" && chmod +x "/bin/grpc_health_probe" + + +# With the trick below, Go's build cache is kept between builds. +# https://github.com/golang/go/issues/27719#issuecomment-514747274 +RUN --mount=type=cache,target=/go/pkg/mod \ + --mount=type=cache,target=/root/.cache/go-build \ + GOPROXY="https://proxy.golang.org,direct" go mod download + +# We don't copy the pkg and cmd directories until here so the above layers can +# be reused. +COPY --from=source /source/pkg pkg +COPY --from=source /source/cmd cmd + +RUN if [ ! -z "$lint" ]; then \ + # Run golangci-lint to detect issues + golangci-lint run --timeout=10m ./cmd/kubeapps-apis/... && \ + golangci-lint run --timeout=10m ./pkg/...; \ + fi + +# Lint the proto files to detect errors at build time +RUN /tmp/buf lint ./cmd/kubeapps-apis + +# Build the main grpc server +RUN --mount=type=cache,target=/go/pkg/mod \ + --mount=type=cache,target=/root/.cache/go-build \ + go build \ + -ldflags "-X github.com/vmware-tanzu/kubeapps/cmd/kubeapps-apis/cmd.version=$VERSION" \ + ./cmd/kubeapps-apis + +# Build 'kapp-controller' plugin, version 'v1alpha1' +RUN --mount=type=cache,target=/go/pkg/mod \ + --mount=type=cache,target=/root/.cache/go-build \ + GOPROXY="https://proxy.golang.org,direct" \ + go build \ + -ldflags "-X github.com/vmware-tanzu/kubeapps/cmd/kubeapps-apis/cmd.version=$VERSION" \ + -o /kapp-controller-packages-v1alpha1-plugin.so -buildmode=plugin \ + ./cmd/kubeapps-apis/plugins/kapp_controller/packages/v1alpha1/*.go + +## Build 'fluxv2' plugin, version 'v1alpha1' +RUN --mount=type=cache,target=/go/pkg/mod \ + --mount=type=cache,target=/root/.cache/go-build \ + GOPROXY="https://proxy.golang.org,direct" \ + go build \ + -ldflags "-X github.com/vmware-tanzu/kubeapps/cmd/kubeapps-apis/cmd.version=$VERSION" \ + -o /fluxv2-packages-v1alpha1-plugin.so -buildmode=plugin \ + ./cmd/kubeapps-apis/plugins/fluxv2/packages/v1alpha1/*.go + +## Build 'helm' plugin, version 'v1alpha1' +RUN --mount=type=cache,target=/go/pkg/mod \ + --mount=type=cache,target=/root/.cache/go-build \ + GOPROXY="https://proxy.golang.org,direct" \ + go build \ + -ldflags "-X github.com/vmware-tanzu/kubeapps/cmd/kubeapps-apis/cmd.version=$VERSION" \ + -o /helm-packages-v1alpha1-plugin.so -buildmode=plugin \ + ./cmd/kubeapps-apis/plugins/helm/packages/v1alpha1/*.go + +## Build 'resources' plugin, version 'v1alpha1' +RUN --mount=type=cache,target=/go/pkg/mod \ + --mount=type=cache,target=/root/.cache/go-build \ + GOPROXY="https://proxy.golang.org,direct" \ + go build \ + -ldflags "-X github.com/vmware-tanzu/kubeapps/cmd/kubeapps-apis/cmd.version=$VERSION" \ + -o /resources-v1alpha1-plugin.so -buildmode=plugin \ + ./cmd/kubeapps-apis/plugins/resources/v1alpha1/*.go + +# Note: unlike the other docker images for go, we cannot use scratch as the plugins +# are loaded using the dynamic linker. +FROM bitnami/minideb:bookworm +COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ +COPY --from=builder /go/src/github.com/vmware-tanzu/kubeapps/kubeapps-apis /kubeapps-apis +COPY --from=builder /kapp-controller-packages-v1alpha1-plugin.so /plugins/kapp-controller-packages/ +COPY --from=builder /fluxv2-packages-v1alpha1-plugin.so /plugins/fluxv2-packages/ +COPY --from=builder /helm-packages-v1alpha1-plugin.so /plugins/helm-packages/ +COPY --from=builder /resources-v1alpha1-plugin.so /plugins/resources/ +COPY --from=builder /bin/grpc_health_probe /bin/ + +# Ensure the container user will be able to write to the k8s discovery client cache. +RUN mkdir -p /.kube/cache && chown 1001:1001 /.kube/cache + +EXPOSE 50051 +USER 1001 +ENTRYPOINT [ "/kubeapps-apis" ] +CMD [ "--help" ] diff --git a/packages/system/dashboard/images/kubeapps-apis/dockerfile.diff b/packages/system/dashboard/images/kubeapps-apis/dockerfile.diff new file mode 100644 index 00000000..ac997072 --- /dev/null +++ b/packages/system/dashboard/images/kubeapps-apis/dockerfile.diff @@ -0,0 +1,34 @@ +diff --git b/system/kubeapps/images/kubeapps-apis/Dockerfile a/system/kubeapps/images/kubeapps-apis/Dockerfile +index e5fcd8c..f72964d 100644 +--- b/system/kubeapps/images/kubeapps-apis/Dockerfile ++++ a/system/kubeapps/images/kubeapps-apis/Dockerfile +@@ -3,9 +3,17 @@ + + # syntax = docker/dockerfile:1 + ++FROM alpine as source ++ARG VERSION=v2.9.0 ++RUN apk add --no-cache patch ++WORKDIR /source ++RUN wget -O- https://github.com/vmware-tanzu/kubeapps/archive/refs/tags/${VERSION}.tar.gz | tar xzf - --strip-components=1 ++COPY fix-flux.diff /patches/fix-flux.diff ++RUN patch -p1 < /patches/fix-flux.diff ++ + FROM bitnami/golang:1.21.1 as builder + WORKDIR /go/src/github.com/vmware-tanzu/kubeapps +-COPY go.mod go.sum ./ ++COPY --from=source /source/go.mod /source/go.sum ./ + ARG VERSION="devel" + ARG TARGETARCH + +@@ -40,8 +48,8 @@ RUN --mount=type=cache,target=/go/pkg/mod \ + + # We don't copy the pkg and cmd directories until here so the above layers can + # be reused. +-COPY pkg pkg +-COPY cmd cmd ++COPY --from=source /source/pkg pkg ++COPY --from=source /source/cmd cmd + + RUN if [ ! -z "$lint" ]; then \ + # Run golangci-lint to detect issues diff --git a/packages/system/dashboard/images/kubeapps-apis/fix-flux.diff b/packages/system/dashboard/images/kubeapps-apis/fix-flux.diff new file mode 100644 index 00000000..fb0023b7 --- /dev/null +++ b/packages/system/dashboard/images/kubeapps-apis/fix-flux.diff @@ -0,0 +1,28 @@ +diff --git a/cmd/kubeapps-apis/plugins/fluxv2/packages/v1alpha1/repo.go b/cmd/kubeapps-apis/plugins/fluxv2/packages/v1alpha1/repo.go +index 8886f4d479e..1ab08c074a5 100644 +--- a/cmd/kubeapps-apis/plugins/fluxv2/packages/v1alpha1/repo.go ++++ b/cmd/kubeapps-apis/plugins/fluxv2/packages/v1alpha1/repo.go +@@ -579,9 +579,9 @@ func (s *repoEventSink) onAddRepo(key string, obj ctrlclient.Object) (interface{ + // ref https://fluxcd.io/docs/components/source/helmrepositories/#status + func (s *repoEventSink) onAddHttpRepo(repo sourcev1.HelmRepository) ([]byte, bool, error) { + if artifact := repo.GetArtifact(); artifact != nil { +- if checksum := artifact.Checksum; checksum == "" { ++ if checksum := artifact.Digest; checksum == "" { + return nil, false, connect.NewError(connect.CodeInternal, +- fmt.Errorf("expected field status.artifact.checksum not found on HelmRepository\n[%s]", ++ fmt.Errorf("expected field status.artifact.digest not found on HelmRepository\n[%s]", + common.PrettyPrint(repo))) + } else { + return s.indexAndEncode(checksum, repo) +@@ -721,9 +721,9 @@ func (s *repoEventSink) onModifyHttpRepo(key string, oldValue interface{}, repo + // ref https://fluxcd.io/docs/components/source/helmrepositories/#status + var newChecksum string + if artifact := repo.GetArtifact(); artifact != nil { +- if newChecksum = artifact.Checksum; newChecksum == "" { ++ if newChecksum = artifact.Digest; newChecksum == "" { + return nil, false, connect.NewError(connect.CodeInternal, +- fmt.Errorf("expected field status.artifact.checksum not found on HelmRepository\n[%s]", ++ fmt.Errorf("expected field status.artifact.digest not found on HelmRepository\n[%s]", + common.PrettyPrint(repo))) + } + } else { diff --git a/packages/system/dashboard/images/kubeapps-apis/labels.diff b/packages/system/dashboard/images/kubeapps-apis/labels.diff new file mode 100644 index 00000000..71e1cc6a --- /dev/null +++ b/packages/system/dashboard/images/kubeapps-apis/labels.diff @@ -0,0 +1,59 @@ +diff --git a/cmd/kubeapps-apis/plugins/fluxv2/packages/v1alpha1/release.go b/cmd/kubeapps-apis/plugins/fluxv2/packages/v1alpha1/release.go +index fe7ca772d..3b46afbd1 100644 +--- a/cmd/kubeapps-apis/plugins/fluxv2/packages/v1alpha1/release.go ++++ b/cmd/kubeapps-apis/plugins/fluxv2/packages/v1alpha1/release.go +@@ -29,8 +29,10 @@ import ( + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/api/meta" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ++ "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/types" + log "k8s.io/klog/v2" ++ ctrlclient "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/yaml" + ) + +@@ -54,7 +56,10 @@ func (s *Server) listReleasesInCluster(ctx context.Context, headers http.Header, + // see any results created/updated/deleted after the first request is issued + // To fix this, we must make use of resourceVersion := relList.GetResourceVersion() + var relList helmv2.HelmReleaseList +- if err = client.List(ctx, &relList); err != nil { ++ listOptions := ctrlclient.ListOptions{ ++ LabelSelector: labels.SelectorFromSet(labels.Set{"cozystack.io/ui": "true"}), ++ } ++ if err = client.List(ctx, &relList, &listOptions); err != nil { + return nil, connecterror.FromK8sError("list", "HelmRelease", namespace+"/*", err) + } else { + return relList.Items, nil +@@ -511,6 +516,9 @@ func (s *Server) newFluxHelmRelease(chart *models.Chart, targetName types.Namesp + ObjectMeta: metav1.ObjectMeta{ + Name: chart.Name + "-" + targetName.Name, + Namespace: targetName.Namespace, ++ Labels: map[string]string{ ++ "cozystack.io/ui": "true", ++ }, + }, + Spec: helmv2.HelmReleaseSpec{ + Chart: helmv2.HelmChartTemplate{ +diff --git a/cmd/kubeapps-apis/plugins/fluxv2/packages/v1alpha1/repo.go b/cmd/kubeapps-apis/plugins/fluxv2/packages/v1alpha1/repo.go +index 1ab08c074..cd7b3b9aa 100644 +--- a/cmd/kubeapps-apis/plugins/fluxv2/packages/v1alpha1/repo.go ++++ b/cmd/kubeapps-apis/plugins/fluxv2/packages/v1alpha1/repo.go +@@ -32,6 +32,7 @@ import ( + apiv1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/meta" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ++ "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/types" + "k8s.io/apimachinery/pkg/util/sets" + log "k8s.io/klog/v2" +@@ -64,7 +65,8 @@ func (s *Server) listReposInNamespace(ctx context.Context, headers http.Header, + + var repoList sourcev1.HelmRepositoryList + listOptions := ctrlclient.ListOptions{ +- Namespace: ns, ++ Namespace: ns, ++ LabelSelector: labels.SelectorFromSet(labels.Set{"cozystack.io/ui": "true"}), + } + if err := client.List(backgroundCtx, &repoList, &listOptions); err != nil { + return nil, connecterror.FromK8sError("list", "HelmRepository", "", err) diff --git a/packages/system/dashboard/images/kubeapps-apis/reconcile-strategy.diff b/packages/system/dashboard/images/kubeapps-apis/reconcile-strategy.diff new file mode 100644 index 00000000..fc1cc233 --- /dev/null +++ b/packages/system/dashboard/images/kubeapps-apis/reconcile-strategy.diff @@ -0,0 +1,12 @@ +diff --git a/cmd/kubeapps-apis/plugins/fluxv2/packages/v1alpha1/release.go b/cmd/kubeapps-apis/plugins/fluxv2/packages/v1alpha1/release.go +index fe7ca772d..8111feb1c 100644 +--- a/cmd/kubeapps-apis/plugins/fluxv2/packages/v1alpha1/release.go ++++ b/cmd/kubeapps-apis/plugins/fluxv2/packages/v1alpha1/release.go +@@ -521,6 +529,7 @@ func (s *Server) newFluxHelmRelease(chart *models.Chart, targetName types.Namesp + Kind: sourcev1.HelmRepositoryKind, + Namespace: chart.Repo.Namespace, + }, ++ ReconcileStrategy: "Revision", + }, + }, + }, diff --git a/packages/system/dashboard/templates/_helpers.tpl b/packages/system/dashboard/templates/_helpers.tpl new file mode 100644 index 00000000..55e735db --- /dev/null +++ b/packages/system/dashboard/templates/_helpers.tpl @@ -0,0 +1,13 @@ +{{/* +Return the proper dashboard image name +*/}} +{{- define "kubeapps.dashboard.image" -}} +{{ .Files.Get "images/dashboard.tag" | trim }}@{{ index (.Files.Get "images/dashboard.json" | fromJson) "containerimage.digest" }} +{{- end -}} + +{{/* +Return the proper kubeappsapis image name +*/}} +{{- define "kubeapps.kubeappsapis.image" -}} +{{ .Files.Get "images/kubeapps-apis.tag" | trim }}@{{ index (.Files.Get "images/kubeapps-apis.json" | fromJson) "containerimage.digest" }} +{{- end -}} diff --git a/packages/system/dashboard/templates/allow-from-kubeapps.yaml b/packages/system/dashboard/templates/allow-from-kubeapps.yaml new file mode 100644 index 00000000..c8850d88 --- /dev/null +++ b/packages/system/dashboard/templates/allow-from-kubeapps.yaml @@ -0,0 +1,14 @@ +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: allow-from-dashboard + namespace: cozy-fluxcd +spec: + ingress: + - from: + - namespaceSelector: + matchLabels: + kubernetes.io/metadata.name: cozy-dashboard + podSelector: {} + policyTypes: + - Ingress diff --git a/packages/system/dashboard/values.yaml b/packages/system/dashboard/values.yaml new file mode 100644 index 00000000..28aeeec3 --- /dev/null +++ b/packages/system/dashboard/values.yaml @@ -0,0 +1,17 @@ +kubeapps: + fullnameOverride: dashboard + + postgresql: + enabled: false + + packaging: + helm: + enabled: false + flux: + enabled: true + + dashboard: + customStyle: | + #serviceaccount-selector { + display: none; + } diff --git a/packages/system/fluxcd/.helmignore b/packages/system/fluxcd/.helmignore new file mode 100644 index 00000000..d5c178e8 --- /dev/null +++ b/packages/system/fluxcd/.helmignore @@ -0,0 +1,3 @@ +images +hack +.gitkeep diff --git a/packages/system/fluxcd/Chart.yaml b/packages/system/fluxcd/Chart.yaml new file mode 100644 index 00000000..81787d63 --- /dev/null +++ b/packages/system/fluxcd/Chart.yaml @@ -0,0 +1,2 @@ +name: cozy-fluxcd +version: 1.0.0 diff --git a/packages/system/fluxcd/Makefile b/packages/system/fluxcd/Makefile new file mode 100644 index 00000000..ca472364 --- /dev/null +++ b/packages/system/fluxcd/Makefile @@ -0,0 +1,15 @@ +NAMESPACE=cozy-fluxcd +NAME=fluxcd + +show: + helm template --dry-run=server -n $(NAMESPACE) $(NAME) . + +apply: + helm upgrade -i -n $(NAMESPACE) $(NAME) . + +diff: + helm diff upgrade --allow-unreleased --normalize-manifests -n $(NAMESPACE) $(NAME) . + +update: + rm -rf charts + helm pull oci://ghcr.io/fluxcd-community/charts/flux2 --untar --untardir charts diff --git a/packages/system/fluxcd/charts/flux2/.helmignore b/packages/system/fluxcd/charts/flux2/.helmignore new file mode 100644 index 00000000..98229532 --- /dev/null +++ b/packages/system/fluxcd/charts/flux2/.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/packages/system/fluxcd/charts/flux2/Chart.yaml b/packages/system/fluxcd/charts/flux2/Chart.yaml new file mode 100644 index 00000000..dd49f819 --- /dev/null +++ b/packages/system/fluxcd/charts/flux2/Chart.yaml @@ -0,0 +1,11 @@ +annotations: + artifacthub.io/changes: | + - "feat: adding CRD and RBAC annotation option" +apiVersion: v2 +appVersion: 2.1.2 +description: A Helm chart for flux2 +name: flux2 +sources: +- https://github.com/fluxcd-community/helm-charts +type: application +version: 2.11.1 diff --git a/packages/system/fluxcd/charts/flux2/README.md b/packages/system/fluxcd/charts/flux2/README.md new file mode 100644 index 00000000..88b4d0ec --- /dev/null +++ b/packages/system/fluxcd/charts/flux2/README.md @@ -0,0 +1,174 @@ +# flux2 + +![Version: 2.11.0](https://img.shields.io/badge/Version-2.11.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 2.1.2](https://img.shields.io/badge/AppVersion-2.1.2-informational?style=flat-square) + +A Helm chart for flux2 + +This helm chart is maintained and released by the fluxcd-community on a best effort basis. + +## Source Code + +* + +## Values + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| cli.affinity | object | `{}` | | +| cli.annotations | object | `{}` | | +| cli.image | string | `"ghcr.io/fluxcd/flux-cli"` | | +| cli.nodeSelector | object | `{}` | | +| cli.serviceAccount.automount | bool | `true` | | +| cli.tag | string | `"v2.1.2"` | | +| cli.tolerations | list | `[]` | | +| clusterDomain | string | `"cluster.local"` | | +| crds.annotations | object | `{}` | Add annotations to all CRD resources, e.g. "helm.sh/resource-policy": keep | +| extraObjects | list | `[]` | Array of extra K8s manifests to deploy | +| helmController.affinity | object | `{}` | | +| helmController.annotations."prometheus.io/port" | string | `"8080"` | | +| helmController.annotations."prometheus.io/scrape" | string | `"true"` | | +| helmController.container.additionalArgs | list | `[]` | | +| helmController.create | bool | `true` | | +| helmController.extraEnv | list | `[]` | | +| helmController.image | string | `"ghcr.io/fluxcd/helm-controller"` | | +| helmController.imagePullPolicy | string | `""` | | +| helmController.labels | object | `{}` | | +| helmController.nodeSelector | object | `{}` | | +| helmController.priorityClassName | string | `""` | | +| helmController.resources.limits | object | `{}` | | +| helmController.resources.requests.cpu | string | `"100m"` | | +| helmController.resources.requests.memory | string | `"64Mi"` | | +| helmController.serviceAccount.annotations | object | `{}` | | +| helmController.serviceAccount.automount | bool | `true` | | +| helmController.serviceAccount.create | bool | `true` | | +| helmController.tag | string | `"v0.36.2"` | | +| helmController.tolerations | list | `[]` | | +| imageAutomationController.affinity | object | `{}` | | +| imageAutomationController.annotations."prometheus.io/port" | string | `"8080"` | | +| imageAutomationController.annotations."prometheus.io/scrape" | string | `"true"` | | +| imageAutomationController.container.additionalArgs | list | `[]` | | +| imageAutomationController.create | bool | `true` | | +| imageAutomationController.extraEnv | list | `[]` | | +| imageAutomationController.image | string | `"ghcr.io/fluxcd/image-automation-controller"` | | +| imageAutomationController.imagePullPolicy | string | `""` | | +| imageAutomationController.labels | object | `{}` | | +| imageAutomationController.nodeSelector | object | `{}` | | +| imageAutomationController.priorityClassName | string | `""` | | +| imageAutomationController.resources.limits | object | `{}` | | +| imageAutomationController.resources.requests.cpu | string | `"100m"` | | +| imageAutomationController.resources.requests.memory | string | `"64Mi"` | | +| imageAutomationController.serviceAccount.annotations | object | `{}` | | +| imageAutomationController.serviceAccount.automount | bool | `true` | | +| imageAutomationController.serviceAccount.create | bool | `true` | | +| imageAutomationController.tag | string | `"v0.36.1"` | | +| imageAutomationController.tolerations | list | `[]` | | +| imagePullSecrets | list | `[]` | contents of pod imagePullSecret in form 'name=[secretName]'; applied to all controllers | +| imageReflectionController.affinity | object | `{}` | | +| imageReflectionController.annotations."prometheus.io/port" | string | `"8080"` | | +| imageReflectionController.annotations."prometheus.io/scrape" | string | `"true"` | | +| imageReflectionController.container.additionalArgs | list | `[]` | | +| imageReflectionController.create | bool | `true` | | +| imageReflectionController.extraEnv | list | `[]` | | +| imageReflectionController.image | string | `"ghcr.io/fluxcd/image-reflector-controller"` | | +| imageReflectionController.imagePullPolicy | string | `""` | | +| imageReflectionController.labels | object | `{}` | | +| imageReflectionController.nodeSelector | object | `{}` | | +| imageReflectionController.priorityClassName | string | `""` | | +| imageReflectionController.resources.limits | object | `{}` | | +| imageReflectionController.resources.requests.cpu | string | `"100m"` | | +| imageReflectionController.resources.requests.memory | string | `"64Mi"` | | +| imageReflectionController.serviceAccount.annotations | object | `{}` | | +| imageReflectionController.serviceAccount.automount | bool | `true` | | +| imageReflectionController.serviceAccount.create | bool | `true` | | +| imageReflectionController.tag | string | `"v0.30.0"` | | +| imageReflectionController.tolerations | list | `[]` | | +| installCRDs | bool | `true` | | +| kustomizeController.affinity | object | `{}` | | +| kustomizeController.annotations."prometheus.io/port" | string | `"8080"` | | +| kustomizeController.annotations."prometheus.io/scrape" | string | `"true"` | | +| kustomizeController.container.additionalArgs | list | `[]` | | +| kustomizeController.create | bool | `true` | | +| kustomizeController.envFrom | object | `{"map":{"name":""},"secret":{"name":""}}` | Defines envFrom using a configmap and/or secret. | +| kustomizeController.extraEnv | list | `[]` | | +| kustomizeController.extraSecretMounts | list | `[]` | Defines additional mounts with secrets. Secrets must be manually created in the namespace or with kustomizeController.secret | +| kustomizeController.image | string | `"ghcr.io/fluxcd/kustomize-controller"` | | +| kustomizeController.imagePullPolicy | string | `""` | | +| kustomizeController.labels | object | `{}` | | +| kustomizeController.nodeSelector | object | `{}` | | +| kustomizeController.priorityClassName | string | `""` | | +| kustomizeController.resources.limits | object | `{}` | | +| kustomizeController.resources.requests.cpu | string | `"100m"` | | +| kustomizeController.resources.requests.memory | string | `"64Mi"` | | +| kustomizeController.secret.create | bool | `false` | Create a secret to use it with extraSecretMounts. Defaults to false. | +| kustomizeController.secret.data | object | `{}` | | +| kustomizeController.secret.name | string | `""` | | +| kustomizeController.serviceAccount.annotations | object | `{}` | | +| kustomizeController.serviceAccount.automount | bool | `true` | | +| kustomizeController.serviceAccount.create | bool | `true` | | +| kustomizeController.tag | string | `"v1.1.1"` | | +| kustomizeController.tolerations | list | `[]` | | +| logLevel | string | `"info"` | | +| multitenancy.defaultServiceAccount | string | `"default"` | All Kustomizations and HelmReleases which don’t have spec.serviceAccountName specified, will use the default account from the tenant’s namespace. Tenants have to specify a service account in their Flux resources to be able to deploy workloads in their namespaces as the default account has no permissions. | +| multitenancy.enabled | bool | `false` | Implement the patches for Multi-tenancy lockdown. See https://fluxcd.io/docs/installation/#multi-tenancy-lockdown | +| multitenancy.privileged | bool | `true` | Both kustomize-controller and helm-controller service accounts run privileged with cluster-admin ClusterRoleBinding. Disable if you want to run them with a minimum set of permissions. | +| notificationController.affinity | object | `{}` | | +| notificationController.annotations."prometheus.io/port" | string | `"8080"` | | +| notificationController.annotations."prometheus.io/scrape" | string | `"true"` | | +| notificationController.container.additionalArgs | list | `[]` | | +| notificationController.create | bool | `true` | | +| notificationController.extraEnv | list | `[]` | | +| notificationController.image | string | `"ghcr.io/fluxcd/notification-controller"` | | +| notificationController.imagePullPolicy | string | `""` | | +| notificationController.labels | object | `{}` | | +| notificationController.nodeSelector | object | `{}` | | +| notificationController.priorityClassName | string | `""` | | +| notificationController.resources.limits | object | `{}` | | +| notificationController.resources.requests.cpu | string | `"100m"` | | +| notificationController.resources.requests.memory | string | `"64Mi"` | | +| notificationController.service.annotations | object | `{}` | | +| notificationController.service.labels | object | `{}` | | +| notificationController.serviceAccount.annotations | object | `{}` | | +| notificationController.serviceAccount.automount | bool | `true` | | +| notificationController.serviceAccount.create | bool | `true` | | +| notificationController.tag | string | `"v1.1.0"` | | +| notificationController.tolerations | list | `[]` | | +| notificationController.webhookReceiver.ingress.annotations | object | `{}` | | +| notificationController.webhookReceiver.ingress.create | bool | `false` | | +| notificationController.webhookReceiver.ingress.hosts[0].host | string | `"flux-webhook.example.com"` | | +| notificationController.webhookReceiver.ingress.hosts[0].paths[0].path | string | `"/"` | | +| notificationController.webhookReceiver.ingress.hosts[0].paths[0].pathType | string | `"ImplementationSpecific"` | | +| notificationController.webhookReceiver.ingress.labels | object | `{}` | | +| notificationController.webhookReceiver.ingress.tls | list | `[]` | | +| notificationController.webhookReceiver.service.annotations | object | `{}` | | +| notificationController.webhookReceiver.service.labels | object | `{}` | | +| policies.create | bool | `true` | | +| prometheus.podMonitor.create | bool | `false` | Enables podMonitor endpoint | +| prometheus.podMonitor.podMetricsEndpoints[0].port | string | `"http-prom"` | | +| prometheus.podMonitor.podMetricsEndpoints[0].relabelings[0].action | string | `"keep"` | | +| prometheus.podMonitor.podMetricsEndpoints[0].relabelings[0].regex | string | `"Running"` | | +| prometheus.podMonitor.podMetricsEndpoints[0].relabelings[0].sourceLabels[0] | string | `"__meta_kubernetes_pod_phase"` | | +| rbac.annotations | object | `{}` | Add annotations to all RBAC resources, e.g. "helm.sh/resource-policy": keep | +| rbac.create | bool | `true` | | +| rbac.createAggregation | bool | `true` | Grant the Kubernetes view, edit and admin roles access to Flux custom resources | +| sourceController.affinity | object | `{}` | | +| sourceController.annotations."prometheus.io/port" | string | `"8080"` | | +| sourceController.annotations."prometheus.io/scrape" | string | `"true"` | | +| sourceController.container.additionalArgs | list | `[]` | | +| sourceController.create | bool | `true` | | +| sourceController.extraEnv | list | `[]` | | +| sourceController.image | string | `"ghcr.io/fluxcd/source-controller"` | | +| sourceController.imagePullPolicy | string | `""` | | +| sourceController.labels | object | `{}` | | +| sourceController.nodeSelector | object | `{}` | | +| sourceController.priorityClassName | string | `""` | | +| sourceController.resources.limits | object | `{}` | | +| sourceController.resources.requests.cpu | string | `"100m"` | | +| sourceController.resources.requests.memory | string | `"64Mi"` | | +| sourceController.service.annotations | object | `{}` | | +| sourceController.service.labels | object | `{}` | | +| sourceController.serviceAccount.annotations | object | `{}` | | +| sourceController.serviceAccount.automount | bool | `true` | | +| sourceController.serviceAccount.create | bool | `true` | | +| sourceController.tag | string | `"v1.1.2"` | | +| sourceController.tolerations | list | `[]` | | +| watchAllNamespaces | bool | `true` | | diff --git a/packages/system/fluxcd/charts/flux2/templates/_helper.tpl b/packages/system/fluxcd/charts/flux2/templates/_helper.tpl new file mode 100644 index 00000000..6a36293e --- /dev/null +++ b/packages/system/fluxcd/charts/flux2/templates/_helper.tpl @@ -0,0 +1,7 @@ +{{- define "template.image" -}} +{{- if eq (substr 0 7 .tag) "sha256:" -}} +{{- printf "%s@%s" .image .tag -}} +{{- else -}} +{{- printf "%s:%s" .image .tag -}} +{{- end -}} +{{- end -}} diff --git a/packages/system/fluxcd/charts/flux2/templates/aggregate-clusterroles.yaml b/packages/system/fluxcd/charts/flux2/templates/aggregate-clusterroles.yaml new file mode 100644 index 00000000..432895b2 --- /dev/null +++ b/packages/system/fluxcd/charts/flux2/templates/aggregate-clusterroles.yaml @@ -0,0 +1,47 @@ +{{- if .Values.rbac.createAggregation }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + {{- with .Values.rbac.annotations }} + annotations: {{ toYaml . | nindent 4 }} + {{- end }} + name: flux-edit + labels: + rbac.authorization.k8s.io/aggregate-to-edit: "true" + rbac.authorization.k8s.io/aggregate-to-admin: "true" +rules: + - apiGroups: + - notification.toolkit.fluxcd.io + - source.toolkit.fluxcd.io + - helm.toolkit.fluxcd.io + - image.toolkit.fluxcd.io + - kustomize.toolkit.fluxcd.io + resources: ["*"] + verbs: + - create + - delete + - deletecollection + - patch + - update +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: flux-view + labels: + rbac.authorization.k8s.io/aggregate-to-admin: "true" + rbac.authorization.k8s.io/aggregate-to-edit: "true" + rbac.authorization.k8s.io/aggregate-to-view: "true" +rules: + - apiGroups: + - notification.toolkit.fluxcd.io + - source.toolkit.fluxcd.io + - helm.toolkit.fluxcd.io + - image.toolkit.fluxcd.io + - kustomize.toolkit.fluxcd.io + resources: ["*"] + verbs: + - get + - list + - watch +{{- end }} diff --git a/packages/system/fluxcd/charts/flux2/templates/cluster-reconciler-clusterrolebinding.yaml b/packages/system/fluxcd/charts/flux2/templates/cluster-reconciler-clusterrolebinding.yaml new file mode 100644 index 00000000..0228c1bc --- /dev/null +++ b/packages/system/fluxcd/charts/flux2/templates/cluster-reconciler-clusterrolebinding.yaml @@ -0,0 +1,26 @@ +{{- if and .Values.rbac.create (or (not .Values.multitenancy.enabled) .Values.multitenancy.privileged) }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + {{- with .Values.rbac.annotations }} + annotations: {{ toYaml . | nindent 4 }} + {{- end }} + labels: + app.kubernetes.io/instance: {{ .Release.Namespace | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} + app.kubernetes.io/part-of: flux + helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} + name: cluster-reconciler +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: cluster-admin +subjects: +- kind: ServiceAccount + name: kustomize-controller + namespace: {{ .Release.Namespace }} +- kind: ServiceAccount + name: helm-controller + namespace: {{ .Release.Namespace }} +{{- end }} \ No newline at end of file diff --git a/packages/system/fluxcd/charts/flux2/templates/cluster-reconciler-impersonator-clusterrole.yaml b/packages/system/fluxcd/charts/flux2/templates/cluster-reconciler-impersonator-clusterrole.yaml new file mode 100644 index 00000000..e77c13ea --- /dev/null +++ b/packages/system/fluxcd/charts/flux2/templates/cluster-reconciler-impersonator-clusterrole.yaml @@ -0,0 +1,19 @@ +{{- if and .Values.rbac.create .Values.multitenancy.enabled (not .Values.multitenancy.privileged) }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + {{- with .Values.rbac.annotations }} + annotations: {{ toYaml . | nindent 4 }} + {{- end }} + name: cluster-reconciler-impersonator + labels: + app.kubernetes.io/instance: {{ .Release.Namespace | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} + app.kubernetes.io/part-of: flux + helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} +rules: +- apiGroups: [""] + resources: ["serviceaccounts"] + verbs: ["impersonate"] +{{- end }} diff --git a/packages/system/fluxcd/charts/flux2/templates/cluster-reconciler-impersonator-clusterrolebinding.yaml b/packages/system/fluxcd/charts/flux2/templates/cluster-reconciler-impersonator-clusterrolebinding.yaml new file mode 100644 index 00000000..588c7d49 --- /dev/null +++ b/packages/system/fluxcd/charts/flux2/templates/cluster-reconciler-impersonator-clusterrolebinding.yaml @@ -0,0 +1,26 @@ +{{- if and .Values.rbac.create .Values.multitenancy.enabled (not .Values.multitenancy.privileged) }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + {{- with .Values.rbac.annotations }} + annotations: {{ toYaml . | nindent 4 }} + {{- end }} + labels: + app.kubernetes.io/instance: {{ .Release.Namespace | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} + app.kubernetes.io/part-of: flux + helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} + name: cluster-reconciler-impersonator +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: cluster-reconciler-impersonator +subjects: +- kind: ServiceAccount + name: kustomize-controller + namespace: {{ .Release.Namespace }} +- kind: ServiceAccount + name: helm-controller + namespace: {{ .Release.Namespace }} +{{- end }} diff --git a/packages/system/fluxcd/charts/flux2/templates/crd-controller-clusterrole.yaml b/packages/system/fluxcd/charts/flux2/templates/crd-controller-clusterrole.yaml new file mode 100644 index 00000000..cea0a1ca --- /dev/null +++ b/packages/system/fluxcd/charts/flux2/templates/crd-controller-clusterrole.yaml @@ -0,0 +1,82 @@ +{{- if and .Values.rbac.create }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + {{- with .Values.rbac.annotations }} + annotations: {{ toYaml . | nindent 4 }} + {{- end }} + name: crd-controller + labels: + app.kubernetes.io/instance: {{ .Release.Namespace | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} + app.kubernetes.io/part-of: flux + helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} +rules: +- apiGroups: ['source.toolkit.fluxcd.io'] + resources: ['*'] + verbs: ['*'] +- apiGroups: ['kustomize.toolkit.fluxcd.io'] + resources: ['*'] + verbs: ['*'] +- apiGroups: ['helm.toolkit.fluxcd.io'] + resources: ['*'] + verbs: ['*'] +- apiGroups: ['notification.toolkit.fluxcd.io'] + resources: ['*'] + verbs: ['*'] +- apiGroups: ['image.toolkit.fluxcd.io'] + resources: ['*'] + verbs: ['*'] +- apiGroups: + - "" + resources: + - namespaces + - secrets + - configmaps + - serviceaccounts + verbs: + - get + - list + - watch +- apiGroups: + - "" + resources: + - events + verbs: + - create + - patch +# required by leader election +- apiGroups: + - "" + resources: + - configmaps + verbs: + - get + - list + - watch + - create + - update + - patch + - delete +- apiGroups: + - "" + resources: + - configmaps/status + verbs: + - get + - update + - patch +- apiGroups: + - "coordination.k8s.io" + resources: + - leases + verbs: + - get + - list + - watch + - create + - update + - patch + - delete +{{- end }} diff --git a/packages/system/fluxcd/charts/flux2/templates/crd-controller-clusterrolebinding.yaml b/packages/system/fluxcd/charts/flux2/templates/crd-controller-clusterrolebinding.yaml new file mode 100644 index 00000000..51e716f0 --- /dev/null +++ b/packages/system/fluxcd/charts/flux2/templates/crd-controller-clusterrolebinding.yaml @@ -0,0 +1,38 @@ +{{- if and .Values.rbac.create }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + {{- with .Values.rbac.annotations }} + annotations: {{ toYaml . | nindent 4 }} + {{- end }} + name: crd-controller + labels: + app.kubernetes.io/instance: {{ .Release.Namespace | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} + app.kubernetes.io/part-of: flux + helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: crd-controller +subjects: + - kind: ServiceAccount + name: kustomize-controller + namespace: {{ .Release.Namespace }} + - kind: ServiceAccount + name: helm-controller + namespace: {{ .Release.Namespace }} + - kind: ServiceAccount + name: source-controller + namespace: {{ .Release.Namespace }} + - kind: ServiceAccount + name: notification-controller + namespace: {{ .Release.Namespace }} + - kind: ServiceAccount + name: image-reflector-controller + namespace: {{ .Release.Namespace }} + - kind: ServiceAccount + name: image-automation-controller + namespace: {{ .Release.Namespace }} +{{- end }} diff --git a/packages/system/fluxcd/charts/flux2/templates/extra-manifests.yaml b/packages/system/fluxcd/charts/flux2/templates/extra-manifests.yaml new file mode 100644 index 00000000..a9bb3b6b --- /dev/null +++ b/packages/system/fluxcd/charts/flux2/templates/extra-manifests.yaml @@ -0,0 +1,4 @@ +{{ range .Values.extraObjects }} +--- +{{ tpl (toYaml .) $ }} +{{ end }} diff --git a/packages/system/fluxcd/charts/flux2/templates/helm-controller-sa.yaml b/packages/system/fluxcd/charts/flux2/templates/helm-controller-sa.yaml new file mode 100644 index 00000000..9d4ff589 --- /dev/null +++ b/packages/system/fluxcd/charts/flux2/templates/helm-controller-sa.yaml @@ -0,0 +1,18 @@ +{{- if and .Values.helmController.create}} +{{- if .Values.helmController.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + labels: + app.kubernetes.io/component: helm-controller + app.kubernetes.io/instance: {{ .Release.Namespace | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} + app.kubernetes.io/part-of: flux + helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} + name: helm-controller + {{- with .Values.helmController.serviceAccount.annotations }} + annotations: {{ toYaml . | nindent 4 }} + {{- end }} +{{- end -}} +{{- end -}} diff --git a/packages/system/fluxcd/charts/flux2/templates/helm-controller.crds.yaml b/packages/system/fluxcd/charts/flux2/templates/helm-controller.crds.yaml new file mode 100644 index 00000000..7dde6cca --- /dev/null +++ b/packages/system/fluxcd/charts/flux2/templates/helm-controller.crds.yaml @@ -0,0 +1,935 @@ +{{- if and .Values.installCRDs .Values.helmController.create }} +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.12.0 + {{- with .Values.crds.annotations }} + {{- . | toYaml | nindent 4 }} + {{- end }} + labels: + app.kubernetes.io/component: helm-controller + app.kubernetes.io/instance: '{{ .Release.Namespace }}' + app.kubernetes.io/managed-by: '{{ .Release.Service }}' + app.kubernetes.io/part-of: flux + app.kubernetes.io/version: '{{ .Chart.AppVersion }}' + helm.sh/chart: '{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}' + name: helmreleases.helm.toolkit.fluxcd.io +spec: + group: helm.toolkit.fluxcd.io + names: + kind: HelmRelease + listKind: HelmReleaseList + plural: helmreleases + shortNames: + - hr + singular: helmrelease + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + - jsonPath: .status.conditions[?(@.type=="Ready")].status + name: Ready + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].message + name: Status + type: string + name: v2beta1 + schema: + openAPIV3Schema: + description: HelmRelease is the Schema for the helmreleases 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: HelmReleaseSpec defines the desired state of a Helm release. + properties: + chart: + description: Chart defines the template of the v1beta2.HelmChart that + should be created for this HelmRelease. + properties: + metadata: + description: ObjectMeta holds the template for metadata like labels + and annotations. + properties: + annotations: + additionalProperties: + type: string + description: 'Annotations is an unstructured key value map + stored with a resource that may be set by external tools + to store and retrieve arbitrary metadata. They are not queryable + and should be preserved when modifying objects. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/' + type: object + labels: + additionalProperties: + type: string + description: 'Map of string keys and values that can be used + to organize and categorize (scope and select) objects. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/' + type: object + type: object + spec: + description: Spec holds the template for the v1beta2.HelmChartSpec + for this HelmRelease. + properties: + chart: + description: The name or path the Helm chart is available + at in the SourceRef. + type: string + interval: + description: Interval at which to check the v1beta2.Source + for updates. Defaults to 'HelmReleaseSpec.Interval'. + pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ + type: string + reconcileStrategy: + default: ChartVersion + description: Determines what enables the creation of a new + artifact. Valid values are ('ChartVersion', 'Revision'). + See the documentation of the values for an explanation on + their behavior. Defaults to ChartVersion when omitted. + enum: + - ChartVersion + - Revision + type: string + sourceRef: + description: The name and namespace of the v1beta2.Source + the chart is available at. + properties: + apiVersion: + description: APIVersion of the referent. + type: string + kind: + description: Kind of the referent. + enum: + - HelmRepository + - GitRepository + - Bucket + type: string + name: + description: Name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: Namespace of the referent. + maxLength: 63 + minLength: 1 + type: string + required: + - name + type: object + valuesFile: + description: Alternative values file to use as the default + chart values, expected to be a relative path in the SourceRef. + Deprecated in favor of ValuesFiles, for backwards compatibility + the file defined here is merged before the ValuesFiles items. + Ignored when omitted. + type: string + valuesFiles: + description: Alternative list of values files to use as the + chart values (values.yaml is not included by default), expected + to be a relative path in the SourceRef. Values files are + merged in the order of this list with the last file overriding + the first. Ignored when omitted. + items: + type: string + type: array + verify: + description: Verify contains the secret name containing the + trusted public keys used to verify the signature and specifies + which provider to use to check whether OCI image is authentic. + This field is only supported for OCI sources. Chart dependencies, + which are not bundled in the umbrella chart artifact, are + not verified. + properties: + provider: + default: cosign + description: Provider specifies the technology used to + sign the OCI Helm chart. + enum: + - cosign + type: string + secretRef: + description: SecretRef specifies the Kubernetes Secret + containing the trusted public keys. + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + required: + - provider + type: object + version: + default: '*' + description: Version semver expression, ignored for charts + from v1beta2.GitRepository and v1beta2.Bucket sources. Defaults + to latest when omitted. + type: string + required: + - chart + - sourceRef + type: object + required: + - spec + type: object + dependsOn: + description: DependsOn may contain a meta.NamespacedObjectReference + slice with references to HelmRelease resources that must be ready + before this HelmRelease can be reconciled. + items: + description: NamespacedObjectReference contains enough information + to locate the referenced Kubernetes resource object in any namespace. + properties: + name: + description: Name of the referent. + type: string + namespace: + description: Namespace of the referent, when not specified it + acts as LocalObjectReference. + type: string + required: + - name + type: object + type: array + install: + description: Install holds the configuration for Helm install actions + for this HelmRelease. + properties: + crds: + description: "CRDs upgrade CRDs from the Helm Chart's crds directory + according to the CRD upgrade policy provided here. Valid values + are `Skip`, `Create` or `CreateReplace`. Default is `Create` + and if omitted CRDs are installed but not updated. \n Skip: + do neither install nor replace (update) any CRDs. \n Create: + new CRDs are created, existing CRDs are neither updated nor + deleted. \n CreateReplace: new CRDs are created, existing CRDs + are updated (replaced) but not deleted. \n By default, CRDs + are applied (installed) during Helm install action. With this + option users can opt-in to CRD replace existing CRDs on Helm + install actions, which is not (yet) natively supported by Helm. + https://helm.sh/docs/chart_best_practices/custom_resource_definitions." + enum: + - Skip + - Create + - CreateReplace + type: string + createNamespace: + description: CreateNamespace tells the Helm install action to + create the HelmReleaseSpec.TargetNamespace if it does not exist + yet. On uninstall, the namespace will not be garbage collected. + type: boolean + disableHooks: + description: DisableHooks prevents hooks from running during the + Helm install action. + type: boolean + disableOpenAPIValidation: + description: DisableOpenAPIValidation prevents the Helm install + action from validating rendered templates against the Kubernetes + OpenAPI Schema. + type: boolean + disableWait: + description: DisableWait disables the waiting for resources to + be ready after a Helm install has been performed. + type: boolean + disableWaitForJobs: + description: DisableWaitForJobs disables waiting for jobs to complete + after a Helm install has been performed. + type: boolean + remediation: + description: Remediation holds the remediation configuration for + when the Helm install action for the HelmRelease fails. The + default is to not perform any action. + properties: + ignoreTestFailures: + description: IgnoreTestFailures tells the controller to skip + remediation when the Helm tests are run after an install + action but fail. Defaults to 'Test.IgnoreFailures'. + type: boolean + remediateLastFailure: + description: RemediateLastFailure tells the controller to + remediate the last failure, when no retries remain. Defaults + to 'false'. + type: boolean + retries: + description: Retries is the number of retries that should + be attempted on failures before bailing. Remediation, using + an uninstall, is performed between each attempt. Defaults + to '0', a negative integer equals to unlimited retries. + type: integer + type: object + replace: + description: Replace tells the Helm install action to re-use the + 'ReleaseName', but only if that name is a deleted release which + remains in the history. + type: boolean + skipCRDs: + description: "SkipCRDs tells the Helm install action to not install + any CRDs. By default, CRDs are installed if not already present. + \n Deprecated use CRD policy (`crds`) attribute with value `Skip` + instead." + type: boolean + timeout: + description: Timeout is the time to wait for any individual Kubernetes + operation (like Jobs for hooks) during the performance of a + Helm install action. Defaults to 'HelmReleaseSpec.Timeout'. + pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ + type: string + type: object + interval: + description: Interval at which to reconcile the Helm release. This + interval is approximate and may be subject to jitter to ensure efficient + use of resources. + pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ + type: string + kubeConfig: + description: KubeConfig for reconciling the HelmRelease on a remote + cluster. When used in combination with HelmReleaseSpec.ServiceAccountName, + forces the controller to act on behalf of that Service Account at + the target cluster. If the --default-service-account flag is set, + its value will be used as a controller level fallback for when HelmReleaseSpec.ServiceAccountName + is empty. + properties: + secretRef: + description: SecretRef holds the name of a secret that contains + a key with the kubeconfig file as the value. If no key is set, + the key will default to 'value'. It is recommended that the + kubeconfig is self-contained, and the secret is regularly updated + if credentials such as a cloud-access-token expire. Cloud specific + `cmd-path` auth helpers will not function without adding binaries + and credentials to the Pod that is responsible for reconciling + Kubernetes resources. + properties: + key: + description: Key in the Secret, when not specified an implementation-specific + default key is used. + type: string + name: + description: Name of the Secret. + type: string + required: + - name + type: object + required: + - secretRef + type: object + maxHistory: + description: MaxHistory is the number of revisions saved by Helm for + this HelmRelease. Use '0' for an unlimited number of revisions; + defaults to '10'. + type: integer + persistentClient: + description: "PersistentClient tells the controller to use a persistent + Kubernetes client for this release. When enabled, the client will + be reused for the duration of the reconciliation, instead of being + created and destroyed for each (step of a) Helm action. \n This + can improve performance, but may cause issues with some Helm charts + that for example do create Custom Resource Definitions during installation + outside Helm's CRD lifecycle hooks, which are then not observed + to be available by e.g. post-install hooks. \n If not set, it defaults + to true." + type: boolean + postRenderers: + description: PostRenderers holds an array of Helm PostRenderers, which + will be applied in order of their definition. + items: + description: PostRenderer contains a Helm PostRenderer specification. + properties: + kustomize: + description: Kustomization to apply as PostRenderer. + properties: + images: + description: Images is a list of (image name, new name, + new tag or digest) for changing image names, tags or digests. + This can also be achieved with a patch, but this operator + is simpler to specify. + items: + description: Image contains an image name, a new name, + a new tag or digest, which will replace the original + name and tag. + properties: + digest: + description: Digest is the value used to replace the + original image tag. If digest is present NewTag + value is ignored. + type: string + name: + description: Name is a tag-less image name. + type: string + newName: + description: NewName is the value used to replace + the original name. + type: string + newTag: + description: NewTag is the value used to replace the + original tag. + type: string + required: + - name + type: object + type: array + patches: + description: Strategic merge and JSON patches, defined as + inline YAML objects, capable of targeting objects based + on kind, label and annotation selectors. + items: + description: Patch contains an inline StrategicMerge or + JSON6902 patch, and the target the patch should be applied + to. + properties: + patch: + description: Patch contains an inline StrategicMerge + patch or an inline JSON6902 patch with an array + of operation objects. + type: string + target: + description: Target points to the resources that the + patch document should be applied to. + properties: + annotationSelector: + description: AnnotationSelector is a string that + follows the label selection expression https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#api + It matches with the resource annotations. + type: string + group: + description: Group is the API group to select + resources from. Together with Version and Kind + it is capable of unambiguously identifying and/or + selecting resources. https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md + type: string + kind: + description: Kind of the API Group to select resources + from. Together with Group and Version it is + capable of unambiguously identifying and/or + selecting resources. https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md + type: string + labelSelector: + description: LabelSelector is a string that follows + the label selection expression https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#api + It matches with the resource labels. + type: string + name: + description: Name to match resources with. + type: string + namespace: + description: Namespace to select resources from. + type: string + version: + description: Version of the API Group to select + resources from. Together with Group and Kind + it is capable of unambiguously identifying and/or + selecting resources. https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md + type: string + type: object + required: + - patch + type: object + type: array + patchesJson6902: + description: JSON 6902 patches, defined as inline YAML objects. + items: + description: JSON6902Patch contains a JSON6902 patch and + the target the patch should be applied to. + properties: + patch: + description: Patch contains the JSON6902 patch document + with an array of operation objects. + items: + description: JSON6902 is a JSON6902 operation object. + https://datatracker.ietf.org/doc/html/rfc6902#section-4 + properties: + from: + description: From contains a JSON-pointer value + that references a location within the target + document where the operation is performed. + The meaning of the value depends on the value + of Op, and is NOT taken into account by all + operations. + type: string + op: + description: Op indicates the operation to perform. + Its value MUST be one of "add", "remove", + "replace", "move", "copy", or "test". https://datatracker.ietf.org/doc/html/rfc6902#section-4 + enum: + - test + - remove + - add + - replace + - move + - copy + type: string + path: + description: Path contains the JSON-pointer + value that references a location within the + target document where the operation is performed. + The meaning of the value depends on the value + of Op. + type: string + value: + description: Value contains a valid JSON structure. + The meaning of the value depends on the value + of Op, and is NOT taken into account by all + operations. + x-kubernetes-preserve-unknown-fields: true + required: + - op + - path + type: object + type: array + target: + description: Target points to the resources that the + patch document should be applied to. + properties: + annotationSelector: + description: AnnotationSelector is a string that + follows the label selection expression https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#api + It matches with the resource annotations. + type: string + group: + description: Group is the API group to select + resources from. Together with Version and Kind + it is capable of unambiguously identifying and/or + selecting resources. https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md + type: string + kind: + description: Kind of the API Group to select resources + from. Together with Group and Version it is + capable of unambiguously identifying and/or + selecting resources. https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md + type: string + labelSelector: + description: LabelSelector is a string that follows + the label selection expression https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#api + It matches with the resource labels. + type: string + name: + description: Name to match resources with. + type: string + namespace: + description: Namespace to select resources from. + type: string + version: + description: Version of the API Group to select + resources from. Together with Group and Kind + it is capable of unambiguously identifying and/or + selecting resources. https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md + type: string + type: object + required: + - patch + - target + type: object + type: array + patchesStrategicMerge: + description: Strategic merge patches, defined as inline + YAML objects. + items: + x-kubernetes-preserve-unknown-fields: true + type: array + type: object + type: object + type: array + releaseName: + description: ReleaseName used for the Helm release. Defaults to a + composition of '[TargetNamespace-]Name'. + maxLength: 53 + minLength: 1 + type: string + rollback: + description: Rollback holds the configuration for Helm rollback actions + for this HelmRelease. + properties: + cleanupOnFail: + description: CleanupOnFail allows deletion of new resources created + during the Helm rollback action when it fails. + type: boolean + disableHooks: + description: DisableHooks prevents hooks from running during the + Helm rollback action. + type: boolean + disableWait: + description: DisableWait disables the waiting for resources to + be ready after a Helm rollback has been performed. + type: boolean + disableWaitForJobs: + description: DisableWaitForJobs disables waiting for jobs to complete + after a Helm rollback has been performed. + type: boolean + force: + description: Force forces resource updates through a replacement + strategy. + type: boolean + recreate: + description: Recreate performs pod restarts for the resource if + applicable. + type: boolean + timeout: + description: Timeout is the time to wait for any individual Kubernetes + operation (like Jobs for hooks) during the performance of a + Helm rollback action. Defaults to 'HelmReleaseSpec.Timeout'. + pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ + type: string + type: object + serviceAccountName: + description: The name of the Kubernetes service account to impersonate + when reconciling this HelmRelease. + type: string + storageNamespace: + description: StorageNamespace used for the Helm storage. Defaults + to the namespace of the HelmRelease. + maxLength: 63 + minLength: 1 + type: string + suspend: + description: Suspend tells the controller to suspend reconciliation + for this HelmRelease, it does not apply to already started reconciliations. + Defaults to false. + type: boolean + targetNamespace: + description: TargetNamespace to target when performing operations + for the HelmRelease. Defaults to the namespace of the HelmRelease. + maxLength: 63 + minLength: 1 + type: string + test: + description: Test holds the configuration for Helm test actions for + this HelmRelease. + properties: + enable: + description: Enable enables Helm test actions for this HelmRelease + after an Helm install or upgrade action has been performed. + type: boolean + ignoreFailures: + description: IgnoreFailures tells the controller to skip remediation + when the Helm tests are run but fail. Can be overwritten for + tests run after install or upgrade actions in 'Install.IgnoreTestFailures' + and 'Upgrade.IgnoreTestFailures'. + type: boolean + timeout: + description: Timeout is the time to wait for any individual Kubernetes + operation during the performance of a Helm test action. Defaults + to 'HelmReleaseSpec.Timeout'. + pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ + type: string + type: object + timeout: + description: Timeout is the time to wait for any individual Kubernetes + operation (like Jobs for hooks) during the performance of a Helm + action. Defaults to '5m0s'. + pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ + type: string + uninstall: + description: Uninstall holds the configuration for Helm uninstall + actions for this HelmRelease. + properties: + deletionPropagation: + default: background + description: DeletionPropagation specifies the deletion propagation + policy when a Helm uninstall is performed. + enum: + - background + - foreground + - orphan + type: string + disableHooks: + description: DisableHooks prevents hooks from running during the + Helm rollback action. + type: boolean + disableWait: + description: DisableWait disables waiting for all the resources + to be deleted after a Helm uninstall is performed. + type: boolean + keepHistory: + description: KeepHistory tells Helm to remove all associated resources + and mark the release as deleted, but retain the release history. + type: boolean + timeout: + description: Timeout is the time to wait for any individual Kubernetes + operation (like Jobs for hooks) during the performance of a + Helm uninstall action. Defaults to 'HelmReleaseSpec.Timeout'. + pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ + type: string + type: object + upgrade: + description: Upgrade holds the configuration for Helm upgrade actions + for this HelmRelease. + properties: + cleanupOnFail: + description: CleanupOnFail allows deletion of new resources created + during the Helm upgrade action when it fails. + type: boolean + crds: + description: "CRDs upgrade CRDs from the Helm Chart's crds directory + according to the CRD upgrade policy provided here. Valid values + are `Skip`, `Create` or `CreateReplace`. Default is `Skip` and + if omitted CRDs are neither installed nor upgraded. \n Skip: + do neither install nor replace (update) any CRDs. \n Create: + new CRDs are created, existing CRDs are neither updated nor + deleted. \n CreateReplace: new CRDs are created, existing CRDs + are updated (replaced) but not deleted. \n By default, CRDs + are not applied during Helm upgrade action. With this option + users can opt-in to CRD upgrade, which is not (yet) natively + supported by Helm. https://helm.sh/docs/chart_best_practices/custom_resource_definitions." + enum: + - Skip + - Create + - CreateReplace + type: string + disableHooks: + description: DisableHooks prevents hooks from running during the + Helm upgrade action. + type: boolean + disableOpenAPIValidation: + description: DisableOpenAPIValidation prevents the Helm upgrade + action from validating rendered templates against the Kubernetes + OpenAPI Schema. + type: boolean + disableWait: + description: DisableWait disables the waiting for resources to + be ready after a Helm upgrade has been performed. + type: boolean + disableWaitForJobs: + description: DisableWaitForJobs disables waiting for jobs to complete + after a Helm upgrade has been performed. + type: boolean + force: + description: Force forces resource updates through a replacement + strategy. + type: boolean + preserveValues: + description: PreserveValues will make Helm reuse the last release's + values and merge in overrides from 'Values'. Setting this flag + makes the HelmRelease non-declarative. + type: boolean + remediation: + description: Remediation holds the remediation configuration for + when the Helm upgrade action for the HelmRelease fails. The + default is to not perform any action. + properties: + ignoreTestFailures: + description: IgnoreTestFailures tells the controller to skip + remediation when the Helm tests are run after an upgrade + action but fail. Defaults to 'Test.IgnoreFailures'. + type: boolean + remediateLastFailure: + description: RemediateLastFailure tells the controller to + remediate the last failure, when no retries remain. Defaults + to 'false' unless 'Retries' is greater than 0. + type: boolean + retries: + description: Retries is the number of retries that should + be attempted on failures before bailing. Remediation, using + 'Strategy', is performed between each attempt. Defaults + to '0', a negative integer equals to unlimited retries. + type: integer + strategy: + description: Strategy to use for failure remediation. Defaults + to 'rollback'. + enum: + - rollback + - uninstall + type: string + type: object + timeout: + description: Timeout is the time to wait for any individual Kubernetes + operation (like Jobs for hooks) during the performance of a + Helm upgrade action. Defaults to 'HelmReleaseSpec.Timeout'. + pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ + type: string + type: object + values: + description: Values holds the values for this Helm release. + x-kubernetes-preserve-unknown-fields: true + valuesFrom: + description: ValuesFrom holds references to resources containing Helm + values for this HelmRelease, and information about how they should + be merged. + items: + description: ValuesReference contains a reference to a resource + containing Helm values, and optionally the key they can be found + at. + properties: + kind: + description: Kind of the values referent, valid values are ('Secret', + 'ConfigMap'). + enum: + - Secret + - ConfigMap + type: string + name: + description: Name of the values referent. Should reside in the + same namespace as the referring resource. + maxLength: 253 + minLength: 1 + type: string + optional: + description: Optional marks this ValuesReference as optional. + When set, a not found error for the values reference is ignored, + but any ValuesKey, TargetPath or transient error will still + result in a reconciliation failure. + type: boolean + targetPath: + description: TargetPath is the YAML dot notation path the value + should be merged at. When set, the ValuesKey is expected to + be a single flat value. Defaults to 'None', which results + in the values getting merged at the root. + maxLength: 250 + pattern: ^([a-zA-Z0-9_\-.\\\/]|\[[0-9]{1,5}\])+$ + type: string + valuesKey: + description: ValuesKey is the data key where the values.yaml + or a specific value can be found at. Defaults to 'values.yaml'. + When set, must be a valid Data Key, consisting of alphanumeric + characters, '-', '_' or '.'. + maxLength: 253 + pattern: ^[\-._a-zA-Z0-9]+$ + type: string + required: + - kind + - name + type: object + type: array + required: + - chart + - interval + type: object + status: + default: + observedGeneration: -1 + description: HelmReleaseStatus defines the observed state of a HelmRelease. + properties: + conditions: + description: Conditions holds the conditions for the HelmRelease. + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + \n type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + 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 + failures: + description: Failures is the reconciliation failure count against + the latest desired state. It is reset after a successful reconciliation. + format: int64 + type: integer + helmChart: + description: HelmChart is the namespaced name of the HelmChart resource + created by the controller for the HelmRelease. + type: string + installFailures: + description: InstallFailures is the install failure count against + the latest desired state. It is reset after a successful reconciliation. + format: int64 + type: integer + lastAppliedRevision: + description: LastAppliedRevision is the revision of the last successfully + applied source. + type: string + lastAttemptedRevision: + description: LastAttemptedRevision is the revision of the last reconciliation + attempt. + type: string + lastAttemptedValuesChecksum: + description: LastAttemptedValuesChecksum is the SHA1 checksum of the + values of the last reconciliation attempt. + type: string + lastHandledReconcileAt: + description: LastHandledReconcileAt holds the value of the most recent + reconcile request value, so a change of the annotation value can + be detected. + type: string + lastReleaseRevision: + description: LastReleaseRevision is the revision of the last successful + Helm release. + type: integer + observedGeneration: + description: ObservedGeneration is the last observed generation. + format: int64 + type: integer + upgradeFailures: + description: UpgradeFailures is the upgrade failure count against + the latest desired state. It is reset after a successful reconciliation. + format: int64 + type: integer + type: object + type: object + served: true + storage: true + subresources: + status: {} +{{- end }} diff --git a/packages/system/fluxcd/charts/flux2/templates/helm-controller.yaml b/packages/system/fluxcd/charts/flux2/templates/helm-controller.yaml new file mode 100644 index 00000000..0811c156 --- /dev/null +++ b/packages/system/fluxcd/charts/flux2/templates/helm-controller.yaml @@ -0,0 +1,133 @@ +{{- if and .Values.helmController.create}} +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app.kubernetes.io/component: helm-controller + app.kubernetes.io/instance: {{ .Release.Namespace | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} + app.kubernetes.io/part-of: flux + helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} + control-plane: controller + {{- with .Values.helmController.labels }} + {{- . | toYaml | nindent 4 }} + {{- end }} + name: helm-controller +spec: + {{- if kindIs "invalid" .Values.helmController.replicas }} + replicas: 1 + {{- else }} + replicas: {{ .Values.helmController.replicas }} + {{- end}} + selector: + matchLabels: + app: helm-controller + template: + metadata: + {{- with .Values.helmController.annotations }} + annotations: {{ toYaml . | nindent 8 }} + {{- end }} + labels: + app: helm-controller +{{ with .Values.helmController.labels }}{{ toYaml . | indent 8 }}{{ end }} + spec: + automountServiceAccountToken: {{ .Values.helmController.serviceAccount.automount }} + {{- if .Values.helmController.initContainers}} + initContainers: + {{- toYaml .Values.helmController.initContainers | nindent 8}} + {{- end}} + containers: + - args: + {{- if .Values.multitenancy.enabled }} + - --no-cross-namespace-refs=true + - --default-service-account={{ .Values.multitenancy.defaultServiceAccount | default "default" }} + {{- end}} + {{- if .Values.notificationController.create }} + - --events-addr=http://notification-controller.$(RUNTIME_NAMESPACE).svc.{{ .Values.clusterDomain | default "cluster.local" }}. + {{- end}} + - --watch-all-namespaces={{ .Values.watchAllNamespaces }} + - --log-level={{ .Values.logLevel | default "info" }} + - --log-encoding=json + - --enable-leader-election + {{- range .Values.helmController.container.additionalArgs }} + - {{ . }} + {{- end}} + env: + - name: RUNTIME_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + {{- with .Values.helmController.extraEnv }} + {{- toYaml . | nindent 8 }} + {{- end }} + image: {{ template "template.image" .Values.helmController }} + {{- if .Values.helmController.imagePullPolicy }} + imagePullPolicy: {{ .Values.helmController.imagePullPolicy }} + {{- else }} + imagePullPolicy: IfNotPresent + {{- end }} + livenessProbe: + httpGet: + path: /healthz + port: healthz + name: manager + ports: + - containerPort: 8080 + name: http-prom + - containerPort: 9440 + name: healthz + protocol: TCP + readinessProbe: + httpGet: + path: /readyz + port: healthz + {{- with .Values.helmController.resources }} + resources: {{ toYaml . | nindent 10 }} + {{- end }} + {{- if .Values.helmController.securityContext }} + securityContext: {{ toYaml .Values.helmController.securityContext | nindent 10 }} + {{- else }} + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + readOnlyRootFilesystem: true + runAsNonRoot: true + seccompProfile: + type: RuntimeDefault + {{- end}} + volumeMounts: + - mountPath: /tmp + name: temp + {{- if .Values.helmController.volumeMounts }} + {{- toYaml .Values.helmController.volumeMounts | nindent 8 }} + {{- end}} + {{- if .Values.helmController.priorityClassName }} + priorityClassName: {{ .Values.helmController.priorityClassName | quote }} + {{- end }} + {{- if .Values.helmController.podSecurityContext }} + securityContext: {{ toYaml .Values.helmController.podSecurityContext | nindent 8 }} + {{- end }} + serviceAccountName: helm-controller + {{- if .Values.imagePullSecrets }} + imagePullSecrets: {{ toYaml .Values.imagePullSecrets | nindent 6 }} + {{- end }} + terminationGracePeriodSeconds: 600 + volumes: + - emptyDir: {} + name: temp + {{- if .Values.helmController.volumes }} + {{- toYaml .Values.helmController.volumes | nindent 6 }} + {{- end}} + {{- with .Values.helmController.nodeSelector }} + nodeSelector: {{ toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.helmController.affinity }} + affinity: {{ toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.helmController.tolerations }} + tolerations: {{ toYaml . | nindent 8 }} + {{- end }} +{{- end }} diff --git a/packages/system/fluxcd/charts/flux2/templates/image-automation-controller-sa.yaml b/packages/system/fluxcd/charts/flux2/templates/image-automation-controller-sa.yaml new file mode 100644 index 00000000..ac41e696 --- /dev/null +++ b/packages/system/fluxcd/charts/flux2/templates/image-automation-controller-sa.yaml @@ -0,0 +1,18 @@ +{{- if and .Values.imageAutomationController.create }} +{{- if .Values.imageAutomationController.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + labels: + app.kubernetes.io/component: image-automation-controller + app.kubernetes.io/instance: {{ .Release.Namespace | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} + app.kubernetes.io/part-of: flux + helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} + name: image-automation-controller + {{- with .Values.imageAutomationController.serviceAccount.annotations }} + annotations: {{ toYaml . | nindent 4 }} + {{- end }} +{{- end -}} +{{- end -}} diff --git a/packages/system/fluxcd/charts/flux2/templates/image-automation-controller.crds.yaml b/packages/system/fluxcd/charts/flux2/templates/image-automation-controller.crds.yaml new file mode 100644 index 00000000..53b711ee --- /dev/null +++ b/packages/system/fluxcd/charts/flux2/templates/image-automation-controller.crds.yaml @@ -0,0 +1,326 @@ +{{- if and .Values.installCRDs .Values.imageAutomationController.create }} +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.12.0 + {{- with .Values.crds.annotations }} + {{- . | toYaml | nindent 4 }} + {{- end }} + labels: + app.kubernetes.io/component: image-automation-controller + app.kubernetes.io/instance: '{{ .Release.Namespace }}' + app.kubernetes.io/managed-by: '{{ .Release.Service }}' + app.kubernetes.io/part-of: flux + app.kubernetes.io/version: '{{ .Chart.AppVersion }}' + helm.sh/chart: '{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}' + name: imageupdateautomations.image.toolkit.fluxcd.io +spec: + group: image.toolkit.fluxcd.io + names: + kind: ImageUpdateAutomation + listKind: ImageUpdateAutomationList + plural: imageupdateautomations + singular: imageupdateautomation + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .status.lastAutomationRunTime + name: Last run + type: string + name: v1beta1 + schema: + openAPIV3Schema: + description: ImageUpdateAutomation is the Schema for the imageupdateautomations + 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: ImageUpdateAutomationSpec defines the desired state of ImageUpdateAutomation + properties: + git: + description: GitSpec contains all the git-specific definitions. This + is technically optional, but in practice mandatory until there are + other kinds of source allowed. + properties: + checkout: + description: Checkout gives the parameters for cloning the git + repository, ready to make changes. If not present, the `spec.ref` + field from the referenced `GitRepository` or its default will + be used. + properties: + ref: + description: Reference gives a branch, tag or commit to clone + from the Git repository. + properties: + branch: + description: Branch to check out, defaults to 'master' + if no other field is defined. + type: string + commit: + description: "Commit SHA to check out, takes precedence + over all reference fields. \n This can be combined with + Branch to shallow clone the branch, in which the commit + is expected to exist." + type: string + name: + description: "Name of the reference to check out; takes + precedence over Branch, Tag and SemVer. \n It must be + a valid Git reference: https://git-scm.com/docs/git-check-ref-format#_description + Examples: \"refs/heads/main\", \"refs/tags/v0.1.0\", + \"refs/pull/420/head\", \"refs/merge-requests/1/head\"" + type: string + semver: + description: SemVer tag expression to check out, takes + precedence over Tag. + type: string + tag: + description: Tag to check out, takes precedence over Branch. + type: string + type: object + required: + - ref + type: object + commit: + description: Commit specifies how to commit to the git repository. + properties: + author: + description: Author gives the email and optionally the name + to use as the author of commits. + properties: + email: + description: Email gives the email to provide when making + a commit. + type: string + name: + description: Name gives the name to provide when making + a commit. + type: string + required: + - email + type: object + messageTemplate: + description: MessageTemplate provides a template for the commit + message, into which will be interpolated the details of + the change made. + type: string + signingKey: + description: SigningKey provides the option to sign commits + with a GPG key + properties: + secretRef: + description: SecretRef holds the name to a secret that + contains a 'git.asc' key corresponding to the ASCII + Armored file containing the GPG signing keypair as the + value. It must be in the same namespace as the ImageUpdateAutomation. + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + type: object + required: + - author + type: object + push: + description: Push specifies how and where to push commits made + by the automation. If missing, commits are pushed (back) to + `.spec.checkout.branch` or its default. + properties: + branch: + description: Branch specifies that commits should be pushed + to the branch named. The branch is created using `.spec.checkout.branch` + as the starting point, if it doesn't already exist. + type: string + options: + additionalProperties: + type: string + description: 'Options specifies the push options that are + sent to the Git server when performing a push operation. + For details, see: https://git-scm.com/docs/git-push#Documentation/git-push.txt---push-optionltoptiongt' + type: object + refspec: + description: 'Refspec specifies the Git Refspec to use for + a push operation. If both Branch and Refspec are provided, + then the commit is pushed to the branch and also using the + specified refspec. For more details about Git Refspecs, + see: https://git-scm.com/book/en/v2/Git-Internals-The-Refspec' + type: string + type: object + required: + - commit + type: object + interval: + description: Interval gives an lower bound for how often the automation + run should be attempted. + pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ + type: string + sourceRef: + description: SourceRef refers to the resource giving access details + to a git repository. + properties: + apiVersion: + description: API version of the referent. + type: string + kind: + default: GitRepository + description: Kind of the referent. + enum: + - GitRepository + type: string + name: + description: Name of the referent. + type: string + namespace: + description: Namespace of the referent, defaults to the namespace + of the Kubernetes resource object that contains the reference. + type: string + required: + - kind + - name + type: object + suspend: + description: Suspend tells the controller to not run this automation, + until it is unset (or set to false). Defaults to false. + type: boolean + update: + default: + strategy: Setters + description: Update gives the specification for how to update the + files in the repository. This can be left empty, to use the default + value. + properties: + path: + description: Path to the directory containing the manifests to + be updated. Defaults to 'None', which translates to the root + path of the GitRepositoryRef. + type: string + strategy: + default: Setters + description: Strategy names the strategy to be used. + enum: + - Setters + type: string + required: + - strategy + type: object + required: + - interval + - sourceRef + type: object + status: + default: + observedGeneration: -1 + description: ImageUpdateAutomationStatus defines the observed state of + ImageUpdateAutomation + properties: + conditions: + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + \n type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + 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 + lastAutomationRunTime: + description: LastAutomationRunTime records the last time the controller + ran this automation through to completion (even if no updates were + made). + format: date-time + type: string + lastHandledReconcileAt: + description: LastHandledReconcileAt holds the value of the most recent + reconcile request value, so a change of the annotation value can + be detected. + type: string + lastPushCommit: + description: LastPushCommit records the SHA1 of the last commit made + by the controller, for this automation object + type: string + lastPushTime: + description: LastPushTime records the time of the last pushed change. + format: date-time + type: string + observedGeneration: + format: int64 + type: integer + type: object + type: object + served: true + storage: true + subresources: + status: {} +{{- end }} diff --git a/packages/system/fluxcd/charts/flux2/templates/image-automation-controller.yaml b/packages/system/fluxcd/charts/flux2/templates/image-automation-controller.yaml new file mode 100644 index 00000000..47da44d5 --- /dev/null +++ b/packages/system/fluxcd/charts/flux2/templates/image-automation-controller.yaml @@ -0,0 +1,135 @@ +{{- if and .Values.imageAutomationController.create}} +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app.kubernetes.io/component: image-automation-controller + app.kubernetes.io/instance: {{ .Release.Namespace | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} + app.kubernetes.io/part-of: flux + helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} + control-plane: controller + {{- with .Values.imageAutomationController.labels }} + {{- . | toYaml | nindent 4 }} + {{- end }} + name: image-automation-controller +spec: + {{- if kindIs "invalid" .Values.imageAutomationController.replicas }} + replicas: 1 + {{- else }} + replicas: {{ .Values.imageAutomationController.replicas }} + {{- end}} + selector: + matchLabels: + app: image-automation-controller + template: + metadata: + {{- with .Values.imageAutomationController.annotations }} + annotations: {{ toYaml . | nindent 8 }} + {{- end }} + labels: + app: image-automation-controller +{{ with .Values.imageAutomationController.labels }}{{ toYaml . | indent 8 }}{{ end }} + spec: + automountServiceAccountToken: {{ .Values.imageAutomationController.serviceAccount.automount }} + {{- if .Values.imageAutomationController.initContainers}} + initContainers: + {{- toYaml .Values.imageAutomationController.initContainers | nindent 8}} + {{- end}} + containers: + - args: + {{- if .Values.multitenancy.enabled }} + - --no-cross-namespace-refs=true + {{- end}} + {{- if .Values.notificationController.create }} + - --events-addr=http://notification-controller.$(RUNTIME_NAMESPACE).svc.{{ .Values.clusterDomain | default "cluster.local" }}. + {{- end}} + - --watch-all-namespaces={{ .Values.watchAllNamespaces }} + - --log-level={{ .Values.logLevel | default "info" }} + - --log-encoding=json + - --enable-leader-election + {{- range .Values.imageAutomationController.container.additionalArgs }} + - {{ . }} + {{- end}} + env: + - name: RUNTIME_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + {{- with .Values.imageAutomationController.extraEnv }} + {{- toYaml . | nindent 8 }} + {{- end }} + image: {{ template "template.image" .Values.imageAutomationController }} + {{- if .Values.imageAutomationController.imagePullPolicy }} + imagePullPolicy: {{ .Values.imageAutomationController.imagePullPolicy }} + {{- else }} + imagePullPolicy: IfNotPresent + {{- end }} + livenessProbe: + httpGet: + path: /healthz + port: healthz + name: manager + ports: + - containerPort: 8080 + name: http-prom + - containerPort: 9440 + name: healthz + protocol: TCP + readinessProbe: + httpGet: + path: /readyz + port: healthz + {{- with .Values.imageAutomationController.resources }} + resources: {{ toYaml . | nindent 10 }} + {{- end }} + {{- if .Values.imageAutomationController.securityContext }} + securityContext: {{ toYaml .Values.imageAutomationController.securityContext | nindent 10 }} + {{- else }} + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + readOnlyRootFilesystem: true + runAsNonRoot: true + seccompProfile: + type: RuntimeDefault + {{- end}} + volumeMounts: + - mountPath: /tmp + name: temp + {{- if .Values.imageAutomationController.volumeMounts }} + {{- toYaml .Values.imageAutomationController.volumeMounts | nindent 8 }} + {{- end}} + {{- if .Values.imageAutomationController.priorityClassName }} + priorityClassName: {{ .Values.imageAutomationController.priorityClassName | quote }} + {{- end }} + {{- if .Values.imageAutomationController.podSecurityContext }} + securityContext: {{ toYaml .Values.imageAutomationController.podSecurityContext | nindent 8 }} + {{- else }} + securityContext: + fsGroup: 1337 + {{- end}} + serviceAccountName: image-automation-controller + {{- if .Values.imagePullSecrets }} + imagePullSecrets: {{ toYaml .Values.imagePullSecrets | nindent 6 }} + {{- end }} + terminationGracePeriodSeconds: 10 + volumes: + - emptyDir: {} + name: temp + {{- if .Values.imageAutomationController.volumes }} + {{- toYaml .Values.imageAutomationController.volumes | nindent 6 }} + {{- end}} + {{- with .Values.imageAutomationController.nodeSelector }} + nodeSelector: {{ toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.imageAutomationController.affinity }} + affinity: {{ toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.imageAutomationController.tolerations }} + tolerations: {{ toYaml . | nindent 8 }} + {{- end }} +{{- end }} diff --git a/packages/system/fluxcd/charts/flux2/templates/image-reflector-controller-sa.yaml b/packages/system/fluxcd/charts/flux2/templates/image-reflector-controller-sa.yaml new file mode 100644 index 00000000..16f9cb9d --- /dev/null +++ b/packages/system/fluxcd/charts/flux2/templates/image-reflector-controller-sa.yaml @@ -0,0 +1,18 @@ +{{- if and .Values.imageReflectionController.create }} +{{- if .Values.imageReflectionController.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + labels: + app.kubernetes.io/component: image-reflector-controller + app.kubernetes.io/instance: {{ .Release.Namespace | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} + app.kubernetes.io/part-of: flux + helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} + name: image-reflector-controller + {{- with .Values.imageReflectionController.serviceAccount.annotations }} + annotations: {{ toYaml . | nindent 4 }} + {{- end }} +{{- end -}} +{{- end -}} diff --git a/packages/system/fluxcd/charts/flux2/templates/image-reflector-controller.crds.yaml b/packages/system/fluxcd/charts/flux2/templates/image-reflector-controller.crds.yaml new file mode 100644 index 00000000..fb300889 --- /dev/null +++ b/packages/system/fluxcd/charts/flux2/templates/image-reflector-controller.crds.yaml @@ -0,0 +1,897 @@ +{{- if and .Values.installCRDs .Values.imageReflectionController.create }} +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.12.0 + {{- with .Values.crds.annotations }} + {{- . | toYaml | nindent 4 }} + {{- end }} + labels: + app.kubernetes.io/component: image-reflector-controller + app.kubernetes.io/instance: '{{ .Release.Namespace }}' + app.kubernetes.io/managed-by: '{{ .Release.Service }}' + app.kubernetes.io/part-of: flux + app.kubernetes.io/version: '{{ .Chart.AppVersion }}' + helm.sh/chart: '{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}' + name: imagepolicies.image.toolkit.fluxcd.io +spec: + group: image.toolkit.fluxcd.io + names: + kind: ImagePolicy + listKind: ImagePolicyList + plural: imagepolicies + singular: imagepolicy + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .status.latestImage + name: LatestImage + type: string + name: v1beta1 + schema: + openAPIV3Schema: + description: ImagePolicy is the Schema for the imagepolicies 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: ImagePolicySpec defines the parameters for calculating the + ImagePolicy + properties: + filterTags: + description: FilterTags enables filtering for only a subset of tags + based on a set of rules. If no rules are provided, all the tags + from the repository will be ordered and compared. + properties: + extract: + description: Extract allows a capture group to be extracted from + the specified regular expression pattern, useful before tag + evaluation. + type: string + pattern: + description: Pattern specifies a regular expression pattern used + to filter for image tags. + type: string + type: object + imageRepositoryRef: + description: ImageRepositoryRef points at the object specifying the + image being scanned + properties: + name: + description: Name of the referent. + type: string + namespace: + description: Namespace of the referent, when not specified it + acts as LocalObjectReference. + type: string + required: + - name + type: object + policy: + description: Policy gives the particulars of the policy to be followed + in selecting the most recent image + properties: + alphabetical: + description: Alphabetical set of rules to use for alphabetical + ordering of the tags. + properties: + order: + default: asc + description: Order specifies the sorting order of the tags. + Given the letters of the alphabet as tags, ascending order + would select Z, and descending order would select A. + enum: + - asc + - desc + type: string + type: object + numerical: + description: Numerical set of rules to use for numerical ordering + of the tags. + properties: + order: + default: asc + description: Order specifies the sorting order of the tags. + Given the integer values from 0 to 9 as tags, ascending + order would select 9, and descending order would select + 0. + enum: + - asc + - desc + type: string + type: object + semver: + description: SemVer gives a semantic version range to check against + the tags available. + properties: + range: + description: Range gives a semver range for the image tag; + the highest version within the range that's a tag yields + the latest image. + type: string + required: + - range + type: object + type: object + required: + - imageRepositoryRef + - policy + type: object + status: + default: + observedGeneration: -1 + description: ImagePolicyStatus defines the observed state of ImagePolicy + properties: + conditions: + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + \n type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + 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 + latestImage: + description: LatestImage gives the first in the list of images scanned + by the image repository, when filtered and ordered according to + the policy. + type: string + observedGeneration: + format: int64 + type: integer + type: object + type: object + served: true + storage: false + subresources: + status: {} + - additionalPrinterColumns: + - jsonPath: .status.latestImage + name: LatestImage + type: string + name: v1beta2 + schema: + openAPIV3Schema: + description: ImagePolicy is the Schema for the imagepolicies 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: ImagePolicySpec defines the parameters for calculating the + ImagePolicy. + properties: + filterTags: + description: FilterTags enables filtering for only a subset of tags + based on a set of rules. If no rules are provided, all the tags + from the repository will be ordered and compared. + properties: + extract: + description: Extract allows a capture group to be extracted from + the specified regular expression pattern, useful before tag + evaluation. + type: string + pattern: + description: Pattern specifies a regular expression pattern used + to filter for image tags. + type: string + type: object + imageRepositoryRef: + description: ImageRepositoryRef points at the object specifying the + image being scanned + properties: + name: + description: Name of the referent. + type: string + namespace: + description: Namespace of the referent, when not specified it + acts as LocalObjectReference. + type: string + required: + - name + type: object + policy: + description: Policy gives the particulars of the policy to be followed + in selecting the most recent image + properties: + alphabetical: + description: Alphabetical set of rules to use for alphabetical + ordering of the tags. + properties: + order: + default: asc + description: Order specifies the sorting order of the tags. + Given the letters of the alphabet as tags, ascending order + would select Z, and descending order would select A. + enum: + - asc + - desc + type: string + type: object + numerical: + description: Numerical set of rules to use for numerical ordering + of the tags. + properties: + order: + default: asc + description: Order specifies the sorting order of the tags. + Given the integer values from 0 to 9 as tags, ascending + order would select 9, and descending order would select + 0. + enum: + - asc + - desc + type: string + type: object + semver: + description: SemVer gives a semantic version range to check against + the tags available. + properties: + range: + description: Range gives a semver range for the image tag; + the highest version within the range that's a tag yields + the latest image. + type: string + required: + - range + type: object + type: object + required: + - imageRepositoryRef + - policy + type: object + status: + default: + observedGeneration: -1 + description: ImagePolicyStatus defines the observed state of ImagePolicy + properties: + conditions: + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + \n type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + 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 + latestImage: + description: LatestImage gives the first in the list of images scanned + by the image repository, when filtered and ordered according to + the policy. + type: string + observedGeneration: + format: int64 + type: integer + observedPreviousImage: + description: ObservedPreviousImage is the observed previous LatestImage. + It is used to keep track of the previous and current images. + 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.12.0 + {{- with .Values.crds.annotations }} + {{- . | toYaml | nindent 4 }} + {{- end }} + labels: + app.kubernetes.io/component: image-reflector-controller + app.kubernetes.io/instance: '{{ .Release.Namespace }}' + app.kubernetes.io/managed-by: '{{ .Release.Service }}' + app.kubernetes.io/part-of: flux + app.kubernetes.io/version: '{{ .Chart.AppVersion }}' + helm.sh/chart: '{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}' + name: imagerepositories.image.toolkit.fluxcd.io +spec: + group: image.toolkit.fluxcd.io + names: + kind: ImageRepository + listKind: ImageRepositoryList + plural: imagerepositories + singular: imagerepository + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .status.lastScanResult.scanTime + name: Last scan + type: string + - jsonPath: .status.lastScanResult.tagCount + name: Tags + type: string + name: v1beta1 + schema: + openAPIV3Schema: + description: ImageRepository is the Schema for the imagerepositories 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: ImageRepositorySpec defines the parameters for scanning an + image repository, e.g., `fluxcd/flux`. + properties: + accessFrom: + description: AccessFrom defines an ACL for allowing cross-namespace + references to the ImageRepository object based on the caller's namespace + labels. + properties: + namespaceSelectors: + description: NamespaceSelectors is the list of namespace selectors + to which this ACL applies. Items in this list are evaluated + using a logical OR operation. + items: + description: NamespaceSelector selects the namespaces to which + this ACL applies. An empty map of MatchLabels matches all + namespaces in a cluster. + properties: + 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 + type: array + required: + - namespaceSelectors + type: object + certSecretRef: + description: "CertSecretRef can be given the name of a secret containing + either or both of \n - a PEM-encoded client certificate (`certFile`) + and private key (`keyFile`); - a PEM-encoded CA certificate (`caFile`) + \n and whichever are supplied, will be used for connecting to the + registry. The client cert and key are useful if you are authenticating + with a certificate; the CA cert is useful if you are using a self-signed + server certificate." + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + exclusionList: + description: ExclusionList is a list of regex strings used to exclude + certain tags from being stored in the database. + items: + type: string + type: array + image: + description: Image is the name of the image repository + type: string + interval: + description: Interval is the length of time to wait between scans + of the image repository. + pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ + type: string + secretRef: + description: SecretRef can be given the name of a secret containing + credentials to use for the image registry. The secret should be + created with `kubectl create secret docker-registry`, or the equivalent. + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + serviceAccountName: + description: ServiceAccountName is the name of the Kubernetes ServiceAccount + used to authenticate the image pull if the service account has attached + pull secrets. + maxLength: 253 + type: string + suspend: + description: This flag tells the controller to suspend subsequent + image scans. It does not apply to already started scans. Defaults + to false. + type: boolean + timeout: + description: Timeout for image scanning. Defaults to 'Interval' duration. + pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m))+$ + type: string + type: object + status: + default: + observedGeneration: -1 + description: ImageRepositoryStatus defines the observed state of ImageRepository + properties: + canonicalImageName: + description: CanonicalName is the name of the image repository with + all the implied bits made explicit; e.g., `docker.io/library/alpine` + rather than `alpine`. + type: string + conditions: + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + \n type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + 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 + lastHandledReconcileAt: + description: LastHandledReconcileAt holds the value of the most recent + reconcile request value, so a change of the annotation value can + be detected. + type: string + lastScanResult: + description: LastScanResult contains the number of fetched tags. + properties: + scanTime: + format: date-time + type: string + tagCount: + type: integer + required: + - tagCount + type: object + observedGeneration: + description: ObservedGeneration is the last reconciled generation. + format: int64 + type: integer + type: object + type: object + served: true + storage: false + subresources: + status: {} + - additionalPrinterColumns: + - jsonPath: .status.lastScanResult.scanTime + name: Last scan + type: string + - jsonPath: .status.lastScanResult.tagCount + name: Tags + type: string + name: v1beta2 + schema: + openAPIV3Schema: + description: ImageRepository is the Schema for the imagerepositories 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: ImageRepositorySpec defines the parameters for scanning an + image repository, e.g., `fluxcd/flux`. + properties: + accessFrom: + description: AccessFrom defines an ACL for allowing cross-namespace + references to the ImageRepository object based on the caller's namespace + labels. + properties: + namespaceSelectors: + description: NamespaceSelectors is the list of namespace selectors + to which this ACL applies. Items in this list are evaluated + using a logical OR operation. + items: + description: NamespaceSelector selects the namespaces to which + this ACL applies. An empty map of MatchLabels matches all + namespaces in a cluster. + properties: + 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 + type: array + required: + - namespaceSelectors + type: object + certSecretRef: + description: "CertSecretRef can be given the name of a Secret containing + either or both of \n - a PEM-encoded client certificate (`tls.crt`) + and private key (`tls.key`); - a PEM-encoded CA certificate (`ca.crt`) + \n and whichever are supplied, will be used for connecting to the + registry. The client cert and key are useful if you are authenticating + with a certificate; the CA cert is useful if you are using a self-signed + server certificate. The Secret must be of type `Opaque` or `kubernetes.io/tls`. + \n Note: Support for the `caFile`, `certFile` and `keyFile` keys + has been deprecated." + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + exclusionList: + default: + - ^.*\.sig$ + description: ExclusionList is a list of regex strings used to exclude + certain tags from being stored in the database. + items: + type: string + maxItems: 25 + type: array + image: + description: Image is the name of the image repository + type: string + interval: + description: Interval is the length of time to wait between scans + of the image repository. + pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ + type: string + provider: + default: generic + description: The provider used for authentication, can be 'aws', 'azure', + 'gcp' or 'generic'. When not specified, defaults to 'generic'. + enum: + - generic + - aws + - azure + - gcp + type: string + secretRef: + description: SecretRef can be given the name of a secret containing + credentials to use for the image registry. The secret should be + created with `kubectl create secret docker-registry`, or the equivalent. + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + serviceAccountName: + description: ServiceAccountName is the name of the Kubernetes ServiceAccount + used to authenticate the image pull if the service account has attached + pull secrets. + maxLength: 253 + type: string + suspend: + description: This flag tells the controller to suspend subsequent + image scans. It does not apply to already started scans. Defaults + to false. + type: boolean + timeout: + description: Timeout for image scanning. Defaults to 'Interval' duration. + pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m))+$ + type: string + type: object + status: + default: + observedGeneration: -1 + description: ImageRepositoryStatus defines the observed state of ImageRepository + properties: + canonicalImageName: + description: CanonicalName is the name of the image repository with + all the implied bits made explicit; e.g., `docker.io/library/alpine` + rather than `alpine`. + type: string + conditions: + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + \n type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + 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 + lastHandledReconcileAt: + description: LastHandledReconcileAt holds the value of the most recent + reconcile request value, so a change of the annotation value can + be detected. + type: string + lastScanResult: + description: LastScanResult contains the number of fetched tags. + properties: + latestTags: + items: + type: string + type: array + scanTime: + format: date-time + type: string + tagCount: + type: integer + required: + - tagCount + type: object + observedExclusionList: + description: ObservedExclusionList is a list of observed exclusion + list. It reflects the exclusion rules used for the observed scan + result in spec.lastScanResult. + items: + type: string + type: array + observedGeneration: + description: ObservedGeneration is the last reconciled generation. + format: int64 + type: integer + type: object + type: object + served: true + storage: true + subresources: + status: {} +{{- end }} diff --git a/packages/system/fluxcd/charts/flux2/templates/image-reflector-controller.yaml b/packages/system/fluxcd/charts/flux2/templates/image-reflector-controller.yaml new file mode 100644 index 00000000..58abd295 --- /dev/null +++ b/packages/system/fluxcd/charts/flux2/templates/image-reflector-controller.yaml @@ -0,0 +1,139 @@ +{{- if and .Values.imageReflectionController.create }} +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app.kubernetes.io/component: image-reflector-controller + app.kubernetes.io/instance: {{ .Release.Namespace | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} + app.kubernetes.io/part-of: flux + helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} + control-plane: controller + {{- with .Values.imageReflectionController.labels }} + {{- . | toYaml | nindent 4 }} + {{- end }} + name: image-reflector-controller +spec: + {{- if kindIs "invalid" .Values.imageReflectionController.replicas }} + replicas: 1 + {{- else }} + replicas: {{ .Values.imageReflectionController.replicas }} + {{- end}} + selector: + matchLabels: + app: image-reflector-controller + template: + metadata: + {{- with .Values.imageReflectionController.annotations }} + annotations: {{ toYaml . | nindent 8 }} + {{- end }} + labels: + app: image-reflector-controller +{{ with .Values.imageReflectionController.labels }}{{ toYaml . | indent 8 }}{{ end }} + spec: + automountServiceAccountToken: {{ .Values.imageReflectionController.serviceAccount.automount }} + {{- if .Values.imageReflectionController.initContainers}} + initContainers: + {{- toYaml .Values.imageReflectionController.initContainers | nindent 8}} + {{- end}} + containers: + - args: + {{- if .Values.multitenancy.enabled }} + - --no-cross-namespace-refs=true + {{- end}} + {{- if .Values.notificationController.create }} + - --events-addr=http://notification-controller.$(RUNTIME_NAMESPACE).svc.{{ .Values.clusterDomain | default "cluster.local" }}. + {{- end}} + - --watch-all-namespaces={{ .Values.watchAllNamespaces }} + - --log-level={{ .Values.logLevel | default "info" }} + - --log-encoding=json + - --enable-leader-election + {{- range .Values.imageReflectionController.container.additionalArgs }} + - {{ . }} + {{- end}} + env: + - name: RUNTIME_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + {{- with .Values.imageReflectionController.extraEnv }} + {{- toYaml . | nindent 8 }} + {{- end }} + image: {{ template "template.image" .Values.imageReflectionController }} + {{- if .Values.imageReflectionController.imagePullPolicy }} + imagePullPolicy: {{ .Values.imageReflectionController.imagePullPolicy }} + {{- else }} + imagePullPolicy: IfNotPresent + {{- end }} + livenessProbe: + httpGet: + path: /healthz + port: healthz + name: manager + ports: + - containerPort: 8080 + name: http-prom + - containerPort: 9440 + name: healthz + protocol: TCP + readinessProbe: + httpGet: + path: /readyz + port: healthz + {{- with .Values.imageReflectionController.resources }} + resources: {{ toYaml . | nindent 10 }} + {{- end }} + {{- if .Values.imageReflectionController.securityContext }} + securityContext: {{ toYaml .Values.imageReflectionController.securityContext | nindent 10 }} + {{- else }} + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + readOnlyRootFilesystem: true + runAsNonRoot: true + seccompProfile: + type: RuntimeDefault + {{- end}} + volumeMounts: + - mountPath: /tmp + name: temp + - mountPath: /data + name: data + {{- if .Values.imageReflectionController.volumeMounts }} + {{- toYaml .Values.imageReflectionController.volumeMounts | nindent 8 }} + {{- end}} + {{- if .Values.imageReflectionController.priorityClassName }} + priorityClassName: {{ .Values.imageReflectionController.priorityClassName | quote }} + {{- end }} + {{- if .Values.imageReflectionController.podSecurityContext }} + securityContext: {{ toYaml .Values.imageReflectionController.podSecurityContext | nindent 8 }} + {{- else }} + securityContext: + fsGroup: 1337 + {{- end}} + serviceAccountName: image-reflector-controller + {{- if .Values.imagePullSecrets }} + imagePullSecrets: {{ toYaml .Values.imagePullSecrets | nindent 6 }} + {{- end }} + terminationGracePeriodSeconds: 10 + volumes: + - emptyDir: {} + name: temp + - emptyDir: {} + name: data + {{- if .Values.imageReflectionController.volumes }} + {{- toYaml .Values.imageReflectionController.volumes | nindent 6 }} + {{- end}} + {{- with .Values.imageReflectionController.nodeSelector }} + nodeSelector: {{ toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.imageReflectionController.affinity }} + affinity: {{ toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.imageReflectionController.tolerations }} + tolerations: {{ toYaml . | nindent 8 }} + {{- end }} +{{- end }} diff --git a/packages/system/fluxcd/charts/flux2/templates/kustomize-controller-sa.yaml b/packages/system/fluxcd/charts/flux2/templates/kustomize-controller-sa.yaml new file mode 100644 index 00000000..140c30b1 --- /dev/null +++ b/packages/system/fluxcd/charts/flux2/templates/kustomize-controller-sa.yaml @@ -0,0 +1,18 @@ +{{- if and .Values.kustomizeController.create }} +{{- if .Values.kustomizeController.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + labels: + app.kubernetes.io/component: kustomize-controller + app.kubernetes.io/instance: {{ .Release.Namespace | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} + app.kubernetes.io/part-of: flux + helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} + name: kustomize-controller + {{- with .Values.kustomizeController.serviceAccount.annotations }} + annotations: {{ toYaml . | nindent 4 }} + {{- end }} +{{- end -}} +{{- end -}} diff --git a/packages/system/fluxcd/charts/flux2/templates/kustomize-controller-secret.yaml b/packages/system/fluxcd/charts/flux2/templates/kustomize-controller-secret.yaml new file mode 100644 index 00000000..8a547043 --- /dev/null +++ b/packages/system/fluxcd/charts/flux2/templates/kustomize-controller-secret.yaml @@ -0,0 +1,18 @@ +{{- if and .Values.kustomizeController.secret.create }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ .Values.kustomizeController.secret.name }} + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/instance: {{ .Release.Namespace | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} + app.kubernetes.io/part-of: flux + helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} +type: Opaque +data: + {{- range $key, $value := .Values.kustomizeController.secret.data }} + {{ $key }}: {{ $value | toString | b64enc | quote }} + {{- end }} +{{- end }} diff --git a/packages/system/fluxcd/charts/flux2/templates/kustomize-controller.crds.yaml b/packages/system/fluxcd/charts/flux2/templates/kustomize-controller.crds.yaml new file mode 100644 index 00000000..433cce66 --- /dev/null +++ b/packages/system/fluxcd/charts/flux2/templates/kustomize-controller.crds.yaml @@ -0,0 +1,1640 @@ +{{- if and .Values.installCRDs .Values.kustomizeController.create }} +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.12.0 + {{- with .Values.crds.annotations }} + {{- . | toYaml | nindent 4 }} + {{- end }} + labels: + app.kubernetes.io/component: kustomize-controller + app.kubernetes.io/instance: '{{ .Release.Namespace }}' + app.kubernetes.io/managed-by: '{{ .Release.Service }}' + app.kubernetes.io/part-of: flux + app.kubernetes.io/version: '{{ .Chart.AppVersion }}' + helm.sh/chart: '{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}' + name: kustomizations.kustomize.toolkit.fluxcd.io +spec: + group: kustomize.toolkit.fluxcd.io + names: + kind: Kustomization + listKind: KustomizationList + plural: kustomizations + shortNames: + - ks + singular: kustomization + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + - jsonPath: .status.conditions[?(@.type=="Ready")].status + name: Ready + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].message + name: Status + type: string + name: v1 + schema: + openAPIV3Schema: + description: Kustomization is the Schema for the kustomizations 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: KustomizationSpec defines the configuration to calculate + the desired state from a Source using Kustomize. + properties: + commonMetadata: + description: CommonMetadata specifies the common labels and annotations + that are applied to all resources. Any existing label or annotation + will be overridden if its key matches a common one. + properties: + annotations: + additionalProperties: + type: string + description: Annotations to be added to the object's metadata. + type: object + labels: + additionalProperties: + type: string + description: Labels to be added to the object's metadata. + type: object + type: object + components: + description: Components specifies relative paths to specifications + of other Components. + items: + type: string + type: array + decryption: + description: Decrypt Kubernetes secrets before applying them on the + cluster. + properties: + provider: + description: Provider is the name of the decryption engine. + enum: + - sops + type: string + secretRef: + description: The secret name containing the private OpenPGP keys + used for decryption. + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + required: + - provider + type: object + dependsOn: + description: DependsOn may contain a meta.NamespacedObjectReference + slice with references to Kustomization resources that must be ready + before this Kustomization can be reconciled. + items: + description: NamespacedObjectReference contains enough information + to locate the referenced Kubernetes resource object in any namespace. + properties: + name: + description: Name of the referent. + type: string + namespace: + description: Namespace of the referent, when not specified it + acts as LocalObjectReference. + type: string + required: + - name + type: object + type: array + force: + default: false + description: Force instructs the controller to recreate resources + when patching fails due to an immutable field change. + type: boolean + healthChecks: + description: A list of resources to be included in the health assessment. + items: + description: NamespacedObjectKindReference contains enough information + to locate the typed referenced Kubernetes resource object in any + namespace. + properties: + apiVersion: + description: API version of the referent, if not specified the + Kubernetes preferred version will be used. + type: string + kind: + description: Kind of the referent. + type: string + name: + description: Name of the referent. + type: string + namespace: + description: Namespace of the referent, when not specified it + acts as LocalObjectReference. + type: string + required: + - kind + - name + type: object + type: array + images: + description: Images is a list of (image name, new name, new tag or + digest) for changing image names, tags or digests. This can also + be achieved with a patch, but this operator is simpler to specify. + items: + description: Image contains an image name, a new name, a new tag + or digest, which will replace the original name and tag. + properties: + digest: + description: Digest is the value used to replace the original + image tag. If digest is present NewTag value is ignored. + type: string + name: + description: Name is a tag-less image name. + type: string + newName: + description: NewName is the value used to replace the original + name. + type: string + newTag: + description: NewTag is the value used to replace the original + tag. + type: string + required: + - name + type: object + type: array + interval: + description: The interval at which to reconcile the Kustomization. + This interval is approximate and may be subject to jitter to ensure + efficient use of resources. + pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ + type: string + kubeConfig: + description: The KubeConfig for reconciling the Kustomization on a + remote cluster. When used in combination with KustomizationSpec.ServiceAccountName, + forces the controller to act on behalf of that Service Account at + the target cluster. If the --default-service-account flag is set, + its value will be used as a controller level fallback for when KustomizationSpec.ServiceAccountName + is empty. + properties: + secretRef: + description: SecretRef holds the name of a secret that contains + a key with the kubeconfig file as the value. If no key is set, + the key will default to 'value'. It is recommended that the + kubeconfig is self-contained, and the secret is regularly updated + if credentials such as a cloud-access-token expire. Cloud specific + `cmd-path` auth helpers will not function without adding binaries + and credentials to the Pod that is responsible for reconciling + Kubernetes resources. + properties: + key: + description: Key in the Secret, when not specified an implementation-specific + default key is used. + type: string + name: + description: Name of the Secret. + type: string + required: + - name + type: object + required: + - secretRef + type: object + patches: + description: Strategic merge and JSON patches, defined as inline YAML + objects, capable of targeting objects based on kind, label and annotation + selectors. + items: + description: Patch contains an inline StrategicMerge or JSON6902 + patch, and the target the patch should be applied to. + properties: + patch: + description: Patch contains an inline StrategicMerge patch or + an inline JSON6902 patch with an array of operation objects. + type: string + target: + description: Target points to the resources that the patch document + should be applied to. + properties: + annotationSelector: + description: AnnotationSelector is a string that follows + the label selection expression https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#api + It matches with the resource annotations. + type: string + group: + description: Group is the API group to select resources + from. Together with Version and Kind it is capable of + unambiguously identifying and/or selecting resources. + https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md + type: string + kind: + description: Kind of the API Group to select resources from. + Together with Group and Version it is capable of unambiguously + identifying and/or selecting resources. https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md + type: string + labelSelector: + description: LabelSelector is a string that follows the + label selection expression https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#api + It matches with the resource labels. + type: string + name: + description: Name to match resources with. + type: string + namespace: + description: Namespace to select resources from. + type: string + version: + description: Version of the API Group to select resources + from. Together with Group and Kind it is capable of unambiguously + identifying and/or selecting resources. https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md + type: string + type: object + required: + - patch + type: object + type: array + path: + description: Path to the directory containing the kustomization.yaml + file, or the set of plain YAMLs a kustomization.yaml should be generated + for. Defaults to 'None', which translates to the root path of the + SourceRef. + type: string + postBuild: + description: PostBuild describes which actions to perform on the YAML + manifest generated by building the kustomize overlay. + properties: + substitute: + additionalProperties: + type: string + description: Substitute holds a map of key/value pairs. The variables + defined in your YAML manifests that match any of the keys defined + in the map will be substituted with the set value. Includes + support for bash string replacement functions e.g. ${var:=default}, + ${var:position} and ${var/substring/replacement}. + type: object + substituteFrom: + description: SubstituteFrom holds references to ConfigMaps and + Secrets containing the variables and their values to be substituted + in the YAML manifests. The ConfigMap and the Secret data keys + represent the var names, and they must match the vars declared + in the manifests for the substitution to happen. + items: + description: SubstituteReference contains a reference to a resource + containing the variables name and value. + properties: + kind: + description: Kind of the values referent, valid values are + ('Secret', 'ConfigMap'). + enum: + - Secret + - ConfigMap + type: string + name: + description: Name of the values referent. Should reside + in the same namespace as the referring resource. + maxLength: 253 + minLength: 1 + type: string + optional: + default: false + description: Optional indicates whether the referenced resource + must exist, or whether to tolerate its absence. If true + and the referenced resource is absent, proceed as if the + resource was present but empty, without any variables + defined. + type: boolean + required: + - kind + - name + type: object + type: array + type: object + prune: + description: Prune enables garbage collection. + type: boolean + retryInterval: + description: The interval at which to retry a previously failed reconciliation. + When not specified, the controller uses the KustomizationSpec.Interval + value to retry failures. + pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ + type: string + serviceAccountName: + description: The name of the Kubernetes service account to impersonate + when reconciling this Kustomization. + type: string + sourceRef: + description: Reference of the source where the kustomization file + is. + properties: + apiVersion: + description: API version of the referent. + type: string + kind: + description: Kind of the referent. + enum: + - OCIRepository + - GitRepository + - Bucket + type: string + name: + description: Name of the referent. + type: string + namespace: + description: Namespace of the referent, defaults to the namespace + of the Kubernetes resource object that contains the reference. + type: string + required: + - kind + - name + type: object + suspend: + description: This flag tells the controller to suspend subsequent + kustomize executions, it does not apply to already started executions. + Defaults to false. + type: boolean + targetNamespace: + description: TargetNamespace sets or overrides the namespace in the + kustomization.yaml file. + maxLength: 63 + minLength: 1 + type: string + timeout: + description: Timeout for validation, apply and health checking operations. + Defaults to 'Interval' duration. + pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ + type: string + wait: + description: Wait instructs the controller to check the health of + all the reconciled resources. When enabled, the HealthChecks are + ignored. Defaults to false. + type: boolean + required: + - interval + - prune + - sourceRef + type: object + status: + default: + observedGeneration: -1 + description: KustomizationStatus defines the observed state of a kustomization. + properties: + conditions: + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + \n type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + 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 + inventory: + description: Inventory contains the list of Kubernetes resource object + references that have been successfully applied. + properties: + entries: + description: Entries of Kubernetes resource object references. + items: + description: ResourceRef contains the information necessary + to locate a resource within a cluster. + properties: + id: + description: ID is the string representation of the Kubernetes + resource object's metadata, in the format '___'. + type: string + v: + description: Version is the API version of the Kubernetes + resource object's kind. + type: string + required: + - id + - v + type: object + type: array + required: + - entries + type: object + lastAppliedRevision: + description: The last successfully applied revision. Equals the Revision + of the applied Artifact from the referenced Source. + type: string + lastAttemptedRevision: + description: LastAttemptedRevision is the revision of the last reconciliation + attempt. + type: string + lastHandledReconcileAt: + description: LastHandledReconcileAt holds the value of the most recent + reconcile request value, so a change of the annotation value can + be detected. + type: string + observedGeneration: + description: ObservedGeneration is the last reconciled generation. + format: int64 + type: integer + type: object + type: object + served: true + storage: true + subresources: + status: {} + - additionalPrinterColumns: + - jsonPath: .status.conditions[?(@.type=="Ready")].status + name: Ready + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].message + name: Status + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + deprecated: true + deprecationWarning: v1beta1 Kustomization is deprecated, upgrade to v1 + name: v1beta1 + schema: + openAPIV3Schema: + description: Kustomization is the Schema for the kustomizations 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: KustomizationSpec defines the desired state of a kustomization. + properties: + decryption: + description: Decrypt Kubernetes secrets before applying them on the + cluster. + properties: + provider: + description: Provider is the name of the decryption engine. + enum: + - sops + type: string + secretRef: + description: The secret name containing the private OpenPGP keys + used for decryption. + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + required: + - provider + type: object + dependsOn: + description: DependsOn may contain a meta.NamespacedObjectReference + slice with references to Kustomization resources that must be ready + before this Kustomization can be reconciled. + items: + description: NamespacedObjectReference contains enough information + to locate the referenced Kubernetes resource object in any namespace. + properties: + name: + description: Name of the referent. + type: string + namespace: + description: Namespace of the referent, when not specified it + acts as LocalObjectReference. + type: string + required: + - name + type: object + type: array + force: + default: false + description: Force instructs the controller to recreate resources + when patching fails due to an immutable field change. + type: boolean + healthChecks: + description: A list of resources to be included in the health assessment. + items: + description: NamespacedObjectKindReference contains enough information + to locate the typed referenced Kubernetes resource object in any + namespace. + properties: + apiVersion: + description: API version of the referent, if not specified the + Kubernetes preferred version will be used. + type: string + kind: + description: Kind of the referent. + type: string + name: + description: Name of the referent. + type: string + namespace: + description: Namespace of the referent, when not specified it + acts as LocalObjectReference. + type: string + required: + - kind + - name + type: object + type: array + images: + description: Images is a list of (image name, new name, new tag or + digest) for changing image names, tags or digests. This can also + be achieved with a patch, but this operator is simpler to specify. + items: + description: Image contains an image name, a new name, a new tag + or digest, which will replace the original name and tag. + properties: + digest: + description: Digest is the value used to replace the original + image tag. If digest is present NewTag value is ignored. + type: string + name: + description: Name is a tag-less image name. + type: string + newName: + description: NewName is the value used to replace the original + name. + type: string + newTag: + description: NewTag is the value used to replace the original + tag. + type: string + required: + - name + type: object + type: array + interval: + description: The interval at which to reconcile the Kustomization. + type: string + kubeConfig: + description: The KubeConfig for reconciling the Kustomization on a + remote cluster. When specified, KubeConfig takes precedence over + ServiceAccountName. + properties: + secretRef: + description: SecretRef holds the name to a secret that contains + a 'value' key with the kubeconfig file as the value. It must + be in the same namespace as the Kustomization. It is recommended + that the kubeconfig is self-contained, and the secret is regularly + updated if credentials such as a cloud-access-token expire. + Cloud specific `cmd-path` auth helpers will not function without + adding binaries and credentials to the Pod that is responsible + for reconciling the Kustomization. + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + type: object + patches: + description: Strategic merge and JSON patches, defined as inline YAML + objects, capable of targeting objects based on kind, label and annotation + selectors. + items: + description: Patch contains an inline StrategicMerge or JSON6902 + patch, and the target the patch should be applied to. + properties: + patch: + description: Patch contains an inline StrategicMerge patch or + an inline JSON6902 patch with an array of operation objects. + type: string + target: + description: Target points to the resources that the patch document + should be applied to. + properties: + annotationSelector: + description: AnnotationSelector is a string that follows + the label selection expression https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#api + It matches with the resource annotations. + type: string + group: + description: Group is the API group to select resources + from. Together with Version and Kind it is capable of + unambiguously identifying and/or selecting resources. + https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md + type: string + kind: + description: Kind of the API Group to select resources from. + Together with Group and Version it is capable of unambiguously + identifying and/or selecting resources. https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md + type: string + labelSelector: + description: LabelSelector is a string that follows the + label selection expression https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#api + It matches with the resource labels. + type: string + name: + description: Name to match resources with. + type: string + namespace: + description: Namespace to select resources from. + type: string + version: + description: Version of the API Group to select resources + from. Together with Group and Kind it is capable of unambiguously + identifying and/or selecting resources. https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md + type: string + type: object + required: + - patch + type: object + type: array + patchesJson6902: + description: JSON 6902 patches, defined as inline YAML objects. + items: + description: JSON6902Patch contains a JSON6902 patch and the target + the patch should be applied to. + properties: + patch: + description: Patch contains the JSON6902 patch document with + an array of operation objects. + items: + description: JSON6902 is a JSON6902 operation object. https://datatracker.ietf.org/doc/html/rfc6902#section-4 + properties: + from: + description: From contains a JSON-pointer value that references + a location within the target document where the operation + is performed. The meaning of the value depends on the + value of Op, and is NOT taken into account by all operations. + type: string + op: + description: Op indicates the operation to perform. Its + value MUST be one of "add", "remove", "replace", "move", + "copy", or "test". https://datatracker.ietf.org/doc/html/rfc6902#section-4 + enum: + - test + - remove + - add + - replace + - move + - copy + type: string + path: + description: Path contains the JSON-pointer value that + references a location within the target document where + the operation is performed. The meaning of the value + depends on the value of Op. + type: string + value: + description: Value contains a valid JSON structure. The + meaning of the value depends on the value of Op, and + is NOT taken into account by all operations. + x-kubernetes-preserve-unknown-fields: true + required: + - op + - path + type: object + type: array + target: + description: Target points to the resources that the patch document + should be applied to. + properties: + annotationSelector: + description: AnnotationSelector is a string that follows + the label selection expression https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#api + It matches with the resource annotations. + type: string + group: + description: Group is the API group to select resources + from. Together with Version and Kind it is capable of + unambiguously identifying and/or selecting resources. + https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md + type: string + kind: + description: Kind of the API Group to select resources from. + Together with Group and Version it is capable of unambiguously + identifying and/or selecting resources. https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md + type: string + labelSelector: + description: LabelSelector is a string that follows the + label selection expression https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#api + It matches with the resource labels. + type: string + name: + description: Name to match resources with. + type: string + namespace: + description: Namespace to select resources from. + type: string + version: + description: Version of the API Group to select resources + from. Together with Group and Kind it is capable of unambiguously + identifying and/or selecting resources. https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md + type: string + type: object + required: + - patch + - target + type: object + type: array + patchesStrategicMerge: + description: Strategic merge patches, defined as inline YAML objects. + items: + x-kubernetes-preserve-unknown-fields: true + type: array + path: + description: Path to the directory containing the kustomization.yaml + file, or the set of plain YAMLs a kustomization.yaml should be generated + for. Defaults to 'None', which translates to the root path of the + SourceRef. + type: string + postBuild: + description: PostBuild describes which actions to perform on the YAML + manifest generated by building the kustomize overlay. + properties: + substitute: + additionalProperties: + type: string + description: Substitute holds a map of key/value pairs. The variables + defined in your YAML manifests that match any of the keys defined + in the map will be substituted with the set value. Includes + support for bash string replacement functions e.g. ${var:=default}, + ${var:position} and ${var/substring/replacement}. + type: object + substituteFrom: + description: SubstituteFrom holds references to ConfigMaps and + Secrets containing the variables and their values to be substituted + in the YAML manifests. The ConfigMap and the Secret data keys + represent the var names and they must match the vars declared + in the manifests for the substitution to happen. + items: + description: SubstituteReference contains a reference to a resource + containing the variables name and value. + properties: + kind: + description: Kind of the values referent, valid values are + ('Secret', 'ConfigMap'). + enum: + - Secret + - ConfigMap + type: string + name: + description: Name of the values referent. Should reside + in the same namespace as the referring resource. + maxLength: 253 + minLength: 1 + type: string + required: + - kind + - name + type: object + type: array + type: object + prune: + description: Prune enables garbage collection. + type: boolean + retryInterval: + description: The interval at which to retry a previously failed reconciliation. + When not specified, the controller uses the KustomizationSpec.Interval + value to retry failures. + type: string + serviceAccountName: + description: The name of the Kubernetes service account to impersonate + when reconciling this Kustomization. + type: string + sourceRef: + description: Reference of the source where the kustomization file + is. + properties: + apiVersion: + description: API version of the referent + type: string + kind: + description: Kind of the referent + enum: + - GitRepository + - Bucket + type: string + name: + description: Name of the referent + type: string + namespace: + description: Namespace of the referent, defaults to the Kustomization + namespace + type: string + required: + - kind + - name + type: object + suspend: + description: This flag tells the controller to suspend subsequent + kustomize executions, it does not apply to already started executions. + Defaults to false. + type: boolean + targetNamespace: + description: TargetNamespace sets or overrides the namespace in the + kustomization.yaml file. + maxLength: 63 + minLength: 1 + type: string + timeout: + description: Timeout for validation, apply and health checking operations. + Defaults to 'Interval' duration. + type: string + validation: + description: Validate the Kubernetes objects before applying them + on the cluster. The validation strategy can be 'client' (local dry-run), + 'server' (APIServer dry-run) or 'none'. When 'Force' is 'true', + validation will fallback to 'client' if set to 'server' because + server-side validation is not supported in this scenario. + enum: + - none + - client + - server + type: string + required: + - interval + - prune + - sourceRef + type: object + status: + default: + observedGeneration: -1 + description: KustomizationStatus defines the observed state of a kustomization. + properties: + conditions: + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + \n type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + 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 + lastAppliedRevision: + description: The last successfully applied revision. The revision + format for Git sources is /. + type: string + lastAttemptedRevision: + description: LastAttemptedRevision is the revision of the last reconciliation + attempt. + type: string + lastHandledReconcileAt: + description: LastHandledReconcileAt holds the value of the most recent + reconcile request value, so a change of the annotation value can + be detected. + type: string + observedGeneration: + description: ObservedGeneration is the last reconciled generation. + format: int64 + type: integer + snapshot: + description: The last successfully applied revision metadata. + properties: + checksum: + description: The manifests sha1 checksum. + type: string + entries: + description: A list of Kubernetes kinds grouped by namespace. + items: + description: Snapshot holds the metadata of namespaced Kubernetes + objects + properties: + kinds: + additionalProperties: + type: string + description: The list of Kubernetes kinds. + type: object + namespace: + description: The namespace of this entry. + type: string + required: + - kinds + type: object + type: array + required: + - checksum + - entries + type: object + type: object + type: object + served: true + storage: false + subresources: + status: {} + - additionalPrinterColumns: + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + - jsonPath: .status.conditions[?(@.type=="Ready")].status + name: Ready + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].message + name: Status + type: string + deprecated: true + deprecationWarning: v1beta2 Kustomization is deprecated, upgrade to v1 + name: v1beta2 + schema: + openAPIV3Schema: + description: Kustomization is the Schema for the kustomizations 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: KustomizationSpec defines the configuration to calculate + the desired state from a Source using Kustomize. + properties: + commonMetadata: + description: CommonMetadata specifies the common labels and annotations + that are applied to all resources. Any existing label or annotation + will be overridden if its key matches a common one. + properties: + annotations: + additionalProperties: + type: string + description: Annotations to be added to the object's metadata. + type: object + labels: + additionalProperties: + type: string + description: Labels to be added to the object's metadata. + type: object + type: object + components: + description: Components specifies relative paths to specifications + of other Components. + items: + type: string + type: array + decryption: + description: Decrypt Kubernetes secrets before applying them on the + cluster. + properties: + provider: + description: Provider is the name of the decryption engine. + enum: + - sops + type: string + secretRef: + description: The secret name containing the private OpenPGP keys + used for decryption. + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + required: + - provider + type: object + dependsOn: + description: DependsOn may contain a meta.NamespacedObjectReference + slice with references to Kustomization resources that must be ready + before this Kustomization can be reconciled. + items: + description: NamespacedObjectReference contains enough information + to locate the referenced Kubernetes resource object in any namespace. + properties: + name: + description: Name of the referent. + type: string + namespace: + description: Namespace of the referent, when not specified it + acts as LocalObjectReference. + type: string + required: + - name + type: object + type: array + force: + default: false + description: Force instructs the controller to recreate resources + when patching fails due to an immutable field change. + type: boolean + healthChecks: + description: A list of resources to be included in the health assessment. + items: + description: NamespacedObjectKindReference contains enough information + to locate the typed referenced Kubernetes resource object in any + namespace. + properties: + apiVersion: + description: API version of the referent, if not specified the + Kubernetes preferred version will be used. + type: string + kind: + description: Kind of the referent. + type: string + name: + description: Name of the referent. + type: string + namespace: + description: Namespace of the referent, when not specified it + acts as LocalObjectReference. + type: string + required: + - kind + - name + type: object + type: array + images: + description: Images is a list of (image name, new name, new tag or + digest) for changing image names, tags or digests. This can also + be achieved with a patch, but this operator is simpler to specify. + items: + description: Image contains an image name, a new name, a new tag + or digest, which will replace the original name and tag. + properties: + digest: + description: Digest is the value used to replace the original + image tag. If digest is present NewTag value is ignored. + type: string + name: + description: Name is a tag-less image name. + type: string + newName: + description: NewName is the value used to replace the original + name. + type: string + newTag: + description: NewTag is the value used to replace the original + tag. + type: string + required: + - name + type: object + type: array + interval: + description: The interval at which to reconcile the Kustomization. + pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ + type: string + kubeConfig: + description: The KubeConfig for reconciling the Kustomization on a + remote cluster. When used in combination with KustomizationSpec.ServiceAccountName, + forces the controller to act on behalf of that Service Account at + the target cluster. If the --default-service-account flag is set, + its value will be used as a controller level fallback for when KustomizationSpec.ServiceAccountName + is empty. + properties: + secretRef: + description: SecretRef holds the name of a secret that contains + a key with the kubeconfig file as the value. If no key is set, + the key will default to 'value'. It is recommended that the + kubeconfig is self-contained, and the secret is regularly updated + if credentials such as a cloud-access-token expire. Cloud specific + `cmd-path` auth helpers will not function without adding binaries + and credentials to the Pod that is responsible for reconciling + Kubernetes resources. + properties: + key: + description: Key in the Secret, when not specified an implementation-specific + default key is used. + type: string + name: + description: Name of the Secret. + type: string + required: + - name + type: object + required: + - secretRef + type: object + patches: + description: Strategic merge and JSON patches, defined as inline YAML + objects, capable of targeting objects based on kind, label and annotation + selectors. + items: + description: Patch contains an inline StrategicMerge or JSON6902 + patch, and the target the patch should be applied to. + properties: + patch: + description: Patch contains an inline StrategicMerge patch or + an inline JSON6902 patch with an array of operation objects. + type: string + target: + description: Target points to the resources that the patch document + should be applied to. + properties: + annotationSelector: + description: AnnotationSelector is a string that follows + the label selection expression https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#api + It matches with the resource annotations. + type: string + group: + description: Group is the API group to select resources + from. Together with Version and Kind it is capable of + unambiguously identifying and/or selecting resources. + https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md + type: string + kind: + description: Kind of the API Group to select resources from. + Together with Group and Version it is capable of unambiguously + identifying and/or selecting resources. https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md + type: string + labelSelector: + description: LabelSelector is a string that follows the + label selection expression https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#api + It matches with the resource labels. + type: string + name: + description: Name to match resources with. + type: string + namespace: + description: Namespace to select resources from. + type: string + version: + description: Version of the API Group to select resources + from. Together with Group and Kind it is capable of unambiguously + identifying and/or selecting resources. https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md + type: string + type: object + required: + - patch + type: object + type: array + patchesJson6902: + description: 'JSON 6902 patches, defined as inline YAML objects. Deprecated: + Use Patches instead.' + items: + description: JSON6902Patch contains a JSON6902 patch and the target + the patch should be applied to. + properties: + patch: + description: Patch contains the JSON6902 patch document with + an array of operation objects. + items: + description: JSON6902 is a JSON6902 operation object. https://datatracker.ietf.org/doc/html/rfc6902#section-4 + properties: + from: + description: From contains a JSON-pointer value that references + a location within the target document where the operation + is performed. The meaning of the value depends on the + value of Op, and is NOT taken into account by all operations. + type: string + op: + description: Op indicates the operation to perform. Its + value MUST be one of "add", "remove", "replace", "move", + "copy", or "test". https://datatracker.ietf.org/doc/html/rfc6902#section-4 + enum: + - test + - remove + - add + - replace + - move + - copy + type: string + path: + description: Path contains the JSON-pointer value that + references a location within the target document where + the operation is performed. The meaning of the value + depends on the value of Op. + type: string + value: + description: Value contains a valid JSON structure. The + meaning of the value depends on the value of Op, and + is NOT taken into account by all operations. + x-kubernetes-preserve-unknown-fields: true + required: + - op + - path + type: object + type: array + target: + description: Target points to the resources that the patch document + should be applied to. + properties: + annotationSelector: + description: AnnotationSelector is a string that follows + the label selection expression https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#api + It matches with the resource annotations. + type: string + group: + description: Group is the API group to select resources + from. Together with Version and Kind it is capable of + unambiguously identifying and/or selecting resources. + https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md + type: string + kind: + description: Kind of the API Group to select resources from. + Together with Group and Version it is capable of unambiguously + identifying and/or selecting resources. https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md + type: string + labelSelector: + description: LabelSelector is a string that follows the + label selection expression https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#api + It matches with the resource labels. + type: string + name: + description: Name to match resources with. + type: string + namespace: + description: Namespace to select resources from. + type: string + version: + description: Version of the API Group to select resources + from. Together with Group and Kind it is capable of unambiguously + identifying and/or selecting resources. https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md + type: string + type: object + required: + - patch + - target + type: object + type: array + patchesStrategicMerge: + description: 'Strategic merge patches, defined as inline YAML objects. + Deprecated: Use Patches instead.' + items: + x-kubernetes-preserve-unknown-fields: true + type: array + path: + description: Path to the directory containing the kustomization.yaml + file, or the set of plain YAMLs a kustomization.yaml should be generated + for. Defaults to 'None', which translates to the root path of the + SourceRef. + type: string + postBuild: + description: PostBuild describes which actions to perform on the YAML + manifest generated by building the kustomize overlay. + properties: + substitute: + additionalProperties: + type: string + description: Substitute holds a map of key/value pairs. The variables + defined in your YAML manifests that match any of the keys defined + in the map will be substituted with the set value. Includes + support for bash string replacement functions e.g. ${var:=default}, + ${var:position} and ${var/substring/replacement}. + type: object + substituteFrom: + description: SubstituteFrom holds references to ConfigMaps and + Secrets containing the variables and their values to be substituted + in the YAML manifests. The ConfigMap and the Secret data keys + represent the var names and they must match the vars declared + in the manifests for the substitution to happen. + items: + description: SubstituteReference contains a reference to a resource + containing the variables name and value. + properties: + kind: + description: Kind of the values referent, valid values are + ('Secret', 'ConfigMap'). + enum: + - Secret + - ConfigMap + type: string + name: + description: Name of the values referent. Should reside + in the same namespace as the referring resource. + maxLength: 253 + minLength: 1 + type: string + optional: + default: false + description: Optional indicates whether the referenced resource + must exist, or whether to tolerate its absence. If true + and the referenced resource is absent, proceed as if the + resource was present but empty, without any variables + defined. + type: boolean + required: + - kind + - name + type: object + type: array + type: object + prune: + description: Prune enables garbage collection. + type: boolean + retryInterval: + description: The interval at which to retry a previously failed reconciliation. + When not specified, the controller uses the KustomizationSpec.Interval + value to retry failures. + pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ + type: string + serviceAccountName: + description: The name of the Kubernetes service account to impersonate + when reconciling this Kustomization. + type: string + sourceRef: + description: Reference of the source where the kustomization file + is. + properties: + apiVersion: + description: API version of the referent. + type: string + kind: + description: Kind of the referent. + enum: + - OCIRepository + - GitRepository + - Bucket + type: string + name: + description: Name of the referent. + type: string + namespace: + description: Namespace of the referent, defaults to the namespace + of the Kubernetes resource object that contains the reference. + type: string + required: + - kind + - name + type: object + suspend: + description: This flag tells the controller to suspend subsequent + kustomize executions, it does not apply to already started executions. + Defaults to false. + type: boolean + targetNamespace: + description: TargetNamespace sets or overrides the namespace in the + kustomization.yaml file. + maxLength: 63 + minLength: 1 + type: string + timeout: + description: Timeout for validation, apply and health checking operations. + Defaults to 'Interval' duration. + pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ + type: string + validation: + description: 'Deprecated: Not used in v1beta2.' + enum: + - none + - client + - server + type: string + wait: + description: Wait instructs the controller to check the health of + all the reconciled resources. When enabled, the HealthChecks are + ignored. Defaults to false. + type: boolean + required: + - interval + - prune + - sourceRef + type: object + status: + default: + observedGeneration: -1 + description: KustomizationStatus defines the observed state of a kustomization. + properties: + conditions: + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + \n type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + 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 + inventory: + description: Inventory contains the list of Kubernetes resource object + references that have been successfully applied. + properties: + entries: + description: Entries of Kubernetes resource object references. + items: + description: ResourceRef contains the information necessary + to locate a resource within a cluster. + properties: + id: + description: ID is the string representation of the Kubernetes + resource object's metadata, in the format '___'. + type: string + v: + description: Version is the API version of the Kubernetes + resource object's kind. + type: string + required: + - id + - v + type: object + type: array + required: + - entries + type: object + lastAppliedRevision: + description: The last successfully applied revision. Equals the Revision + of the applied Artifact from the referenced Source. + type: string + lastAttemptedRevision: + description: LastAttemptedRevision is the revision of the last reconciliation + attempt. + type: string + lastHandledReconcileAt: + description: LastHandledReconcileAt holds the value of the most recent + reconcile request value, so a change of the annotation value can + be detected. + type: string + observedGeneration: + description: ObservedGeneration is the last reconciled generation. + format: int64 + type: integer + type: object + type: object + served: true + storage: false + subresources: + status: {} +{{- end }} diff --git a/packages/system/fluxcd/charts/flux2/templates/kustomize-controller.yaml b/packages/system/fluxcd/charts/flux2/templates/kustomize-controller.yaml new file mode 100644 index 00000000..fff3ed0d --- /dev/null +++ b/packages/system/fluxcd/charts/flux2/templates/kustomize-controller.yaml @@ -0,0 +1,158 @@ +{{- if and .Values.kustomizeController.create }} +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app.kubernetes.io/component: kustomize-controller + app.kubernetes.io/instance: {{ .Release.Namespace | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} + app.kubernetes.io/part-of: flux + helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} + control-plane: controller + {{- with .Values.kustomizeController.labels }} + {{- . | toYaml | nindent 4 }} + {{- end }} + name: kustomize-controller +spec: + {{- if kindIs "invalid" .Values.kustomizeController.replicas }} + replicas: 1 + {{- else }} + replicas: {{ .Values.kustomizeController.replicas }} + {{- end}} + selector: + matchLabels: + app: kustomize-controller + template: + metadata: + {{- with .Values.kustomizeController.annotations }} + annotations: {{ toYaml . | nindent 8 }} + {{- end }} + labels: + app: kustomize-controller +{{ with .Values.kustomizeController.labels }}{{ toYaml . | indent 8 }}{{ end }} + spec: + automountServiceAccountToken: {{ .Values.kustomizeController.serviceAccount.automount }} + {{- if .Values.kustomizeController.initContainers}} + initContainers: + {{- toYaml .Values.kustomizeController.initContainers | nindent 8}} + {{- end}} + containers: + - args: + {{- if .Values.multitenancy.enabled }} + - --no-cross-namespace-refs=true + - --default-service-account={{ .Values.multitenancy.defaultServiceAccount | default "default" }} + {{- end}} + {{- if .Values.notificationController.create }} + - --events-addr=http://notification-controller.$(RUNTIME_NAMESPACE).svc.{{ .Values.clusterDomain | default "cluster.local" }}. + {{- end}} + - --watch-all-namespaces={{ .Values.watchAllNamespaces }} + - --log-level={{ .Values.logLevel | default "info" }} + - --log-encoding=json + - --enable-leader-election + {{- range .Values.kustomizeController.container.additionalArgs }} + - {{ . }} + {{- end}} + env: + - name: RUNTIME_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + {{- with .Values.kustomizeController.extraEnv }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if or (.Values.kustomizeController.envFrom.map.name) (.Values.kustomizeController.envFrom.secret.name) }} + envFrom: + {{- if .Values.kustomizeController.envFrom.map.name }} + - configMapRef: + name: {{ .Values.kustomizeController.envFrom.map.name }} + {{- end }} + {{- if .Values.kustomizeController.envFrom.secret.name }} + - secretRef: + name: {{ .Values.kustomizeController.envFrom.secret.name }} + {{- end }} + {{- end }} + image: {{ template "template.image" .Values.kustomizeController }} + {{- if .Values.kustomizeController.imagePullPolicy }} + imagePullPolicy: {{ .Values.kustomizeController.imagePullPolicy }} + {{- else }} + imagePullPolicy: IfNotPresent + {{- end }} + livenessProbe: + httpGet: + path: /healthz + port: healthz + name: manager + ports: + - containerPort: 8080 + name: http-prom + - containerPort: 9440 + name: healthz + protocol: TCP + readinessProbe: + httpGet: + path: /readyz + port: healthz + {{- with .Values.kustomizeController.resources }} + resources: {{ toYaml . | nindent 10 }} + {{- end }} + {{- if .Values.kustomizeController.securityContext }} + securityContext: {{ toYaml .Values.kustomizeController.securityContext | nindent 10 }} + {{- else }} + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + readOnlyRootFilesystem: true + runAsNonRoot: true + seccompProfile: + type: RuntimeDefault + {{- end}} + volumeMounts: + - mountPath: /tmp + name: temp + {{- if .Values.kustomizeController.volumeMounts }} + {{- toYaml .Values.kustomizeController.volumeMounts | nindent 8 }} + {{- end}} + {{- if .Values.kustomizeController.priorityClassName }} + priorityClassName: {{ .Values.kustomizeController.priorityClassName | quote }} + {{- end }} + {{- range .Values.kustomizeController.extraSecretMounts }} + - name: {{ .name }} + mountPath: {{ .mountPath }} + subPath: {{ .subPath }} + readOnly: {{ .readOnly }} + {{- end }} + {{- if .Values.kustomizeController.podSecurityContext }} + securityContext: {{ toYaml .Values.kustomizeController.podSecurityContext | nindent 8 }} + {{- else }} + securityContext: + fsGroup: 1337 + {{- end}} + serviceAccountName: kustomize-controller + {{- if .Values.imagePullSecrets }} + imagePullSecrets: {{ toYaml .Values.imagePullSecrets | nindent 6 }} + {{- end }} + terminationGracePeriodSeconds: 60 + volumes: + - emptyDir: {} + name: temp + {{- if .Values.kustomizeController.volumes }} + {{- toYaml .Values.kustomizeController.volumes | nindent 6 }} + {{- end}} + {{- range .Values.kustomizeController.extraSecretMounts }} + - name: {{ .name }} + secret: + secretName: {{ .secretName }} + {{- end }} + {{- with .Values.kustomizeController.nodeSelector }} + nodeSelector: {{ toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.kustomizeController.affinity }} + affinity: {{ toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.kustomizeController.tolerations }} + tolerations: {{ toYaml . | nindent 8 }} + {{- end }} +{{- end }} diff --git a/packages/system/fluxcd/charts/flux2/templates/notification-controller-ingress.yaml b/packages/system/fluxcd/charts/flux2/templates/notification-controller-ingress.yaml new file mode 100644 index 00000000..942cd68c --- /dev/null +++ b/packages/system/fluxcd/charts/flux2/templates/notification-controller-ingress.yaml @@ -0,0 +1,49 @@ +{{- if and .Values.notificationController.create .Values.notificationController.webhookReceiver.ingress.create }} +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + labels: + app.kubernetes.io/instance: {{ .Release.Namespace | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} + app.kubernetes.io/part-of: flux + helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} + control-plane: controller + {{- with .Values.notificationController.webhookReceiver.ingress.labels }}{{ toYaml . | nindent 4 }}{{ end }} + {{- with .Values.notificationController.webhookReceiver.ingress.annotations }} + annotations: + {{- range $key, $value := . }} + {{ $key }}: {{ tpl $value $ | quote }} + {{- end }} + {{- end }} + name: webhook-receiver +spec: + {{- if .Values.notificationController.webhookReceiver.ingress.ingressClassName }} + ingressClassName: {{ .Values.notificationController.webhookReceiver.ingress.ingressClassName }} + {{- end -}} + {{- if .Values.notificationController.webhookReceiver.ingress.tls }} + tls: + {{- range .Values.notificationController.webhookReceiver.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} + {{- end }} + rules: + {{- range .Values.notificationController.webhookReceiver.ingress.hosts }} + - host: {{ .host | quote }} + http: + paths: + {{- range .paths }} + - path: {{ .path }} + pathType: {{ .pathType }} + backend: + service: + name: webhook-receiver + port: + number: 80 + {{- end }} + {{- end }} +{{- end }} diff --git a/packages/system/fluxcd/charts/flux2/templates/notification-controller-sa.yaml b/packages/system/fluxcd/charts/flux2/templates/notification-controller-sa.yaml new file mode 100644 index 00000000..b44e8dac --- /dev/null +++ b/packages/system/fluxcd/charts/flux2/templates/notification-controller-sa.yaml @@ -0,0 +1,18 @@ +{{- if and .Values.notificationController.create -}} +{{- if .Values.notificationController.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + labels: + app.kubernetes.io/component: notification-controller + app.kubernetes.io/instance: {{ .Release.Namespace | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} + app.kubernetes.io/part-of: flux + helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} + name: notification-controller + {{- with .Values.notificationController.serviceAccount.annotations }} + annotations: {{ toYaml . | nindent 4 }} + {{- end }} +{{- end -}} +{{- end -}} diff --git a/packages/system/fluxcd/charts/flux2/templates/notification-controller-service.yaml b/packages/system/fluxcd/charts/flux2/templates/notification-controller-service.yaml new file mode 100644 index 00000000..79b12dc6 --- /dev/null +++ b/packages/system/fluxcd/charts/flux2/templates/notification-controller-service.yaml @@ -0,0 +1,29 @@ +{{- if and .Values.notificationController.create }} +apiVersion: v1 +kind: Service +metadata: + labels: + app.kubernetes.io/instance: {{ .Release.Namespace | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} + app.kubernetes.io/part-of: flux + helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} + control-plane: controller + {{- with .Values.notificationController.service.labels }}{{ toYaml . | nindent 4 }}{{ end }} + name: notification-controller + {{- with .Values.notificationController.service.annotations }} + annotations: {{ toYaml . | nindent 4 }} + {{- end }} +spec: + ports: + - name: http + port: 80 + protocol: TCP + targetPort: http + {{- if .Values.notificationController.service.ports }} + {{- toYaml .Values.notificationController.service.ports | nindent 2 }} + {{- end}} + selector: + app: notification-controller + type: ClusterIP +{{- end }} diff --git a/packages/system/fluxcd/charts/flux2/templates/notification-controller-webhook-service.yaml b/packages/system/fluxcd/charts/flux2/templates/notification-controller-webhook-service.yaml new file mode 100644 index 00000000..3d71034a --- /dev/null +++ b/packages/system/fluxcd/charts/flux2/templates/notification-controller-webhook-service.yaml @@ -0,0 +1,26 @@ +{{- if and .Values.notificationController.create }} +apiVersion: v1 +kind: Service +metadata: + labels: + app.kubernetes.io/instance: {{ .Release.Namespace | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} + app.kubernetes.io/part-of: flux + helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} + control-plane: controller + {{- with .Values.notificationController.webhookReceiver.service.labels }}{{ toYaml . | nindent 4 }}{{ end }} + name: webhook-receiver + {{- with .Values.notificationController.webhookReceiver.service.annotations }} + annotations: {{ toYaml . | nindent 4 }} + {{- end }} +spec: + ports: + - name: http + port: 80 + protocol: TCP + targetPort: 9292 + selector: + app: notification-controller + type: ClusterIP +{{- end }} diff --git a/packages/system/fluxcd/charts/flux2/templates/notification-controller.crds.yaml b/packages/system/fluxcd/charts/flux2/templates/notification-controller.crds.yaml new file mode 100644 index 00000000..732422be --- /dev/null +++ b/packages/system/fluxcd/charts/flux2/templates/notification-controller.crds.yaml @@ -0,0 +1,1529 @@ +{{- if and .Values.installCRDs .Values.notificationController.create }} +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.12.0 + {{- with .Values.crds.annotations }} + {{- . | toYaml | nindent 4 }} + {{- end }} + labels: + app.kubernetes.io/instance: '{{ .Release.Namespace }}' + app.kubernetes.io/managed-by: '{{ .Release.Service }}' + app.kubernetes.io/part-of: flux + app.kubernetes.io/version: '{{ .Chart.AppVersion }}' + helm.sh/chart: '{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}' + name: alerts.notification.toolkit.fluxcd.io +spec: + group: notification.toolkit.fluxcd.io + names: + kind: Alert + listKind: AlertList + plural: alerts + singular: alert + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + - jsonPath: .status.conditions[?(@.type=="Ready")].status + name: Ready + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].message + name: Status + type: string + name: v1beta1 + schema: + openAPIV3Schema: + description: Alert is the Schema for the alerts 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: AlertSpec defines an alerting rule for events involving a + list of objects + properties: + eventSeverity: + default: info + description: Filter events based on severity, defaults to ('info'). + If set to 'info' no events will be filtered. + enum: + - info + - error + type: string + eventSources: + description: Filter events based on the involved objects. + items: + description: CrossNamespaceObjectReference contains enough information + to let you locate the typed referenced object at cluster level + properties: + apiVersion: + description: API version of the referent + type: string + kind: + description: Kind of the referent + enum: + - Bucket + - GitRepository + - Kustomization + - HelmRelease + - HelmChart + - HelmRepository + - ImageRepository + - ImagePolicy + - ImageUpdateAutomation + - OCIRepository + type: string + 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 + name: + description: Name of the referent + maxLength: 53 + minLength: 1 + type: string + namespace: + description: Namespace of the referent + maxLength: 53 + minLength: 1 + type: string + required: + - name + type: object + type: array + exclusionList: + description: A list of Golang regular expressions to be used for excluding + messages. + items: + type: string + type: array + providerRef: + description: Send events using this provider. + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + summary: + description: Short description of the impact and affected cluster. + type: string + suspend: + description: This flag tells the controller to suspend subsequent + events dispatching. Defaults to false. + type: boolean + required: + - eventSources + - providerRef + type: object + status: + default: + observedGeneration: -1 + description: AlertStatus defines the observed state of Alert + properties: + conditions: + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + \n type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + 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 + observedGeneration: + description: ObservedGeneration is the last observed generation. + format: int64 + type: integer + type: object + type: object + served: true + storage: false + subresources: + status: {} + - additionalPrinterColumns: + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + - jsonPath: .status.conditions[?(@.type=="Ready")].status + name: Ready + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].message + name: Status + type: string + name: v1beta2 + schema: + openAPIV3Schema: + description: Alert is the Schema for the alerts 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: AlertSpec defines an alerting rule for events involving a + list of objects. + properties: + eventMetadata: + additionalProperties: + type: string + description: EventMetadata is an optional field for adding metadata + to events dispatched by the controller. This can be used for enhancing + the context of the event. If a field would override one already + present on the original event as generated by the emitter, then + the override doesn't happen, i.e. the original value is preserved, + and an info log is printed. + type: object + eventSeverity: + default: info + description: EventSeverity specifies how to filter events based on + severity. If set to 'info' no events will be filtered. + enum: + - info + - error + type: string + eventSources: + description: EventSources specifies how to filter events based on + the involved object kind, name and namespace. + items: + description: CrossNamespaceObjectReference contains enough information + to let you locate the typed referenced object at cluster level + properties: + apiVersion: + description: API version of the referent + type: string + kind: + description: Kind of the referent + enum: + - Bucket + - GitRepository + - Kustomization + - HelmRelease + - HelmChart + - HelmRepository + - ImageRepository + - ImagePolicy + - ImageUpdateAutomation + - OCIRepository + type: string + 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. MatchLabels requires the name to be set to `*`. + type: object + name: + description: Name of the referent If multiple resources are + targeted `*` may be set. + maxLength: 53 + minLength: 1 + type: string + namespace: + description: Namespace of the referent + maxLength: 53 + minLength: 1 + type: string + required: + - kind + - name + type: object + type: array + exclusionList: + description: ExclusionList specifies a list of Golang regular expressions + to be used for excluding messages. + items: + type: string + type: array + inclusionList: + description: InclusionList specifies a list of Golang regular expressions + to be used for including messages. + items: + type: string + type: array + providerRef: + description: ProviderRef specifies which Provider this Alert should + use. + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + summary: + description: Summary holds a short description of the impact and affected + cluster. + maxLength: 255 + type: string + suspend: + description: Suspend tells the controller to suspend subsequent events + handling for this Alert. + type: boolean + required: + - eventSources + - providerRef + type: object + status: + default: + observedGeneration: -1 + description: AlertStatus defines the observed state of the Alert. + properties: + conditions: + description: Conditions holds the conditions for the Alert. + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + \n type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + 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 + lastHandledReconcileAt: + description: LastHandledReconcileAt holds the value of the most recent + reconcile request value, so a change of the annotation value can + be detected. + type: string + observedGeneration: + description: ObservedGeneration is the last observed generation. + format: int64 + type: integer + 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.12.0 + {{- with .Values.crds.annotations }} + {{- . | toYaml | nindent 4 }} + {{- end }} + labels: + app.kubernetes.io/instance: '{{ .Release.Namespace }}' + app.kubernetes.io/managed-by: '{{ .Release.Service }}' + app.kubernetes.io/part-of: flux + app.kubernetes.io/version: '{{ .Chart.AppVersion }}' + helm.sh/chart: '{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}' + name: providers.notification.toolkit.fluxcd.io +spec: + group: notification.toolkit.fluxcd.io + names: + kind: Provider + listKind: ProviderList + plural: providers + singular: provider + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + - jsonPath: .status.conditions[?(@.type=="Ready")].status + name: Ready + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].message + name: Status + type: string + name: v1beta1 + schema: + openAPIV3Schema: + description: Provider is the Schema for the providers 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: ProviderSpec defines the desired state of Provider + properties: + address: + description: HTTP/S webhook address of this provider + pattern: ^(http|https):// + type: string + certSecretRef: + description: CertSecretRef can be given the name of a secret containing + a PEM-encoded CA certificate (`caFile`) + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + channel: + description: Alert channel for this provider + type: string + proxy: + description: HTTP/S address of the proxy + pattern: ^(http|https):// + type: string + secretRef: + description: Secret reference containing the provider webhook URL + using "address" as data key + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + suspend: + description: This flag tells the controller to suspend subsequent + events handling. Defaults to false. + type: boolean + timeout: + description: Timeout for sending alerts to the provider. + pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m))+$ + type: string + type: + description: Type of provider + enum: + - slack + - discord + - msteams + - rocket + - generic + - generic-hmac + - github + - gitlab + - bitbucket + - azuredevops + - googlechat + - webex + - sentry + - azureeventhub + - telegram + - lark + - matrix + - opsgenie + - alertmanager + - grafana + - githubdispatch + type: string + username: + description: Bot username for this provider + type: string + required: + - type + type: object + status: + default: + observedGeneration: -1 + description: ProviderStatus defines the observed state of Provider + properties: + conditions: + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + \n type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + 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 + observedGeneration: + description: ObservedGeneration is the last reconciled generation. + format: int64 + type: integer + type: object + type: object + served: true + storage: false + subresources: + status: {} + - additionalPrinterColumns: + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + - jsonPath: .status.conditions[?(@.type=="Ready")].status + name: Ready + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].message + name: Status + type: string + name: v1beta2 + schema: + openAPIV3Schema: + description: Provider is the Schema for the providers 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: ProviderSpec defines the desired state of the Provider. + properties: + address: + description: Address specifies the endpoint, in a generic sense, to + where alerts are sent. What kind of endpoint depends on the specific + Provider type being used. For the generic Provider, for example, + this is an HTTP/S address. For other Provider types this could be + a project ID or a namespace. + maxLength: 2048 + type: string + certSecretRef: + description: "CertSecretRef specifies the Secret containing a PEM-encoded + CA certificate (in the `ca.crt` key). \n Note: Support for the `caFile` + key has been deprecated." + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + channel: + description: Channel specifies the destination channel where events + should be posted. + maxLength: 2048 + type: string + interval: + description: Interval at which to reconcile the Provider with its + Secret references. + pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ + type: string + proxy: + description: Proxy the HTTP/S address of the proxy server. + maxLength: 2048 + pattern: ^(http|https)://.*$ + type: string + secretRef: + description: SecretRef specifies the Secret containing the authentication + credentials for this Provider. + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + suspend: + description: Suspend tells the controller to suspend subsequent events + handling for this Provider. + type: boolean + timeout: + description: Timeout for sending alerts to the Provider. + pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m))+$ + type: string + type: + description: Type specifies which Provider implementation to use. + enum: + - slack + - discord + - msteams + - rocket + - generic + - generic-hmac + - github + - gitlab + - gitea + - bitbucket + - azuredevops + - googlechat + - googlepubsub + - webex + - sentry + - azureeventhub + - telegram + - lark + - matrix + - opsgenie + - alertmanager + - grafana + - githubdispatch + - pagerduty + - datadog + type: string + username: + description: Username specifies the name under which events are posted. + maxLength: 2048 + type: string + required: + - type + type: object + status: + default: + observedGeneration: -1 + description: ProviderStatus defines the observed state of the Provider. + properties: + conditions: + description: Conditions holds the conditions for the Provider. + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + \n type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + 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 + lastHandledReconcileAt: + description: LastHandledReconcileAt holds the value of the most recent + reconcile request value, so a change of the annotation value can + be detected. + type: string + observedGeneration: + description: ObservedGeneration is the last reconciled generation. + format: int64 + type: integer + 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.12.0 + {{- with .Values.crds.annotations }} + {{- . | toYaml | nindent 4 }} + {{- end }} + labels: + app.kubernetes.io/instance: '{{ .Release.Namespace }}' + app.kubernetes.io/managed-by: '{{ .Release.Service }}' + app.kubernetes.io/part-of: flux + app.kubernetes.io/version: '{{ .Chart.AppVersion }}' + helm.sh/chart: '{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}' + name: receivers.notification.toolkit.fluxcd.io +spec: + group: notification.toolkit.fluxcd.io + names: + kind: Receiver + listKind: ReceiverList + plural: receivers + singular: receiver + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + - jsonPath: .status.conditions[?(@.type=="Ready")].status + name: Ready + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].message + name: Status + type: string + name: v1 + schema: + openAPIV3Schema: + description: Receiver is the Schema for the receivers 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: ReceiverSpec defines the desired state of the Receiver. + properties: + events: + description: Events specifies the list of event types to handle, e.g. + 'push' for GitHub or 'Push Hook' for GitLab. + items: + type: string + type: array + interval: + default: 10m + description: Interval at which to reconcile the Receiver with its + Secret references. + pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ + type: string + resources: + description: A list of resources to be notified about changes. + items: + description: CrossNamespaceObjectReference contains enough information + to let you locate the typed referenced object at cluster level + properties: + apiVersion: + description: API version of the referent + type: string + kind: + description: Kind of the referent + enum: + - Bucket + - GitRepository + - Kustomization + - HelmRelease + - HelmChart + - HelmRepository + - ImageRepository + - ImagePolicy + - ImageUpdateAutomation + - OCIRepository + type: string + 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. MatchLabels requires the name to be set to `*`. + type: object + name: + description: Name of the referent If multiple resources are + targeted `*` may be set. + maxLength: 53 + minLength: 1 + type: string + namespace: + description: Namespace of the referent + maxLength: 53 + minLength: 1 + type: string + required: + - kind + - name + type: object + type: array + secretRef: + description: SecretRef specifies the Secret containing the token used + to validate the payload authenticity. + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + suspend: + description: Suspend tells the controller to suspend subsequent events + handling for this receiver. + type: boolean + type: + description: Type of webhook sender, used to determine the validation + procedure and payload deserialization. + enum: + - generic + - generic-hmac + - github + - gitlab + - bitbucket + - harbor + - dockerhub + - quay + - gcr + - nexus + - acr + type: string + required: + - resources + - secretRef + - type + type: object + status: + default: + observedGeneration: -1 + description: ReceiverStatus defines the observed state of the Receiver. + properties: + conditions: + description: Conditions holds the conditions for the Receiver. + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + \n type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + 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 + lastHandledReconcileAt: + description: LastHandledReconcileAt holds the value of the most recent + reconcile request value, so a change of the annotation value can + be detected. + type: string + observedGeneration: + description: ObservedGeneration is the last observed generation of + the Receiver object. + format: int64 + type: integer + webhookPath: + description: WebhookPath is the generated incoming webhook address + in the format of '/hook/sha256sum(token+name+namespace)'. + type: string + type: object + type: object + served: true + storage: true + subresources: + status: {} + - additionalPrinterColumns: + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + - jsonPath: .status.conditions[?(@.type=="Ready")].status + name: Ready + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].message + name: Status + type: string + deprecated: true + deprecationWarning: v1beta1 Receiver is deprecated, upgrade to v1 + name: v1beta1 + schema: + openAPIV3Schema: + description: Receiver is the Schema for the receivers 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: ReceiverSpec defines the desired state of Receiver + properties: + events: + description: A list of events to handle, e.g. 'push' for GitHub or + 'Push Hook' for GitLab. + items: + type: string + type: array + resources: + description: A list of resources to be notified about changes. + items: + description: CrossNamespaceObjectReference contains enough information + to let you locate the typed referenced object at cluster level + properties: + apiVersion: + description: API version of the referent + type: string + kind: + description: Kind of the referent + enum: + - Bucket + - GitRepository + - Kustomization + - HelmRelease + - HelmChart + - HelmRepository + - ImageRepository + - ImagePolicy + - ImageUpdateAutomation + - OCIRepository + type: string + 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 + name: + description: Name of the referent + maxLength: 53 + minLength: 1 + type: string + namespace: + description: Namespace of the referent + maxLength: 53 + minLength: 1 + type: string + required: + - name + type: object + type: array + secretRef: + description: Secret reference containing the token used to validate + the payload authenticity + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + suspend: + description: This flag tells the controller to suspend subsequent + events handling. Defaults to false. + type: boolean + type: + description: Type of webhook sender, used to determine the validation + procedure and payload deserialization. + enum: + - generic + - generic-hmac + - github + - gitlab + - bitbucket + - harbor + - dockerhub + - quay + - gcr + - nexus + - acr + type: string + required: + - resources + - type + type: object + status: + default: + observedGeneration: -1 + description: ReceiverStatus defines the observed state of Receiver + properties: + conditions: + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + \n type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + 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 + observedGeneration: + description: ObservedGeneration is the last observed generation. + format: int64 + type: integer + url: + description: Generated webhook URL in the format of '/hook/sha256sum(token+name+namespace)'. + type: string + type: object + type: object + served: true + storage: false + subresources: + status: {} + - additionalPrinterColumns: + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + - jsonPath: .status.conditions[?(@.type=="Ready")].status + name: Ready + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].message + name: Status + type: string + deprecated: true + deprecationWarning: v1beta2 Receiver is deprecated, upgrade to v1 + name: v1beta2 + schema: + openAPIV3Schema: + description: Receiver is the Schema for the receivers 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: ReceiverSpec defines the desired state of the Receiver. + properties: + events: + description: Events specifies the list of event types to handle, e.g. + 'push' for GitHub or 'Push Hook' for GitLab. + items: + type: string + type: array + interval: + description: Interval at which to reconcile the Receiver with its + Secret references. + pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ + type: string + resources: + description: A list of resources to be notified about changes. + items: + description: CrossNamespaceObjectReference contains enough information + to let you locate the typed referenced object at cluster level + properties: + apiVersion: + description: API version of the referent + type: string + kind: + description: Kind of the referent + enum: + - Bucket + - GitRepository + - Kustomization + - HelmRelease + - HelmChart + - HelmRepository + - ImageRepository + - ImagePolicy + - ImageUpdateAutomation + - OCIRepository + type: string + 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. MatchLabels requires the name to be set to `*`. + type: object + name: + description: Name of the referent If multiple resources are + targeted `*` may be set. + maxLength: 53 + minLength: 1 + type: string + namespace: + description: Namespace of the referent + maxLength: 53 + minLength: 1 + type: string + required: + - kind + - name + type: object + type: array + secretRef: + description: SecretRef specifies the Secret containing the token used + to validate the payload authenticity. + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + suspend: + description: Suspend tells the controller to suspend subsequent events + handling for this receiver. + type: boolean + type: + description: Type of webhook sender, used to determine the validation + procedure and payload deserialization. + enum: + - generic + - generic-hmac + - github + - gitlab + - bitbucket + - harbor + - dockerhub + - quay + - gcr + - nexus + - acr + type: string + required: + - resources + - type + type: object + status: + default: + observedGeneration: -1 + description: ReceiverStatus defines the observed state of the Receiver. + properties: + conditions: + description: Conditions holds the conditions for the Receiver. + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + \n type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + 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 + lastHandledReconcileAt: + description: LastHandledReconcileAt holds the value of the most recent + reconcile request value, so a change of the annotation value can + be detected. + type: string + observedGeneration: + description: ObservedGeneration is the last observed generation of + the Receiver object. + format: int64 + type: integer + url: + description: 'URL is the generated incoming webhook address in the + format of ''/hook/sha256sum(token+name+namespace)''. Deprecated: + Replaced by WebhookPath.' + type: string + webhookPath: + description: WebhookPath is the generated incoming webhook address + in the format of '/hook/sha256sum(token+name+namespace)'. + type: string + type: object + type: object + served: true + storage: false + subresources: + status: {} +{{- end }} diff --git a/packages/system/fluxcd/charts/flux2/templates/notification-controller.yaml b/packages/system/fluxcd/charts/flux2/templates/notification-controller.yaml new file mode 100644 index 00000000..d4d6772d --- /dev/null +++ b/packages/system/fluxcd/charts/flux2/templates/notification-controller.yaml @@ -0,0 +1,136 @@ +{{- if and .Values.notificationController.create }} +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app.kubernetes.io/component: notification-controller + app.kubernetes.io/instance: {{ .Release.Namespace | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} + app.kubernetes.io/part-of: flux + helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} + control-plane: controller + {{- with .Values.notificationController.labels }} + {{- . | toYaml | nindent 4 }} + {{- end }} + name: notification-controller +spec: + {{- if kindIs "invalid" .Values.notificationController.replicas }} + replicas: 1 + {{- else }} + replicas: {{ .Values.notificationController.replicas }} + {{- end}} + selector: + matchLabels: + app: notification-controller + template: + metadata: + {{- with .Values.notificationController.annotations }} + annotations: {{ toYaml . | nindent 8 }} + {{- end }} + labels: + app: notification-controller +{{ with .Values.notificationController.labels }}{{ toYaml . | indent 8 }}{{ end }} + spec: + automountServiceAccountToken: {{ .Values.notificationController.serviceAccount.automount }} + {{- if .Values.notificationController.initContainers}} + initContainers: + {{- toYaml .Values.notificationController.initContainers | nindent 8}} + {{- end}} + containers: + - args: + {{- if .Values.multitenancy.enabled }} + - --no-cross-namespace-refs=true + {{- end}} + - --watch-all-namespaces={{ .Values.watchAllNamespaces }} + - --log-level={{ .Values.logLevel | default "info" }} + - --log-encoding=json + - --enable-leader-election + {{- range .Values.notificationController.container.additionalArgs }} + - {{ . }} + {{- end}} + env: + - name: RUNTIME_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + {{- with .Values.notificationController.extraEnv }} + {{- toYaml . | nindent 8 }} + {{- end }} + image: {{ template "template.image" .Values.notificationController }} + {{- if .Values.notificationController.imagePullPolicy }} + imagePullPolicy: {{ .Values.notificationController.imagePullPolicy }} + {{- else }} + imagePullPolicy: IfNotPresent + {{- end }} + livenessProbe: + httpGet: + path: /healthz + port: healthz + name: manager + ports: + - containerPort: 9090 + name: http + protocol: TCP + - containerPort: 9292 + name: http-webhook + protocol: TCP + - containerPort: 8080 + name: http-prom + protocol: TCP + - containerPort: 9440 + name: healthz + protocol: TCP + readinessProbe: + httpGet: + path: /readyz + port: healthz + {{- with .Values.notificationController.resources }} + resources: {{ toYaml . | nindent 10 }} + {{- end }} + {{- if .Values.notificationController.securityContext }} + securityContext: {{ toYaml .Values.notificationController.securityContext | nindent 10 }} + {{- else }} + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + readOnlyRootFilesystem: true + runAsNonRoot: true + seccompProfile: + type: RuntimeDefault + {{- end}} + volumeMounts: + - mountPath: /tmp + name: temp + {{- if .Values.notificationController.volumeMounts }} + {{- toYaml .Values.notificationController.volumeMounts | nindent 8 }} + {{- end}} + {{- if .Values.notificationController.priorityClassName }} + priorityClassName: {{ .Values.notificationController.priorityClassName | quote }} + {{- end }} + {{- if .Values.notificationController.podSecurityContext }} + securityContext: {{ toYaml .Values.notificationController.podSecurityContext | nindent 8 }} + {{- end }} + serviceAccountName: notification-controller + {{- if .Values.imagePullSecrets }} + imagePullSecrets: {{ toYaml .Values.imagePullSecrets | nindent 6 }} + {{- end }} + terminationGracePeriodSeconds: 10 + volumes: + - emptyDir: {} + name: temp + {{- if .Values.notificationController.volumes }} + {{- toYaml .Values.notificationController.volumes | nindent 6 }} + {{- end}} + {{- with .Values.notificationController.nodeSelector }} + nodeSelector: {{ toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.notificationController.affinity }} + affinity: {{ toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.notificationController.tolerations }} + tolerations: {{ toYaml . | nindent 8 }} + {{- end }} +{{- end }} diff --git a/packages/system/fluxcd/charts/flux2/templates/podmonitor.yaml b/packages/system/fluxcd/charts/flux2/templates/podmonitor.yaml new file mode 100644 index 00000000..3db75272 --- /dev/null +++ b/packages/system/fluxcd/charts/flux2/templates/podmonitor.yaml @@ -0,0 +1,32 @@ +{{ if .Values.prometheus.podMonitor.create }} +apiVersion: monitoring.coreos.com/v1 +kind: PodMonitor +metadata: + name: {{ .Release.Name }} + labels: + app.kubernetes.io/instance: {{ .Release.Namespace | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} + app.kubernetes.io/part-of: flux + helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} + {{- range $key, $value := .Values.prometheus.podMonitor.additionalLabels }} + {{ $key }}: {{ $value | quote }} + {{- end }} +spec: + namespaceSelector: + matchNames: + - {{ .Release.Namespace }} + selector: + matchExpressions: + - key: app + operator: In + values: + - helm-controller + - source-controller + - kustomize-controller + - notification-controller + - image-automation-controller + - image-reflector-controller + podMetricsEndpoints: +{{ toYaml .Values.prometheus.podMonitor.podMetricsEndpoints | indent 4 }} +{{- end }} diff --git a/packages/system/fluxcd/charts/flux2/templates/policies.yaml b/packages/system/fluxcd/charts/flux2/templates/policies.yaml new file mode 100644 index 00000000..731e2980 --- /dev/null +++ b/packages/system/fluxcd/charts/flux2/templates/policies.yaml @@ -0,0 +1,63 @@ +{{- if and .Values.policies.create}} +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + labels: + app.kubernetes.io/instance: {{ .Release.Namespace | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} + app.kubernetes.io/part-of: flux + helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} + name: allow-egress +spec: + egress: + - {} + ingress: + - from: + - podSelector: {} + podSelector: {} + policyTypes: + - Ingress + - Egress +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + labels: + app.kubernetes.io/instance: {{ .Release.Namespace | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} + app.kubernetes.io/part-of: flux + helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} + name: allow-scraping +spec: + ingress: + - from: + - namespaceSelector: {} + ports: + - port: 8080 + protocol: TCP + podSelector: {} + policyTypes: + - Ingress +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + labels: + app.kubernetes.io/instance: {{ .Release.Namespace | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} + app.kubernetes.io/part-of: flux + helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} + name: allow-webhooks +spec: + ingress: + - from: + - namespaceSelector: {} + podSelector: + matchLabels: + app: notification-controller + policyTypes: + - Ingress +{{- end }} diff --git a/packages/system/fluxcd/charts/flux2/templates/pre-install-job-serviceaccount.yaml b/packages/system/fluxcd/charts/flux2/templates/pre-install-job-serviceaccount.yaml new file mode 100644 index 00000000..f6348698 --- /dev/null +++ b/packages/system/fluxcd/charts/flux2/templates/pre-install-job-serviceaccount.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + labels: + app.kubernetes.io/instance: {{ .Release.Namespace | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} + app.kubernetes.io/part-of: flux + helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} + name: "{{ .Release.Name }}-flux-check" + annotations: + "helm.sh/hook": pre-install + "helm.sh/hook-weight": "-10" + "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded diff --git a/packages/system/fluxcd/charts/flux2/templates/pre-install-job.yaml b/packages/system/fluxcd/charts/flux2/templates/pre-install-job.yaml new file mode 100644 index 00000000..2c2541f5 --- /dev/null +++ b/packages/system/fluxcd/charts/flux2/templates/pre-install-job.yaml @@ -0,0 +1,72 @@ +apiVersion: batch/v1 +kind: Job +metadata: + name: "{{ .Release.Name }}-flux-check" + labels: + app.kubernetes.io/instance: {{ .Release.Namespace | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} + app.kubernetes.io/part-of: flux + helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} + annotations: + "helm.sh/hook": pre-install + "helm.sh/hook-weight": "-5" + "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded +spec: + backoffLimit: 1 + template: + metadata: + name: "{{ .Release.Name }}" + {{- with .Values.cli.annotations }} + annotations: {{ toYaml . | nindent 8 }} + {{- end }} + labels: + app.kubernetes.io/instance: {{ .Release.Namespace | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} + app.kubernetes.io/part-of: flux + helm.sh/chart: "{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}" + spec: + restartPolicy: Never + serviceAccountName: "{{ .Release.Name }}-flux-check" + automountServiceAccountToken: {{ .Values.cli.serviceAccount.automount }} + containers: + - name: flux-cli + image: {{ template "template.image" .Values.cli }} + command: ["/usr/local/bin/flux", "check", "--pre", "--namespace", {{ .Release.Namespace }}] + {{- with .Values.cli.resources }} + resources: {{ toYaml . | nindent 10 }} + {{- end }} + {{- if .Values.cli.securityContext }} + securityContext: {{ toYaml .Values.cli.securityContext | nindent 10 }} + {{- else }} + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + readOnlyRootFilesystem: true + runAsNonRoot: true + seccompProfile: + type: RuntimeDefault + {{- end}} + {{- if .Values.cli.volumeMounts }} + volumeMounts: + {{- toYaml .Values.cli.volumeMounts | nindent 10 }} + {{- end}} + {{- if .Values.imagePullSecrets }} + imagePullSecrets: {{ toYaml .Values.imagePullSecrets | nindent 6 }} + {{- end }} + {{- with .Values.cli.nodeSelector }} + nodeSelector: {{ toYaml . | nindent 8 }} + {{- end }} + {{- if .Values.cli.volumes }} + volumes: + {{- toYaml .Values.cli.volumes | nindent 8 }} + {{- end}} + {{- with .Values.cli.affinity }} + affinity: {{ toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.cli.tolerations }} + tolerations: {{ toYaml . | nindent 8 }} + {{- end }} diff --git a/packages/system/fluxcd/charts/flux2/templates/source-controller-service.yaml b/packages/system/fluxcd/charts/flux2/templates/source-controller-service.yaml new file mode 100644 index 00000000..25caae35 --- /dev/null +++ b/packages/system/fluxcd/charts/flux2/templates/source-controller-service.yaml @@ -0,0 +1,29 @@ +{{- if .Values.sourceController.create }} +apiVersion: v1 +kind: Service +metadata: + labels: + app.kubernetes.io/instance: {{ .Release.Namespace | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} + app.kubernetes.io/part-of: flux + helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} + control-plane: controller + {{- with .Values.sourceController.service.labels }}{{ toYaml . | nindent 4 }}{{ end }} + name: source-controller + {{- with .Values.sourceController.service.annotations }} + annotations: {{ toYaml . | nindent 4 }} + {{- end }} +spec: + ports: + - name: http + port: 80 + protocol: TCP + targetPort: http + {{- if .Values.sourceController.service.ports }} + {{- toYaml .Values.sourceController.service.ports | nindent 2 }} + {{- end}} + selector: + app: source-controller + type: ClusterIP +{{- end }} diff --git a/packages/system/fluxcd/charts/flux2/templates/source-controller-serviceaccount.yaml b/packages/system/fluxcd/charts/flux2/templates/source-controller-serviceaccount.yaml new file mode 100644 index 00000000..286a625f --- /dev/null +++ b/packages/system/fluxcd/charts/flux2/templates/source-controller-serviceaccount.yaml @@ -0,0 +1,18 @@ +{{- if .Values.sourceController.create -}} +{{- if .Values.sourceController.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + labels: + app.kubernetes.io/component: source-controller + app.kubernetes.io/instance: {{ .Release.Namespace | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} + app.kubernetes.io/part-of: flux + helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} + name: source-controller + {{- with .Values.sourceController.serviceAccount.annotations }} + annotations: {{ toYaml . | nindent 4 }} + {{- end }} +{{- end -}} +{{- end -}} diff --git a/packages/system/fluxcd/charts/flux2/templates/source-controller.crds.yaml b/packages/system/fluxcd/charts/flux2/templates/source-controller.crds.yaml new file mode 100644 index 00000000..40f0e7c5 --- /dev/null +++ b/packages/system/fluxcd/charts/flux2/templates/source-controller.crds.yaml @@ -0,0 +1,3230 @@ +{{- if and .Values.installCRDs .Values.sourceController.create }} +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.12.0 + {{- with .Values.crds.annotations }} + {{- . | toYaml | nindent 4 }} + {{- end }} + labels: + app.kubernetes.io/component: source-controller + app.kubernetes.io/instance: '{{ .Release.Namespace }}' + app.kubernetes.io/managed-by: '{{ .Release.Service }}' + app.kubernetes.io/part-of: flux + app.kubernetes.io/version: '{{ .Chart.AppVersion }}' + helm.sh/chart: '{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}' + name: buckets.source.toolkit.fluxcd.io +spec: + group: source.toolkit.fluxcd.io + names: + kind: Bucket + listKind: BucketList + plural: buckets + singular: bucket + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .spec.endpoint + name: Endpoint + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].status + name: Ready + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].message + name: Status + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1beta1 + schema: + openAPIV3Schema: + description: Bucket is the Schema for the buckets 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: BucketSpec defines the desired state of an S3 compatible + bucket + properties: + accessFrom: + description: AccessFrom defines an Access Control List for allowing + cross-namespace references to this object. + properties: + namespaceSelectors: + description: NamespaceSelectors is the list of namespace selectors + to which this ACL applies. Items in this list are evaluated + using a logical OR operation. + items: + description: NamespaceSelector selects the namespaces to which + this ACL applies. An empty map of MatchLabels matches all + namespaces in a cluster. + properties: + 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 + type: array + required: + - namespaceSelectors + type: object + bucketName: + description: The bucket name. + type: string + endpoint: + description: The bucket endpoint address. + type: string + ignore: + description: Ignore overrides the set of excluded patterns in the + .sourceignore format (which is the same as .gitignore). If not provided, + a default will be used, consult the documentation for your version + to find out what those are. + type: string + insecure: + description: Insecure allows connecting to a non-TLS S3 HTTP endpoint. + type: boolean + interval: + description: The interval at which to check for bucket updates. + type: string + provider: + default: generic + description: The S3 compatible storage provider name, default ('generic'). + enum: + - generic + - aws + - gcp + type: string + region: + description: The bucket region. + type: string + secretRef: + description: The name of the secret containing authentication credentials + for the Bucket. + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + suspend: + description: This flag tells the controller to suspend the reconciliation + of this source. + type: boolean + timeout: + default: 60s + description: The timeout for download operations, defaults to 60s. + type: string + required: + - bucketName + - endpoint + - interval + type: object + status: + default: + observedGeneration: -1 + description: BucketStatus defines the observed state of a bucket + properties: + artifact: + description: Artifact represents the output of the last successful + Bucket sync. + properties: + checksum: + description: Checksum is the SHA256 checksum of the artifact. + type: string + lastUpdateTime: + description: LastUpdateTime is the timestamp corresponding to + the last update of this artifact. + format: date-time + type: string + path: + description: Path is the relative file path of this artifact. + type: string + revision: + description: Revision is a human readable identifier traceable + in the origin source system. It can be a Git commit SHA, Git + tag, a Helm index timestamp, a Helm chart version, etc. + type: string + url: + description: URL is the HTTP address of this artifact. + type: string + required: + - path + - url + type: object + conditions: + description: Conditions holds the conditions for the Bucket. + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + \n type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + 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 + lastHandledReconcileAt: + description: LastHandledReconcileAt holds the value of the most recent + reconcile request value, so a change of the annotation value can + be detected. + type: string + observedGeneration: + description: ObservedGeneration is the last observed generation. + format: int64 + type: integer + url: + description: URL is the download link for the artifact output of the + last Bucket sync. + type: string + type: object + type: object + served: true + storage: false + subresources: + status: {} + - additionalPrinterColumns: + - jsonPath: .spec.endpoint + name: Endpoint + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + - jsonPath: .status.conditions[?(@.type=="Ready")].status + name: Ready + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].message + name: Status + type: string + name: v1beta2 + schema: + openAPIV3Schema: + description: Bucket is the Schema for the buckets 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: BucketSpec specifies the required configuration to produce + an Artifact for an object storage bucket. + properties: + accessFrom: + description: 'AccessFrom specifies an Access Control List for allowing + cross-namespace references to this object. NOTE: Not implemented, + provisional as of https://github.com/fluxcd/flux2/pull/2092' + properties: + namespaceSelectors: + description: NamespaceSelectors is the list of namespace selectors + to which this ACL applies. Items in this list are evaluated + using a logical OR operation. + items: + description: NamespaceSelector selects the namespaces to which + this ACL applies. An empty map of MatchLabels matches all + namespaces in a cluster. + properties: + 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 + type: array + required: + - namespaceSelectors + type: object + bucketName: + description: BucketName is the name of the object storage bucket. + type: string + endpoint: + description: Endpoint is the object storage address the BucketName + is located at. + type: string + ignore: + description: Ignore overrides the set of excluded patterns in the + .sourceignore format (which is the same as .gitignore). If not provided, + a default will be used, consult the documentation for your version + to find out what those are. + type: string + insecure: + description: Insecure allows connecting to a non-TLS HTTP Endpoint. + type: boolean + interval: + description: Interval at which the Bucket Endpoint is checked for + updates. This interval is approximate and may be subject to jitter + to ensure efficient use of resources. + pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ + type: string + provider: + default: generic + description: Provider of the object storage bucket. Defaults to 'generic', + which expects an S3 (API) compatible object storage. + enum: + - generic + - aws + - gcp + - azure + type: string + region: + description: Region of the Endpoint where the BucketName is located + in. + type: string + secretRef: + description: SecretRef specifies the Secret containing authentication + credentials for the Bucket. + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + suspend: + description: Suspend tells the controller to suspend the reconciliation + of this Bucket. + type: boolean + timeout: + default: 60s + description: Timeout for fetch operations, defaults to 60s. + pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m))+$ + type: string + required: + - bucketName + - endpoint + - interval + type: object + status: + default: + observedGeneration: -1 + description: BucketStatus records the observed state of a Bucket. + properties: + artifact: + description: Artifact represents the last successful Bucket reconciliation. + properties: + digest: + description: Digest is the digest of the file in the form of ':'. + pattern: ^[a-z0-9]+(?:[.+_-][a-z0-9]+)*:[a-zA-Z0-9=_-]+$ + type: string + lastUpdateTime: + description: LastUpdateTime is the timestamp corresponding to + the last update of the Artifact. + format: date-time + type: string + metadata: + additionalProperties: + type: string + description: Metadata holds upstream information such as OCI annotations. + type: object + path: + description: Path is the relative file path of the Artifact. It + can be used to locate the file in the root of the Artifact storage + on the local file system of the controller managing the Source. + type: string + revision: + description: Revision is a human-readable identifier traceable + in the origin source system. It can be a Git commit SHA, Git + tag, a Helm chart version, etc. + type: string + size: + description: Size is the number of bytes in the file. + format: int64 + type: integer + url: + description: URL is the HTTP address of the Artifact as exposed + by the controller managing the Source. It can be used to retrieve + the Artifact for consumption, e.g. by another controller applying + the Artifact contents. + type: string + required: + - lastUpdateTime + - path + - revision + - url + type: object + conditions: + description: Conditions holds the conditions for the Bucket. + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + \n type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + 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 + lastHandledReconcileAt: + description: LastHandledReconcileAt holds the value of the most recent + reconcile request value, so a change of the annotation value can + be detected. + type: string + observedGeneration: + description: ObservedGeneration is the last observed generation of + the Bucket object. + format: int64 + type: integer + observedIgnore: + description: ObservedIgnore is the observed exclusion patterns used + for constructing the source artifact. + type: string + url: + description: URL is the dynamic fetch link for the latest Artifact. + It is provided on a "best effort" basis, and using the precise BucketStatus.Artifact + data is recommended. + 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.12.0 + {{- with .Values.crds.annotations }} + {{- . | toYaml | nindent 4 }} + {{- end }} + labels: + app.kubernetes.io/component: source-controller + app.kubernetes.io/instance: '{{ .Release.Namespace }}' + app.kubernetes.io/managed-by: '{{ .Release.Service }}' + app.kubernetes.io/part-of: flux + app.kubernetes.io/version: '{{ .Chart.AppVersion }}' + helm.sh/chart: '{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}' + name: gitrepositories.source.toolkit.fluxcd.io +spec: + group: source.toolkit.fluxcd.io + names: + kind: GitRepository + listKind: GitRepositoryList + plural: gitrepositories + shortNames: + - gitrepo + singular: gitrepository + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .spec.url + name: URL + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + - jsonPath: .status.conditions[?(@.type=="Ready")].status + name: Ready + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].message + name: Status + type: string + name: v1 + schema: + openAPIV3Schema: + description: GitRepository is the Schema for the gitrepositories 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: GitRepositorySpec specifies the required configuration to + produce an Artifact for a Git repository. + properties: + ignore: + description: Ignore overrides the set of excluded patterns in the + .sourceignore format (which is the same as .gitignore). If not provided, + a default will be used, consult the documentation for your version + to find out what those are. + type: string + include: + description: Include specifies a list of GitRepository resources which + Artifacts should be included in the Artifact produced for this GitRepository. + items: + description: GitRepositoryInclude specifies a local reference to + a GitRepository which Artifact (sub-)contents must be included, + and where they should be placed. + properties: + fromPath: + description: FromPath specifies the path to copy contents from, + defaults to the root of the Artifact. + type: string + repository: + description: GitRepositoryRef specifies the GitRepository which + Artifact contents must be included. + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + toPath: + description: ToPath specifies the path to copy contents to, + defaults to the name of the GitRepositoryRef. + type: string + required: + - repository + type: object + type: array + interval: + description: Interval at which the GitRepository URL is checked for + updates. This interval is approximate and may be subject to jitter + to ensure efficient use of resources. + pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ + type: string + proxySecretRef: + description: ProxySecretRef specifies the Secret containing the proxy + configuration to use while communicating with the Git server. + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + recurseSubmodules: + description: RecurseSubmodules enables the initialization of all submodules + within the GitRepository as cloned from the URL, using their default + settings. + type: boolean + ref: + description: Reference specifies the Git reference to resolve and + monitor for changes, defaults to the 'master' branch. + properties: + branch: + description: Branch to check out, defaults to 'master' if no other + field is defined. + type: string + commit: + description: "Commit SHA to check out, takes precedence over all + reference fields. \n This can be combined with Branch to shallow + clone the branch, in which the commit is expected to exist." + type: string + name: + description: "Name of the reference to check out; takes precedence + over Branch, Tag and SemVer. \n It must be a valid Git reference: + https://git-scm.com/docs/git-check-ref-format#_description Examples: + \"refs/heads/main\", \"refs/tags/v0.1.0\", \"refs/pull/420/head\", + \"refs/merge-requests/1/head\"" + type: string + semver: + description: SemVer tag expression to check out, takes precedence + over Tag. + type: string + tag: + description: Tag to check out, takes precedence over Branch. + type: string + type: object + secretRef: + description: SecretRef specifies the Secret containing authentication + credentials for the GitRepository. For HTTPS repositories the Secret + must contain 'username' and 'password' fields for basic auth or + 'bearerToken' field for token auth. For SSH repositories the Secret + must contain 'identity' and 'known_hosts' fields. + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + suspend: + description: Suspend tells the controller to suspend the reconciliation + of this GitRepository. + type: boolean + timeout: + default: 60s + description: Timeout for Git operations like cloning, defaults to + 60s. + pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m))+$ + type: string + url: + description: URL specifies the Git repository URL, it can be an HTTP/S + or SSH address. + pattern: ^(http|https|ssh)://.*$ + type: string + verify: + description: Verification specifies the configuration to verify the + Git commit signature(s). + properties: + mode: + default: HEAD + description: "Mode specifies which Git object(s) should be verified. + \n The variants \"head\" and \"HEAD\" both imply the same thing, + i.e. verify the commit that the HEAD of the Git repository points + to. The variant \"head\" solely exists to ensure backwards compatibility." + enum: + - head + - HEAD + - Tag + - TagAndHEAD + type: string + secretRef: + description: SecretRef specifies the Secret containing the public + keys of trusted Git authors. + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + required: + - secretRef + type: object + required: + - interval + - url + type: object + status: + default: + observedGeneration: -1 + description: GitRepositoryStatus records the observed state of a Git repository. + properties: + artifact: + description: Artifact represents the last successful GitRepository + reconciliation. + properties: + digest: + description: Digest is the digest of the file in the form of ':'. + pattern: ^[a-z0-9]+(?:[.+_-][a-z0-9]+)*:[a-zA-Z0-9=_-]+$ + type: string + lastUpdateTime: + description: LastUpdateTime is the timestamp corresponding to + the last update of the Artifact. + format: date-time + type: string + metadata: + additionalProperties: + type: string + description: Metadata holds upstream information such as OCI annotations. + type: object + path: + description: Path is the relative file path of the Artifact. It + can be used to locate the file in the root of the Artifact storage + on the local file system of the controller managing the Source. + type: string + revision: + description: Revision is a human-readable identifier traceable + in the origin source system. It can be a Git commit SHA, Git + tag, a Helm chart version, etc. + type: string + size: + description: Size is the number of bytes in the file. + format: int64 + type: integer + url: + description: URL is the HTTP address of the Artifact as exposed + by the controller managing the Source. It can be used to retrieve + the Artifact for consumption, e.g. by another controller applying + the Artifact contents. + type: string + required: + - lastUpdateTime + - path + - revision + - url + type: object + conditions: + description: Conditions holds the conditions for the GitRepository. + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + \n type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + 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 + includedArtifacts: + description: IncludedArtifacts contains a list of the last successfully + included Artifacts as instructed by GitRepositorySpec.Include. + items: + description: Artifact represents the output of a Source reconciliation. + properties: + digest: + description: Digest is the digest of the file in the form of + ':'. + pattern: ^[a-z0-9]+(?:[.+_-][a-z0-9]+)*:[a-zA-Z0-9=_-]+$ + type: string + lastUpdateTime: + description: LastUpdateTime is the timestamp corresponding to + the last update of the Artifact. + format: date-time + type: string + metadata: + additionalProperties: + type: string + description: Metadata holds upstream information such as OCI + annotations. + type: object + path: + description: Path is the relative file path of the Artifact. + It can be used to locate the file in the root of the Artifact + storage on the local file system of the controller managing + the Source. + type: string + revision: + description: Revision is a human-readable identifier traceable + in the origin source system. It can be a Git commit SHA, Git + tag, a Helm chart version, etc. + type: string + size: + description: Size is the number of bytes in the file. + format: int64 + type: integer + url: + description: URL is the HTTP address of the Artifact as exposed + by the controller managing the Source. It can be used to retrieve + the Artifact for consumption, e.g. by another controller applying + the Artifact contents. + type: string + required: + - lastUpdateTime + - path + - revision + - url + type: object + type: array + lastHandledReconcileAt: + description: LastHandledReconcileAt holds the value of the most recent + reconcile request value, so a change of the annotation value can + be detected. + type: string + observedGeneration: + description: ObservedGeneration is the last observed generation of + the GitRepository object. + format: int64 + type: integer + observedIgnore: + description: ObservedIgnore is the observed exclusion patterns used + for constructing the source artifact. + type: string + observedInclude: + description: ObservedInclude is the observed list of GitRepository + resources used to produce the current Artifact. + items: + description: GitRepositoryInclude specifies a local reference to + a GitRepository which Artifact (sub-)contents must be included, + and where they should be placed. + properties: + fromPath: + description: FromPath specifies the path to copy contents from, + defaults to the root of the Artifact. + type: string + repository: + description: GitRepositoryRef specifies the GitRepository which + Artifact contents must be included. + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + toPath: + description: ToPath specifies the path to copy contents to, + defaults to the name of the GitRepositoryRef. + type: string + required: + - repository + type: object + type: array + observedRecurseSubmodules: + description: ObservedRecurseSubmodules is the observed resource submodules + configuration used to produce the current Artifact. + type: boolean + sourceVerificationMode: + description: SourceVerificationMode is the last used verification + mode indicating which Git object(s) have been verified. + type: string + type: object + type: object + served: true + storage: true + subresources: + status: {} + - additionalPrinterColumns: + - jsonPath: .spec.url + name: URL + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].status + name: Ready + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].message + name: Status + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + deprecated: true + deprecationWarning: v1beta1 GitRepository is deprecated, upgrade to v1 + name: v1beta1 + schema: + openAPIV3Schema: + description: GitRepository is the Schema for the gitrepositories 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: GitRepositorySpec defines the desired state of a Git repository. + properties: + accessFrom: + description: AccessFrom defines an Access Control List for allowing + cross-namespace references to this object. + properties: + namespaceSelectors: + description: NamespaceSelectors is the list of namespace selectors + to which this ACL applies. Items in this list are evaluated + using a logical OR operation. + items: + description: NamespaceSelector selects the namespaces to which + this ACL applies. An empty map of MatchLabels matches all + namespaces in a cluster. + properties: + 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 + type: array + required: + - namespaceSelectors + type: object + gitImplementation: + default: go-git + description: Determines which git client library to use. Defaults + to go-git, valid values are ('go-git', 'libgit2'). + enum: + - go-git + - libgit2 + type: string + ignore: + description: Ignore overrides the set of excluded patterns in the + .sourceignore format (which is the same as .gitignore). If not provided, + a default will be used, consult the documentation for your version + to find out what those are. + type: string + include: + description: Extra git repositories to map into the repository + items: + description: GitRepositoryInclude defines a source with a from and + to path. + properties: + fromPath: + description: The path to copy contents from, defaults to the + root directory. + type: string + repository: + description: Reference to a GitRepository to include. + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + toPath: + description: The path to copy contents to, defaults to the name + of the source ref. + type: string + required: + - repository + type: object + type: array + interval: + description: The interval at which to check for repository updates. + type: string + recurseSubmodules: + description: When enabled, after the clone is created, initializes + all submodules within, using their default settings. This option + is available only when using the 'go-git' GitImplementation. + type: boolean + ref: + description: The Git reference to checkout and monitor for changes, + defaults to master branch. + properties: + branch: + description: The Git branch to checkout, defaults to master. + type: string + commit: + description: The Git commit SHA to checkout, if specified Tag + filters will be ignored. + type: string + semver: + description: The Git tag semver expression, takes precedence over + Tag. + type: string + tag: + description: The Git tag to checkout, takes precedence over Branch. + type: string + type: object + secretRef: + description: The secret name containing the Git credentials. For HTTPS + repositories the secret must contain username and password fields. + For SSH repositories the secret must contain identity and known_hosts + fields. + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + suspend: + description: This flag tells the controller to suspend the reconciliation + of this source. + type: boolean + timeout: + default: 60s + description: The timeout for remote Git operations like cloning, defaults + to 60s. + type: string + url: + description: The repository URL, can be a HTTP/S or SSH address. + pattern: ^(http|https|ssh)://.*$ + type: string + verify: + description: Verify OpenPGP signature for the Git commit HEAD points + to. + properties: + mode: + description: Mode describes what git object should be verified, + currently ('head'). + enum: + - head + type: string + secretRef: + description: The secret name containing the public keys of all + trusted Git authors. + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + required: + - mode + type: object + required: + - interval + - url + type: object + status: + default: + observedGeneration: -1 + description: GitRepositoryStatus defines the observed state of a Git repository. + properties: + artifact: + description: Artifact represents the output of the last successful + repository sync. + properties: + checksum: + description: Checksum is the SHA256 checksum of the artifact. + type: string + lastUpdateTime: + description: LastUpdateTime is the timestamp corresponding to + the last update of this artifact. + format: date-time + type: string + path: + description: Path is the relative file path of this artifact. + type: string + revision: + description: Revision is a human readable identifier traceable + in the origin source system. It can be a Git commit SHA, Git + tag, a Helm index timestamp, a Helm chart version, etc. + type: string + url: + description: URL is the HTTP address of this artifact. + type: string + required: + - path + - url + type: object + conditions: + description: Conditions holds the conditions for the GitRepository. + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + \n type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + 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 + includedArtifacts: + description: IncludedArtifacts represents the included artifacts from + the last successful repository sync. + items: + description: Artifact represents the output of a source synchronisation. + properties: + checksum: + description: Checksum is the SHA256 checksum of the artifact. + type: string + lastUpdateTime: + description: LastUpdateTime is the timestamp corresponding to + the last update of this artifact. + format: date-time + type: string + path: + description: Path is the relative file path of this artifact. + type: string + revision: + description: Revision is a human readable identifier traceable + in the origin source system. It can be a Git commit SHA, Git + tag, a Helm index timestamp, a Helm chart version, etc. + type: string + url: + description: URL is the HTTP address of this artifact. + type: string + required: + - path + - url + type: object + type: array + lastHandledReconcileAt: + description: LastHandledReconcileAt holds the value of the most recent + reconcile request value, so a change of the annotation value can + be detected. + type: string + observedGeneration: + description: ObservedGeneration is the last observed generation. + format: int64 + type: integer + url: + description: URL is the download link for the artifact output of the + last repository sync. + type: string + type: object + type: object + served: true + storage: false + subresources: + status: {} + - additionalPrinterColumns: + - jsonPath: .spec.url + name: URL + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + - jsonPath: .status.conditions[?(@.type=="Ready")].status + name: Ready + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].message + name: Status + type: string + deprecated: true + deprecationWarning: v1beta2 GitRepository is deprecated, upgrade to v1 + name: v1beta2 + schema: + openAPIV3Schema: + description: GitRepository is the Schema for the gitrepositories 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: GitRepositorySpec specifies the required configuration to + produce an Artifact for a Git repository. + properties: + accessFrom: + description: 'AccessFrom specifies an Access Control List for allowing + cross-namespace references to this object. NOTE: Not implemented, + provisional as of https://github.com/fluxcd/flux2/pull/2092' + properties: + namespaceSelectors: + description: NamespaceSelectors is the list of namespace selectors + to which this ACL applies. Items in this list are evaluated + using a logical OR operation. + items: + description: NamespaceSelector selects the namespaces to which + this ACL applies. An empty map of MatchLabels matches all + namespaces in a cluster. + properties: + 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 + type: array + required: + - namespaceSelectors + type: object + gitImplementation: + default: go-git + description: 'GitImplementation specifies which Git client library + implementation to use. Defaults to ''go-git'', valid values are + (''go-git'', ''libgit2''). Deprecated: gitImplementation is deprecated + now that ''go-git'' is the only supported implementation.' + enum: + - go-git + - libgit2 + type: string + ignore: + description: Ignore overrides the set of excluded patterns in the + .sourceignore format (which is the same as .gitignore). If not provided, + a default will be used, consult the documentation for your version + to find out what those are. + type: string + include: + description: Include specifies a list of GitRepository resources which + Artifacts should be included in the Artifact produced for this GitRepository. + items: + description: GitRepositoryInclude specifies a local reference to + a GitRepository which Artifact (sub-)contents must be included, + and where they should be placed. + properties: + fromPath: + description: FromPath specifies the path to copy contents from, + defaults to the root of the Artifact. + type: string + repository: + description: GitRepositoryRef specifies the GitRepository which + Artifact contents must be included. + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + toPath: + description: ToPath specifies the path to copy contents to, + defaults to the name of the GitRepositoryRef. + type: string + required: + - repository + type: object + type: array + interval: + description: Interval at which to check the GitRepository for updates. + pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ + type: string + recurseSubmodules: + description: RecurseSubmodules enables the initialization of all submodules + within the GitRepository as cloned from the URL, using their default + settings. + type: boolean + ref: + description: Reference specifies the Git reference to resolve and + monitor for changes, defaults to the 'master' branch. + properties: + branch: + description: Branch to check out, defaults to 'master' if no other + field is defined. + type: string + commit: + description: "Commit SHA to check out, takes precedence over all + reference fields. \n This can be combined with Branch to shallow + clone the branch, in which the commit is expected to exist." + type: string + name: + description: "Name of the reference to check out; takes precedence + over Branch, Tag and SemVer. \n It must be a valid Git reference: + https://git-scm.com/docs/git-check-ref-format#_description Examples: + \"refs/heads/main\", \"refs/tags/v0.1.0\", \"refs/pull/420/head\", + \"refs/merge-requests/1/head\"" + type: string + semver: + description: SemVer tag expression to check out, takes precedence + over Tag. + type: string + tag: + description: Tag to check out, takes precedence over Branch. + type: string + type: object + secretRef: + description: SecretRef specifies the Secret containing authentication + credentials for the GitRepository. For HTTPS repositories the Secret + must contain 'username' and 'password' fields for basic auth or + 'bearerToken' field for token auth. For SSH repositories the Secret + must contain 'identity' and 'known_hosts' fields. + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + suspend: + description: Suspend tells the controller to suspend the reconciliation + of this GitRepository. + type: boolean + timeout: + default: 60s + description: Timeout for Git operations like cloning, defaults to + 60s. + pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m))+$ + type: string + url: + description: URL specifies the Git repository URL, it can be an HTTP/S + or SSH address. + pattern: ^(http|https|ssh)://.*$ + type: string + verify: + description: Verification specifies the configuration to verify the + Git commit signature(s). + properties: + mode: + description: Mode specifies what Git object should be verified, + currently ('head'). + enum: + - head + type: string + secretRef: + description: SecretRef specifies the Secret containing the public + keys of trusted Git authors. + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + required: + - mode + - secretRef + type: object + required: + - interval + - url + type: object + status: + default: + observedGeneration: -1 + description: GitRepositoryStatus records the observed state of a Git repository. + properties: + artifact: + description: Artifact represents the last successful GitRepository + reconciliation. + properties: + digest: + description: Digest is the digest of the file in the form of ':'. + pattern: ^[a-z0-9]+(?:[.+_-][a-z0-9]+)*:[a-zA-Z0-9=_-]+$ + type: string + lastUpdateTime: + description: LastUpdateTime is the timestamp corresponding to + the last update of the Artifact. + format: date-time + type: string + metadata: + additionalProperties: + type: string + description: Metadata holds upstream information such as OCI annotations. + type: object + path: + description: Path is the relative file path of the Artifact. It + can be used to locate the file in the root of the Artifact storage + on the local file system of the controller managing the Source. + type: string + revision: + description: Revision is a human-readable identifier traceable + in the origin source system. It can be a Git commit SHA, Git + tag, a Helm chart version, etc. + type: string + size: + description: Size is the number of bytes in the file. + format: int64 + type: integer + url: + description: URL is the HTTP address of the Artifact as exposed + by the controller managing the Source. It can be used to retrieve + the Artifact for consumption, e.g. by another controller applying + the Artifact contents. + type: string + required: + - lastUpdateTime + - path + - revision + - url + type: object + conditions: + description: Conditions holds the conditions for the GitRepository. + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + \n type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + 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 + contentConfigChecksum: + description: "ContentConfigChecksum is a checksum of all the configurations + related to the content of the source artifact: - .spec.ignore - + .spec.recurseSubmodules - .spec.included and the checksum of the + included artifacts observed in .status.observedGeneration version + of the object. This can be used to determine if the content of the + included repository has changed. It has the format of `:`, + for example: `sha256:`. \n Deprecated: Replaced with explicit + fields for observed artifact content config in the status." + type: string + includedArtifacts: + description: IncludedArtifacts contains a list of the last successfully + included Artifacts as instructed by GitRepositorySpec.Include. + items: + description: Artifact represents the output of a Source reconciliation. + properties: + digest: + description: Digest is the digest of the file in the form of + ':'. + pattern: ^[a-z0-9]+(?:[.+_-][a-z0-9]+)*:[a-zA-Z0-9=_-]+$ + type: string + lastUpdateTime: + description: LastUpdateTime is the timestamp corresponding to + the last update of the Artifact. + format: date-time + type: string + metadata: + additionalProperties: + type: string + description: Metadata holds upstream information such as OCI + annotations. + type: object + path: + description: Path is the relative file path of the Artifact. + It can be used to locate the file in the root of the Artifact + storage on the local file system of the controller managing + the Source. + type: string + revision: + description: Revision is a human-readable identifier traceable + in the origin source system. It can be a Git commit SHA, Git + tag, a Helm chart version, etc. + type: string + size: + description: Size is the number of bytes in the file. + format: int64 + type: integer + url: + description: URL is the HTTP address of the Artifact as exposed + by the controller managing the Source. It can be used to retrieve + the Artifact for consumption, e.g. by another controller applying + the Artifact contents. + type: string + required: + - lastUpdateTime + - path + - revision + - url + type: object + type: array + lastHandledReconcileAt: + description: LastHandledReconcileAt holds the value of the most recent + reconcile request value, so a change of the annotation value can + be detected. + type: string + observedGeneration: + description: ObservedGeneration is the last observed generation of + the GitRepository object. + format: int64 + type: integer + observedIgnore: + description: ObservedIgnore is the observed exclusion patterns used + for constructing the source artifact. + type: string + observedInclude: + description: ObservedInclude is the observed list of GitRepository + resources used to to produce the current Artifact. + items: + description: GitRepositoryInclude specifies a local reference to + a GitRepository which Artifact (sub-)contents must be included, + and where they should be placed. + properties: + fromPath: + description: FromPath specifies the path to copy contents from, + defaults to the root of the Artifact. + type: string + repository: + description: GitRepositoryRef specifies the GitRepository which + Artifact contents must be included. + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + toPath: + description: ToPath specifies the path to copy contents to, + defaults to the name of the GitRepositoryRef. + type: string + required: + - repository + type: object + type: array + observedRecurseSubmodules: + description: ObservedRecurseSubmodules is the observed resource submodules + configuration used to produce the current Artifact. + type: boolean + url: + description: URL is the dynamic fetch link for the latest Artifact. + It is provided on a "best effort" basis, and using the precise GitRepositoryStatus.Artifact + data is recommended. + type: string + type: object + type: object + served: true + storage: false + subresources: + status: {} +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.12.0 + {{- with .Values.crds.annotations }} + {{- . | toYaml | nindent 4 }} + {{- end }} + labels: + app.kubernetes.io/component: source-controller + app.kubernetes.io/instance: '{{ .Release.Namespace }}' + app.kubernetes.io/managed-by: '{{ .Release.Service }}' + app.kubernetes.io/part-of: flux + app.kubernetes.io/version: '{{ .Chart.AppVersion }}' + helm.sh/chart: '{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}' + name: helmcharts.source.toolkit.fluxcd.io +spec: + group: source.toolkit.fluxcd.io + names: + kind: HelmChart + listKind: HelmChartList + plural: helmcharts + shortNames: + - hc + singular: helmchart + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .spec.chart + name: Chart + type: string + - jsonPath: .spec.version + name: Version + type: string + - jsonPath: .spec.sourceRef.kind + name: Source Kind + type: string + - jsonPath: .spec.sourceRef.name + name: Source Name + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].status + name: Ready + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].message + name: Status + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1beta1 + schema: + openAPIV3Schema: + description: HelmChart is the Schema for the helmcharts 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: HelmChartSpec defines the desired state of a Helm chart. + properties: + accessFrom: + description: AccessFrom defines an Access Control List for allowing + cross-namespace references to this object. + properties: + namespaceSelectors: + description: NamespaceSelectors is the list of namespace selectors + to which this ACL applies. Items in this list are evaluated + using a logical OR operation. + items: + description: NamespaceSelector selects the namespaces to which + this ACL applies. An empty map of MatchLabels matches all + namespaces in a cluster. + properties: + 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 + type: array + required: + - namespaceSelectors + type: object + chart: + description: The name or path the Helm chart is available at in the + SourceRef. + type: string + interval: + description: The interval at which to check the Source for updates. + type: string + reconcileStrategy: + default: ChartVersion + description: Determines what enables the creation of a new artifact. + Valid values are ('ChartVersion', 'Revision'). See the documentation + of the values for an explanation on their behavior. Defaults to + ChartVersion when omitted. + enum: + - ChartVersion + - Revision + type: string + sourceRef: + description: The reference to the Source the chart is available at. + properties: + apiVersion: + description: APIVersion of the referent. + type: string + kind: + description: Kind of the referent, valid values are ('HelmRepository', + 'GitRepository', 'Bucket'). + enum: + - HelmRepository + - GitRepository + - Bucket + type: string + name: + description: Name of the referent. + type: string + required: + - kind + - name + type: object + suspend: + description: This flag tells the controller to suspend the reconciliation + of this source. + type: boolean + valuesFile: + description: Alternative values file to use as the default chart values, + expected to be a relative path in the SourceRef. Deprecated in favor + of ValuesFiles, for backwards compatibility the file defined here + is merged before the ValuesFiles items. Ignored when omitted. + type: string + valuesFiles: + description: Alternative list of values files to use as the chart + values (values.yaml is not included by default), expected to be + a relative path in the SourceRef. Values files are merged in the + order of this list with the last file overriding the first. Ignored + when omitted. + items: + type: string + type: array + version: + default: '*' + description: The chart version semver expression, ignored for charts + from GitRepository and Bucket sources. Defaults to latest when omitted. + type: string + required: + - chart + - interval + - sourceRef + type: object + status: + default: + observedGeneration: -1 + description: HelmChartStatus defines the observed state of the HelmChart. + properties: + artifact: + description: Artifact represents the output of the last successful + chart sync. + properties: + checksum: + description: Checksum is the SHA256 checksum of the artifact. + type: string + lastUpdateTime: + description: LastUpdateTime is the timestamp corresponding to + the last update of this artifact. + format: date-time + type: string + path: + description: Path is the relative file path of this artifact. + type: string + revision: + description: Revision is a human readable identifier traceable + in the origin source system. It can be a Git commit SHA, Git + tag, a Helm index timestamp, a Helm chart version, etc. + type: string + url: + description: URL is the HTTP address of this artifact. + type: string + required: + - path + - url + type: object + conditions: + description: Conditions holds the conditions for the HelmChart. + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + \n type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + 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 + lastHandledReconcileAt: + description: LastHandledReconcileAt holds the value of the most recent + reconcile request value, so a change of the annotation value can + be detected. + type: string + observedGeneration: + description: ObservedGeneration is the last observed generation. + format: int64 + type: integer + url: + description: URL is the download link for the last chart pulled. + type: string + type: object + type: object + served: true + storage: false + subresources: + status: {} + - additionalPrinterColumns: + - jsonPath: .spec.chart + name: Chart + type: string + - jsonPath: .spec.version + name: Version + type: string + - jsonPath: .spec.sourceRef.kind + name: Source Kind + type: string + - jsonPath: .spec.sourceRef.name + name: Source Name + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + - jsonPath: .status.conditions[?(@.type=="Ready")].status + name: Ready + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].message + name: Status + type: string + name: v1beta2 + schema: + openAPIV3Schema: + description: HelmChart is the Schema for the helmcharts 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: HelmChartSpec specifies the desired state of a Helm chart. + properties: + accessFrom: + description: 'AccessFrom specifies an Access Control List for allowing + cross-namespace references to this object. NOTE: Not implemented, + provisional as of https://github.com/fluxcd/flux2/pull/2092' + properties: + namespaceSelectors: + description: NamespaceSelectors is the list of namespace selectors + to which this ACL applies. Items in this list are evaluated + using a logical OR operation. + items: + description: NamespaceSelector selects the namespaces to which + this ACL applies. An empty map of MatchLabels matches all + namespaces in a cluster. + properties: + 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 + type: array + required: + - namespaceSelectors + type: object + chart: + description: Chart is the name or path the Helm chart is available + at in the SourceRef. + type: string + interval: + description: Interval at which the HelmChart SourceRef is checked + for updates. This interval is approximate and may be subject to + jitter to ensure efficient use of resources. + pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ + type: string + reconcileStrategy: + default: ChartVersion + description: ReconcileStrategy determines what enables the creation + of a new artifact. Valid values are ('ChartVersion', 'Revision'). + See the documentation of the values for an explanation on their + behavior. Defaults to ChartVersion when omitted. + enum: + - ChartVersion + - Revision + type: string + sourceRef: + description: SourceRef is the reference to the Source the chart is + available at. + properties: + apiVersion: + description: APIVersion of the referent. + type: string + kind: + description: Kind of the referent, valid values are ('HelmRepository', + 'GitRepository', 'Bucket'). + enum: + - HelmRepository + - GitRepository + - Bucket + type: string + name: + description: Name of the referent. + type: string + required: + - kind + - name + type: object + suspend: + description: Suspend tells the controller to suspend the reconciliation + of this source. + type: boolean + valuesFile: + description: ValuesFile is an alternative values file to use as the + default chart values, expected to be a relative path in the SourceRef. + Deprecated in favor of ValuesFiles, for backwards compatibility + the file specified here is merged before the ValuesFiles items. + Ignored when omitted. + type: string + valuesFiles: + description: ValuesFiles is an alternative list of values files to + use as the chart values (values.yaml is not included by default), + expected to be a relative path in the SourceRef. Values files are + merged in the order of this list with the last file overriding the + first. Ignored when omitted. + items: + type: string + type: array + verify: + description: Verify contains the secret name containing the trusted + public keys used to verify the signature and specifies which provider + to use to check whether OCI image is authentic. This field is only + supported when using HelmRepository source with spec.type 'oci'. + Chart dependencies, which are not bundled in the umbrella chart + artifact, are not verified. + properties: + provider: + default: cosign + description: Provider specifies the technology used to sign the + OCI Artifact. + enum: + - cosign + type: string + secretRef: + description: SecretRef specifies the Kubernetes Secret containing + the trusted public keys. + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + required: + - provider + type: object + version: + default: '*' + description: Version is the chart version semver expression, ignored + for charts from GitRepository and Bucket sources. Defaults to latest + when omitted. + type: string + required: + - chart + - interval + - sourceRef + type: object + status: + default: + observedGeneration: -1 + description: HelmChartStatus records the observed state of the HelmChart. + properties: + artifact: + description: Artifact represents the output of the last successful + reconciliation. + properties: + digest: + description: Digest is the digest of the file in the form of ':'. + pattern: ^[a-z0-9]+(?:[.+_-][a-z0-9]+)*:[a-zA-Z0-9=_-]+$ + type: string + lastUpdateTime: + description: LastUpdateTime is the timestamp corresponding to + the last update of the Artifact. + format: date-time + type: string + metadata: + additionalProperties: + type: string + description: Metadata holds upstream information such as OCI annotations. + type: object + path: + description: Path is the relative file path of the Artifact. It + can be used to locate the file in the root of the Artifact storage + on the local file system of the controller managing the Source. + type: string + revision: + description: Revision is a human-readable identifier traceable + in the origin source system. It can be a Git commit SHA, Git + tag, a Helm chart version, etc. + type: string + size: + description: Size is the number of bytes in the file. + format: int64 + type: integer + url: + description: URL is the HTTP address of the Artifact as exposed + by the controller managing the Source. It can be used to retrieve + the Artifact for consumption, e.g. by another controller applying + the Artifact contents. + type: string + required: + - lastUpdateTime + - path + - revision + - url + type: object + conditions: + description: Conditions holds the conditions for the HelmChart. + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + \n type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + 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 + lastHandledReconcileAt: + description: LastHandledReconcileAt holds the value of the most recent + reconcile request value, so a change of the annotation value can + be detected. + type: string + observedChartName: + description: ObservedChartName is the last observed chart name as + specified by the resolved chart reference. + type: string + observedGeneration: + description: ObservedGeneration is the last observed generation of + the HelmChart object. + format: int64 + type: integer + observedSourceArtifactRevision: + description: ObservedSourceArtifactRevision is the last observed Artifact.Revision + of the HelmChartSpec.SourceRef. + type: string + url: + description: URL is the dynamic fetch link for the latest Artifact. + It is provided on a "best effort" basis, and using the precise BucketStatus.Artifact + data is recommended. + 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.12.0 + {{- with .Values.crds.annotations }} + {{- . | toYaml | nindent 4 }} + {{- end }} + labels: + app.kubernetes.io/component: source-controller + app.kubernetes.io/instance: '{{ .Release.Namespace }}' + app.kubernetes.io/managed-by: '{{ .Release.Service }}' + app.kubernetes.io/part-of: flux + app.kubernetes.io/version: '{{ .Chart.AppVersion }}' + helm.sh/chart: '{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}' + name: helmrepositories.source.toolkit.fluxcd.io +spec: + group: source.toolkit.fluxcd.io + names: + kind: HelmRepository + listKind: HelmRepositoryList + plural: helmrepositories + shortNames: + - helmrepo + singular: helmrepository + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .spec.url + name: URL + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].status + name: Ready + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].message + name: Status + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1beta1 + schema: + openAPIV3Schema: + description: HelmRepository is the Schema for the helmrepositories 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: HelmRepositorySpec defines the reference to a Helm repository. + properties: + accessFrom: + description: AccessFrom defines an Access Control List for allowing + cross-namespace references to this object. + properties: + namespaceSelectors: + description: NamespaceSelectors is the list of namespace selectors + to which this ACL applies. Items in this list are evaluated + using a logical OR operation. + items: + description: NamespaceSelector selects the namespaces to which + this ACL applies. An empty map of MatchLabels matches all + namespaces in a cluster. + properties: + 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 + type: array + required: + - namespaceSelectors + type: object + interval: + description: The interval at which to check the upstream for updates. + type: string + passCredentials: + description: PassCredentials allows the credentials from the SecretRef + to be passed on to a host that does not match the host as defined + in URL. This may be required if the host of the advertised chart + URLs in the index differ from the defined URL. Enabling this should + be done with caution, as it can potentially result in credentials + getting stolen in a MITM-attack. + type: boolean + secretRef: + description: The name of the secret containing authentication credentials + for the Helm repository. For HTTP/S basic auth the secret must contain + username and password fields. For TLS the secret must contain a + certFile and keyFile, and/or caFile fields. + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + suspend: + description: This flag tells the controller to suspend the reconciliation + of this source. + type: boolean + timeout: + default: 60s + description: The timeout of index downloading, defaults to 60s. + type: string + url: + description: The Helm repository URL, a valid URL contains at least + a protocol and host. + type: string + required: + - interval + - url + type: object + status: + default: + observedGeneration: -1 + description: HelmRepositoryStatus defines the observed state of the HelmRepository. + properties: + artifact: + description: Artifact represents the output of the last successful + repository sync. + properties: + checksum: + description: Checksum is the SHA256 checksum of the artifact. + type: string + lastUpdateTime: + description: LastUpdateTime is the timestamp corresponding to + the last update of this artifact. + format: date-time + type: string + path: + description: Path is the relative file path of this artifact. + type: string + revision: + description: Revision is a human readable identifier traceable + in the origin source system. It can be a Git commit SHA, Git + tag, a Helm index timestamp, a Helm chart version, etc. + type: string + url: + description: URL is the HTTP address of this artifact. + type: string + required: + - path + - url + type: object + conditions: + description: Conditions holds the conditions for the HelmRepository. + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + \n type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + 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 + lastHandledReconcileAt: + description: LastHandledReconcileAt holds the value of the most recent + reconcile request value, so a change of the annotation value can + be detected. + type: string + observedGeneration: + description: ObservedGeneration is the last observed generation. + format: int64 + type: integer + url: + description: URL is the download link for the last index fetched. + type: string + type: object + type: object + served: true + storage: false + subresources: + status: {} + - additionalPrinterColumns: + - jsonPath: .spec.url + name: URL + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + - jsonPath: .status.conditions[?(@.type=="Ready")].status + name: Ready + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].message + name: Status + type: string + name: v1beta2 + schema: + openAPIV3Schema: + description: HelmRepository is the Schema for the helmrepositories 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: HelmRepositorySpec specifies the required configuration to + produce an Artifact for a Helm repository index YAML. + properties: + accessFrom: + description: 'AccessFrom specifies an Access Control List for allowing + cross-namespace references to this object. NOTE: Not implemented, + provisional as of https://github.com/fluxcd/flux2/pull/2092' + properties: + namespaceSelectors: + description: NamespaceSelectors is the list of namespace selectors + to which this ACL applies. Items in this list are evaluated + using a logical OR operation. + items: + description: NamespaceSelector selects the namespaces to which + this ACL applies. An empty map of MatchLabels matches all + namespaces in a cluster. + properties: + 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 + type: array + required: + - namespaceSelectors + type: object + certSecretRef: + description: "CertSecretRef can be given the name of a Secret containing + either or both of \n - a PEM-encoded client certificate (`tls.crt`) + and private key (`tls.key`); - a PEM-encoded CA certificate (`ca.crt`) + \n and whichever are supplied, will be used for connecting to the + registry. The client cert and key are useful if you are authenticating + with a certificate; the CA cert is useful if you are using a self-signed + server certificate. The Secret must be of type `Opaque` or `kubernetes.io/tls`. + \n It takes precedence over the values specified in the Secret referred + to by `.spec.secretRef`." + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + interval: + description: Interval at which the HelmRepository URL is checked for + updates. This interval is approximate and may be subject to jitter + to ensure efficient use of resources. + pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ + type: string + passCredentials: + description: PassCredentials allows the credentials from the SecretRef + to be passed on to a host that does not match the host as defined + in URL. This may be required if the host of the advertised chart + URLs in the index differ from the defined URL. Enabling this should + be done with caution, as it can potentially result in credentials + getting stolen in a MITM-attack. + type: boolean + provider: + default: generic + description: Provider used for authentication, can be 'aws', 'azure', + 'gcp' or 'generic'. This field is optional, and only taken into + account if the .spec.type field is set to 'oci'. When not specified, + defaults to 'generic'. + enum: + - generic + - aws + - azure + - gcp + type: string + secretRef: + description: SecretRef specifies the Secret containing authentication + credentials for the HelmRepository. For HTTP/S basic auth the secret + must contain 'username' and 'password' fields. Support for TLS auth + using the 'certFile' and 'keyFile', and/or 'caFile' keys is deprecated. + Please use `.spec.certSecretRef` instead. + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + suspend: + description: Suspend tells the controller to suspend the reconciliation + of this HelmRepository. + type: boolean + timeout: + default: 60s + description: Timeout is used for the index fetch operation for an + HTTPS helm repository, and for remote OCI Repository operations + like pulling for an OCI helm repository. Its default value is 60s. + pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m))+$ + type: string + type: + description: Type of the HelmRepository. When this field is set to "oci", + the URL field value must be prefixed with "oci://". + enum: + - default + - oci + type: string + url: + description: URL of the Helm repository, a valid URL contains at least + a protocol and host. + type: string + required: + - interval + - url + type: object + status: + default: + observedGeneration: -1 + description: HelmRepositoryStatus records the observed state of the HelmRepository. + properties: + artifact: + description: Artifact represents the last successful HelmRepository + reconciliation. + properties: + digest: + description: Digest is the digest of the file in the form of ':'. + pattern: ^[a-z0-9]+(?:[.+_-][a-z0-9]+)*:[a-zA-Z0-9=_-]+$ + type: string + lastUpdateTime: + description: LastUpdateTime is the timestamp corresponding to + the last update of the Artifact. + format: date-time + type: string + metadata: + additionalProperties: + type: string + description: Metadata holds upstream information such as OCI annotations. + type: object + path: + description: Path is the relative file path of the Artifact. It + can be used to locate the file in the root of the Artifact storage + on the local file system of the controller managing the Source. + type: string + revision: + description: Revision is a human-readable identifier traceable + in the origin source system. It can be a Git commit SHA, Git + tag, a Helm chart version, etc. + type: string + size: + description: Size is the number of bytes in the file. + format: int64 + type: integer + url: + description: URL is the HTTP address of the Artifact as exposed + by the controller managing the Source. It can be used to retrieve + the Artifact for consumption, e.g. by another controller applying + the Artifact contents. + type: string + required: + - lastUpdateTime + - path + - revision + - url + type: object + conditions: + description: Conditions holds the conditions for the HelmRepository. + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + \n type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + 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 + lastHandledReconcileAt: + description: LastHandledReconcileAt holds the value of the most recent + reconcile request value, so a change of the annotation value can + be detected. + type: string + observedGeneration: + description: ObservedGeneration is the last observed generation of + the HelmRepository object. + format: int64 + type: integer + url: + description: URL is the dynamic fetch link for the latest Artifact. + It is provided on a "best effort" basis, and using the precise HelmRepositoryStatus.Artifact + data is recommended. + 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.12.0 + {{- with .Values.crds.annotations }} + {{- . | toYaml | nindent 4 }} + {{- end }} + labels: + app.kubernetes.io/component: source-controller + app.kubernetes.io/instance: '{{ .Release.Namespace }}' + app.kubernetes.io/managed-by: '{{ .Release.Service }}' + app.kubernetes.io/part-of: flux + app.kubernetes.io/version: '{{ .Chart.AppVersion }}' + helm.sh/chart: '{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}' + name: ocirepositories.source.toolkit.fluxcd.io +spec: + group: source.toolkit.fluxcd.io + names: + kind: OCIRepository + listKind: OCIRepositoryList + plural: ocirepositories + shortNames: + - ocirepo + singular: ocirepository + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .spec.url + name: URL + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].status + name: Ready + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].message + name: Status + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1beta2 + schema: + openAPIV3Schema: + description: OCIRepository is the Schema for the ocirepositories 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: OCIRepositorySpec defines the desired state of OCIRepository + properties: + certSecretRef: + description: "CertSecretRef can be given the name of a Secret containing + either or both of \n - a PEM-encoded client certificate (`tls.crt`) + and private key (`tls.key`); - a PEM-encoded CA certificate (`ca.crt`) + \n and whichever are supplied, will be used for connecting to the + registry. The client cert and key are useful if you are authenticating + with a certificate; the CA cert is useful if you are using a self-signed + server certificate. The Secret must be of type `Opaque` or `kubernetes.io/tls`. + \n Note: Support for the `caFile`, `certFile` and `keyFile` keys + have been deprecated." + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + ignore: + description: Ignore overrides the set of excluded patterns in the + .sourceignore format (which is the same as .gitignore). If not provided, + a default will be used, consult the documentation for your version + to find out what those are. + type: string + insecure: + description: Insecure allows connecting to a non-TLS HTTP container + registry. + type: boolean + interval: + description: Interval at which the OCIRepository URL is checked for + updates. This interval is approximate and may be subject to jitter + to ensure efficient use of resources. + pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ + type: string + layerSelector: + description: LayerSelector specifies which layer should be extracted + from the OCI artifact. When not specified, the first layer found + in the artifact is selected. + properties: + mediaType: + description: MediaType specifies the OCI media type of the layer + which should be extracted from the OCI Artifact. The first layer + matching this type is selected. + type: string + operation: + description: Operation specifies how the selected layer should + be processed. By default, the layer compressed content is extracted + to storage. When the operation is set to 'copy', the layer compressed + content is persisted to storage as it is. + enum: + - extract + - copy + type: string + type: object + provider: + default: generic + description: The provider used for authentication, can be 'aws', 'azure', + 'gcp' or 'generic'. When not specified, defaults to 'generic'. + enum: + - generic + - aws + - azure + - gcp + type: string + ref: + description: The OCI reference to pull and monitor for changes, defaults + to the latest tag. + properties: + digest: + description: Digest is the image digest to pull, takes precedence + over SemVer. The value should be in the format 'sha256:'. + type: string + semver: + description: SemVer is the range of tags to pull selecting the + latest within the range, takes precedence over Tag. + type: string + tag: + description: Tag is the image tag to pull, defaults to latest. + type: string + type: object + secretRef: + description: SecretRef contains the secret name containing the registry + login credentials to resolve image metadata. The secret must be + of type kubernetes.io/dockerconfigjson. + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + serviceAccountName: + description: 'ServiceAccountName is the name of the Kubernetes ServiceAccount + used to authenticate the image pull if the service account has attached + pull secrets. For more information: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#add-imagepullsecrets-to-a-service-account' + type: string + suspend: + description: This flag tells the controller to suspend the reconciliation + of this source. + type: boolean + timeout: + default: 60s + description: The timeout for remote OCI Repository operations like + pulling, defaults to 60s. + pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m))+$ + type: string + url: + description: URL is a reference to an OCI artifact repository hosted + on a remote container registry. + pattern: ^oci://.*$ + type: string + verify: + description: Verify contains the secret name containing the trusted + public keys used to verify the signature and specifies which provider + to use to check whether OCI image is authentic. + properties: + provider: + default: cosign + description: Provider specifies the technology used to sign the + OCI Artifact. + enum: + - cosign + type: string + secretRef: + description: SecretRef specifies the Kubernetes Secret containing + the trusted public keys. + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + required: + - provider + type: object + required: + - interval + - url + type: object + status: + default: + observedGeneration: -1 + description: OCIRepositoryStatus defines the observed state of OCIRepository + properties: + artifact: + description: Artifact represents the output of the last successful + OCI Repository sync. + properties: + digest: + description: Digest is the digest of the file in the form of ':'. + pattern: ^[a-z0-9]+(?:[.+_-][a-z0-9]+)*:[a-zA-Z0-9=_-]+$ + type: string + lastUpdateTime: + description: LastUpdateTime is the timestamp corresponding to + the last update of the Artifact. + format: date-time + type: string + metadata: + additionalProperties: + type: string + description: Metadata holds upstream information such as OCI annotations. + type: object + path: + description: Path is the relative file path of the Artifact. It + can be used to locate the file in the root of the Artifact storage + on the local file system of the controller managing the Source. + type: string + revision: + description: Revision is a human-readable identifier traceable + in the origin source system. It can be a Git commit SHA, Git + tag, a Helm chart version, etc. + type: string + size: + description: Size is the number of bytes in the file. + format: int64 + type: integer + url: + description: URL is the HTTP address of the Artifact as exposed + by the controller managing the Source. It can be used to retrieve + the Artifact for consumption, e.g. by another controller applying + the Artifact contents. + type: string + required: + - lastUpdateTime + - path + - revision + - url + type: object + conditions: + description: Conditions holds the conditions for the OCIRepository. + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + \n type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + 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 + contentConfigChecksum: + description: "ContentConfigChecksum is a checksum of all the configurations + related to the content of the source artifact: - .spec.ignore - + .spec.layerSelector observed in .status.observedGeneration version + of the object. This can be used to determine if the content configuration + has changed and the artifact needs to be rebuilt. It has the format + of `:`, for example: `sha256:`. \n Deprecated: + Replaced with explicit fields for observed artifact content config + in the status." + type: string + lastHandledReconcileAt: + description: LastHandledReconcileAt holds the value of the most recent + reconcile request value, so a change of the annotation value can + be detected. + type: string + observedGeneration: + description: ObservedGeneration is the last observed generation. + format: int64 + type: integer + observedIgnore: + description: ObservedIgnore is the observed exclusion patterns used + for constructing the source artifact. + type: string + observedLayerSelector: + description: ObservedLayerSelector is the observed layer selector + used for constructing the source artifact. + properties: + mediaType: + description: MediaType specifies the OCI media type of the layer + which should be extracted from the OCI Artifact. The first layer + matching this type is selected. + type: string + operation: + description: Operation specifies how the selected layer should + be processed. By default, the layer compressed content is extracted + to storage. When the operation is set to 'copy', the layer compressed + content is persisted to storage as it is. + enum: + - extract + - copy + type: string + type: object + url: + description: URL is the download link for the artifact output of the + last OCI Repository sync. + type: string + type: object + type: object + served: true + storage: true + subresources: + status: {} +{{- end }} diff --git a/packages/system/fluxcd/charts/flux2/templates/source-controller.yaml b/packages/system/fluxcd/charts/flux2/templates/source-controller.yaml new file mode 100644 index 00000000..940e237b --- /dev/null +++ b/packages/system/fluxcd/charts/flux2/templates/source-controller.yaml @@ -0,0 +1,144 @@ +{{- if .Values.sourceController.create }} +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app.kubernetes.io/component: source-controller + app.kubernetes.io/instance: {{ .Release.Namespace | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} + app.kubernetes.io/part-of: flux + helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} + control-plane: controller + {{- with .Values.sourceController.labels }} + {{- . | toYaml | nindent 4 }} + {{- end }} + name: source-controller +spec: + {{- if kindIs "invalid" .Values.sourceController.replicas }} + replicas: 1 + {{- else }} + replicas: {{ .Values.sourceController.replicas }} + {{- end}} + selector: + matchLabels: + app: source-controller + strategy: + type: Recreate + template: + metadata: + {{- with .Values.sourceController.annotations }} + annotations: {{ toYaml . | nindent 8 }} + {{- end }} + labels: + app: source-controller +{{ with .Values.sourceController.labels }}{{ toYaml . | indent 8 }}{{ end }} + spec: + automountServiceAccountToken: {{ .Values.sourceController.serviceAccount.automount }} + {{- if .Values.sourceController.initContainers}} + initContainers: + {{- toYaml .Values.sourceController.initContainers | nindent 8}} + {{- end}} + containers: + - args: + {{- if .Values.notificationController.create }} + - --events-addr=http://notification-controller.$(RUNTIME_NAMESPACE).svc.{{ .Values.clusterDomain | default "cluster.local" }}. + {{- end}} + - --watch-all-namespaces={{ .Values.watchAllNamespaces }} + - --log-level={{ .Values.logLevel | default "info" }} + - --log-encoding=json + - --enable-leader-election + - --storage-path=/data + - --storage-adv-addr=source-controller.$(RUNTIME_NAMESPACE).svc.{{ .Values.clusterDomain | default "cluster.local" }}. + {{- range .Values.sourceController.container.additionalArgs }} + - {{ . }} + {{- end}} + env: + - name: RUNTIME_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + {{- with .Values.sourceController.extraEnv }} + {{- toYaml . | nindent 8 }} + {{- end }} + image: {{ template "template.image" .Values.sourceController }} + {{- if .Values.sourceController.imagePullPolicy }} + imagePullPolicy: {{ .Values.sourceController.imagePullPolicy }} + {{- else }} + imagePullPolicy: IfNotPresent + {{- end }} + livenessProbe: + httpGet: + path: /healthz + port: healthz + name: manager + ports: + - containerPort: 9090 + name: http + protocol: TCP + - containerPort: 8080 + name: http-prom + protocol: TCP + - containerPort: 9440 + name: healthz + protocol: TCP + readinessProbe: + httpGet: + path: / + port: http + {{- with .Values.sourceController.resources }} + resources: {{ toYaml . | nindent 10 }} + {{- end }} + {{- if .Values.sourceController.securityContext }} + securityContext: {{ toYaml .Values.sourceController.securityContext | nindent 10 }} + {{- else }} + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + readOnlyRootFilesystem: true + runAsNonRoot: true + seccompProfile: + type: RuntimeDefault + {{- end}} + volumeMounts: + - mountPath: /data + name: data + - mountPath: /tmp + name: tmp + {{- if .Values.sourceController.volumeMounts }} + {{- toYaml .Values.sourceController.volumeMounts | nindent 8 }} + {{- end}} + {{- if .Values.sourceController.priorityClassName }} + priorityClassName: {{ .Values.sourceController.priorityClassName | quote }} + {{- end }} + {{- if .Values.sourceController.podSecurityContext }} + securityContext: {{ toYaml .Values.sourceController.podSecurityContext | nindent 8 }} + {{- else }} + securityContext: + fsGroup: 1337 + {{- end}} + serviceAccountName: source-controller + {{- if .Values.imagePullSecrets }} + imagePullSecrets: {{ toYaml .Values.imagePullSecrets | nindent 6 }} + {{- end }} + terminationGracePeriodSeconds: 10 + volumes: + - emptyDir: {} + name: data + - emptyDir: {} + name: tmp + {{- if .Values.sourceController.volumes }} + {{- toYaml .Values.sourceController.volumes | nindent 6 }} + {{- end}} + {{- with .Values.sourceController.nodeSelector }} + nodeSelector: {{ toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.sourceController.affinity }} + affinity: {{ toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.sourceController.tolerations }} + tolerations: {{ toYaml . | nindent 8 }} + {{- end }} +{{- end }} diff --git a/packages/system/fluxcd/charts/flux2/values.yaml b/packages/system/fluxcd/charts/flux2/values.yaml new file mode 100644 index 00000000..3815b41d --- /dev/null +++ b/packages/system/fluxcd/charts/flux2/values.yaml @@ -0,0 +1,325 @@ +# global + +installCRDs: true +crds: + # -- Add annotations to all CRD resources, e.g. "helm.sh/resource-policy": keep + annotations: {} + +multitenancy: + # -- Implement the patches for Multi-tenancy lockdown. + # See https://fluxcd.io/docs/installation/#multi-tenancy-lockdown + enabled: false + # -- All Kustomizations and HelmReleases which don’t have spec.serviceAccountName + # specified, will use the default account from the tenant’s namespace. + # Tenants have to specify a service account in their Flux resources to be able + # to deploy workloads in their namespaces as the default account has no permissions. + defaultServiceAccount: "default" + # -- Both kustomize-controller and helm-controller service accounts run privileged + # with cluster-admin ClusterRoleBinding. Disable if you want to run them with a + # minimum set of permissions. + privileged: true + +clusterDomain: cluster.local + +cli: + image: ghcr.io/fluxcd/flux-cli + tag: v2.1.2 + nodeSelector: {} + affinity: {} + tolerations: [] + annotations: {} + serviceAccount: + automount: true + +# controllers + +helmController: + create: true + image: ghcr.io/fluxcd/helm-controller + tag: v0.36.2 + resources: + limits: {} + # cpu: 1000m + # memory: 1Gi + requests: + cpu: 100m + memory: 64Mi + priorityClassName: "" + annotations: + prometheus.io/port: "8080" + prometheus.io/scrape: "true" + labels: {} + container: + additionalArgs: [] + extraEnv: [] + serviceAccount: + create: true + automount: true + annotations: {} + imagePullPolicy: "" + nodeSelector: {} + # expects input structure as per specification https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.11/#affinity-v1-core + # for example: + # affinity: + # nodeAffinity: + # requiredDuringSchedulingIgnoredDuringExecution: + # nodeSelectorTerms: + # - matchExpressions: + # - key: foo.bar.com/role + # operator: In + # values: + # - master + + affinity: {} + # expects input structure as per specification https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.11/#toleration-v1-core + # for example: + # tolerations: + # - key: foo.bar.com/role + # operator: Equal + # value: master + # effect: NoSchedule + + tolerations: [] + +imageAutomationController: + create: true + image: ghcr.io/fluxcd/image-automation-controller + tag: v0.36.1 + resources: + limits: {} + # cpu: 1000m + # memory: 1Gi + requests: + cpu: 100m + memory: 64Mi + priorityClassName: "" + annotations: + prometheus.io/port: "8080" + prometheus.io/scrape: "true" + labels: {} + container: + additionalArgs: [] + extraEnv: [] + serviceAccount: + create: true + automount: true + annotations: {} + imagePullPolicy: "" + nodeSelector: {} + affinity: {} + tolerations: [] + +imageReflectionController: + create: true + image: ghcr.io/fluxcd/image-reflector-controller + tag: v0.30.0 + resources: + limits: {} + # cpu: 1000m + # memory: 1Gi + requests: + cpu: 100m + memory: 64Mi + priorityClassName: "" + annotations: + prometheus.io/port: "8080" + prometheus.io/scrape: "true" + labels: {} + container: + additionalArgs: [] + extraEnv: [] + serviceAccount: + create: true + automount: true + annotations: {} + imagePullPolicy: "" + nodeSelector: {} + affinity: {} + tolerations: [] + +kustomizeController: + create: true + image: ghcr.io/fluxcd/kustomize-controller + tag: v1.1.1 + resources: + limits: {} + # cpu: 1000m + # memory: 1Gi + requests: + cpu: 100m + memory: 64Mi + priorityClassName: "" + annotations: + prometheus.io/port: "8080" + prometheus.io/scrape: "true" + labels: {} + container: + additionalArgs: [] + extraEnv: [] + serviceAccount: + create: true + automount: true + annotations: {} + imagePullPolicy: "" + secret: + # -- Create a secret to use it with extraSecretMounts. Defaults to false. + create: false + name: "" + data: {} + # -- Defines envFrom using a configmap and/or secret. + envFrom: + map: + name: "" + secret: + name: "" + # -- Defines additional mounts with secrets. + # Secrets must be manually created in the namespace or with kustomizeController.secret + extraSecretMounts: [] + # - name: secret-files + # mountPath: /etc/secrets + # subPath: "" + # secretName: secret-files + # readOnly: true + + nodeSelector: {} + affinity: {} + tolerations: [] + +notificationController: + create: true + image: ghcr.io/fluxcd/notification-controller + tag: v1.1.0 + resources: + limits: {} + # cpu: 1000m + # memory: 1Gi + requests: + cpu: 100m + memory: 64Mi + priorityClassName: "" + annotations: + prometheus.io/port: "8080" + prometheus.io/scrape: "true" + labels: {} + container: + additionalArgs: [] + extraEnv: [] + serviceAccount: + create: true + automount: true + annotations: {} + imagePullPolicy: "" + service: + labels: {} + annotations: {} + webhookReceiver: + service: + labels: {} + annotations: {} + ingress: + create: false + # ingressClassName: nginx + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + labels: {} + hosts: + - host: flux-webhook.example.com + paths: + - path: / + pathType: ImplementationSpecific + tls: [] + # - secretName: flux-webhook-tls + # hosts: + # - flux-webhook.example.com + + + nodeSelector: {} + affinity: {} + tolerations: [] + +sourceController: + create: true + image: ghcr.io/fluxcd/source-controller + tag: v1.1.2 + resources: + limits: {} + # cpu: 1000m + # memory: 1Gi + requests: + cpu: 100m + memory: 64Mi + priorityClassName: "" + annotations: + prometheus.io/port: "8080" + prometheus.io/scrape: "true" + labels: {} + container: + additionalArgs: [] + serviceAccount: + create: true + automount: true + annotations: {} + imagePullPolicy: "" + service: + labels: {} + annotations: {} + nodeSelector: {} + affinity: {} + tolerations: [] + extraEnv: [] + +policies: + create: true + +rbac: + create: true + # -- Grant the Kubernetes view, edit and admin roles access to Flux custom resources + createAggregation: true + # -- Add annotations to all RBAC resources, e.g. "helm.sh/resource-policy": keep + annotations: {} + +logLevel: info +watchAllNamespaces: true + +# -- contents of pod imagePullSecret in form 'name=[secretName]'; applied to all controllers +imagePullSecrets: [] + +# -- Array of extra K8s manifests to deploy +extraObjects: [] +# Example usage from https://fluxcd.io/docs/components/source/buckets/#static-authentication +# - apiVersion: source.toolkit.fluxcd.io/v1beta2 +# kind: Bucket +# metadata: +# name: podinfo +# namespace: default +# spec: +# interval: 1m +# provider: generic +# bucketName: podinfo +# endpoint: minio.minio.svc.cluster.local:9000 +# insecure: true +# secretRef: +# name: minio-credentials +# - apiVersion: v1 +# kind: Secret +# metadata: +# name: minio-credentials +# namespace: default +# type: Opaque +# data: +# accesskey: +# secretkey: + +# Enables podMonitor creation for the Prometheus Operator +prometheus: + podMonitor: + # -- Enables podMonitor endpoint + create: false + podMetricsEndpoints: + - port: http-prom + relabelings: + # https://github.com/prometheus-operator/prometheus-operator/issues/4816 + - sourceLabels: [__meta_kubernetes_pod_phase] + action: keep + regex: Running diff --git a/packages/system/fluxcd/values.yaml b/packages/system/fluxcd/values.yaml new file mode 100644 index 00000000..e69de29b diff --git a/packages/system/grafana-oncall/Chart.yaml b/packages/system/grafana-oncall/Chart.yaml new file mode 100644 index 00000000..03573358 --- /dev/null +++ b/packages/system/grafana-oncall/Chart.yaml @@ -0,0 +1,2 @@ +name: cozy-grafana-oncall +version: 1.0.0 diff --git a/packages/system/grafana-oncall/Makefile b/packages/system/grafana-oncall/Makefile new file mode 100644 index 00000000..033be23a --- /dev/null +++ b/packages/system/grafana-oncall/Makefile @@ -0,0 +1,6 @@ +update: + rm -rf charts + helm repo add grafana https://grafana.github.io/helm-charts + helm repo update grafana + helm pull grafana/oncall --untar --untardir charts + rm -rf charts/oncall/charts diff --git a/packages/system/grafana-oncall/charts/oncall/.helmignore b/packages/system/grafana-oncall/charts/oncall/.helmignore new file mode 100644 index 00000000..fd6e5fd3 --- /dev/null +++ b/packages/system/grafana-oncall/charts/oncall/.helmignore @@ -0,0 +1,26 @@ +# 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/ + +# exclude helm unit tests +tests/ diff --git a/packages/system/grafana-oncall/charts/oncall/Chart.lock b/packages/system/grafana-oncall/charts/oncall/Chart.lock new file mode 100644 index 00000000..cab54bbf --- /dev/null +++ b/packages/system/grafana-oncall/charts/oncall/Chart.lock @@ -0,0 +1,27 @@ +dependencies: +- name: cert-manager + repository: https://charts.jetstack.io + version: v1.8.0 +- name: mariadb + repository: https://charts.bitnami.com/bitnami + version: 12.2.5 +- name: postgresql + repository: https://charts.bitnami.com/bitnami + version: 11.9.10 +- name: rabbitmq + repository: https://charts.bitnami.com/bitnami + version: 12.0.0 +- name: redis + repository: https://charts.bitnami.com/bitnami + version: 16.13.2 +- name: grafana + repository: https://grafana.github.io/helm-charts + version: 6.57.1 +- name: ingress-nginx + repository: https://kubernetes.github.io/ingress-nginx + version: 4.1.4 +- name: prometheus + repository: https://prometheus-community.github.io/helm-charts + version: 25.8.2 +digest: sha256:edc9fef449a694cd319135e37ac84f8247ac9ad0c48ac86099dae4e428beb7b7 +generated: "2024-01-26T17:54:48.132209769Z" diff --git a/packages/system/grafana-oncall/charts/oncall/Chart.yaml b/packages/system/grafana-oncall/charts/oncall/Chart.yaml new file mode 100644 index 00000000..3f490e21 --- /dev/null +++ b/packages/system/grafana-oncall/charts/oncall/Chart.yaml @@ -0,0 +1,39 @@ +apiVersion: v2 +appVersion: v1.3.94 +dependencies: +- condition: cert-manager.enabled + name: cert-manager + repository: https://charts.jetstack.io + version: v1.8.0 +- condition: mariadb.enabled + name: mariadb + repository: https://charts.bitnami.com/bitnami + version: 12.2.5 +- condition: postgresql.enabled + name: postgresql + repository: https://charts.bitnami.com/bitnami + version: 11.9.10 +- condition: rabbitmq.enabled + name: rabbitmq + repository: https://charts.bitnami.com/bitnami + version: 12.0.0 +- condition: redis.enabled + name: redis + repository: https://charts.bitnami.com/bitnami + version: 16.13.2 +- condition: grafana.enabled + name: grafana + repository: https://grafana.github.io/helm-charts + version: 6.57.1 +- condition: ingress-nginx.enabled + name: ingress-nginx + repository: https://kubernetes.github.io/ingress-nginx + version: 4.1.4 +- condition: prometheus.enabled + name: prometheus + repository: https://prometheus-community.github.io/helm-charts + version: 25.8.2 +description: Developer-friendly incident response with brilliant Slack integration +name: oncall +type: application +version: 1.3.94 diff --git a/packages/system/grafana-oncall/charts/oncall/README.md b/packages/system/grafana-oncall/charts/oncall/README.md new file mode 100644 index 00000000..993f0649 --- /dev/null +++ b/packages/system/grafana-oncall/charts/oncall/README.md @@ -0,0 +1,431 @@ +# Grafana OnCall Helm Chart + +This Grafana OnCall Chart is the best way to operate Grafana OnCall on Kubernetes. +It will deploy Grafana OnCall engine and celery workers, along with RabbitMQ cluster, Redis Cluster, and MySQL 5.7 database. +It will also deploy cert manager and nginx ingress controller, as Grafana OnCall backend might need to be externally available +to receive alerts from other monitoring systems. Grafana OnCall engine acts as a backend and can be connected to the +Grafana frontend plugin named Grafana OnCall. +Architecture diagram can be found [here](https://raw.githubusercontent.com/grafana/oncall/dev/docs/img/architecture_diagram.png) + +## Production usage + +**Default helm chart configuration is not intended for production.** +The helm chart includes all the services into a single release, which is not recommended for production usage. +It is recommended to run stateful services such as MySQL and RabbitMQ separately from this release or use managed +PaaS solutions. It will significantly reduce the overhead of managing them. +Here are the instructions on how to set up your own [ingress](#set-up-external-access), [MySQL](#connect-external-mysql), +[RabbitMQ](#connect-external-rabbitmq), [Redis](#connect-external-redis) + +### Cluster requirements + +- ensure you can run x86-64/amd64 workloads. arm64 architecture is currently not supported +- kubernetes version 1.25+ is not supported, if cert-manager is enabled + +## Install + +### Prepare the repo + +```bash +# Add the repository +helm repo add grafana https://grafana.github.io/helm-charts +helm repo update +``` + +### Installing the helm chart + +```bash +# Install the chart +helm install \ + --wait \ + --set base_url=example.com \ + --set grafana."grafana\.ini".server.domain=example.com \ + release-oncall \ + grafana/oncall +``` + +Follow the `helm install` output to finish setting up Grafana OnCall backend and Grafana OnCall frontend plugin e.g. + +```bash +👋 Your Grafana OnCall instance has been successfully deployed + + ❗ Set up a DNS record for your domain (use A Record and "@" to point a root domain to the IP address) + Get the external IP address by running the following commands and point example.com to it: + + kubectl get ingress release-oncall -o jsonpath="{.status.loadBalancer.ingress[0].ip}" + + Wait until the dns record got propagated. + NOTE: Check with the following command: nslookup example.com + Try reaching https://example.com/ready/ from the browser, make sure it is not cached locally + + 🦎 Grafana was installed as a part of this helm release. Open https://example.com/grafana/plugins/grafana-oncall-app + The User is admin + Get password by running this command: + + kubectl get secret --namespace default release-oncall-grafana -o jsonpath="{.data.admin-password}" | base64 --decode ; echo + + 🔗 Connect Grafana OnCall Plugin to Grafana OnCall backend: + + Fill the Grafana OnCall Backend URL: + + http://release-oncall-engine:8080 + +🎉🎉🎉 Done! 🎉🎉🎉 +``` + +## Configuration + +You can edit values.yml to make changes to the helm chart configuration and re-deploy the release with the following command: + +```bash +helm upgrade \ + --install \ + --wait \ + --set base_url=example.com \ + --set grafana."grafana\.ini".server.domain=example.com \ + release-oncall \ + grafana/oncall +``` + +### Passwords and external secrets + +As OnCall subcharts are Bitname charts, there is a common approach to secrets. Bundled charts allow specifying passwords +in values.yaml explicitly or as K8s secret value. OnCall chart refers either to secret created in sub-chart or +to specified external secret. +Similarly, if component chart is disabled, the password(s) can be supplied in `external` value +(e.g. externalMysql) explicitly or as K8s secret value. In the first case, the secret is created with the specified +value. In the second case the external secret is used. + +- If `.auth.existingSecret` is non-empty, then this secret is used. Secret keys are pre-defined by chart. +- If subchart supports password files and `.customPasswordFiles` dictionary is non-empty, then password files + are used. Dictionary keys are pre-defined per sub-chart. Password files are not supported by OnCall chart and should + not be used with bundled sub-charts. +- Passwords are specified via `auth` section values, e.g. `auth.password`. K8s secret is created. + - If `.auth.forcePassword` is `true`, then passwords MUST be specified. Otherwise, missing passwords + are generated. + +If external component is used instead of the bundled one: + +- If existingSecret within appropriate external component values is non-empty (e.g. `externalMysql.existingSecret`) then + it is used together with corresponding key names, e.g. `externalMysql.passwordKey`. +- Otherwise, corresponding password values are used, e.g. `externalMysql.password`. K8s secret is created by OnCall chart. + +Below is the summary for the dependent charts. + +MySQL/MariaDB: + +```yaml +database: + type: "mysql" # This is default +mariaDB: + enabled: true # Default + auth: + existingSecret: "" + forcePassword: false + # Secret name: `-mariadb` + rootPassword: "" # Secret key: mariadb-root-password + password: "" # Secret key: mariadb-password + replicationPassword: "" # Secret key: mariadb-replication-password +externalMysql: + password: "" + existingSecret: "" + passwordKey: "" +``` + +Postgres: + +```yaml +database: + type: postgresql +mariadb: + enabled: false # Must be set to false for Postgres +postgresql: + enabled: true # Must be set to true for bundled Postgres + auth: + existingSecret: "" + secretKeys: + adminPasswordKey: "" + userPasswordKey: "" # Not needed + replicationPasswordKey: "" # Not needed with disabled replication + # Secret name: `-postgresql` + postgresPassword: "" # password for admin user postgres. As non-admin user is not created, only this one is relevant. + password: "" # Not needed + replicationPassword: "" # Not needed with disabled replication +externalPostgresql: + user: "" + password: "" + existingSecret: "" + passwordKey: "" +``` + +Rabbitmq: + +```yaml +rabbitmq: + enabled: true + auth: + existingPasswordSecret: "" # Must contain `rabbitmq-password` key + existingErlangSecret: "" # Must contain `rabbitmq-erlang-cookie` key + # Secret name: `-rabbitmq` + password: "" + erlangCookie: "" +externalRabbitmq: + user: "" + password: "" + existingSecret: "" + passwordKey: "" + usernameKey: "" +``` + +Redis: + +```yaml +redis: + enabled: true + auth: + existingSecret: "" + existingSecretPasswordKey: "" + # Secret name: `-redis` + password: "" +externalRedis: + password: "" + existingSecret: "" + passwordKey: "" +``` + +### Running split ingestion and API services + +You can run a detached service for handling integrations by setting up the following variables: + +```yaml +detached_integrations: + enabled: true +detached_integrations_service: + enabled: true +``` + +This will run an integrations-only service listening by default in port 30003. + +### Set up Slack and Telegram + +You can set up Slack connection via following variables: + +```yaml +oncall: + slack: + enabled: true + commandName: oncall + clientId: ~ + clientSecret: ~ + signingSecret: ~ + existingSecret: "" + clientIdKey: "" + clientSecretKey: "" + signingSecretKey: "" + redirectHost: ~ +``` + +`oncall.slack.commandName` is used for changing default bot slash command, +`oncall`. In slack, it could be called via `/`. + +To set up Telegram token and webhook url use: + +```yaml +oncall: + telegram: + enabled: true + token: ~ + webhookUrl: ~ +``` + +To use Telegram long polling instead of webhook use: + +```yaml +telegramPolling: + enabled: true +``` + +### Set up external access + +Grafana OnCall can be connected to the external monitoring systems or grafana deployed to the other cluster. +Nginx Ingress Controller and Cert Manager charts are included in the helm chart with the default configuration. +If you set the DNS A Record pointing to the external IP address of the installation with the Hostname matching +base_url parameter, https will be automatically set up. If grafana is enabled in the chart values, it will also be +available on `https:///grafana/`. See the details in `helm install` output. + +To use a different ingress controller or tls certificate management system, set the following values to +false and edit ingress settings + +```yaml +ingress-nginx: + enabled: false + +cert-manager: + enabled: false + +ingress: + enabled: true + annotations: + kubernetes.io/ingress.class: "nginx" + cert-manager.io/issuer: "letsencrypt-prod" +``` + +### Use PostgreSQL instead of MySQL + +It is possible to use PostgreSQL instead of MySQL. To do so, set mariadb.enabled to `false`, +postgresql.enabled to `true` and database.type to `postgresql`. + +```yaml +mariadb: + enabled: false + +postgresql: + enabled: true + +database: + type: postgresql +``` + +### Connect external MySQL + +It is recommended to use the managed MySQL 5.7 database provided by your cloud provider +Make sure to create the database with the following parameters before installing this chart + +```sql +CREATE DATABASE oncall CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; +``` + +To use an external MySQL instance set mariadb.enabled to `false` and configure the `externalMysql` parameters. + +```yaml +mariadb: + enabled: false + +# Make sure to create the database with the following parameters: +# CREATE DATABASE oncall CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; +externalMysql: + host: + port: + db_name: + user: + password: + existingSecret: "" + usernameKey: username + passwordKey: password +``` + +### Connect external PostgreSQL + +To use an external PostgreSQL instance set mariadb.enabled to `false`, +postgresql.enabled to `false`, database.type to `postgresql` and configure +the `externalPostgresql` parameters. + +```yaml +mariadb: + enabled: false + +postgresql: + enabled: false + +database: + type: postgresql + +# Make sure to create the database with the following parameters: +# CREATE DATABASE oncall WITH ENCODING UTF8; +externalPostgresql: + host: + port: + db_name: + user: + password: + existingSecret: "" + passwordKey: password +``` + +### Connect external RabbitMQ + +Option 1. Install RabbitMQ separately into the cluster using the [official documentation](https://www.rabbitmq.com/kubernetes/operator/operator-overview.html) +Option 2. Use managed solution such as [CloudAMPQ](https://www.cloudamqp.com/) + +To use an external RabbitMQ instance set rabbitmq.enabled to `false` and configure the `externalRabbitmq` parameters. + +```yaml +rabbitmq: + enabled: false # Disable the RabbitMQ dependency from the release + +externalRabbitmq: + host: + port: + user: + password: + protocol: + vhost: + existingSecret: "" + passwordKey: password + usernameKey: username +``` + +### Connect external Redis + +To use an external Redis instance set redis.enabled to `false` and configure the `externalRedis` parameters. + +```yaml +redis: + enabled: false # Disable the Redis dependency from the release + +externalRedis: + host: + password: + existingSecret: "" + passwordKey: password +``` + +## Update + +```bash +# Add & upgrade the repository +helm repo add grafana https://grafana.github.io/helm-charts +helm repo update + +# Re-deploy +helm upgrade \ + --install \ + --wait \ + --set base_url=example.com \ + --set grafana."grafana\.ini".server.domain=example.com \ + release-oncall \ + grafana/oncall +``` + +After re-deploying, please also update the Grafana OnCall plugin on the plugin version page. +See [Grafana docs](https://grafana.com/docs/grafana/latest/administration/plugin-management/#update-a-plugin) for +more info on updating Grafana plugins. + +## Uninstall + +### Uninstalling the helm chart + +```bash +helm delete release-oncall +``` + +### Clean up PVC's + +```bash +kubectl delete pvc data-release-oncall-mariadb-0 data-release-oncall-rabbitmq-0 \ +redis-data-release-oncall-redis-master-0 redis-data-release-oncall-redis-replicas-0 \ +redis-data-release-oncall-redis-replicas-1 redis-data-release-oncall-redis-replicas-2 +``` + +### Clean up secrets + +```bash +kubectl delete secrets certificate-tls release-oncall-cert-manager-webhook-ca release-oncall-ingress-nginx-admission +``` + +## Troubleshooting + +### Issues during initial configuration + +In the event that you run into issues during initial configuration, it is possible that mismatching versions between +your OnCall backend and UI is the culprit. Ensure that the versions match, and if not, +consider updating your `helm` deployment. diff --git a/packages/system/grafana-oncall/charts/oncall/templates/NOTES.txt b/packages/system/grafana-oncall/charts/oncall/templates/NOTES.txt new file mode 100644 index 00000000..4eee164c --- /dev/null +++ b/packages/system/grafana-oncall/charts/oncall/templates/NOTES.txt @@ -0,0 +1,41 @@ +================================================================= +📞 Grafana OnCall Notes +================================================================= + +👋 Your Grafana OnCall instance has been successfully deployed + +{{- if not .Values.migrate.enabled }} + 🤖 To migrate the database run these commands: + + export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "oncall.name" . }},app.kubernetes.io/instance={{ .Release.Name }},app.kubernetes.io/component=engine" -o jsonpath="{.items[0].metadata.name}") + kubectl exec -it $POD_NAME -c wait-for-db -- bash -c "python manage.py migrate;" +{{- end }} + + ❗ Set up a DNS record for your domain (use A Record and "@" to point a root domain to the IP address) + Get the external IP address by running the following commands and point {{ .Values.base_url }} to it: + + kubectl get ingress {{ include "oncall.fullname" . }} -o jsonpath="{.status.loadBalancer.ingress[0].ip}" + + Wait until the dns record got propagated. + NOTE: Check with the following command: nslookup {{ .Values.base_url }} + Try reaching https://{{ .Values.base_url }}/ready/ from the browser, make sure it is not cached locally + +{{- if .Values.grafana.enabled }} + 🦎 Grafana was installed as a part of this helm release. Open https://{{ .Values.base_url }}/grafana/plugins/grafana-oncall-app + The User is {{ .Values.grafana.adminUser }} + Get password by running this command: + + kubectl get secret --namespace {{ .Release.Namespace }} {{ template "oncall.grafana.fullname" . }} -o jsonpath="{.data.admin-password}" | base64 --decode ; echo + +{{- else }} + 🦎 Grafana was NOT installed as a part of this helm release. Open external Grafana, go to "Configuration" - "Plugins" and find Grafana OnCall plugin + NOTE: Make sure your external Grafana is available by the network for the containers installed by this release. +{{- end }} + + 🔗 Connect Grafana OnCall Plugin to Grafana OnCall backend: + + Fill the Grafana OnCall Backend URL: + + http://{{ include "oncall.engine.fullname" . }}:8080 + +🎉🎉🎉 Done! 🎉🎉🎉 diff --git a/packages/system/grafana-oncall/charts/oncall/templates/_env.tpl b/packages/system/grafana-oncall/charts/oncall/templates/_env.tpl new file mode 100644 index 00000000..56dff3e5 --- /dev/null +++ b/packages/system/grafana-oncall/charts/oncall/templates/_env.tpl @@ -0,0 +1,656 @@ +{{- define "snippet.oncall.env" -}} +- name: BASE_URL + value: {{ .Values.base_url_protocol }}://{{ .Values.base_url }} +- name: SECRET_KEY + valueFrom: + secretKeyRef: + name: {{ include "snippet.oncall.secret.name" . }} + key: {{ include "snippet.oncall.secret.secretKey" . | quote }} +- name: MIRAGE_SECRET_KEY + valueFrom: + secretKeyRef: + name: {{ include "snippet.oncall.secret.name" . }} + key: {{ include "snippet.oncall.secret.mirageSecretKey" . | quote }} +- name: MIRAGE_CIPHER_IV + value: {{ .Values.oncall.mirageCipherIV | default "1234567890abcdef" | quote }} +- name: DJANGO_SETTINGS_MODULE + value: "settings.helm" +- name: AMIXR_DJANGO_ADMIN_PATH + value: "admin" +- name: OSS + value: "True" +- name: DETACHED_INTEGRATIONS_SERVER + value: {{ .Values.detached_integrations.enabled | toString | title | quote }} +{{- include "snippet.oncall.uwsgi" . }} +- name: BROKER_TYPE + value: {{ .Values.broker.type | default "rabbitmq" }} +- name: GRAFANA_API_URL + value: {{ include "snippet.grafana.url" . | quote }} +{{- end }} + +{{- define "snippet.oncall.secret.name" -}} +{{ if .Values.oncall.secrets.existingSecret -}} + {{ .Values.oncall.secrets.existingSecret }} +{{- else -}} + {{ include "oncall.fullname" . }} +{{- end }} +{{- end }} + +{{- define "snippet.oncall.secret.secretKey" -}} +{{ if .Values.oncall.secrets.existingSecret -}} + {{ required "oncall.secrets.secretKey is required if oncall.secret.existingSecret is not empty" .Values.oncall.secrets.secretKey }} +{{- else -}} + SECRET_KEY +{{- end }} +{{- end }} + +{{- define "snippet.oncall.secret.mirageSecretKey" -}} +{{ if .Values.oncall.secrets.existingSecret -}} + {{ required "oncall.secrets.mirageSecretKey is required if oncall.secret.existingSecret is not empty" .Values.oncall.secrets.mirageSecretKey }} +{{- else -}} + MIRAGE_SECRET_KEY +{{- end }} +{{- end }} + +{{- define "snippet.oncall.uwsgi" -}} +{{- if .Values.uwsgi }} + {{- range $key, $value := .Values.uwsgi }} +- name: UWSGI_{{ $key | upper | replace "-" "_" }} + value: {{ $value | quote }} + {{- end }} +{{- end }} +{{- end }} + +{{- define "snippet.oncall.slack.env" -}} +- name: FEATURE_SLACK_INTEGRATION_ENABLED + value: {{ .Values.oncall.slack.enabled | toString | title | quote }} +{{- if .Values.oncall.slack.enabled }} +- name: SLACK_SLASH_COMMAND_NAME + value: "/{{ .Values.oncall.slack.commandName | default "oncall" }}" +{{- if .Values.oncall.slack.existingSecret }} +- name: SLACK_CLIENT_OAUTH_ID + valueFrom: + secretKeyRef: + name: {{ .Values.oncall.slack.existingSecret }} + key: {{ required "oncall.slack.clientIdKey is required if oncall.slack.existingSecret is not empty" .Values.oncall.slack.clientIdKey | quote }} +- name: SLACK_CLIENT_OAUTH_SECRET + valueFrom: + secretKeyRef: + name: {{ .Values.oncall.slack.existingSecret }} + key: {{ required "oncall.slack.clientSecretKey is required if oncall.slack.existingSecret is not empty" .Values.oncall.slack.clientSecretKey | quote }} +- name: SLACK_SIGNING_SECRET + valueFrom: + secretKeyRef: + name: {{ .Values.oncall.slack.existingSecret }} + key: {{ required "oncall.slack.signingSecretKey is required if oncall.slack.existingSecret is not empty" .Values.oncall.slack.signingSecretKey | quote }} +{{- else }} +- name: SLACK_CLIENT_OAUTH_ID + value: {{ .Values.oncall.slack.clientId | default "" | quote }} +- name: SLACK_CLIENT_OAUTH_SECRET + value: {{ .Values.oncall.slack.clientSecret | default "" | quote }} +- name: SLACK_SIGNING_SECRET + value: {{ .Values.oncall.slack.signingSecret | default "" | quote }} +{{- end }} +- name: SLACK_INSTALL_RETURN_REDIRECT_HOST + value: {{ .Values.oncall.slack.redirectHost | default (printf "https://%s" .Values.base_url) | quote }} +{{- end }} +{{- end }} + +{{- define "snippet.oncall.telegram.env" -}} +{{- if .Values.telegramPolling.enabled -}} +{{- $_ := set .Values.oncall.telegram "enabled" true -}} +{{- end -}} +- name: FEATURE_TELEGRAM_INTEGRATION_ENABLED + value: {{ .Values.oncall.telegram.enabled | toString | title | quote }} +{{- if .Values.oncall.telegram.enabled }} +{{- if .Values.telegramPolling.enabled }} +- name: FEATURE_TELEGRAM_LONG_POLLING_ENABLED + value: {{ .Values.telegramPolling.enabled | toString | title | quote }} +{{- end }} +- name: TELEGRAM_WEBHOOK_HOST + value: {{ .Values.oncall.telegram.webhookUrl | default (printf "https://%s" .Values.base_url) | quote }} +{{- if .Values.oncall.telegram.existingSecret }} +- name: TELEGRAM_TOKEN + valueFrom: + secretKeyRef: + name: {{ .Values.oncall.telegram.existingSecret }} + key: {{ required "oncall.telegram.tokenKey is required if oncall.telegram.existingSecret is not empty" .Values.oncall.telegram.tokenKey | quote }} +{{- else }} +- name: TELEGRAM_TOKEN + value: {{ .Values.oncall.telegram.token | default "" | quote }} +{{- end }} +{{- end }} +{{- end }} + +{{- define "snippet.oncall.twilio.env" }} +{{- with .Values.oncall.twilio }} +{{- if .existingSecret }} +- name: TWILIO_ACCOUNT_SID + valueFrom: + secretKeyRef: + name: {{ .existingSecret }} + key: {{ required "oncall.twilio.accountSid is required if oncall.twilio.existingSecret is not empty" .accountSid | quote }} +{{- if .authTokenKey }} +- name: TWILIO_AUTH_TOKEN + valueFrom: + secretKeyRef: + name: {{ .existingSecret }} + key: {{ required "oncall.twilio.authTokenKey is required if oncall.twilio.existingSecret is not empty" .authTokenKey | quote }} +{{- end }} +- name: TWILIO_NUMBER + valueFrom: + secretKeyRef: + name: {{ .existingSecret }} + key: {{ required "oncall.twilio.phoneNumberKey is required if oncall.twilio.existingSecret is not empty" .phoneNumberKey | quote }} +- name: TWILIO_VERIFY_SERVICE_SID + valueFrom: + secretKeyRef: + name: {{ .existingSecret }} + key: {{ required "oncall.twilio.verifySidKey is required if oncall.twilio.existingSecret is not empty" .verifySidKey | quote }} +{{- if and .apiKeySidKey .apiKeySecretKey }} +- name: TWILIO_API_KEY_SID + valueFrom: + secretKeyRef: + name: {{ .existingSecret }} + key: {{ required "oncall.twilio.apiKeySidKey is required if oncall.twilio.existingSecret is not empty" .apiKeySidKey | quote }} +- name: TWILIO_API_KEY_SECRET + valueFrom: + secretKeyRef: + name: {{ .existingSecret }} + key: {{ required "oncall.twilio.apiKeySecretKey is required if oncall.twilio.existingSecret is not empty" .apiKeySecretKey | quote }} +{{- end }} +{{- else }} +{{- if .accountSid }} +- name: TWILIO_ACCOUNT_SID + value: {{ .accountSid | quote }} +{{- end }} +{{- if .authToken }} +- name: TWILIO_AUTH_TOKEN + value: {{ .authToken | quote }} +{{- end }} +{{- if .phoneNumber }} +- name: TWILIO_NUMBER + value: {{ .phoneNumber | quote }} +{{- end }} +{{- if .verifySid }} +- name: TWILIO_VERIFY_SERVICE_SID + value: {{ .verifySid | quote }} +{{- end }} +{{- if .apiKeySid }} +- name: TWILIO_API_KEY_SID + value: {{ .apiKeySid | quote }} +{{- end }} +{{- if .apiKeySecret }} +- name: TWILIO_API_KEY_SECRET + value: {{ .apiKeySecret | quote }} +{{- end }} +{{- end }} +{{- if .limitPhone }} +- name: PHONE_NOTIFICATIONS_LIMIT + value: {{ .limitPhone | quote }} +{{- end }} +{{- end }} +{{- end }} + +{{- define "snippet.celery.env" }} +{{- if .Values.celery.worker_queue }} +- name: CELERY_WORKER_QUEUE + value: {{ .Values.celery.worker_queue | quote }} +{{- end }} +{{- if .Values.celery.worker_concurrency }} +- name: CELERY_WORKER_CONCURRENCY + value: {{ .Values.celery.worker_concurrency | quote }} +{{- end }} +{{- if .Values.celery.worker_max_tasks_per_child }} +- name: CELERY_WORKER_MAX_TASKS_PER_CHILD + value: {{ .Values.celery.worker_max_tasks_per_child | quote }} +{{- end }} +{{- if .Values.celery.worker_beat_enabled }} +- name: CELERY_WORKER_BEAT_ENABLED + value: {{ .Values.celery.worker_beat_enabled | quote }} +{{- end }} +{{- if .Values.celery.worker_shutdown_interval }} +- name: CELERY_WORKER_SHUTDOWN_INTERVAL + value: {{ .Values.celery.worker_shutdown_interval | quote }} +{{- end }} +{{- end }} + +{{- define "snippet.grafana.url" -}} +{{ if .Values.grafana.enabled -}} + http://{{ include "oncall.grafana.fullname" . }} +{{- else -}} + {{ required "externalGrafana.url is required when not grafana.enabled" .Values.externalGrafana.url }} +{{- end }} +{{- end }} + +{{- define "snippet.mysql.env" -}} +- name: MYSQL_HOST + value: {{ include "snippet.mysql.host" . | quote }} +- name: MYSQL_PORT + value: {{ include "snippet.mysql.port" . | quote }} +- name: MYSQL_DB_NAME + value: {{ include "snippet.mysql.db" . | quote }} +- name: MYSQL_USER +{{- if and (not .Values.mariadb.enabled) .Values.externalMysql.existingSecret .Values.externalMysql.usernameKey (not .Values.externalMysql.user) }} + valueFrom: + secretKeyRef: + name: {{ include "snippet.mysql.password.secret.name" . }} + key: {{ .Values.externalMysql.usernameKey | quote }} +{{- else }} + value: {{ include "snippet.mysql.user" . | quote }} +{{- end }} +- name: MYSQL_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "snippet.mysql.password.secret.name" . }} + key: {{ include "snippet.mysql.password.secret.key" . | quote }} +{{- if not .Values.mariadb.enabled }} +{{- with .Values.externalMysql.options }} +- name: MYSQL_OPTIONS + value: {{ . | quote }} +{{- end }} +{{- end }} +{{- end }} + +{{- define "snippet.mysql.password.secret.name" -}} +{{ if .Values.mariadb.enabled -}} + {{ if .Values.mariadb.auth.existingSecret -}} + {{ .Values.mariadb.auth.existingSecret }} + {{- else -}} + {{ include "oncall.mariadb.fullname" . }} + {{- end }} +{{- else -}} + {{ if .Values.externalMysql.existingSecret -}} + {{ .Values.externalMysql.existingSecret }} + {{- else -}} + {{ include "oncall.fullname" . }}-mysql-external + {{- end }} +{{- end }} +{{- end }} + +{{- define "snippet.mysql.password.secret.key" -}} +{{ if and (not .Values.mariadb.enabled) .Values.externalMysql.existingSecret .Values.externalMysql.passwordKey -}} + {{ .Values.externalMysql.passwordKey }} +{{- else -}} + mariadb-root-password +{{- end }} +{{- end }} + +{{- define "snippet.mysql.host" -}} +{{ if and (not .Values.mariadb.enabled) .Values.externalMysql.host -}} + {{ .Values.externalMysql.host }} +{{- else -}} + {{ include "oncall.mariadb.fullname" . }} +{{- end }} +{{- end }} + +{{- define "snippet.mysql.port" -}} +{{ if and (not .Values.mariadb.enabled) .Values.externalMysql.port -}} + {{ .Values.externalMysql.port }} +{{- else -}} + 3306 +{{- end }} +{{- end }} + +{{- define "snippet.mysql.db" -}} +{{ if and (not .Values.mariadb.enabled) .Values.externalMysql.db_name -}} + {{ .Values.externalMysql.db_name }} +{{- else -}} + {{ .Values.mariadb.auth.database | default "oncall" }} +{{- end }} +{{- end }} + +{{- define "snippet.mysql.user" -}} +{{ if and (not .Values.mariadb.enabled) .Values.externalMysql.user -}} + {{ .Values.externalMysql.user }} +{{- else -}} + {{ .Values.mariadb.auth.username | default "root" }} +{{- end }} +{{- end }} + +{{- define "snippet.postgresql.env" -}} +- name: DATABASE_TYPE + value: {{ .Values.database.type | quote }} +- name: DATABASE_HOST + value: {{ include "snippet.postgresql.host" . | quote }} +- name: DATABASE_PORT + value: {{ include "snippet.postgresql.port" . | quote }} +- name: DATABASE_NAME + value: {{ include "snippet.postgresql.db" . | quote }} +- name: DATABASE_USER + value: {{ include "snippet.postgresql.user" . | quote }} +- name: DATABASE_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "snippet.postgresql.password.secret.name" . }} + key: {{ include "snippet.postgresql.password.secret.key" . | quote }} +{{- if not .Values.postgresql.enabled }} +{{- with .Values.externalPostgresql.options }} +- name: DATABASE_OPTIONS + value: {{ . | quote }} +{{- end }} +{{- end }} +{{- end }} + +{{- define "snippet.sqlite.env" -}} +- name: DATABASE_TYPE + value: sqlite3 +- name: DATABASE_NAME + value: /etc/app/oncall.db +{{- end }} + +{{- define "snippet.postgresql.password.secret.name" -}} +{{ if .Values.postgresql.enabled -}} + {{ if .Values.postgresql.auth.existingSecret -}} + {{ .Values.postgresql.auth.existingSecret }} + {{- else -}} + {{ include "oncall.postgresql.fullname" . }} + {{- end }} +{{- else -}} + {{ if .Values.externalPostgresql.existingSecret -}} + {{ .Values.externalPostgresql.existingSecret }} + {{- else -}} + {{ include "oncall.fullname" . }}-postgresql-external + {{- end }} +{{- end }} +{{- end }} + +{{- define "snippet.postgresql.password.secret.key" -}} +{{ if .Values.postgresql.enabled -}} + {{ if .Values.postgresql.auth.existingSecret -}} + {{ required "postgresql.auth.secretKeys.adminPasswordKey is required if database.type=postgres and postgresql.enabled and postgresql.auth.existingSecret" .Values.postgresql.auth.secretKeys.adminPasswordKey }} + {{- else -}} + {{ include "postgresql.userPasswordKey" .Subcharts.postgresql }} + {{- end }} +{{- else -}} + {{ if .Values.externalPostgresql.existingSecret -}} + {{ required "externalPostgresql.passwordKey is required if database.type=postgres and not postgresql.enabled and postgresql.auth.existingSecret" .Values.externalPostgresql.passwordKey }} + {{- else -}} + postgres-password + {{- end }} +{{- end }} +{{- end }} + +{{- define "snippet.postgresql.host" -}} +{{ if not .Values.postgresql.enabled -}} + {{ required "externalPostgresql.host is required if database.type=postgres and not postgresql.enabled" .Values.externalPostgresql.host }} +{{- else -}} + {{ include "oncall.postgresql.fullname" . }} +{{- end }} +{{- end }} + +{{- define "snippet.postgresql.port" -}} +{{ if and (not .Values.postgresql.enabled) .Values.externalPostgresql.port -}} + {{ .Values.externalPostgresql.port }} +{{- else -}} + 5432 +{{- end }} +{{- end }} + +{{- define "snippet.postgresql.db" -}} +{{ if not .Values.postgresql.enabled -}} + {{ .Values.externalPostgresql.db_name | default "oncall" }} +{{- else -}} + {{ .Values.postgresql.auth.database | default "oncall" }} +{{- end }} +{{- end }} + +{{- define "snippet.postgresql.user" -}} +{{ if not .Values.postgresql.enabled -}} + {{ .Values.externalPostgresql.user | default "postgres" }} +{{- else -}} + {{ .Values.postgresql.auth.username | default "postgres" }} +{{- end }} +{{- end }} + +{{- define "snippet.rabbitmq.env" }} +- name: RABBITMQ_USERNAME +{{- if and (not .Values.rabbitmq.enabled) .Values.externalRabbitmq.existingSecret .Values.externalRabbitmq.usernameKey (not .Values.externalRabbitmq.user) }} + valueFrom: + secretKeyRef: + name: {{ include "snippet.rabbitmq.password.secret.name" . }} + key: {{ .Values.externalRabbitmq.usernameKey | quote }} +{{- else }} + value: {{ include "snippet.rabbitmq.user" . | quote }} +{{- end }} +- name: RABBITMQ_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "snippet.rabbitmq.password.secret.name" . }} + key: {{ include "snippet.rabbitmq.password.secret.key" . | quote }} +- name: RABBITMQ_HOST + value: {{ include "snippet.rabbitmq.host" . | quote }} +- name: RABBITMQ_PORT + value: {{ include "snippet.rabbitmq.port" . | quote }} +- name: RABBITMQ_PROTOCOL + value: {{ include "snippet.rabbitmq.protocol" . | quote }} +- name: RABBITMQ_VHOST + value: {{ include "snippet.rabbitmq.vhost" . | quote }} +{{- end }} + +{{- define "snippet.rabbitmq.user" -}} +{{ if not .Values.rabbitmq.enabled -}} + {{ required "externalRabbitmq.user is required if not rabbitmq.enabled" .Values.externalRabbitmq.user }} +{{- else -}} + user +{{- end }} +{{- end }} + +{{- define "snippet.rabbitmq.host" -}} +{{ if not .Values.rabbitmq.enabled -}} + {{ required "externalRabbitmq.host is required if not rabbitmq.enabled" .Values.externalRabbitmq.host }} +{{- else -}} + {{ include "oncall.rabbitmq.fullname" . }} +{{- end }} +{{- end }} + +{{- define "snippet.rabbitmq.port" -}} +{{ if and (not .Values.rabbitmq.enabled) .Values.externalRabbitmq.port -}} + {{ required "externalRabbitmq.port is required if not rabbitmq.enabled" .Values.externalRabbitmq.port }} +{{- else -}} + 5672 +{{- end }} +{{- end }} + +{{- define "snippet.rabbitmq.protocol" -}} +{{ if and (not .Values.rabbitmq.enabled) .Values.externalRabbitmq.protocol -}} + {{ .Values.externalRabbitmq.protocol }} +{{- else -}} + amqp +{{- end }} +{{- end }} + +{{- define "snippet.rabbitmq.vhost" -}} +{{ if and (not .Values.rabbitmq.enabled) .Values.externalRabbitmq.vhost -}} + {{ .Values.externalRabbitmq.vhost }} +{{- end }} +{{- end }} + +{{- define "snippet.rabbitmq.password.secret.name" -}} +{{ if .Values.rabbitmq.enabled -}} + {{ if .Values.rabbitmq.auth.existingPasswordSecret -}} + {{ .Values.rabbitmq.auth.existingPasswordSecret }} + {{- else -}} + {{ include "oncall.rabbitmq.fullname" . }} + {{- end }} +{{- else -}} + {{ if .Values.externalRabbitmq.existingSecret -}} + {{ .Values.externalRabbitmq.existingSecret }} + {{- else -}} + {{ include "oncall.fullname" . }}-rabbitmq-external + {{- end }} +{{- end }} +{{- end }} + +{{- define "snippet.rabbitmq.password.secret.key" -}} +{{ if and (not .Values.rabbitmq.enabled) .Values.externalRabbitmq.passwordKey -}} + {{ .Values.externalRabbitmq.passwordKey }} +{{- else -}} + rabbitmq-password +{{- end }} +{{- end }} + +{{- define "snippet.redis.protocol" -}} +{{ default "redis" .Values.externalRedis.protocol | quote }} +{{- end }} + +{{- define "snippet.redis.host" -}} +{{ if not .Values.redis.enabled -}} + {{ required "externalRedis.host is required if not redis.enabled" .Values.externalRedis.host | quote }} +{{- else -}} + {{ include "oncall.redis.fullname" . }}-master +{{- end }} +{{- end }} + +{{- define "snippet.redis.port" -}} +{{ default 6379 .Values.externalRedis.port | quote }} +{{- end }} + +{{- define "snippet.redis.database" -}} +{{ default 0 .Values.externalRedis.database | quote }} +{{- end }} + +{{- define "snippet.redis.password.secret.name" -}} +{{ if .Values.redis.enabled -}} + {{ if .Values.redis.auth.existingSecret -}} + {{ .Values.redis.auth.existingSecret }} + {{- else -}} + {{ include "oncall.redis.fullname" . }} + {{- end }} +{{- else -}} + {{ if .Values.externalRedis.existingSecret -}} + {{ .Values.externalRedis.existingSecret }} + {{- else -}} + {{ include "oncall.fullname" . }}-redis-external + {{- end }} +{{- end }} +{{- end }} + +{{- define "snippet.redis.password.secret.key" -}} +{{ if .Values.redis.enabled -}} + {{ if .Values.redis.auth.existingSecret -}} + {{ required "redis.auth.existingSecretPasswordKey is required if redis.auth.existingSecret is non-empty" .Values.redis.auth.existingSecretPasswordKey }} + {{- else -}} + redis-password + {{- end }} +{{- else -}} + {{ if .Values.externalRedis.existingSecret -}} + {{ required "externalRedis.passwordKey is required if externalRedis.existingSecret is non-empty" .Values.externalRedis.passwordKey }} + {{- else -}} + redis-password + {{- end }} +{{- end }} +{{- end }} + +{{- define "snippet.redis.env" -}} +- name: REDIS_PROTOCOL + value: {{ include "snippet.redis.protocol" . }} +- name: REDIS_HOST + value: {{ include "snippet.redis.host" . }} +- name: REDIS_PORT + value: {{ include "snippet.redis.port" . }} +- name: REDIS_DATABASE + value: {{ include "snippet.redis.database" . }} +- name: REDIS_USERNAME + value: {{ default "" .Values.externalRedis.username | quote }} +- name: REDIS_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "snippet.redis.password.secret.name" . }} + key: {{ include "snippet.redis.password.secret.key" . | quote}} +{{- if and (not .Values.redis.enabled) .Values.externalRedis.ssl_options.enabled }} +- name: REDIS_USE_SSL + value: "true" +{{- with .Values.externalRedis.ssl_options.ca_certs }} +- name: REDIS_SSL_CA_CERTS + value: {{ . | quote }} +{{- end }} +{{- with .Values.externalRedis.ssl_options.certfile }} +- name: REDIS_SSL_CERTFILE + value: {{ . | quote }} +{{- end }} +{{- with .Values.externalRedis.ssl_options.keyfile }} +- name: REDIS_SSL_KEYFILE + value: {{ . | quote }} +{{- end }} +{{- with .Values.externalRedis.ssl_options.cert_reqs }} +- name: REDIS_SSL_CERT_REQS + value: {{ . | quote }} +{{- end }} +{{- end }} +{{- end }} + +{{- /* +when broker.type != rabbitmq, we do not need to include rabbitmq environment variables +*/}} +{{- define "snippet.broker.env" -}} +{{- include "snippet.redis.env" . }} +{{- if eq .Values.broker.type "rabbitmq" -}} +{{- include "snippet.rabbitmq.env" . }} +{{- end }} +{{- end }} + +{{- define "snippet.db.env" -}} +{{- if eq .Values.database.type "mysql" }} +{{- include "snippet.mysql.env" . }} +{{- else if eq .Values.database.type "postgresql" }} +{{- include "snippet.postgresql.env" . }} +{{- else if eq .Values.database.type "sqlite" -}} +{{- include "snippet.sqlite.env" . }} +{{- else -}} +{{- fail "value for .Values.db.type must be either 'mysql', 'postgresql', or 'sqlite'" }} +{{- end }} +{{- end }} + +{{- define "snippet.oncall.smtp.env" -}} +- name: FEATURE_EMAIL_INTEGRATION_ENABLED + value: {{ .Values.oncall.smtp.enabled | toString | title | quote }} +{{- if .Values.oncall.smtp.enabled }} +- name: EMAIL_HOST + value: {{ .Values.oncall.smtp.host | quote }} +- name: EMAIL_PORT + value: {{ .Values.oncall.smtp.port | default "587" | quote }} +- name: EMAIL_HOST_USER + value: {{ .Values.oncall.smtp.username | quote }} +- name: EMAIL_HOST_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "oncall.fullname" . }}-smtp + key: smtp-password + optional: true +- name: EMAIL_USE_TLS + value: {{ .Values.oncall.smtp.tls | default true | toString | title | quote }} +- name: EMAIL_FROM_ADDRESS + value: {{ .Values.oncall.smtp.fromEmail | quote }} +- name: EMAIL_NOTIFICATIONS_LIMIT + value: {{ .Values.oncall.smtp.limitEmail | default "200" | quote }} +{{- end }} +{{- end }} + +{{- define "snippet.oncall.exporter.env" -}} +{{ if .Values.oncall.exporter.enabled -}} +- name: FEATURE_PROMETHEUS_EXPORTER_ENABLED + value: {{ .Values.oncall.exporter.enabled | toString | title | quote }} +- name: PROMETHEUS_EXPORTER_SECRET + valueFrom: + secretKeyRef: + name: {{ include "oncall.fullname" . }}-exporter + key: exporter-secret + optional: true +{{- else -}} +- name: FEATURE_PROMETHEUS_EXPORTER_ENABLED + value: {{ .Values.oncall.exporter.enabled | toString | title | quote }} +{{- end }} +{{- end }} + +{{- define "snippet.oncall.engine.env" -}} +{{ include "snippet.oncall.env" . }} +{{ include "snippet.oncall.slack.env" . }} +{{ include "snippet.oncall.telegram.env" . }} +{{ include "snippet.oncall.smtp.env" . }} +{{ include "snippet.oncall.twilio.env" . }} +{{ include "snippet.oncall.exporter.env" . }} +{{ include "snippet.db.env" . }} +{{ include "snippet.broker.env" . }} +{{ include "oncall.extraEnvs" . }} +{{- end }} diff --git a/packages/system/grafana-oncall/charts/oncall/templates/_helpers.tpl b/packages/system/grafana-oncall/charts/oncall/templates/_helpers.tpl new file mode 100644 index 00000000..6486bfe5 --- /dev/null +++ b/packages/system/grafana-oncall/charts/oncall/templates/_helpers.tpl @@ -0,0 +1,121 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "oncall.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | 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 "oncall.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "oncall.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "oncall.labels" -}} +helm.sh/chart: {{ include "oncall.chart" . }} +{{ include "oncall.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "oncall.selectorLabels" -}} +app.kubernetes.io/name: {{ include "oncall.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "oncall.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "oncall.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} + +{{/* Generate the fullname of mariadb subchart */}} +{{- define "oncall.mariadb.fullname" -}} +{{- printf "%s-%s" .Release.Name "mariadb" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* Generate the fullname of postgresql subchart */}} +{{- define "oncall.postgresql.fullname" -}} +{{- printf "%s-%s" .Release.Name "postgresql" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{- define "oncall.grafana.fullname" -}} +{{- printf "%s-%s" .Release.Name "grafana" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* Generate the fullname of rabbitmq subchart */}} +{{- define "oncall.rabbitmq.fullname" -}} +{{- printf "%s-%s" .Release.Name "rabbitmq" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* Generate the fullname of redis subchart */}} +{{- define "oncall.redis.fullname" -}} +{{- printf "%s-%s" .Release.Name "redis" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* Generate engine image name */}} +{{- define "oncall.engine.image" -}} +{{- printf "%s:%s" .Values.image.repository (.Values.image.tag | default .Chart.AppVersion) }} +{{- end }} + +{{- define "oncall.initContainer" }} +- name: wait-for-db + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + command: ['sh', '-c', "until (python manage.py migrate --check); do echo Waiting for database migrations; sleep 2; done"] + securityContext: + {{ toYaml .Values.init.securityContext | nindent 4 }} + resources: + {{ toYaml .Values.init.resources | nindent 4 }} + env: + {{- include "snippet.oncall.env" . | nindent 4 }} + {{- include "snippet.db.env" . | nindent 4 }} + {{- include "snippet.broker.env" . | nindent 4 }} + {{- include "oncall.extraEnvs" . | nindent 4 }} +{{- end }} + +{{- define "oncall.extraEnvs" -}} +{{- if .Values.env }} + {{- if (kindIs "map" .Values.env) }} + {{- range $key, $value := .Values.env }} +- name: {{ $key }} + value: {{ $value }} + {{- end -}} + {{/* support previous schema */}} + {{- else }} +{{- toYaml .Values.env }} + {{- end }} +{{- end }} +{{- end }} diff --git a/packages/system/grafana-oncall/charts/oncall/templates/celery/_helpers.tpl b/packages/system/grafana-oncall/charts/oncall/templates/celery/_helpers.tpl new file mode 100644 index 00000000..8c37e957 --- /dev/null +++ b/packages/system/grafana-oncall/charts/oncall/templates/celery/_helpers.tpl @@ -0,0 +1,26 @@ +{{/* +Maximum of 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +*/}} +{{- define "oncall.celery.name" -}} +{{ include "oncall.name" . | trunc 55 }}-celery +{{- end }} + +{{- define "oncall.celery.fullname" -}} +{{ include "oncall.fullname" . | trunc 55 }}-celery +{{- end }} + +{{/* +Engine common labels +*/}} +{{- define "oncall.celery.labels" -}} +{{ include "oncall.labels" . }} +app.kubernetes.io/component: celery +{{- end }} + +{{/* +Engine selector labels +*/}} +{{- define "oncall.celery.selectorLabels" -}} +{{ include "oncall.selectorLabels" . }} +app.kubernetes.io/component: celery +{{- end }} diff --git a/packages/system/grafana-oncall/charts/oncall/templates/celery/deployment.yaml b/packages/system/grafana-oncall/charts/oncall/templates/celery/deployment.yaml new file mode 100644 index 00000000..b2498dd1 --- /dev/null +++ b/packages/system/grafana-oncall/charts/oncall/templates/celery/deployment.yaml @@ -0,0 +1,89 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "oncall.celery.fullname" . }} + labels: + {{- include "oncall.celery.labels" . | nindent 4 }} +spec: + replicas: {{ .Values.celery.replicaCount }} + selector: + matchLabels: + {{- include "oncall.celery.selectorLabels" . | nindent 6 }} + template: + metadata: + {{- with .Values.podAnnotations }} + annotations: + random-annotation: {{ randAlphaNum 10 | lower }} + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "oncall.celery.selectorLabels" . | nindent 8 }} + {{- if .Values.celery.podLabels }} + {{- toYaml .Values.celery.podLabels | nindent 8}} + {{- end }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "oncall.serviceAccountName" . }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + initContainers: + {{- include "oncall.initContainer" . | indent 8 }} + {{- with .Values.celery.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.celery.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.celery.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.celery.topologySpreadConstraints }} + topologySpreadConstraints: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.celery.priorityClassName }} + priorityClassName: {{ . }} + {{- end }} + containers: + - name: {{ .Chart.Name }} + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + image: {{ include "oncall.engine.image" . }} + {{- if .Values.oncall.devMode }} + command: ["python", "manage.py", "start_celery"] + {{- else }} + command: ["./celery_with_exporter.sh"] + {{- end }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + env: + {{- include "snippet.celery.env" . | nindent 12 }} + {{- include "snippet.oncall.engine.env" . | nindent 12 }} + {{- if .Values.celery.livenessProbe.enabled }} + livenessProbe: + exec: + command: [ + "bash", + "-c", + "celery -A engine inspect ping -d celery@$HOSTNAME" + ] + initialDelaySeconds: {{ .Values.celery.livenessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.celery.livenessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.celery.livenessProbe.timeoutSeconds }} + {{- end }} + resources: + {{- toYaml .Values.celery.resources | nindent 12 }} + {{- with .Values.celery.extraVolumeMounts }} + volumeMounts: {{- . | toYaml | nindent 12 }} + {{- end }} + {{- with .Values.celery.extraContainers }} + {{- tpl . $ | nindent 8 }} + {{- end }} + {{- with .Values.celery.extraVolumes }} + volumes: {{- . | toYaml | nindent 8 }} + {{- end }} diff --git a/packages/system/grafana-oncall/charts/oncall/templates/cert-issuer.yaml b/packages/system/grafana-oncall/charts/oncall/templates/cert-issuer.yaml new file mode 100644 index 00000000..8b1716f3 --- /dev/null +++ b/packages/system/grafana-oncall/charts/oncall/templates/cert-issuer.yaml @@ -0,0 +1,22 @@ +{{- if (index .Values "cert-manager").enabled }} +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + name: letsencrypt-prod + annotations: + "helm.sh/hook": post-install,post-upgrade +spec: + acme: + # The ACME server URL + server: https://acme-v02.api.letsencrypt.org/directory + # Email address used for ACME registration + email: no-reply@{{ .Values.base_url }} + # Name of a secret used to store the ACME account private key + privateKeySecretRef: + name: letsencrypt-prod + # Enable the HTTP-01 challenge provider + solvers: + - http01: + ingress: + class: nginx +{{- end }} diff --git a/packages/system/grafana-oncall/charts/oncall/templates/engine/_helpers-engine.tpl b/packages/system/grafana-oncall/charts/oncall/templates/engine/_helpers-engine.tpl new file mode 100644 index 00000000..6d498e93 --- /dev/null +++ b/packages/system/grafana-oncall/charts/oncall/templates/engine/_helpers-engine.tpl @@ -0,0 +1,26 @@ +{{/* +Maximum of 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +*/}} +{{- define "oncall.engine.name" -}} +{{ include "oncall.name" . | trunc 55 }}-engine +{{- end }} + +{{- define "oncall.engine.fullname" -}} +{{ include "oncall.fullname" . | trunc 55 }}-engine +{{- end }} + +{{/* +Engine common labels +*/}} +{{- define "oncall.engine.labels" -}} +{{ include "oncall.labels" . }} +app.kubernetes.io/component: engine +{{- end }} + +{{/* +Engien selector labels +*/}} +{{- define "oncall.engine.selectorLabels" -}} +{{ include "oncall.selectorLabels" . }} +app.kubernetes.io/component: engine +{{- end }} diff --git a/packages/system/grafana-oncall/charts/oncall/templates/engine/deployment.yaml b/packages/system/grafana-oncall/charts/oncall/templates/engine/deployment.yaml new file mode 100644 index 00000000..ccb770df --- /dev/null +++ b/packages/system/grafana-oncall/charts/oncall/templates/engine/deployment.yaml @@ -0,0 +1,98 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "oncall.engine.fullname" . }} + labels: + {{- include "oncall.engine.labels" . | nindent 4 }} +spec: + replicas: {{ .Values.engine.replicaCount }} + selector: + matchLabels: + {{- include "oncall.engine.selectorLabels" . | nindent 6 }} + strategy: + {{- toYaml .Values.engine.updateStrategy | nindent 4 }} + template: + metadata: + {{- with .Values.podAnnotations }} + annotations: + random-annotation: {{ randAlphaNum 10 | lower }} + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "oncall.engine.selectorLabels" . | nindent 8 }} + {{- if .Values.engine.podLabels }} + {{- toYaml .Values.engine.podLabels | nindent 8}} + {{- end }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "oncall.serviceAccountName" . }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + initContainers: + {{- include "oncall.initContainer" . | indent 8 }} + containers: + - name: {{ .Chart.Name }} + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + image: {{ include "oncall.engine.image" . }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + {{- if .Values.oncall.devMode }} + command: ["sh", "-c", "uwsgi --disable-logging --py-autoreload 3 --ini uwsgi.ini"] + {{- end }} + ports: + - name: http + containerPort: 8080 + protocol: TCP + env: + {{- include "snippet.oncall.engine.env" . | nindent 12 }} + livenessProbe: + httpGet: + path: /health/ + port: http + periodSeconds: 60 + timeoutSeconds: 3 + readinessProbe: + httpGet: + path: /ready/ + port: http + periodSeconds: 60 + timeoutSeconds: 3 + startupProbe: + httpGet: + path: /startupprobe/ + port: http + periodSeconds: 10 + timeoutSeconds: 3 + resources: + {{- toYaml .Values.engine.resources | nindent 12 }} + {{- with .Values.engine.extraVolumeMounts }} + volumeMounts: {{- . | toYaml | nindent 12 }} + {{- end }} + {{- with .Values.engine.extraContainers }} + {{- tpl . $ | nindent 8 }} + {{- end }} + {{- with .Values.engine.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.engine.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.engine.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.engine.topologySpreadConstraints }} + topologySpreadConstraints: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.engine.priorityClassName }} + priorityClassName: {{ . }} + {{- end }} + {{- with .Values.engine.extraVolumes }} + volumes: {{- . | toYaml | nindent 8 }} + {{- end }} diff --git a/packages/system/grafana-oncall/charts/oncall/templates/engine/job-migrate.yaml b/packages/system/grafana-oncall/charts/oncall/templates/engine/job-migrate.yaml new file mode 100644 index 00000000..09782954 --- /dev/null +++ b/packages/system/grafana-oncall/charts/oncall/templates/engine/job-migrate.yaml @@ -0,0 +1,102 @@ +{{- if .Values.migrate.enabled -}} +apiVersion: batch/v1 +kind: Job +metadata: + {{- if .Values.migrate.useHook }} + name: {{ printf "%s-migrate" (include "oncall.engine.fullname" .) }} + annotations: + "helm.sh/hook": pre-install,pre-upgrade + "helm.sh/hook-weight": "-1" + {{- with .Values.migrate.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- else }} + name: {{ printf "%s-migrate-%s" (include "oncall.engine.fullname" .) (now | date "2006-01-02-15-04-05") }} + {{- with .Values.migrate.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} + {{- end }} + labels: + {{- include "oncall.engine.labels" . | nindent 4 }} +spec: + backoffLimit: 15 + {{- if .Values.migrate.ttlSecondsAfterFinished }} + ttlSecondsAfterFinished: {{ .Values.migrate.ttlSecondsAfterFinished }} + {{- end }} + template: + metadata: + name: {{ printf "%s-migrate-%s" (include "oncall.engine.fullname" .) (now | date "2006-01-02-15-04-05") }} + {{- with .Values.podAnnotations }} + annotations: + random-annotation: {{ randAlphaNum 10 | lower }} + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "oncall.engine.selectorLabels" . | nindent 8 }} + spec: + restartPolicy: Never + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "oncall.serviceAccountName" . }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + {{- with .Values.migrate.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.migrate.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.migrate.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: {{ .Chart.Name }}-migrate + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + image: {{ include "oncall.engine.image" . }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + command: + - /bin/sh + - -c + {{- if eq .Values.database.type "mysql" }} + - | + until (nc -vz $MYSQL_HOST $MYSQL_PORT); + do + echo "waiting for MySQL"; sleep 1; + done + python manage.py migrate + {{- else if eq .Values.database.type "postgresql" }} + - | + until (nc -vz $DATABASE_HOST $DATABASE_PORT); + do + echo "waiting for PostgreSQL"; sleep 1; + done + python manage.py migrate + {{- else }} + - python manage.py migrate + {{- end }} + env: + {{- include "snippet.oncall.env" . | nindent 12 }} + {{- include "snippet.oncall.smtp.env" . | nindent 12 }} + {{- include "snippet.oncall.exporter.env" . | nindent 12 }} + {{- include "snippet.db.env" . | nindent 12 }} + {{- include "snippet.broker.env" . | nindent 12 }} + {{- include "oncall.extraEnvs" . | nindent 12 }} + resources: + {{- toYaml .Values.migrate.resources | nindent 12 }} + {{- with .Values.migrate.extraVolumeMounts }} + volumeMounts: {{- . | toYaml | nindent 10 }} + {{- end }} + {{- with .Values.migrate.extraContainers }} + {{- tpl . $ | nindent 6 }} + {{- end }} + {{- with .Values.migrate.extraVolumes }} + volumes: {{- . | toYaml | nindent 8 }} + {{- end }} +{{- end }} diff --git a/packages/system/grafana-oncall/charts/oncall/templates/engine/service-external.yaml b/packages/system/grafana-oncall/charts/oncall/templates/engine/service-external.yaml new file mode 100644 index 00000000..eec1f0bf --- /dev/null +++ b/packages/system/grafana-oncall/charts/oncall/templates/engine/service-external.yaml @@ -0,0 +1,24 @@ +{{- if .Values.service.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "oncall.engine.fullname" . }}-external + labels: + {{- include "oncall.engine.labels" . | nindent 4 }} + {{- with .Values.service.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + type: {{ .Values.service.type }} + ports: + - port: {{ .Values.service.port }} + targetPort: http + protocol: TCP + name: http + {{- if and (eq .Values.service.type "NodePort") (.Values.service.nodePort) }} + nodePort: {{ .Values.service.nodePort }} + {{- end }} + selector: + {{- include "oncall.engine.selectorLabels" . | nindent 4 }} +{{- end }} \ No newline at end of file diff --git a/packages/system/grafana-oncall/charts/oncall/templates/engine/service-internal.yaml b/packages/system/grafana-oncall/charts/oncall/templates/engine/service-internal.yaml new file mode 100644 index 00000000..07785035 --- /dev/null +++ b/packages/system/grafana-oncall/charts/oncall/templates/engine/service-internal.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "oncall.engine.fullname" . }} + labels: + {{- include "oncall.engine.labels" . | nindent 4 }} +spec: + type: ClusterIP + ports: + - port: 8080 + targetPort: http + protocol: TCP + name: http + selector: + {{- include "oncall.engine.selectorLabels" . | nindent 4 }} diff --git a/packages/system/grafana-oncall/charts/oncall/templates/ingress-regular.yaml b/packages/system/grafana-oncall/charts/oncall/templates/ingress-regular.yaml new file mode 100644 index 00000000..9a5357ff --- /dev/null +++ b/packages/system/grafana-oncall/charts/oncall/templates/ingress-regular.yaml @@ -0,0 +1,65 @@ +{{- if .Values.ingress.enabled -}} +{{- $fullName := include "oncall.fullname" . -}} +{{- $svcPort := .Values.service.port -}} +{{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }} + {{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }} + {{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}} + {{- end }} +{{- end }} +{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1 +{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1beta1 +{{- else -}} +apiVersion: extensions/v1beta1 +{{- end }} +kind: Ingress +metadata: + name: {{ $fullName }} + labels: + {{- include "oncall.labels" . | nindent 4 }} + {{- with .Values.ingress.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }} + ingressClassName: {{ .Values.ingress.className }} + {{- end }} + {{- if .Values.ingress.tls }} + tls: + {{- tpl (toYaml .Values.ingress.tls) . | nindent 4 }} + {{- end }} + rules: + - host: {{ .Values.base_url | quote }} + http: + paths: +{{- if .Values.ingress.extraPaths }} +{{ toYaml .Values.ingress.extraPaths | indent 6}} +{{- end }} + - path: / + pathType: Prefix + backend: + service: + name: {{ include "oncall.engine.fullname" . }} + port: + number: 8080 + {{ if .Values.grafana.enabled }} + - path: /grafana + pathType: Prefix + backend: + service: + name: {{ include "oncall.grafana.fullname" . }} + port: + number: 80 + {{- end }} + {{ if .Values.detached_integrations.enabled }} + - path: /integrations + pathType: Prefix + backend: + service: + name: {{ include "oncall.detached_integrations.fullname" . }} + port: + number: 8080 + {{- end }} +{{- end }} diff --git a/packages/system/grafana-oncall/charts/oncall/templates/integrations/_helpers.tpl b/packages/system/grafana-oncall/charts/oncall/templates/integrations/_helpers.tpl new file mode 100644 index 00000000..6727ed42 --- /dev/null +++ b/packages/system/grafana-oncall/charts/oncall/templates/integrations/_helpers.tpl @@ -0,0 +1,26 @@ +{{/* +Maximum of 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +*/}} +{{- define "oncall.detached_integrations.name" -}} +{{ include "oncall.name" . | trunc 55 }}-integrations +{{- end }} + +{{- define "oncall.detached_integrations.fullname" -}} +{{ include "oncall.fullname" . | trunc 55 }}-integrations +{{- end }} + +{{/* +Integrations common labels +*/}} +{{- define "oncall.detached_integrations.labels" -}} +{{ include "oncall.labels" . }} +app.kubernetes.io/component: integrations +{{- end }} + +{{/* +Integrations selector labels +*/}} +{{- define "oncall.detached_integrations.selectorLabels" -}} +{{ include "oncall.selectorLabels" . }} +app.kubernetes.io/component: integrations +{{- end }} diff --git a/packages/system/grafana-oncall/charts/oncall/templates/integrations/deployment.yaml b/packages/system/grafana-oncall/charts/oncall/templates/integrations/deployment.yaml new file mode 100644 index 00000000..5e08eaf7 --- /dev/null +++ b/packages/system/grafana-oncall/charts/oncall/templates/integrations/deployment.yaml @@ -0,0 +1,99 @@ +{{- if .Values.detached_integrations.enabled -}} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "oncall.detached_integrations.fullname" . }} + labels: + {{- include "oncall.detached_integrations.labels" . | nindent 4 }} +spec: + replicas: {{ .Values.detached_integrations.replicaCount }} + selector: + matchLabels: + {{- include "oncall.detached_integrations.selectorLabels" . | nindent 6 }} + strategy: + {{- toYaml .Values.detached_integrations.updateStrategy | nindent 4 }} + template: + metadata: + {{- with .Values.podAnnotations }} + annotations: + random-annotation: {{ randAlphaNum 10 | lower }} + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "oncall.detached_integrations.selectorLabels" . | nindent 8 }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "oncall.serviceAccountName" . }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + initContainers: + {{- include "oncall.initContainer" . | indent 8 }} + containers: + - name: {{ .Chart.Name }} + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + image: {{ include "oncall.engine.image" . }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + {{- if .Values.oncall.devMode }} + command: ["sh", "-c", "uwsgi --disable-logging --py-autoreload 3 --ini uwsgi.ini"] + {{- end }} + ports: + - name: http + containerPort: 8080 + protocol: TCP + env: + {{- include "snippet.oncall.engine.env" . | nindent 12 }} + - name: ROOT_URLCONF + value: "engine.integrations_urls" + livenessProbe: + httpGet: + path: /health/ + port: http + periodSeconds: 60 + timeoutSeconds: 3 + readinessProbe: + httpGet: + path: /ready/ + port: http + periodSeconds: 60 + timeoutSeconds: 3 + startupProbe: + httpGet: + path: /startupprobe/ + port: http + periodSeconds: 10 + timeoutSeconds: 3 + resources: + {{- toYaml .Values.detached_integrations.resources | nindent 12 }} + {{- with .Values.detached_integrations.extraVolumeMounts }} + volumeMounts: {{- . | toYaml | nindent 12 }} + {{- end }} + {{- with .Values.detached_integrations.extraContainers }} + {{- tpl . $ | nindent 8 }} + {{- end }} + {{- with .Values.detached_integrations.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.detached_integrations.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.detached_integrations.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.detached_integrations.topologySpreadConstraints }} + topologySpreadConstraints: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.detached_integrations.priorityClassName }} + priorityClassName: {{ . }} + {{- end }} + {{- with .Values.detached_integrations.extraVolumes }} + volumes: {{- . | toYaml | nindent 8 }} + {{- end }} +{{- end -}} diff --git a/packages/system/grafana-oncall/charts/oncall/templates/integrations/service-external.yaml b/packages/system/grafana-oncall/charts/oncall/templates/integrations/service-external.yaml new file mode 100644 index 00000000..455d4aa0 --- /dev/null +++ b/packages/system/grafana-oncall/charts/oncall/templates/integrations/service-external.yaml @@ -0,0 +1,24 @@ +{{- if .Values.detached_integrations_service.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "oncall.detached_integrations.fullname" . }}-external + labels: + {{- include "oncall.detached_integrations.labels" . | nindent 4 }} + {{- with .Values.detached_integrations_service.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + type: {{ .Values.detached_integrations_service.type }} + ports: + - port: {{ .Values.detached_integrations_service.port }} + targetPort: http + protocol: TCP + name: http + {{- if and (eq .Values.detached_integrations_service.type "NodePort") (.Values.detached_integrations_service.nodePort) }} + nodePort: {{ .Values.detached_integrations_service.nodePort }} + {{- end }} + selector: + {{- include "oncall.detached_integrations.selectorLabels" . | nindent 4 }} +{{- end }} diff --git a/packages/system/grafana-oncall/charts/oncall/templates/integrations/service-internal.yaml b/packages/system/grafana-oncall/charts/oncall/templates/integrations/service-internal.yaml new file mode 100644 index 00000000..3527b247 --- /dev/null +++ b/packages/system/grafana-oncall/charts/oncall/templates/integrations/service-internal.yaml @@ -0,0 +1,17 @@ +{{- if .Values.detached_integrations.enabled -}} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "oncall.detached_integrations.fullname" . }} + labels: + {{- include "oncall.detached_integrations.labels" . | nindent 4 }} +spec: + type: ClusterIP + ports: + - port: 8080 + targetPort: http + protocol: TCP + name: http + selector: + {{- include "oncall.detached_integrations.selectorLabels" . | nindent 4 }} +{{- end -}} diff --git a/packages/system/grafana-oncall/charts/oncall/templates/secrets.yaml b/packages/system/grafana-oncall/charts/oncall/templates/secrets.yaml new file mode 100644 index 00000000..821592fa --- /dev/null +++ b/packages/system/grafana-oncall/charts/oncall/templates/secrets.yaml @@ -0,0 +1,98 @@ +{{- if not .Values.oncall.secrets.existingSecret }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "oncall.fullname" . }} + labels: + {{- include "oncall.labels" . | nindent 4 }} + {{- if .Values.migrate.useHook }} + annotations: + "helm.sh/hook": pre-install,pre-upgrade + "helm.sh/hook-weight": "-5" + {{- end }} +type: Opaque +data: + {{ include "snippet.oncall.secret.secretKey" . }}: {{ randAlphaNum 40 | b64enc | quote }} + {{ include "snippet.oncall.secret.mirageSecretKey" . }}: {{ randAlphaNum 40 | b64enc | quote }} +--- +{{- end }} +{{- if and (eq .Values.database.type "mysql") (not .Values.mariadb.enabled) (not .Values.externalMysql.existingSecret) }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "oncall.fullname" . }}-mysql-external + {{- if .Values.migrate.useHook }} + annotations: + "helm.sh/hook": pre-install,pre-upgrade + "helm.sh/hook-weight": "-5" + {{- end }} +type: Opaque +data: + mariadb-root-password: {{ required "externalMysql.password is required if not mariadb.enabled and not externalMysql.existingSecret" .Values.externalMysql.password | b64enc | quote }} +--- +{{- end }} +{{- if and (not .Values.postgresql.enabled) (eq .Values.database.type "postgresql") (not .Values.externalPostgresql.existingSecret) }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "oncall.fullname" . }}-postgresql-external + {{- if .Values.migrate.useHook }} + annotations: + "helm.sh/hook": pre-install,pre-upgrade + "helm.sh/hook-weight": "-5" + {{- end }} +type: Opaque +data: + postgres-password: {{ required "externalPostgresql.password is required if not postgresql.enabled and not externalPostgresql.existingSecret" .Values.externalPostgresql.password | b64enc | quote }} +--- +{{- end }} +{{- if and (eq .Values.broker.type "rabbitmq") (not .Values.rabbitmq.enabled) (not .Values.externalRabbitmq.existingSecret) }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "oncall.fullname" . }}-rabbitmq-external + {{- if .Values.migrate.useHook }} + annotations: + "helm.sh/hook": pre-install,pre-upgrade + "helm.sh/hook-weight": "-5" + {{- end }} +type: Opaque +data: + rabbitmq-password: {{ required "externalRabbitmq.password is required if not rabbitmq.enabled and not externalRabbitmq.existingSecret" .Values.externalRabbitmq.password | b64enc | quote }} +--- +{{- end }} +{{- if and (eq .Values.broker.type "redis") (not .Values.redis.enabled) (not .Values.externalRedis.existingSecret) }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "oncall.fullname" . }}-redis-external + {{- if .Values.migrate.useHook }} + annotations: + "helm.sh/hook": pre-install,pre-upgrade + "helm.sh/hook-weight": "-5" + {{- end }} +type: Opaque +data: + redis-password: {{ required "externalRedis.password is required if not redis.enabled and not externalRedis.existingSecret" .Values.externalRedis.password | b64enc | quote }} +--- +{{- end }} +{{- if and .Values.oncall.smtp.enabled .Values.oncall.smtp.password }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "oncall.fullname" . }}-smtp +type: Opaque +data: + smtp-password: {{ .Values.oncall.smtp.password | b64enc | quote }} +--- +{{- end }} +{{- if and .Values.oncall.exporter.enabled .Values.oncall.exporter.authToken }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "oncall.fullname" . }}-exporter +type: Opaque +data: + exporter-secret: {{ .Values.oncall.exporter.authToken | b64enc | quote }} +--- +{{- end }} diff --git a/packages/system/grafana-oncall/charts/oncall/templates/serviceaccount.yaml b/packages/system/grafana-oncall/charts/oncall/templates/serviceaccount.yaml new file mode 100644 index 00000000..d0a5a9eb --- /dev/null +++ b/packages/system/grafana-oncall/charts/oncall/templates/serviceaccount.yaml @@ -0,0 +1,18 @@ +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "oncall.serviceAccountName" . }} + labels: + {{- include "oncall.labels" . | nindent 4 }} + {{- if or (.Values.migrate.useHook) (.Values.serviceAccount.annotations) }} + annotations: + {{- if .Values.migrate.useHook }} + "helm.sh/hook": pre-install,pre-upgrade + "helm.sh/hook-weight": "-5" + {{- end }} + {{- with .Values.serviceAccount.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- end }} +{{- end }} diff --git a/packages/system/grafana-oncall/charts/oncall/templates/telegram-polling/_helpers.tpl b/packages/system/grafana-oncall/charts/oncall/templates/telegram-polling/_helpers.tpl new file mode 100644 index 00000000..d2053dc0 --- /dev/null +++ b/packages/system/grafana-oncall/charts/oncall/templates/telegram-polling/_helpers.tpl @@ -0,0 +1,22 @@ +{{/* +Maximum of 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +*/}} +{{- define "oncall.telegramPolling.fullname" -}} +{{ include "oncall.fullname" . | trunc 45 }}-telegram-polling +{{- end }} + +{{/* +Telegram polling common labels +*/}} +{{- define "oncall.telegramPolling.labels" -}} +{{ include "oncall.labels" . }} +app.kubernetes.io/component: telegram-polling +{{- end }} + +{{/* +Telegram polling selector labels +*/}} +{{- define "oncall.telegramPolling.selectorLabels" -}} +{{ include "oncall.selectorLabels" . }} +app.kubernetes.io/component: telegram-polling +{{- end }} diff --git a/packages/system/grafana-oncall/charts/oncall/templates/telegram-polling/deployment.yaml b/packages/system/grafana-oncall/charts/oncall/templates/telegram-polling/deployment.yaml new file mode 100644 index 00000000..2e448897 --- /dev/null +++ b/packages/system/grafana-oncall/charts/oncall/templates/telegram-polling/deployment.yaml @@ -0,0 +1,53 @@ +{{- if .Values.telegramPolling.enabled -}} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "oncall.telegramPolling.fullname" . }} + labels: + {{- include "oncall.telegramPolling.labels" . | nindent 4 }} +spec: + replicas: 1 + selector: + matchLabels: + {{- include "oncall.telegramPolling.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + {{- include "oncall.telegramPolling.selectorLabels" . | nindent 8 }} + {{- if .Values.telegramPolling.podLabels }} + {{- toYaml .Values.telegramPolling.podLabels | nindent 8 }} + {{- end }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "oncall.serviceAccountName" . }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + initContainers: + {{- include "oncall.initContainer" . | nindent 8 }} + containers: + - name: telegram-polling + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + image: {{ include "oncall.engine.image" . }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + command: ['sh', '-c', 'python manage.py start_telegram_polling'] + env: + {{- include "snippet.oncall.env" . | nindent 12 }} + {{- include "snippet.oncall.telegram.env" . | nindent 12 }} + {{- include "snippet.db.env" . | nindent 12 }} + {{- include "snippet.broker.env" . | nindent 12 }} + {{- include "oncall.extraEnvs" . | nindent 12 }} + {{- with .Values.telegramPolling.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.telegramPolling.extraVolumeMounts }} + volumeMounts: {{- . | toYaml | nindent 12 }} + {{- end }} + {{- with .Values.telegramPolling.extraVolumes }} + volumes: {{- . | toYaml | nindent 8 }} + {{- end }} +{{- end -}} diff --git a/packages/system/grafana-oncall/charts/oncall/templates/ui/_helpers.tpl b/packages/system/grafana-oncall/charts/oncall/templates/ui/_helpers.tpl new file mode 100644 index 00000000..49dcc2e5 --- /dev/null +++ b/packages/system/grafana-oncall/charts/oncall/templates/ui/_helpers.tpl @@ -0,0 +1,8 @@ +{{- define "ui.env" -}} +{{- if .Values.ui.env }} + {{- range $key, $value := .Values.ui.env }} +- name: {{ $key }} + value: "{{ $value }}" + {{- end -}} +{{- end }} +{{- end }} diff --git a/packages/system/grafana-oncall/charts/oncall/templates/ui/deployment.yaml b/packages/system/grafana-oncall/charts/oncall/templates/ui/deployment.yaml new file mode 100644 index 00000000..c094368f --- /dev/null +++ b/packages/system/grafana-oncall/charts/oncall/templates/ui/deployment.yaml @@ -0,0 +1,31 @@ +{{- if .Values.ui.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: oncall-ui + labels: + app.kubernetes.io/component: oncall-ui +spec: + replicas: 1 + selector: + matchLabels: + app.kubernetes.io/component: oncall-ui + template: + metadata: + labels: + app.kubernetes.io/component: oncall-ui + spec: + containers: + - name: oncall-ui + image: "{{ .Values.ui.image.repository }}:{{ .Values.ui.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: IfNotPresent + env: + {{- include "ui.env" . | nindent 12 }} + volumeMounts: + - mountPath: /etc/app + name: hot-reloaded-plugin + volumes: + - name: hot-reloaded-plugin + hostPath: + path: /oncall-plugin +{{- end }} diff --git a/packages/system/grafana-oncall/charts/oncall/values.yaml b/packages/system/grafana-oncall/charts/oncall/values.yaml new file mode 100644 index 00000000..3306f005 --- /dev/null +++ b/packages/system/grafana-oncall/charts/oncall/values.yaml @@ -0,0 +1,719 @@ +# Values for configuring the deployment of Grafana OnCall + +# Set the domain name Grafana OnCall will be installed on. +# If you want to install grafana as a part of this release make sure to configure grafana.grafana.ini.server.domain too +base_url: example.com +base_url_protocol: https + +## Optionally specify an array of imagePullSecrets. +## Secrets must be manually created in the namespace. +## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ +## e.g: +## imagePullSecrets: +## - name: myRegistryKeySecretName +imagePullSecrets: [] + +image: + # Grafana OnCall docker image repository + repository: grafana/oncall + tag: + pullPolicy: Always + +# Whether to create additional service for external connections +# ClusterIP service is always created +service: + enabled: false + type: LoadBalancer + port: 8080 + annotations: {} + +# Engine pods configuration +engine: + replicaCount: 1 + resources: + {} + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + + # Labels for engine pods + podLabels: {} + + ## Deployment update strategy + ## ref: https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#strategy + updateStrategy: + rollingUpdate: + maxSurge: 25% + maxUnavailable: 0 + type: RollingUpdate + + ## Affinity for pod assignment + ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity + affinity: {} + + ## Node labels for pod assignment + ## ref: https://kubernetes.io/docs/user-guide/node-selection/ + nodeSelector: {} + + ## Tolerations for pod assignment + ## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ + tolerations: [] + + ## Topology spread constraints for pod assignment + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/topology-spread-constraints/ + topologySpreadConstraints: [] + + ## Priority class for the pods + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/pod-priority-preemption/ + priorityClassName: "" + + # Extra containers which runs as sidecar + extraContainers: "" + # extraContainers: | + # - name: cloud-sql-proxy + # image: gcr.io/cloud-sql-connectors/cloud-sql-proxy:2.1.2 + # args: + # - --private-ip + # - --port=5432 + # - example:europe-west3:grafana-oncall-db + + # Extra volume mounts for the main app container + extraVolumeMounts: [] + # - mountPath: /mnt/postgres-tls + # name: postgres-tls + # - mountPath: /mnt/redis-tls + # name: redis-tls + + # Extra volumes for the pod + extraVolumes: [] + # - name: postgres-tls + # configMap: + # name: my-postgres-tls + # defaultMode: 0640 + # - name: redis-tls + # configMap: + # name: my-redis-tls + # defaultMode: 0640 + +detached_integrations_service: + enabled: false + type: LoadBalancer + port: 8080 + annotations: {} + +# Integrations pods configuration +detached_integrations: + enabled: false + replicaCount: 1 + resources: + {} + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + + ## Deployment update strategy + ## ref: https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#strategy + updateStrategy: + rollingUpdate: + maxSurge: 25% + maxUnavailable: 0 + type: RollingUpdate + + ## Affinity for pod assignment + ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity + affinity: {} + + ## Node labels for pod assignment + ## ref: https://kubernetes.io/docs/user-guide/node-selection/ + nodeSelector: {} + + ## Tolerations for pod assignment + ## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ + tolerations: [] + + ## Topology spread constraints for pod assignment + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/topology-spread-constraints/ + topologySpreadConstraints: [] + + ## Priority class for the pods + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/pod-priority-preemption/ + priorityClassName: "" + + # Extra containers which runs as sidecar + extraContainers: "" + # extraContainers: | + # - name: cloud-sql-proxy + # image: gcr.io/cloud-sql-connectors/cloud-sql-proxy:2.1.2 + # args: + # - --private-ip + # - --port=5432 + # - example:europe-west3:grafana-oncall-db + + # Extra volume mounts for the container + extraVolumeMounts: [] + # - mountPath: /mnt/postgres-tls + # name: postgres-tls + # - mountPath: /mnt/redis-tls + # name: redis-tls + + # Extra volumes for the pod + extraVolumes: [] + # - name: postgres-tls + # configMap: + # name: my-postgres-tls + # defaultMode: 0640 + # - name: redis-tls + # configMap: + # name: my-redis-tls + # defaultMode: 0640 + +# Celery workers pods configuration +celery: + replicaCount: 1 + worker_queue: "default,critical,long,slack,telegram,webhook,celery,grafana" + worker_concurrency: "1" + worker_max_tasks_per_child: "100" + worker_beat_enabled: "True" + ## Restart of the celery workers once in a given interval as an additional precaution to the probes + ## If this setting is enabled TERM signal will be sent to celery workers + ## It will lead to warm shutdown (waiting for the tasks to complete) and restart the container + ## If this setting is set numbers of pod restarts will increase + ## Comment this line out if you want to remove restarts + worker_shutdown_interval: "65m" + livenessProbe: + enabled: true + initialDelaySeconds: 30 + periodSeconds: 300 + timeoutSeconds: 10 + resources: + {} + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + + # Labels for celery pods + podLabels: {} + + ## Affinity for pod assignment + ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity + affinity: {} + + ## Node labels for pod assignment + ## ref: https://kubernetes.io/docs/user-guide/node-selection/ + nodeSelector: {} + + ## Tolerations for pod assignment + ## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ + tolerations: [] + + ## Topology spread constraints for pod assignment + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/topology-spread-constraints/ + topologySpreadConstraints: [] + + ## Priority class for the pods + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/pod-priority-preemption/ + priorityClassName: "" + + # Extra containers which runs as sidecar + extraContainers: "" + # extraContainers: | + # - name: cloud-sql-proxy + # image: gcr.io/cloud-sql-connectors/cloud-sql-proxy:2.1.2 + # args: + # - --private-ip + # - --port=5432 + # - example:europe-west3:grafana-oncall-db + + # Extra volume mounts for the main container + extraVolumeMounts: [] + # - mountPath: /mnt/postgres-tls + # name: postgres-tls + # - mountPath: /mnt/redis-tls + # name: redis-tls + + # Extra volumes for the pod + extraVolumes: [] + # - name: postgres-tls + # configMap: + # name: my-postgres-tls + # defaultMode: 0640 + # - name: redis-tls + # configMap: + # name: my-redis-tls + # defaultMode: 0640 + +# Telegram polling pod configuration +telegramPolling: + enabled: false + resources: + {} + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + + # Labels for telegram-polling pods + podLabels: {} + + # Extra volume mounts for the main container + extraVolumeMounts: [] + # - mountPath: /mnt/postgres-tls + # name: postgres-tls + # - mountPath: /mnt/redis-tls + # name: redis-tls + + # Extra volumes for the pod + extraVolumes: [] + # - name: postgres-tls + # configMap: + # name: my-postgres-tls + # defaultMode: 0640 + # - name: redis-tls + # configMap: + # name: my-redis-tls + # defaultMode: 0640 + +oncall: + # this is intended to be used for local development. In short, it will mount the ./engine dir into + # any backend related containers, to allow hot-reloading + also run the containers with slightly modified + # startup commands (which configures the hot-reloading) + devMode: false + + # Override default MIRAGE_CIPHER_IV (must be 16 bytes long) + # For existing installation, this should not be changed. + # mirageCipherIV: 1234567890abcdef + # oncall secrets + secrets: + # Use existing secret. (secretKey and mirageSecretKey is required) + existingSecret: "" + # The key in the secret containing secret key + secretKey: "" + # The key in the secret containing mirage secret key + mirageSecretKey: "" + # Slack configures the Grafana Oncall Slack ChatOps integration. + slack: + # Enable the Slack ChatOps integration for the Oncall Engine. + enabled: false + # Sets the Slack bot slash-command + commandName: oncall + # clientId configures the Slack app OAuth2 client ID. + # api.slack.com/apps/ -> Basic Information -> App Credentials -> Client ID + clientId: ~ + # clientSecret configures the Slack app OAuth2 client secret. + # api.slack.com/apps/ -> Basic Information -> App Credentials -> Client Secret + clientSecret: ~ + # signingSecret - configures the Slack app signature secret used to sign + # requests comming from Slack. + # api.slack.com/apps/ -> Basic Information -> App Credentials -> Signing Secret + signingSecret: ~ + # Use existing secret for clientId, clientSecret and signingSecret. + # clientIdKey, clientSecretKey and signingSecretKey are required + existingSecret: "" + # The key in the secret containing OAuth2 client ID + clientIdKey: "" + # The key in the secret containing OAuth2 client secret + clientSecretKey: "" + # The key in the secret containing the Slack app signature secret + signingSecretKey: "" + # OnCall external URL + redirectHost: ~ + telegram: + enabled: false + token: ~ + webhookUrl: ~ + # Use existing secret. (tokenKey is required) + existingSecret: "" + # The key in the secret containing Telegram token + tokenKey: "" + smtp: + enabled: true + host: ~ + port: ~ + username: ~ + password: ~ + tls: ~ + fromEmail: ~ + exporter: + enabled: false + authToken: ~ + twilio: + # Twilio account SID/username to allow OnCall to send SMSes and make phone calls + accountSid: "" + # Twilio password to allow OnCall to send SMSes and make calls + authToken: "" + # Number from which you will receive calls and SMS + # (NOTE: must be quoted, otherwise would be rendered as float value) + phoneNumber: "" + # SID of Twilio service for number verification. You can create a service in Twilio web interface. + # twilio.com -> verify -> create new service + verifySid: "" + # Twilio API key SID/username to allow OnCall to send SMSes and make phone calls + apiKeySid: "" + # Twilio API key secret/password to allow OnCall to send SMSes and make phone calls + apiKeySecret: "" + # Use existing secret for authToken, phoneNumber, verifySid, apiKeySid and apiKeySecret. + existingSecret: "" + # Twilio password to allow OnCall to send SMSes and make calls + # The key in the secret containing the auth token + authTokenKey: "" + # The key in the secret containing the phone number + phoneNumberKey: "" + # The key in the secret containing verify service sid + verifySidKey: "" + # The key in the secret containing api key sid + apiKeySidKey: "" + # The key in the secret containing the api key secret + apiKeySecretKey: "" + # Phone notifications limit (the only non-secret value). + # TODO: rename to phoneNotificationLimit + limitPhone: + +# Whether to run django database migrations automatically +migrate: + enabled: true + # TTL can be unset by setting ttlSecondsAfterFinished: "" + ttlSecondsAfterFinished: 20 + # use a helm hook to manage the migration job + useHook: false + annotations: {} + + ## Affinity for pod assignment + ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity + affinity: {} + + ## Node labels for pod assignment + ## ref: https://kubernetes.io/docs/user-guide/node-selection/ + nodeSelector: {} + + ## Tolerations for pod assignment + ## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ + tolerations: [] + + # Extra containers which runs as sidecar + extraContainers: "" + # extraContainers: | + # - name: cloud-sql-proxy + # image: gcr.io/cloud-sql-connectors/cloud-sql-proxy:2.1.2 + # args: + # - --private-ip + # - --port=5432 + # - example:europe-west3:grafana-oncall-db + resources: + {} + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + + # Extra volume mounts for the main container + extraVolumeMounts: [] + # - mountPath: /mnt/postgres-tls + # name: postgres-tls + # - mountPath: /mnt/redis-tls + # name: redis-tls + + # Extra volumes for the pod + extraVolumes: [] + # - name: postgres-tls + # configMap: + # name: my-postgres-tls + # defaultMode: 0640 + # - name: redis-tls + # configMap: + # name: my-redis-tls + # defaultMode: 0640 + +# Sets environment variables with name capitalized and prefixed with UWSGI_, +# and dashes are substituted with underscores. +# see more: https://uwsgi-docs.readthedocs.io/en/latest/Configuration.html#environment-variables +# Set null to disable all UWSGI environment variables +uwsgi: + listen: 1024 + +# Additional env variables to add to deployments +env: {} + +# Enable ingress object for external access to the resources +ingress: + enabled: true + # className: "" + annotations: + kubernetes.io/ingress.class: "nginx" + cert-manager.io/issuer: "letsencrypt-prod" + tls: + - hosts: + - "{{ .Values.base_url }}" + secretName: certificate-tls + # Extra paths to prepend to the host configuration. If using something + # like an ALB ingress controller, you may want to configure SSL redirects + extraPaths: [] + # - path: /* + # backend: + # serviceName: ssl-redirect + # servicePort: use-annotation + ## Or for k8s > 1.19 + # - path: /* + # pathType: Prefix + # backend: + # service: + # name: ssl-redirect + # port: + # name: use-annotation + +# Whether to install ingress controller +ingress-nginx: + enabled: true + +# Install cert-manager as a part of the release +cert-manager: + enabled: true + # Instal CRD resources + installCRDs: true + webhook: + timeoutSeconds: 30 + # cert-manager tries to use the already used port, changing to another one + # https://github.com/cert-manager/cert-manager/issues/3237 + # https://cert-manager.io/docs/installation/compatibility/ + securePort: 10260 + # Fix self-checks https://github.com/jetstack/cert-manager/issues/4286 + podDnsPolicy: None + podDnsConfig: + nameservers: + - 8.8.8.8 + - 1.1.1.1 + +database: + # can be either mysql or postgresql + type: mysql + +# MySQL is included into this release for the convenience. +# It is recommended to host it separately from this release +# Set mariadb.enabled = false and configure externalMysql +mariadb: + enabled: true + auth: + database: oncall + existingSecret: + primary: + extraEnvVars: + - name: MARIADB_COLLATE + value: utf8mb4_unicode_ci + - name: MARIADB_CHARACTER_SET + value: utf8mb4 + secondary: + extraEnvVars: + - name: MARIADB_COLLATE + value: utf8mb4_unicode_ci + - name: MARIADB_CHARACTER_SET + value: utf8mb4 + +# Make sure to create the database with the following parameters: +# CREATE DATABASE oncall CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; +externalMysql: + host: + port: + db_name: + user: + password: + # Use an existing secret for the mysql password. + existingSecret: + # The key in the secret containing the mysql username + usernameKey: + # The key in the secret containing the mysql password + passwordKey: + # Extra options (see example below) + # Reference: https://pymysql.readthedocs.io/en/latest/modules/connections.html + options: + # options: >- + # ssl_verify_cert=true + # ssl_verify_identity=true + # ssl_ca=/mnt/mysql-tls/ca.crt + # ssl_cert=/mnt/mysql-tls/client.crt + # ssl_key=/mnt/mysql-tls/client.key + +# PostgreSQL is included into this release for the convenience. +# It is recommended to host it separately from this release +# Set postgresql.enabled = false and configure externalPostgresql +postgresql: + enabled: false + auth: + database: oncall + existingSecret: + +# Make sure to create the database with the following parameters: +# CREATE DATABASE oncall WITH ENCODING UTF8; +externalPostgresql: + host: + port: + db_name: + user: + password: + # Use an existing secret for the database password + existingSecret: + # The key in the secret containing the database password + passwordKey: + # Extra options (see example below) + # Reference: https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-PARAMKEYWORDS + options: + # options: >- + # sslmode=verify-full + # sslrootcert=/mnt/postgres-tls/ca.crt + # sslcert=/mnt/postgres-tls/client.crt + # sslkey=/mnt/postgres-tls/client.key + +# RabbitMQ is included into this release for the convenience. +# It is recommended to host it separately from this release +# Set rabbitmq.enabled = false and configure externalRabbitmq +rabbitmq: + enabled: true + auth: + existingPasswordSecret: + +broker: + type: rabbitmq + +externalRabbitmq: + host: + port: + user: + password: + protocol: + vhost: + # Use an existing secret for the rabbitmq password + existingSecret: + # The key in the secret containing the rabbitmq password + passwordKey: "" + # The key in the secret containing the rabbitmq username + usernameKey: username + +# Redis is included into this release for the convenience. +# It is recommended to host it separately from this release +redis: + enabled: true + auth: + existingSecret: + +externalRedis: + protocol: + host: + port: + database: + username: + password: + # Use an existing secret for the redis password + existingSecret: + # The key in the secret containing the redis password + passwordKey: + + # SSL options + ssl_options: + enabled: false + # CA certificate + ca_certs: + # Client SSL certs + certfile: + keyfile: + # SSL verification mode: "cert_none" | "cert_optional" | "cert_required" + cert_reqs: + +# Grafana is included into this release for the convenience. +# It is recommended to host it separately from this release +grafana: + enabled: true + grafana.ini: + server: + domain: example.com + root_url: "%(protocol)s://%(domain)s/grafana" + serve_from_sub_path: true + persistence: + enabled: true + # Disable psp as PodSecurityPolicy is deprecated in v1.21+, unavailable in v1.25+ + rbac: + pspEnabled: false + plugins: + - grafana-oncall-app + +externalGrafana: + # Example: https://grafana.mydomain.com + url: + +nameOverride: "" +fullnameOverride: "" + +serviceAccount: + # Specifies whether a service account should be created + create: true + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" + +podAnnotations: {} + +podSecurityContext: + {} + # fsGroup: 2000 + +securityContext: + {} + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsGroup: 2000 + # runAsUser: 1000 + +init: + securityContext: + {} + # allowPrivilegeEscalation: false + # capabilities: + # drop: + # - ALL + # privileged: false + # readOnlyRootFilesystem: true + # runAsGroup: 2000 + # runAsNonRoot: true + # runAsUser: 1000 + resources: + {} + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + +ui: + # this is intended to be used for local development. In short, it will spin up an additional container + # running the plugin frontend, such that hot reloading can be enabled + enabled: false + image: + repository: oncall/ui + tag: dev + # Additional env vars for the ui container + env: {} + +prometheus: + enabled: false + # extraScrapeConfigs: | + # - job_name: 'oncall-exporter' + # metrics_path: /metrics/ + # static_configs: + # - targets: + # - oncall-dev-engine.default.svc.cluster.local:8080 diff --git a/packages/system/grafana-oncall/values.yaml b/packages/system/grafana-oncall/values.yaml new file mode 100644 index 00000000..a660e0c1 --- /dev/null +++ b/packages/system/grafana-oncall/values.yaml @@ -0,0 +1,19 @@ +oncall: + database: + type: "postgresql" + broker: + type: "redis" + ingress: + enabled: false + cert-manager: + enabled: false + mariadb: + enabled: false + postgresql: + enabled: false + rabbitmq: + enabled: false + redis: + enabled: false + grafana: + enabled: false diff --git a/packages/system/grafana-operator/Chart.yaml b/packages/system/grafana-operator/Chart.yaml new file mode 100644 index 00000000..2aaee3c1 --- /dev/null +++ b/packages/system/grafana-operator/Chart.yaml @@ -0,0 +1,2 @@ +name: cozy-grafana-operator +version: 1.0.0 diff --git a/packages/system/grafana-operator/Makefile b/packages/system/grafana-operator/Makefile new file mode 100644 index 00000000..4064a7f0 --- /dev/null +++ b/packages/system/grafana-operator/Makefile @@ -0,0 +1,17 @@ +NAME=grafana-operator +NAMESPACE=cozy-grafana-operator + +show: + helm template --dry-run=server -n $(NAMESPACE) $(NAME) . + +apply: + helm upgrade -i -n $(NAMESPACE) $(NAME) . + +diff: + helm diff upgrade --allow-unreleased --normalize-manifests -n $(NAMESPACE) $(NAME) . + +update: + rm -rf charts + mkdir -p charts + curl -sSL https://github.com/grafana-operator/grafana-operator/archive/refs/heads/master.tar.gz | \ + tar xzvf - --strip 3 -C charts grafana-operator-master/deploy/helm/grafana-operator diff --git a/packages/system/grafana-operator/charts/grafana-operator/.helmignore b/packages/system/grafana-operator/charts/grafana-operator/.helmignore new file mode 100644 index 00000000..0e8a0eb3 --- /dev/null +++ b/packages/system/grafana-operator/charts/grafana-operator/.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/packages/system/grafana-operator/charts/grafana-operator/Chart.yaml b/packages/system/grafana-operator/charts/grafana-operator/Chart.yaml new file mode 100644 index 00000000..2bbf10b1 --- /dev/null +++ b/packages/system/grafana-operator/charts/grafana-operator/Chart.yaml @@ -0,0 +1,24 @@ +apiVersion: v2 +name: grafana-operator +description: A Helm chart for Kubernetes + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +# Versions are expected to follow Semantic Versioning (https://semver.org/) +version: 0.1.2 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. Versions are not expected to +# follow Semantic Versioning. They should reflect the version the application is using. +# It is recommended to use it with quotes. +appVersion: "v5.6.0" diff --git a/packages/system/grafana-operator/charts/grafana-operator/README.md b/packages/system/grafana-operator/charts/grafana-operator/README.md new file mode 100644 index 00000000..697f1b1a --- /dev/null +++ b/packages/system/grafana-operator/charts/grafana-operator/README.md @@ -0,0 +1,61 @@ +--- +title: "Helm installation" +linkTitle: "Helm installation" +--- + +# grafana-operator + +[grafana-operator](https://github.com/grafana/grafana-operator) for Kubernetes to manage Grafana instances and grafana resources. + +![Version: 0.1.2](https://img.shields.io/badge/Version-0.1.2-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: v5.6.0](https://img.shields.io/badge/AppVersion-v5.6.0-informational?style=flat-square) + +## Installation + +This is a OCI helm chart, helm started support OCI in version 3.8.0. + +```shell +helm upgrade -i grafana-operator oci://ghcr.io/grafana/helm-charts/grafana-operator --version v5.6.0 +``` + +Sadly helm OCI charts currently don't support searching for available versions of a helm [oci registry](https://github.com/helm/helm/issues/11000). + +## Development + +For general and helm specific development instructions please read the [CONTRIBUTING.md](../../../CONTRIBUTING.md) + +## Out of scope + +The chart won't support any configuration of grafana instances or similar. It's only meant to be used to install the grafana-operator. +Deployments of grafana instances using the CRs is supposed to be done outside of the chart. + +Currently the plan is not to support networkpolicy. The operators support os diverse configuration that you have to support all options. +It's easier to just manage this configuration outside of the operator. + +## Values + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| additionalLabels | object | `{}` | additional labels to add to all resources | +| affinity | object | `{}` | pod affinity | +| env | list | `[]` | Additional environment variables | +| fullnameOverride | string | `""` | | +| image.pullPolicy | string | `"IfNotPresent"` | The image pull policy to use in grafana operator container | +| image.repository | string | `"ghcr.io/grafana/grafana-operator"` | grafana operator image repository | +| image.tag | string | `""` | Overrides the image tag whose default is the chart appVersion. | +| imagePullSecrets | list | `[]` | image pull secrets | +| leaderElect | bool | `false` | If you want to run multiple replicas of the grafana-operator, this is not recommended. | +| metricsService.metricsPort | int | `9090` | metrics service port | +| metricsService.type | string | `"ClusterIP"` | metrics service type | +| nameOverride | string | `""` | | +| namespaceScope | bool | `false` | If the operator should run in namespace-scope or not, if true the operator will only be able to manage instances in the same namespace | +| nodeSelector | object | `{}` | pod node selector | +| podAnnotations | object | `{}` | pod annotations | +| podSecurityContext | object | `{}` | pod security context | +| priorityClassName | string | `""` | pod priority class name | +| resources | object | `{}` | grafana operator container resources | +| securityContext | object | `{"capabilities":{"drop":["ALL"]},"readOnlyRootFilesystem":true,"runAsNonRoot":true}` | grafana operator container security context | +| serviceAccount.annotations | object | `{}` | Annotations to add to the service account | +| serviceAccount.create | bool | `true` | Specifies whether a service account should be created | +| serviceAccount.name | string | `""` | The name of the service account to use. If not set and create is true, a name is generated using the fullname template | +| tolerations | list | `[]` | pod tolerations | +| watchNamespaces | string | `""` | Sets the WATCH_NAMESPACE environment variable, it defines which namespaces the operator should be listening for. By default it's all namespaces, if you only want to listen for the same namespace as the operator is deployed to look at namespaceScope. | diff --git a/packages/system/grafana-operator/charts/grafana-operator/README.md.gotmpl b/packages/system/grafana-operator/charts/grafana-operator/README.md.gotmpl new file mode 100644 index 00000000..f6193def --- /dev/null +++ b/packages/system/grafana-operator/charts/grafana-operator/README.md.gotmpl @@ -0,0 +1,37 @@ +--- +title: "Helm installation" +linkTitle: "Helm installation" +--- + +{{ template "chart.header" . }} + +[grafana-operator](https://github.com/grafana/grafana-operator) for Kubernetes to manage Grafana instances and grafana resources. + +{{ template "chart.versionBadge" . }}{{ template "chart.typeBadge" . }}{{ template "chart.appVersionBadge" . }} + +## Installation + +This is a OCI helm chart, helm started support OCI in version 3.8.0. + +```shell +helm upgrade -i grafana-operator oci://ghcr.io/grafana/helm-charts/grafana-operator --version {{ template "chart.appVersion" . }} +``` + +Sadly helm OCI charts currently don't support searching for available versions of a helm [oci registry](https://github.com/helm/helm/issues/11000). + +## Development + +For general and helm specific development instructions please read the [CONTRIBUTING.md](../../../CONTRIBUTING.md) + +## Out of scope + +The chart won't support any configuration of grafana instances or similar. It's only meant to be used to install the grafana-operator. +Deployments of grafana instances using the CRs is supposed to be done outside of the chart. + +Currently the plan is not to support networkpolicy. The operators support os diverse configuration that you have to support all options. +It's easier to just manage this configuration outside of the operator. + +{{ template "chart.requirementsSection" . }} + + +{{ template "chart.valuesSection" . }} diff --git a/packages/system/grafana-operator/charts/grafana-operator/crds/grafana.integreatly.org_grafanadashboards.yaml b/packages/system/grafana-operator/charts/grafana-operator/crds/grafana.integreatly.org_grafanadashboards.yaml new file mode 100644 index 00000000..68b4dd90 --- /dev/null +++ b/packages/system/grafana-operator/charts/grafana-operator/crds/grafana.integreatly.org_grafanadashboards.yaml @@ -0,0 +1,235 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.12.0 + name: grafanadashboards.grafana.integreatly.org +spec: + group: grafana.integreatly.org + names: + kind: GrafanaDashboard + listKind: GrafanaDashboardList + plural: grafanadashboards + singular: grafanadashboard + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .status.NoMatchingInstances + name: No matching instances + type: boolean + - format: date-time + jsonPath: .status.lastResync + name: Last resync + type: date + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1beta1 + schema: + openAPIV3Schema: + properties: + apiVersion: + type: string + kind: + type: string + metadata: + type: object + spec: + properties: + allowCrossNamespaceImport: + type: boolean + configMapRef: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + contentCacheDuration: + type: string + datasources: + items: + properties: + datasourceName: + type: string + inputName: + type: string + required: + - datasourceName + - inputName + type: object + type: array + envFrom: + items: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + type: array + envs: + items: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + folder: + type: string + grafanaCom: + properties: + id: + type: integer + revision: + type: integer + required: + - id + type: object + gzipJson: + format: byte + type: string + instanceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + json: + type: string + jsonnet: + type: string + jsonnetLib: + properties: + fileName: + type: string + gzipJsonnetProject: + format: byte + type: string + jPath: + items: + type: string + type: array + required: + - fileName + - gzipJsonnetProject + type: object + plugins: + items: + properties: + name: + type: string + version: + type: string + required: + - name + - version + type: object + type: array + resyncPeriod: + type: string + url: + type: string + required: + - instanceSelector + type: object + status: + properties: + NoMatchingInstances: + type: boolean + contentCache: + format: byte + type: string + contentTimestamp: + format: date-time + type: string + contentUrl: + type: string + hash: + type: string + lastResync: + format: date-time + type: string + uid: + type: string + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/packages/system/grafana-operator/charts/grafana-operator/crds/grafana.integreatly.org_grafanadatasources.yaml b/packages/system/grafana-operator/charts/grafana-operator/crds/grafana.integreatly.org_grafanadatasources.yaml new file mode 100644 index 00000000..c5795655 --- /dev/null +++ b/packages/system/grafana-operator/charts/grafana-operator/crds/grafana.integreatly.org_grafanadatasources.yaml @@ -0,0 +1,178 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.12.0 + name: grafanadatasources.grafana.integreatly.org +spec: + group: grafana.integreatly.org + names: + kind: GrafanaDatasource + listKind: GrafanaDatasourceList + plural: grafanadatasources + singular: grafanadatasource + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .status.NoMatchingInstances + name: No matching instances + type: boolean + - format: date-time + jsonPath: .status.lastResync + name: Last resync + type: date + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1beta1 + schema: + openAPIV3Schema: + properties: + apiVersion: + type: string + kind: + type: string + metadata: + type: object + spec: + properties: + allowCrossNamespaceImport: + type: boolean + datasource: + properties: + access: + type: string + basicAuth: + type: boolean + basicAuthUser: + type: string + database: + type: string + editable: + type: boolean + isDefault: + type: boolean + jsonData: + type: object + x-kubernetes-preserve-unknown-fields: true + name: + type: string + orgId: + format: int64 + type: integer + secureJsonData: + type: object + x-kubernetes-preserve-unknown-fields: true + type: + type: string + uid: + type: string + url: + type: string + user: + type: string + required: + - access + - name + - type + - url + type: object + instanceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + plugins: + items: + properties: + name: + type: string + version: + type: string + required: + - name + - version + type: object + type: array + resyncPeriod: + type: string + valuesFrom: + items: + properties: + targetPath: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - targetPath + - valueFrom + type: object + type: array + required: + - datasource + - instanceSelector + type: object + status: + properties: + NoMatchingInstances: + type: boolean + hash: + type: string + lastMessage: + type: string + lastResync: + format: date-time + type: string + uid: + type: string + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/packages/system/grafana-operator/charts/grafana-operator/crds/grafana.integreatly.org_grafanafolders.yaml b/packages/system/grafana-operator/charts/grafana-operator/crds/grafana.integreatly.org_grafanafolders.yaml new file mode 100644 index 00000000..fa562b65 --- /dev/null +++ b/packages/system/grafana-operator/charts/grafana-operator/crds/grafana.integreatly.org_grafanafolders.yaml @@ -0,0 +1,85 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.12.0 + name: grafanafolders.grafana.integreatly.org +spec: + group: grafana.integreatly.org + names: + kind: GrafanaFolder + listKind: GrafanaFolderList + plural: grafanafolders + singular: grafanafolder + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .status.NoMatchingInstances + name: No matching instances + type: boolean + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1beta1 + schema: + openAPIV3Schema: + properties: + apiVersion: + type: string + kind: + type: string + metadata: + type: object + spec: + properties: + allowCrossNamespaceImport: + type: boolean + instanceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + permissions: + type: string + resyncPeriod: + type: string + title: + type: string + required: + - instanceSelector + type: object + status: + properties: + NoMatchingInstances: + type: boolean + hash: + type: string + lastResync: + format: date-time + type: string + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/packages/system/grafana-operator/charts/grafana-operator/crds/grafana.integreatly.org_grafanas.yaml b/packages/system/grafana-operator/charts/grafana-operator/crds/grafana.integreatly.org_grafanas.yaml new file mode 100644 index 00000000..23175423 --- /dev/null +++ b/packages/system/grafana-operator/charts/grafana-operator/crds/grafana.integreatly.org_grafanas.yaml @@ -0,0 +1,4007 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.12.0 + name: grafanas.grafana.integreatly.org +spec: + group: grafana.integreatly.org + names: + kind: Grafana + listKind: GrafanaList + plural: grafanas + singular: grafana + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .status.stage + name: Stage + type: string + - jsonPath: .status.stageStatus + name: Stage status + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1beta1 + schema: + openAPIV3Schema: + properties: + apiVersion: + type: string + kind: + type: string + metadata: + type: object + spec: + properties: + client: + properties: + preferIngress: + nullable: true + type: boolean + timeout: + nullable: true + type: integer + type: object + config: + additionalProperties: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-preserve-unknown-fields: true + deployment: + properties: + metadata: + properties: + annotations: + additionalProperties: + type: string + type: object + labels: + additionalProperties: + type: string + type: object + type: object + spec: + properties: + minReadySeconds: + format: int32 + type: integer + paused: + type: boolean + progressDeadlineSeconds: + format: int32 + type: integer + replicas: + format: int32 + type: integer + revisionHistoryLimit: + format: int32 + type: integer + selector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + strategy: + properties: + rollingUpdate: + properties: + maxSurge: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + maxUnavailable: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + type: object + type: + type: string + type: object + template: + properties: + metadata: + properties: + annotations: + additionalProperties: + type: string + type: object + labels: + additionalProperties: + type: string + type: object + type: object + spec: + properties: + activeDeadlineSeconds: + format: int64 + type: integer + affinity: + properties: + nodeAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + preference: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + x-kubernetes-map-type: atomic + weight: + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + properties: + nodeSelectorTerms: + items: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + x-kubernetes-map-type: atomic + type: array + required: + - nodeSelectorTerms + type: object + x-kubernetes-map-type: atomic + type: object + podAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + podAffinityTerm: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + topologyKey: + type: string + required: + - topologyKey + type: object + weight: + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + topologyKey: + type: string + required: + - topologyKey + type: object + type: array + type: object + podAntiAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + podAffinityTerm: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + topologyKey: + type: string + required: + - topologyKey + type: object + weight: + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + topologyKey: + type: string + required: + - topologyKey + type: object + type: array + type: object + type: object + automountServiceAccountToken: + type: boolean + containers: + items: + properties: + args: + items: + type: string + type: array + command: + items: + type: string + type: array + env: + items: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + properties: + containerName: + type: string + divisor: + 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 + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + envFrom: + items: + properties: + configMapRef: + properties: + name: + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + type: string + secretRef: + properties: + name: + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + image: + type: string + imagePullPolicy: + type: string + lifecycle: + properties: + postStart: + properties: + exec: + properties: + command: + items: + type: string + type: array + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + preStop: + properties: + exec: + properties: + command: + items: + type: string + type: array + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + type: object + livenessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + name: + type: string + ports: + items: + properties: + containerPort: + format: int32 + type: integer + hostIP: + type: string + hostPort: + format: int32 + type: integer + name: + type: string + protocol: + default: TCP + type: string + required: + - containerPort + type: object + type: array + x-kubernetes-list-map-keys: + - containerPort + - protocol + x-kubernetes-list-type: map + readinessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + resizePolicy: + items: + properties: + resourceName: + type: string + restartPolicy: + type: string + required: + - resourceName + - restartPolicy + type: object + type: array + x-kubernetes-list-type: atomic + resources: + properties: + claims: + items: + properties: + name: + 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 + 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 + type: object + type: object + restartPolicy: + type: string + securityContext: + properties: + allowPrivilegeEscalation: + type: boolean + capabilities: + properties: + add: + items: + type: string + type: array + drop: + items: + type: string + type: array + type: object + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + startupProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + stdin: + type: boolean + stdinOnce: + type: boolean + terminationMessagePath: + type: string + terminationMessagePolicy: + type: string + tty: + type: boolean + volumeDevices: + items: + properties: + devicePath: + type: string + name: + type: string + required: + - devicePath + - name + type: object + type: array + volumeMounts: + items: + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + subPath: + type: string + subPathExpr: + type: string + required: + - mountPath + - name + type: object + type: array + workingDir: + type: string + required: + - name + type: object + type: array + dnsConfig: + properties: + nameservers: + items: + type: string + type: array + options: + items: + properties: + name: + type: string + value: + type: string + type: object + type: array + searches: + items: + type: string + type: array + type: object + dnsPolicy: + type: string + enableServiceLinks: + type: boolean + ephemeralContainers: + items: + properties: + args: + items: + type: string + type: array + command: + items: + type: string + type: array + env: + items: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + properties: + containerName: + type: string + divisor: + 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 + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + envFrom: + items: + properties: + configMapRef: + properties: + name: + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + type: string + secretRef: + properties: + name: + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + image: + type: string + imagePullPolicy: + type: string + lifecycle: + properties: + postStart: + properties: + exec: + properties: + command: + items: + type: string + type: array + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + preStop: + properties: + exec: + properties: + command: + items: + type: string + type: array + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + type: object + livenessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + name: + type: string + ports: + items: + properties: + containerPort: + format: int32 + type: integer + hostIP: + type: string + hostPort: + format: int32 + type: integer + name: + type: string + protocol: + default: TCP + type: string + required: + - containerPort + type: object + type: array + x-kubernetes-list-map-keys: + - containerPort + - protocol + x-kubernetes-list-type: map + readinessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + resizePolicy: + items: + properties: + resourceName: + type: string + restartPolicy: + type: string + required: + - resourceName + - restartPolicy + type: object + type: array + x-kubernetes-list-type: atomic + resources: + properties: + claims: + items: + properties: + name: + 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 + 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 + type: object + type: object + restartPolicy: + type: string + securityContext: + properties: + allowPrivilegeEscalation: + type: boolean + capabilities: + properties: + add: + items: + type: string + type: array + drop: + items: + type: string + type: array + type: object + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + startupProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + stdin: + type: boolean + stdinOnce: + type: boolean + targetContainerName: + type: string + terminationMessagePath: + type: string + terminationMessagePolicy: + type: string + tty: + type: boolean + volumeDevices: + items: + properties: + devicePath: + type: string + name: + type: string + required: + - devicePath + - name + type: object + type: array + volumeMounts: + items: + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + subPath: + type: string + subPathExpr: + type: string + required: + - mountPath + - name + type: object + type: array + workingDir: + type: string + required: + - name + type: object + type: array + hostAliases: + items: + properties: + hostnames: + items: + type: string + type: array + ip: + type: string + type: object + type: array + hostIPC: + type: boolean + hostNetwork: + type: boolean + hostPID: + type: boolean + hostUsers: + type: boolean + hostname: + type: string + imagePullSecrets: + items: + properties: + name: + type: string + type: object + x-kubernetes-map-type: atomic + type: array + initContainers: + items: + properties: + args: + items: + type: string + type: array + command: + items: + type: string + type: array + env: + items: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + properties: + containerName: + type: string + divisor: + 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 + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + envFrom: + items: + properties: + configMapRef: + properties: + name: + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + type: string + secretRef: + properties: + name: + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + image: + type: string + imagePullPolicy: + type: string + lifecycle: + properties: + postStart: + properties: + exec: + properties: + command: + items: + type: string + type: array + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + preStop: + properties: + exec: + properties: + command: + items: + type: string + type: array + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + type: object + livenessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + name: + type: string + ports: + items: + properties: + containerPort: + format: int32 + type: integer + hostIP: + type: string + hostPort: + format: int32 + type: integer + name: + type: string + protocol: + default: TCP + type: string + required: + - containerPort + type: object + type: array + x-kubernetes-list-map-keys: + - containerPort + - protocol + x-kubernetes-list-type: map + readinessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + resizePolicy: + items: + properties: + resourceName: + type: string + restartPolicy: + type: string + required: + - resourceName + - restartPolicy + type: object + type: array + x-kubernetes-list-type: atomic + resources: + properties: + claims: + items: + properties: + name: + 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 + 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 + type: object + type: object + restartPolicy: + type: string + securityContext: + properties: + allowPrivilegeEscalation: + type: boolean + capabilities: + properties: + add: + items: + type: string + type: array + drop: + items: + type: string + type: array + type: object + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + startupProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + stdin: + type: boolean + stdinOnce: + type: boolean + terminationMessagePath: + type: string + terminationMessagePolicy: + type: string + tty: + type: boolean + volumeDevices: + items: + properties: + devicePath: + type: string + name: + type: string + required: + - devicePath + - name + type: object + type: array + volumeMounts: + items: + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + subPath: + type: string + subPathExpr: + type: string + required: + - mountPath + - name + type: object + type: array + workingDir: + type: string + required: + - name + type: object + type: array + nodeName: + type: string + nodeSelector: + additionalProperties: + type: string + type: object + x-kubernetes-map-type: atomic + os: + properties: + name: + type: string + required: + - name + type: object + overhead: + 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 + type: object + preemptionPolicy: + type: string + priority: + format: int32 + type: integer + priorityClassName: + type: string + readinessGates: + items: + properties: + conditionType: + type: string + required: + - conditionType + type: object + type: array + restartPolicy: + type: string + runtimeClassName: + type: string + schedulerName: + type: string + securityContext: + properties: + fsGroup: + format: int64 + type: integer + fsGroupChangePolicy: + type: string + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + supplementalGroups: + items: + format: int64 + type: integer + type: array + sysctls: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + serviceAccount: + type: string + serviceAccountName: + type: string + setHostnameAsFQDN: + type: boolean + shareProcessNamespace: + type: boolean + subdomain: + type: string + terminationGracePeriodSeconds: + format: int64 + type: integer + tolerations: + items: + properties: + effect: + type: string + key: + type: string + operator: + type: string + tolerationSeconds: + format: int64 + type: integer + value: + type: string + type: object + type: array + topologySpreadConstraints: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + maxSkew: + format: int32 + type: integer + minDomains: + format: int32 + type: integer + nodeAffinityPolicy: + type: string + nodeTaintsPolicy: + type: string + topologyKey: + type: string + whenUnsatisfiable: + type: string + required: + - maxSkew + - topologyKey + - whenUnsatisfiable + type: object + type: array + x-kubernetes-list-map-keys: + - topologyKey + - whenUnsatisfiable + x-kubernetes-list-type: map + volumes: + items: + properties: + awsElasticBlockStore: + properties: + fsType: + type: string + partition: + format: int32 + type: integer + readOnly: + type: boolean + volumeID: + type: string + required: + - volumeID + type: object + azureDisk: + properties: + cachingMode: + type: string + diskName: + type: string + diskURI: + type: string + fsType: + type: string + kind: + type: string + readOnly: + type: boolean + required: + - diskName + - diskURI + type: object + azureFile: + properties: + readOnly: + type: boolean + secretName: + type: string + shareName: + type: string + required: + - secretName + - shareName + type: object + cephfs: + properties: + monitors: + items: + type: string + type: array + path: + type: string + readOnly: + type: boolean + secretFile: + type: string + secretRef: + properties: + name: + type: string + type: object + x-kubernetes-map-type: atomic + user: + type: string + required: + - monitors + type: object + cinder: + properties: + fsType: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + type: string + type: object + x-kubernetes-map-type: atomic + volumeID: + type: string + required: + - volumeID + type: object + configMap: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + name: + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + csi: + properties: + driver: + type: string + fsType: + type: string + nodePublishSecretRef: + properties: + name: + type: string + type: object + x-kubernetes-map-type: atomic + readOnly: + type: boolean + volumeAttributes: + additionalProperties: + type: string + type: object + required: + - driver + type: object + downwardAPI: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + mode: + format: int32 + type: integer + path: + type: string + resourceFieldRef: + properties: + containerName: + type: string + divisor: + 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 + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + required: + - path + type: object + type: array + type: object + emptyDir: + properties: + medium: + type: string + sizeLimit: + 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 + type: object + ephemeral: + properties: + volumeClaimTemplate: + properties: + metadata: + type: object + spec: + properties: + accessModes: + items: + type: string + type: array + dataSource: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + - name + type: object + resources: + properties: + 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 + 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 + type: object + type: object + selector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + storageClassName: + type: string + volumeAttributesClassName: + type: string + volumeMode: + type: string + volumeName: + type: string + type: object + required: + - spec + type: object + type: object + fc: + properties: + fsType: + type: string + lun: + format: int32 + type: integer + readOnly: + type: boolean + targetWWNs: + items: + type: string + type: array + wwids: + items: + type: string + type: array + type: object + flexVolume: + properties: + driver: + type: string + fsType: + type: string + options: + additionalProperties: + type: string + type: object + readOnly: + type: boolean + secretRef: + properties: + name: + type: string + type: object + x-kubernetes-map-type: atomic + required: + - driver + type: object + flocker: + properties: + datasetName: + type: string + datasetUUID: + type: string + type: object + gcePersistentDisk: + properties: + fsType: + type: string + partition: + format: int32 + type: integer + pdName: + type: string + readOnly: + type: boolean + required: + - pdName + type: object + gitRepo: + properties: + directory: + type: string + repository: + type: string + revision: + type: string + required: + - repository + type: object + glusterfs: + properties: + endpoints: + type: string + path: + type: string + readOnly: + type: boolean + required: + - endpoints + - path + type: object + hostPath: + properties: + path: + type: string + type: + type: string + required: + - path + type: object + iscsi: + properties: + chapAuthDiscovery: + type: boolean + chapAuthSession: + type: boolean + fsType: + type: string + initiatorName: + type: string + iqn: + type: string + iscsiInterface: + type: string + lun: + format: int32 + type: integer + portals: + items: + type: string + type: array + readOnly: + type: boolean + secretRef: + properties: + name: + type: string + type: object + x-kubernetes-map-type: atomic + targetPortal: + type: string + required: + - iqn + - lun + - targetPortal + type: object + name: + type: string + nfs: + properties: + path: + type: string + readOnly: + type: boolean + server: + type: string + required: + - path + - server + type: object + persistentVolumeClaim: + properties: + claimName: + type: string + readOnly: + type: boolean + required: + - claimName + type: object + photonPersistentDisk: + properties: + fsType: + type: string + pdID: + type: string + required: + - pdID + type: object + portworxVolume: + properties: + fsType: + type: string + readOnly: + type: boolean + volumeID: + type: string + required: + - volumeID + type: object + projected: + properties: + defaultMode: + format: int32 + type: integer + sources: + items: + properties: + clusterTrustBundle: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + name: + type: string + optional: + type: boolean + path: + type: string + signerName: + type: string + required: + - path + type: object + configMap: + properties: + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + name: + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + downwardAPI: + properties: + items: + items: + properties: + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + mode: + format: int32 + type: integer + path: + type: string + resourceFieldRef: + properties: + containerName: + type: string + divisor: + 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 + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + required: + - path + type: object + type: array + type: object + secret: + properties: + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + name: + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + serviceAccountToken: + properties: + audience: + type: string + expirationSeconds: + format: int64 + type: integer + path: + type: string + required: + - path + type: object + type: object + type: array + type: object + quobyte: + properties: + group: + type: string + readOnly: + type: boolean + registry: + type: string + tenant: + type: string + user: + type: string + volume: + type: string + required: + - registry + - volume + type: object + rbd: + properties: + fsType: + type: string + image: + type: string + keyring: + type: string + monitors: + items: + type: string + type: array + pool: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + type: string + type: object + x-kubernetes-map-type: atomic + user: + type: string + required: + - image + - monitors + type: object + scaleIO: + properties: + fsType: + type: string + gateway: + type: string + protectionDomain: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + type: string + type: object + x-kubernetes-map-type: atomic + sslEnabled: + type: boolean + storageMode: + type: string + storagePool: + type: string + system: + type: string + volumeName: + type: string + required: + - gateway + - secretRef + - system + type: object + secret: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + optional: + type: boolean + secretName: + type: string + type: object + storageos: + properties: + fsType: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + type: string + type: object + x-kubernetes-map-type: atomic + volumeName: + type: string + volumeNamespace: + type: string + type: object + vsphereVolume: + properties: + fsType: + type: string + storagePolicyID: + type: string + storagePolicyName: + type: string + volumePath: + type: string + required: + - volumePath + type: object + required: + - name + type: object + type: array + type: object + type: object + type: object + type: object + external: + properties: + adminPassword: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + adminUser: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + apiKey: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + url: + type: string + required: + - url + type: object + ingress: + properties: + metadata: + properties: + annotations: + additionalProperties: + type: string + type: object + labels: + additionalProperties: + type: string + type: object + type: object + spec: + properties: + defaultBackend: + properties: + resource: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + service: + properties: + name: + type: string + port: + properties: + name: + type: string + number: + format: int32 + type: integer + type: object + required: + - name + type: object + type: object + ingressClassName: + type: string + rules: + items: + properties: + host: + type: string + http: + properties: + paths: + items: + properties: + backend: + properties: + resource: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + service: + properties: + name: + type: string + port: + properties: + name: + type: string + number: + format: int32 + type: integer + type: object + required: + - name + type: object + type: object + path: + type: string + pathType: + type: string + required: + - backend + - pathType + type: object + type: array + x-kubernetes-list-type: atomic + required: + - paths + type: object + type: object + type: array + x-kubernetes-list-type: atomic + tls: + items: + properties: + hosts: + items: + type: string + type: array + x-kubernetes-list-type: atomic + secretName: + type: string + type: object + type: array + x-kubernetes-list-type: atomic + type: object + type: object + jsonnet: + properties: + libraryLabelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + type: object + persistentVolumeClaim: + properties: + metadata: + properties: + annotations: + additionalProperties: + type: string + type: object + labels: + additionalProperties: + type: string + type: object + type: object + spec: + properties: + accessModes: + items: + type: string + type: array + dataSource: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + resources: + properties: + claims: + items: + properties: + name: + 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 + 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 + type: object + type: object + selector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + storageClassName: + type: string + volumeMode: + type: string + volumeName: + type: string + type: object + type: object + preferences: + properties: + homeDashboardUid: + type: string + type: object + route: + properties: + metadata: + properties: + annotations: + additionalProperties: + type: string + type: object + labels: + additionalProperties: + type: string + type: object + type: object + spec: + properties: + alternateBackends: + items: + properties: + kind: + type: string + name: + type: string + weight: + format: int32 + type: integer + required: + - kind + - name + - weight + type: object + type: array + host: + type: string + path: + type: string + port: + properties: + targetPort: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - targetPort + type: object + tls: + properties: + caCertificate: + type: string + certificate: + type: string + destinationCACertificate: + type: string + insecureEdgeTerminationPolicy: + type: string + key: + type: string + termination: + type: string + required: + - termination + type: object + to: + properties: + kind: + type: string + name: + type: string + weight: + format: int32 + type: integer + required: + - kind + - name + - weight + type: object + wildcardPolicy: + type: string + type: object + type: object + service: + properties: + metadata: + properties: + annotations: + additionalProperties: + type: string + type: object + labels: + additionalProperties: + type: string + type: object + type: object + spec: + properties: + allocateLoadBalancerNodePorts: + type: boolean + clusterIP: + type: string + clusterIPs: + items: + type: string + type: array + x-kubernetes-list-type: atomic + externalIPs: + items: + type: string + type: array + externalName: + type: string + externalTrafficPolicy: + type: string + healthCheckNodePort: + format: int32 + type: integer + internalTrafficPolicy: + type: string + ipFamilies: + items: + type: string + type: array + x-kubernetes-list-type: atomic + ipFamilyPolicy: + type: string + loadBalancerClass: + type: string + loadBalancerIP: + type: string + loadBalancerSourceRanges: + items: + type: string + type: array + ports: + items: + properties: + appProtocol: + type: string + name: + type: string + nodePort: + format: int32 + type: integer + port: + format: int32 + type: integer + protocol: + default: TCP + type: string + targetPort: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: array + x-kubernetes-list-map-keys: + - port + - protocol + x-kubernetes-list-type: map + publishNotReadyAddresses: + type: boolean + selector: + additionalProperties: + type: string + type: object + x-kubernetes-map-type: atomic + sessionAffinity: + type: string + sessionAffinityConfig: + properties: + clientIP: + properties: + timeoutSeconds: + format: int32 + type: integer + type: object + type: object + type: + type: string + type: object + type: object + serviceAccount: + properties: + automountServiceAccountToken: + type: boolean + imagePullSecrets: + items: + properties: + name: + type: string + type: object + x-kubernetes-map-type: atomic + type: array + metadata: + properties: + annotations: + additionalProperties: + type: string + type: object + labels: + additionalProperties: + type: string + type: object + type: object + secrets: + items: + properties: + apiVersion: + type: string + fieldPath: + type: string + kind: + type: string + name: + type: string + namespace: + type: string + resourceVersion: + type: string + uid: + type: string + type: object + x-kubernetes-map-type: atomic + type: array + type: object + type: object + status: + properties: + adminUrl: + type: string + dashboards: + items: + type: string + type: array + datasources: + items: + type: string + type: array + folders: + items: + type: string + type: array + lastMessage: + type: string + stage: + type: string + stageStatus: + type: string + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/packages/system/grafana-operator/charts/grafana-operator/templates/_helpers.tpl b/packages/system/grafana-operator/charts/grafana-operator/templates/_helpers.tpl new file mode 100644 index 00000000..f082bf0f --- /dev/null +++ b/packages/system/grafana-operator/charts/grafana-operator/templates/_helpers.tpl @@ -0,0 +1,62 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "grafana-operator.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | 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 "grafana-operator.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "grafana-operator.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "grafana-operator.labels" -}} +helm.sh/chart: {{ include "grafana-operator.chart" . }} +{{ include "grafana-operator.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "grafana-operator.selectorLabels" -}} +app.kubernetes.io/name: {{ include "grafana-operator.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "grafana-operator.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "grafana-operator.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} diff --git a/packages/system/grafana-operator/charts/grafana-operator/templates/cm.yaml b/packages/system/grafana-operator/charts/grafana-operator/templates/cm.yaml new file mode 100644 index 00000000..cc4866e2 --- /dev/null +++ b/packages/system/grafana-operator/charts/grafana-operator/templates/cm.yaml @@ -0,0 +1,24 @@ +{{- if .Values.leaderElect }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "grafana-operator.fullname" . }} + namespace: {{ .Release.Namespace | quote }} + labels: + {{- with .Values.additionalLabels }} + {{- toYaml . | nindent 4 }} + {{- end }} +data: + controller_manager_config.yaml: | + apiVersion: controller-runtime.sigs.k8s.io/v1alpha1 + kind: ControllerManagerConfig + health: + healthProbeBindAddress: :8081 + metrics: + bindAddress: 127.0.0.1:8080 + webhook: + port: 9443 + leaderElection: + leaderElect: true + resourceName: f75f3bba.integreatly.org +{{- end }} diff --git a/packages/system/grafana-operator/charts/grafana-operator/templates/deployment.yaml b/packages/system/grafana-operator/charts/grafana-operator/templates/deployment.yaml new file mode 100644 index 00000000..b22be24e --- /dev/null +++ b/packages/system/grafana-operator/charts/grafana-operator/templates/deployment.yaml @@ -0,0 +1,97 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "grafana-operator.fullname" . }} + namespace: {{ .Release.Namespace | quote }} + labels: + {{- include "grafana-operator.labels" . | nindent 4 }} + {{- with .Values.additionalLabels }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + replicas: 1 + selector: + matchLabels: + {{- include "grafana-operator.selectorLabels" . | nindent 6 }} + template: + metadata: + {{- with .Values.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "grafana-operator.selectorLabels" . | nindent 8 }} + {{- with .Values.additionalLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "grafana-operator.serviceAccountName" . }} + {{- with .Values.podSecurityContext }} + securityContext: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: {{ .Chart.Name }} + {{- with .Values.securityContext }} + securityContext: + {{- toYaml . | nindent 12 }} + {{- end }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + env: + - name: WATCH_NAMESPACE + {{- if and .Values.namespaceScope (eq .Values.watchNamespaces "") }} + value: {{ .Release.Namespace }} + {{ else }} + value: {{ .Values.watchNamespaces }} + {{- end }} + {{- with .Values.env }} + {{- toYaml . | nindent 12 }} + {{- end }} + args: + - --health-probe-bind-address=:8081 + - --metrics-bind-address=0.0.0.0:{{ .Values.metricsService.metricsPort }} + {{- if .Values.leaderElect }} + - --leader-elect + {{- end }} + volumeMounts: + - name: dashboards-dir + mountPath: /tmp/dashboards + ports: + - containerPort: {{ .Values.metricsService.metricsPort }} + name: metrics + protocol: TCP + livenessProbe: + httpGet: + path: /healthz + port: 8081 + readinessProbe: + httpGet: + path: /readyz + port: 8081 + {{- with .Values.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + volumes: + - name: dashboards-dir + emptyDir: {} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if .Values.priorityClassName }} + priorityClassName: {{ .Values.priorityClassName }} + {{- end }} diff --git a/packages/system/grafana-operator/charts/grafana-operator/templates/rbac.yaml b/packages/system/grafana-operator/charts/grafana-operator/templates/rbac.yaml new file mode 100644 index 00000000..983e45e6 --- /dev/null +++ b/packages/system/grafana-operator/charts/grafana-operator/templates/rbac.yaml @@ -0,0 +1,252 @@ +{{- $watchNamespaces := coalesce .Values.watchNamespaces .Release.Namespace }} +{{- $namespaceScoped := false }} +{{- if or (.Values.namespaceScope) (.Values.watchNamespaces) }} +{{- $namespaceScoped = true }} +{{- end }} +{{- $operatorNamespace := .Release.Namespace }} +{{- range ( split "," $watchNamespaces ) }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: {{ if not $namespaceScoped }}Cluster{{ end }}Role +metadata: + {{- if $namespaceScoped }} + namespace: {{ $operatorNamespace }} + {{- end }} + name: grafana-operator-permissions + labels: + {{- include "grafana-operator.labels" $ | nindent 4 }} + {{- with $.Values.additionalLabels }} + {{- toYaml . | nindent 4 }} + {{- end }} +rules: + - apiGroups: + - "" + resources: + - configmaps + verbs: + - get + - list + - watch + - create + - update + - patch + - delete + - apiGroups: + - coordination.k8s.io + resources: + - leases + verbs: + - get + - list + - watch + - create + - update + - patch + - delete + - apiGroups: + - "" + resources: + - events + verbs: + - create + - patch + - apiGroups: + - "" + resources: + - configmaps + - persistentvolumeclaims + - secrets + - serviceaccounts + - services + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: + - "" + resources: + - events + verbs: + - create + - get + - list + - patch + - watch + - apiGroups: + - apps + resources: + - deployments + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: + - grafana.integreatly.org + resources: + - grafanadashboards + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: + - grafana.integreatly.org + resources: + - grafanadashboards/finalizers + verbs: + - update + - apiGroups: + - grafana.integreatly.org + resources: + - grafanadashboards/status + verbs: + - get + - patch + - update + - apiGroups: + - grafana.integreatly.org + resources: + - grafanadatasources + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: + - grafana.integreatly.org + resources: + - grafanadatasources/finalizers + verbs: + - update + - apiGroups: + - grafana.integreatly.org + resources: + - grafanadatasources/status + verbs: + - get + - patch + - update + - apiGroups: + - grafana.integreatly.org + resources: + - grafanafolders + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: + - grafana.integreatly.org + resources: + - grafanafolders/finalizers + verbs: + - update + - apiGroups: + - grafana.integreatly.org + resources: + - grafanafolders/status + verbs: + - get + - patch + - update + - apiGroups: + - grafana.integreatly.org + resources: + - grafanas + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: + - grafana.integreatly.org + resources: + - grafanas/finalizers + verbs: + - update + - apiGroups: + - grafana.integreatly.org + resources: + - grafanas/status + verbs: + - get + - patch + - update + - apiGroups: + - networking.k8s.io + resources: + - ingresses + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: + - route.openshift.io + resources: + - routes + - routes/custom-host + verbs: + - create + - delete + - get + - list + - update + - watch + - apiGroups: + - authentication.k8s.io + resources: + - tokenreviews + verbs: + - create + - apiGroups: + - authorization.k8s.io + resources: + - subjectaccessreviews + verbs: + - create +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: {{ if not $namespaceScoped }}Cluster{{ end }}RoleBinding +metadata: + name: grafana-operator-permissions + {{- if $namespaceScoped }} + namespace: {{ $operatorNamespace }} + {{- end }} + labels: + {{- include "grafana-operator.labels" $ | nindent 4 }} + {{- with $.Values.additionalLabels }} + {{- toYaml . | nindent 4 }} + {{- end }} +subjects: + - kind: ServiceAccount + name: {{ include "grafana-operator.serviceAccountName" $ }} + namespace: {{ $operatorNamespace }} +roleRef: + kind: {{ if not $namespaceScoped }}Cluster{{ end }}Role + name: grafana-operator-permissions + apiGroup: rbac.authorization.k8s.io +{{- end }} diff --git a/packages/system/grafana-operator/charts/grafana-operator/templates/service.yaml b/packages/system/grafana-operator/charts/grafana-operator/templates/service.yaml new file mode 100644 index 00000000..f765c94b --- /dev/null +++ b/packages/system/grafana-operator/charts/grafana-operator/templates/service.yaml @@ -0,0 +1,19 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "grafana-operator.fullname" . }}-metrics-service + namespace: {{ .Release.Namespace | quote }} + labels: + {{- include "grafana-operator.labels" . | nindent 4 }} + {{- with .Values.additionalLabels }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + type: {{ .Values.metricsService.type }} + ports: + - port: {{ .Values.metricsService.metricsPort }} + targetPort: metrics + protocol: TCP + name: metrics + selector: + {{- include "grafana-operator.selectorLabels" . | nindent 4 }} diff --git a/packages/system/grafana-operator/charts/grafana-operator/templates/serviceaccount.yaml b/packages/system/grafana-operator/charts/grafana-operator/templates/serviceaccount.yaml new file mode 100644 index 00000000..1b31f313 --- /dev/null +++ b/packages/system/grafana-operator/charts/grafana-operator/templates/serviceaccount.yaml @@ -0,0 +1,17 @@ +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "grafana-operator.serviceAccountName" . }} + namespace: {{ .Release.Namespace | quote }} + labels: + {{- include "grafana-operator.labels" . | nindent 4 }} + {{- with .Values.additionalLabels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +automountServiceAccountToken: true +{{- end }} diff --git a/packages/system/grafana-operator/charts/grafana-operator/values.yaml b/packages/system/grafana-operator/charts/grafana-operator/values.yaml new file mode 100644 index 00000000..c51ec700 --- /dev/null +++ b/packages/system/grafana-operator/charts/grafana-operator/values.yaml @@ -0,0 +1,80 @@ +# -- If the operator should run in namespace-scope or not, +# if true the operator will only be able to manage instances in the same namespace +namespaceScope: false + +# -- If you want to run multiple replicas of the grafana-operator, this is not recommended. +leaderElect: false + +# -- Sets the WATCH_NAMESPACE environment variable, +# it defines which namespaces the operator should be listening for. +# By default it's all namespaces, if you only want to listen for the same namespace as the operator is deployed to look at namespaceScope. +watchNamespaces: "" + +# -- Additional environment variables +env: [] + # -- grafana image, e.g. docker.io/grafana/grafana:9.1.6, overwrites the default grafana image defined in the operator + # - name: RELATED_IMAGE_GRAFANA + # value: "docker.io/grafana/grafana:9.1.6" + # - name: MY_VAR + # value: "myvalue" + +image: + # -- grafana operator image repository + repository: ghcr.io/grafana/grafana-operator + # -- The image pull policy to use in grafana operator container + pullPolicy: IfNotPresent + # -- Overrides the image tag whose default is the chart appVersion. + tag: "" + +# -- image pull secrets +imagePullSecrets: [] + +nameOverride: "" +fullnameOverride: "" + +serviceAccount: + # -- Specifies whether a service account should be created + create: true + # -- Annotations to add to the service account + annotations: {} + # -- The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" + +metricsService: + # -- metrics service type + type: ClusterIP + # -- metrics service port + metricsPort: 9090 + +# -- additional labels to add to all resources +additionalLabels: {} + +# -- pod annotations +podAnnotations: {} + +# -- pod security context +podSecurityContext: {} + +# -- grafana operator container security context +securityContext: + capabilities: + drop: + - ALL + readOnlyRootFilesystem: true + runAsNonRoot: true + +# -- grafana operator container resources +resources: {} + +# -- pod priority class name +priorityClassName: "" + +# -- pod node selector +nodeSelector: {} + +# -- pod tolerations +tolerations: [] + +# -- pod affinity +affinity: {} diff --git a/packages/system/grafana-operator/values.yaml b/packages/system/grafana-operator/values.yaml new file mode 100644 index 00000000..52c84cae --- /dev/null +++ b/packages/system/grafana-operator/values.yaml @@ -0,0 +1,2 @@ +grafana-operator: + fullnameOverride: grafana-operator diff --git a/packages/system/ingress-nginx/.helmignore b/packages/system/ingress-nginx/.helmignore new file mode 100644 index 00000000..216b462f --- /dev/null +++ b/packages/system/ingress-nginx/.helmignore @@ -0,0 +1,2 @@ +images +hack diff --git a/packages/system/ingress-nginx/Chart.yaml b/packages/system/ingress-nginx/Chart.yaml new file mode 100644 index 00000000..4716918b --- /dev/null +++ b/packages/system/ingress-nginx/Chart.yaml @@ -0,0 +1,2 @@ +name: cozy-ingress-nginx +version: 1.0.0 diff --git a/packages/system/ingress-nginx/Makefile b/packages/system/ingress-nginx/Makefile new file mode 100644 index 00000000..f51895b8 --- /dev/null +++ b/packages/system/ingress-nginx/Makefile @@ -0,0 +1,21 @@ +NAME=ingress-nginx +NAMESPACE=cozy-ingress-nginx + +show: + helm template --dry-run=server -n $(NAMESPACE) $(NAME) . + +apply: + helm upgrade -i -n $(NAMESPACE) $(NAME) . + +diff: + helm diff upgrade --allow-unreleased --normalize-manifests -n $(NAMESPACE) $(NAME) . + +update: + rm -rf charts + helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx + helm repo update ingress-nginx + helm pull ingress-nginx/ingress-nginx --untar --untardir charts + patch -p 3 < patches/add-metrics2.patch + rm -f charts/ingress-nginx/templates/controller-deployment.yaml.orig + rm -rf charts/ingress-nginx/changelog/ + #sed -i '/ type:/a \ allocateLoadBalancerNodePorts: false' charts/ingress-nginx/templates/controller-service.yaml diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/.helmignore b/packages/system/ingress-nginx/charts/ingress-nginx/.helmignore new file mode 100644 index 00000000..109b4081 --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/.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 +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ +__snapshot__ diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/Chart.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/Chart.yaml new file mode 100644 index 00000000..7e633f4f --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/Chart.yaml @@ -0,0 +1,21 @@ +annotations: + artifacthub.io/changes: '- "Update Ingress-Nginx version controller-v1.9.4"' + artifacthub.io/prerelease: "false" +apiVersion: v2 +appVersion: 1.9.4 +description: Ingress controller for Kubernetes using NGINX as a reverse proxy and + load balancer +home: https://github.com/kubernetes/ingress-nginx +icon: https://upload.wikimedia.org/wikipedia/commons/thumb/c/c5/Nginx_logo.svg/500px-Nginx_logo.svg.png +keywords: +- ingress +- nginx +kubeVersion: '>=1.20.0-0' +maintainers: +- name: rikatz +- name: strongjz +- name: tao12345666333 +name: ingress-nginx +sources: +- https://github.com/kubernetes/ingress-nginx +version: 4.8.4 diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/OWNERS b/packages/system/ingress-nginx/charts/ingress-nginx/OWNERS new file mode 100644 index 00000000..6b7e049c --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/OWNERS @@ -0,0 +1,10 @@ +# See the OWNERS docs: https://github.com/kubernetes/community/blob/master/contributors/guide/owners.md + +approvers: +- ingress-nginx-helm-maintainers + +reviewers: +- ingress-nginx-helm-reviewers + +labels: +- area/helm diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/README.md b/packages/system/ingress-nginx/charts/ingress-nginx/README.md new file mode 100644 index 00000000..c03f290d --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/README.md @@ -0,0 +1,527 @@ +# ingress-nginx + +[ingress-nginx](https://github.com/kubernetes/ingress-nginx) Ingress controller for Kubernetes using NGINX as a reverse proxy and load balancer + +![Version: 4.8.4](https://img.shields.io/badge/Version-4.8.4-informational?style=flat-square) ![AppVersion: 1.9.4](https://img.shields.io/badge/AppVersion-1.9.4-informational?style=flat-square) + +To use, add `ingressClassName: nginx` spec field or the `kubernetes.io/ingress.class: nginx` annotation to your Ingress resources. + +This chart bootstraps an ingress-nginx deployment on a [Kubernetes](http://kubernetes.io) cluster using the [Helm](https://helm.sh) package manager. + +## Requirements + +Kubernetes: `>=1.20.0-0` + +## Get Repo Info + +```console +helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx +helm repo update +``` + +## Install Chart + +**Important:** only helm3 is supported + +```console +helm install [RELEASE_NAME] ingress-nginx/ingress-nginx +``` + +The command deploys ingress-nginx on the Kubernetes cluster in the default configuration. + +_See [configuration](#configuration) below._ + +_See [helm install](https://helm.sh/docs/helm/helm_install/) for command documentation._ + +## Uninstall Chart + +```console +helm uninstall [RELEASE_NAME] +``` + +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._ + +## Upgrading Chart + +```console +helm upgrade [RELEASE_NAME] [CHART] --install +``` + +_See [helm upgrade](https://helm.sh/docs/helm/helm_upgrade/) for command documentation._ + +### Migrating from stable/nginx-ingress + +There are two main ways to migrate a release from `stable/nginx-ingress` to `ingress-nginx/ingress-nginx` chart: + +1. For Nginx Ingress controllers used for non-critical services, the easiest method is to [uninstall](#uninstall-chart) the old release and [install](#install-chart) the new one +1. For critical services in production that require zero-downtime, you will want to: + 1. [Install](#install-chart) a second Ingress controller + 1. Redirect your DNS traffic from the old controller to the new controller + 1. Log traffic from both controllers during this changeover + 1. [Uninstall](#uninstall-chart) the old controller once traffic has fully drained from it + +Note that there are some different and upgraded configurations between the two charts, described by Rimas Mocevicius from JFrog in the "Upgrading to ingress-nginx Helm chart" section of [Migrating from Helm chart nginx-ingress to ingress-nginx](https://rimusz.net/migrating-to-ingress-nginx). As the `ingress-nginx/ingress-nginx` chart continues to update, you will want to check current differences by running [helm configuration](#configuration) commands on both charts. + +## Configuration + +See [Customizing the Chart Before Installing](https://helm.sh/docs/intro/using_helm/#customizing-the-chart-before-installing). To see all configurable options with detailed comments, visit the chart's [values.yaml](./values.yaml), or run these configuration commands: + +```console +helm show values ingress-nginx/ingress-nginx +``` + +### PodDisruptionBudget + +Note that the PodDisruptionBudget resource will only be defined if the replicaCount is greater than one, +else it would make it impossible to evacuate a node. See [gh issue #7127](https://github.com/helm/charts/issues/7127) for more info. + +### Prometheus Metrics + +The Ingress-Nginx Controller can export Prometheus metrics, by setting `controller.metrics.enabled` to `true`. + +You can add Prometheus annotations to the metrics service using `controller.metrics.service.annotations`. +Alternatively, if you use the Prometheus Operator, you can enable ServiceMonitor creation using `controller.metrics.serviceMonitor.enabled`. And set `controller.metrics.serviceMonitor.additionalLabels.release="prometheus"`. "release=prometheus" should match the label configured in the prometheus servicemonitor ( see `kubectl get servicemonitor prometheus-kube-prom-prometheus -oyaml -n prometheus`) + +### ingress-nginx nginx\_status page/stats server + +Previous versions of this chart had a `controller.stats.*` configuration block, which is now obsolete due to the following changes in Ingress-Nginx Controller: + +- In [0.16.1](https://github.com/kubernetes/ingress-nginx/blob/main/Changelog.md#0161), the vts (virtual host traffic status) dashboard was removed +- In [0.23.0](https://github.com/kubernetes/ingress-nginx/blob/main/Changelog.md#0230), the status page at port 18080 is now a unix socket webserver only available at localhost. + You can use `curl --unix-socket /tmp/nginx-status-server.sock http://localhost/nginx_status` inside the controller container to access it locally, or use the snippet from [nginx-ingress changelog](https://github.com/kubernetes/ingress-nginx/blob/main/Changelog.md#0230) to re-enable the http server + +### ExternalDNS Service Configuration + +Add an [ExternalDNS](https://github.com/kubernetes-sigs/external-dns) annotation to the LoadBalancer service: + +```yaml +controller: + service: + annotations: + external-dns.alpha.kubernetes.io/hostname: kubernetes-example.com. +``` + +### AWS L7 ELB with SSL Termination + +Annotate the controller as shown in the [nginx-ingress l7 patch](https://github.com/kubernetes/ingress-nginx/blob/ab3a789caae65eec4ad6e3b46b19750b481b6bce/deploy/aws/l7/service-l7.yaml): + +```yaml +controller: + service: + targetPorts: + http: http + https: http + annotations: + service.beta.kubernetes.io/aws-load-balancer-ssl-cert: arn:aws:acm:XX-XXXX-X:XXXXXXXXX:certificate/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXX + service.beta.kubernetes.io/aws-load-balancer-backend-protocol: "http" + service.beta.kubernetes.io/aws-load-balancer-ssl-ports: "https" + service.beta.kubernetes.io/aws-load-balancer-connection-idle-timeout: '3600' +``` + +### Additional Internal Load Balancer + +This setup is useful when you need both external and internal load balancers but don't want to have multiple ingress controllers and multiple ingress objects per application. + +By default, the ingress object will point to the external load balancer address, but if correctly configured, you can make use of the internal one if the URL you are looking up resolves to the internal load balancer's URL. + +You'll need to set both the following values: + +`controller.service.internal.enabled` +`controller.service.internal.annotations` + +If one of them is missing the internal load balancer will not be deployed. Example you may have `controller.service.internal.enabled=true` but no annotations set, in this case no action will be taken. + +`controller.service.internal.annotations` varies with the cloud service you're using. + +Example for AWS: + +```yaml +controller: + service: + internal: + enabled: true + annotations: + # Create internal NLB + service.beta.kubernetes.io/aws-load-balancer-scheme: "internal" + # Create internal ELB(Deprecated) + # service.beta.kubernetes.io/aws-load-balancer-internal: "true" + # Any other annotation can be declared here. +``` + +Example for GCE: + +```yaml +controller: + service: + internal: + enabled: true + annotations: + # Create internal LB. More information: https://cloud.google.com/kubernetes-engine/docs/how-to/internal-load-balancing + # For GKE versions 1.17 and later + networking.gke.io/load-balancer-type: "Internal" + # For earlier versions + # cloud.google.com/load-balancer-type: "Internal" + + # Any other annotation can be declared here. +``` + +Example for Azure: + +```yaml +controller: + service: + annotations: + # Create internal LB + service.beta.kubernetes.io/azure-load-balancer-internal: "true" + # Any other annotation can be declared here. +``` + +Example for Oracle Cloud Infrastructure: + +```yaml +controller: + service: + annotations: + # Create internal LB + service.beta.kubernetes.io/oci-load-balancer-internal: "true" + # Any other annotation can be declared here. +``` + +The load balancer annotations of more cloud service providers can be found: [Internal load balancer](https://kubernetes.io/docs/concepts/services-networking/service/#internal-load-balancer). + +An use case for this scenario is having a split-view DNS setup where the public zone CNAME records point to the external balancer URL while the private zone CNAME records point to the internal balancer URL. This way, you only need one ingress kubernetes object. + +Optionally you can set `controller.service.loadBalancerIP` if you need a static IP for the resulting `LoadBalancer`. + +### Ingress Admission Webhooks + +With nginx-ingress-controller version 0.25+, the Ingress-Nginx Controller pod exposes an endpoint that will integrate with the `validatingwebhookconfiguration` Kubernetes feature to prevent bad ingress from being added to the cluster. +**This feature is enabled by default since 0.31.0.** + +With nginx-ingress-controller in 0.25.* work only with kubernetes 1.14+, 0.26 fix [this issue](https://github.com/kubernetes/ingress-nginx/pull/4521) + +#### How the Chart Configures the Hooks +A validating and configuration requires the endpoint to which the request is sent to use TLS. It is possible to set up custom certificates to do this, but in most cases, a self-signed certificate is enough. The setup of this component requires some more complex orchestration when using helm. The steps are created to be idempotent and to allow turning the feature on and off without running into helm quirks. + +1. A pre-install hook provisions a certificate into the same namespace using a format compatible with provisioning using end user certificates. If the certificate already exists, the hook exits. +2. The Ingress-Nginx Controller pod is configured to use a TLS proxy container, which will load that certificate. +3. Validating and Mutating webhook configurations are created in the cluster. +4. A post-install hook reads the CA from the secret created by step 1 and patches the Validating and Mutating webhook configurations. This process will allow a custom CA provisioned by some other process to also be patched into the webhook configurations. The chosen failure policy is also patched into the webhook configurations + +#### Alternatives +It should be possible to use [cert-manager/cert-manager](https://github.com/cert-manager/cert-manager) if a more complete solution is required. + +You can enable automatic self-signed TLS certificate provisioning via cert-manager by setting the `controller.admissionWebhooks.certManager.enabled` value to true. + +Please ensure that cert-manager is correctly installed and configured. + +### Helm Error When Upgrading: spec.clusterIP: Invalid value: "" + +If you are upgrading this chart from a version between 0.31.0 and 1.2.2 then you may get an error like this: + +```console +Error: UPGRADE FAILED: Service "?????-controller" is invalid: spec.clusterIP: Invalid value: "": field is immutable +``` + +Detail of how and why are in [this issue](https://github.com/helm/charts/pull/13646) but to resolve this you can set `xxxx.service.omitClusterIP` to `true` where `xxxx` is the service referenced in the error. + +As of version `1.26.0` of this chart, by simply not providing any clusterIP value, `invalid: spec.clusterIP: Invalid value: "": field is immutable` will no longer occur since `clusterIP: ""` will not be rendered. + +## Values + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| commonLabels | object | `{}` | | +| controller.addHeaders | object | `{}` | Will add custom headers before sending response traffic to the client according to: https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/configmap/#add-headers | +| controller.admissionWebhooks.annotations | object | `{}` | | +| controller.admissionWebhooks.certManager.admissionCert.duration | string | `""` | | +| controller.admissionWebhooks.certManager.enabled | bool | `false` | | +| controller.admissionWebhooks.certManager.rootCert.duration | string | `""` | | +| controller.admissionWebhooks.certificate | string | `"/usr/local/certificates/cert"` | | +| controller.admissionWebhooks.createSecretJob.name | string | `"create"` | | +| controller.admissionWebhooks.createSecretJob.resources | object | `{}` | | +| controller.admissionWebhooks.createSecretJob.securityContext | object | `{"allowPrivilegeEscalation":false,"capabilities":{"drop":["ALL"]},"readOnlyRootFilesystem":true,"runAsNonRoot":true,"runAsUser":65532,"seccompProfile":{"type":"RuntimeDefault"}}` | Security context for secret creation containers | +| controller.admissionWebhooks.enabled | bool | `true` | | +| controller.admissionWebhooks.existingPsp | string | `""` | Use an existing PSP instead of creating one | +| controller.admissionWebhooks.extraEnvs | list | `[]` | Additional environment variables to set | +| controller.admissionWebhooks.failurePolicy | string | `"Fail"` | Admission Webhook failure policy to use | +| controller.admissionWebhooks.key | string | `"/usr/local/certificates/key"` | | +| controller.admissionWebhooks.labels | object | `{}` | Labels to be added to admission webhooks | +| controller.admissionWebhooks.name | string | `"admission"` | | +| controller.admissionWebhooks.namespaceSelector | object | `{}` | | +| controller.admissionWebhooks.objectSelector | object | `{}` | | +| controller.admissionWebhooks.patch.enabled | bool | `true` | | +| controller.admissionWebhooks.patch.image.digest | string | `"sha256:a7943503b45d552785aa3b5e457f169a5661fb94d82b8a3373bcd9ebaf9aac80"` | | +| controller.admissionWebhooks.patch.image.image | string | `"ingress-nginx/kube-webhook-certgen"` | | +| controller.admissionWebhooks.patch.image.pullPolicy | string | `"IfNotPresent"` | | +| controller.admissionWebhooks.patch.image.registry | string | `"registry.k8s.io"` | | +| controller.admissionWebhooks.patch.image.tag | string | `"v20231011-8b53cabe0"` | | +| controller.admissionWebhooks.patch.labels | object | `{}` | Labels to be added to patch job resources | +| controller.admissionWebhooks.patch.networkPolicy.enabled | bool | `false` | Enable 'networkPolicy' or not | +| controller.admissionWebhooks.patch.nodeSelector."kubernetes.io/os" | string | `"linux"` | | +| controller.admissionWebhooks.patch.podAnnotations | object | `{}` | | +| controller.admissionWebhooks.patch.priorityClassName | string | `""` | Provide a priority class name to the webhook patching job # | +| controller.admissionWebhooks.patch.securityContext | object | `{}` | Security context for secret creation & webhook patch pods | +| controller.admissionWebhooks.patch.tolerations | list | `[]` | | +| controller.admissionWebhooks.patchWebhookJob.name | string | `"patch"` | | +| controller.admissionWebhooks.patchWebhookJob.resources | object | `{}` | | +| controller.admissionWebhooks.patchWebhookJob.securityContext | object | `{"allowPrivilegeEscalation":false,"capabilities":{"drop":["ALL"]},"readOnlyRootFilesystem":true,"runAsNonRoot":true,"runAsUser":65532,"seccompProfile":{"type":"RuntimeDefault"}}` | Security context for webhook patch containers | +| controller.admissionWebhooks.port | int | `8443` | | +| controller.admissionWebhooks.service.annotations | object | `{}` | | +| controller.admissionWebhooks.service.externalIPs | list | `[]` | | +| controller.admissionWebhooks.service.loadBalancerSourceRanges | list | `[]` | | +| controller.admissionWebhooks.service.servicePort | int | `443` | | +| controller.admissionWebhooks.service.type | string | `"ClusterIP"` | | +| controller.affinity | object | `{}` | Affinity and anti-affinity rules for server scheduling to nodes # Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity # | +| controller.allowSnippetAnnotations | bool | `false` | This configuration defines if Ingress Controller should allow users to set their own *-snippet annotations, otherwise this is forbidden / dropped when users add those annotations. Global snippets in ConfigMap are still respected | +| controller.annotations | object | `{}` | Annotations to be added to the controller Deployment or DaemonSet # | +| controller.autoscaling.annotations | object | `{}` | | +| controller.autoscaling.behavior | object | `{}` | | +| controller.autoscaling.enabled | bool | `false` | | +| controller.autoscaling.maxReplicas | int | `11` | | +| controller.autoscaling.minReplicas | int | `1` | | +| controller.autoscaling.targetCPUUtilizationPercentage | int | `50` | | +| controller.autoscaling.targetMemoryUtilizationPercentage | int | `50` | | +| controller.autoscalingTemplate | list | `[]` | | +| controller.config | object | `{}` | Will add custom configuration options to Nginx https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/configmap/ | +| controller.configAnnotations | object | `{}` | Annotations to be added to the controller config configuration configmap. | +| controller.configMapNamespace | string | `""` | Allows customization of the configmap / nginx-configmap namespace; defaults to $(POD_NAMESPACE) | +| controller.containerName | string | `"controller"` | Configures the controller container name | +| controller.containerPort | object | `{"http":80,"https":443}` | Configures the ports that the nginx-controller listens on | +| controller.containerSecurityContext | object | `{}` | Security context for controller containers | +| controller.customTemplate.configMapKey | string | `""` | | +| controller.customTemplate.configMapName | string | `""` | | +| controller.dnsConfig | object | `{}` | Optionally customize the pod dnsConfig. | +| controller.dnsPolicy | string | `"ClusterFirst"` | Optionally change this to ClusterFirstWithHostNet in case you have 'hostNetwork: true'. By default, while using host network, name resolution uses the host's DNS. If you wish nginx-controller to keep resolving names inside the k8s network, use ClusterFirstWithHostNet. | +| controller.electionID | string | `""` | Election ID to use for status update, by default it uses the controller name combined with a suffix of 'leader' | +| controller.enableAnnotationValidations | bool | `false` | | +| controller.enableMimalloc | bool | `true` | Enable mimalloc as a drop-in replacement for malloc. # ref: https://github.com/microsoft/mimalloc # | +| controller.enableTopologyAwareRouting | bool | `false` | This configuration enables Topology Aware Routing feature, used together with service annotation service.kubernetes.io/topology-mode="auto" Defaults to false | +| controller.existingPsp | string | `""` | Use an existing PSP instead of creating one | +| controller.extraArgs | object | `{}` | Additional command line arguments to pass to Ingress-Nginx Controller E.g. to specify the default SSL certificate you can use | +| controller.extraContainers | list | `[]` | Additional containers to be added to the controller pod. See https://github.com/lemonldap-ng-controller/lemonldap-ng-controller as example. | +| controller.extraEnvs | list | `[]` | Additional environment variables to set | +| controller.extraInitContainers | list | `[]` | Containers, which are run before the app containers are started. | +| controller.extraModules | list | `[]` | Modules, which are mounted into the core nginx image. See values.yaml for a sample to add opentelemetry module | +| controller.extraVolumeMounts | list | `[]` | Additional volumeMounts to the controller main container. | +| controller.extraVolumes | list | `[]` | Additional volumes to the controller pod. | +| controller.healthCheckHost | string | `""` | Address to bind the health check endpoint. It is better to set this option to the internal node address if the Ingress-Nginx Controller is running in the `hostNetwork: true` mode. | +| controller.healthCheckPath | string | `"/healthz"` | Path of the health check endpoint. All requests received on the port defined by the healthz-port parameter are forwarded internally to this path. | +| controller.hostAliases | list | `[]` | Optionally customize the pod hostAliases. | +| controller.hostNetwork | bool | `false` | Required for use with CNI based kubernetes installations (such as ones set up by kubeadm), since CNI and hostport don't mix yet. Can be deprecated once https://github.com/kubernetes/kubernetes/issues/23920 is merged | +| controller.hostPort.enabled | bool | `false` | Enable 'hostPort' or not | +| controller.hostPort.ports.http | int | `80` | 'hostPort' http port | +| controller.hostPort.ports.https | int | `443` | 'hostPort' https port | +| controller.hostname | object | `{}` | Optionally customize the pod hostname. | +| controller.image.allowPrivilegeEscalation | bool | `false` | | +| controller.image.chroot | bool | `false` | | +| controller.image.digest | string | `"sha256:5b161f051d017e55d358435f295f5e9a297e66158f136321d9b04520ec6c48a3"` | | +| controller.image.digestChroot | string | `"sha256:5976b1067cfbca8a21d0ba53d71f83543a73316a61ea7f7e436d6cf84ddf9b26"` | | +| controller.image.image | string | `"ingress-nginx/controller"` | | +| controller.image.pullPolicy | string | `"IfNotPresent"` | | +| controller.image.readOnlyRootFilesystem | bool | `false` | | +| controller.image.registry | string | `"registry.k8s.io"` | | +| controller.image.runAsNonRoot | bool | `true` | | +| controller.image.runAsUser | int | `101` | | +| controller.image.seccompProfile.type | string | `"RuntimeDefault"` | | +| controller.image.tag | string | `"v1.9.4"` | | +| controller.ingressClass | string | `"nginx"` | For backwards compatibility with ingress.class annotation, use ingressClass. Algorithm is as follows, first ingressClassName is considered, if not present, controller looks for ingress.class annotation | +| controller.ingressClassByName | bool | `false` | Process IngressClass per name (additionally as per spec.controller). | +| controller.ingressClassResource.controllerValue | string | `"k8s.io/ingress-nginx"` | Controller-value of the controller that is processing this ingressClass | +| controller.ingressClassResource.default | bool | `false` | Is this the default ingressClass for the cluster | +| controller.ingressClassResource.enabled | bool | `true` | Is this ingressClass enabled or not | +| controller.ingressClassResource.name | string | `"nginx"` | Name of the ingressClass | +| controller.ingressClassResource.parameters | object | `{}` | Parameters is a link to a custom resource containing additional configuration for the controller. This is optional if the controller does not require extra parameters. | +| controller.keda.apiVersion | string | `"keda.sh/v1alpha1"` | | +| controller.keda.behavior | object | `{}` | | +| controller.keda.cooldownPeriod | int | `300` | | +| controller.keda.enabled | bool | `false` | | +| controller.keda.maxReplicas | int | `11` | | +| controller.keda.minReplicas | int | `1` | | +| controller.keda.pollingInterval | int | `30` | | +| controller.keda.restoreToOriginalReplicaCount | bool | `false` | | +| controller.keda.scaledObject.annotations | object | `{}` | | +| controller.keda.triggers | list | `[]` | | +| controller.kind | string | `"Deployment"` | Use a `DaemonSet` or `Deployment` | +| controller.labels | object | `{}` | Labels to be added to the controller Deployment or DaemonSet and other resources that do not have option to specify labels # | +| controller.lifecycle | object | `{"preStop":{"exec":{"command":["/wait-shutdown"]}}}` | Improve connection draining when ingress controller pod is deleted using a lifecycle hook: With this new hook, we increased the default terminationGracePeriodSeconds from 30 seconds to 300, allowing the draining of connections up to five minutes. If the active connections end before that, the pod will terminate gracefully at that time. To effectively take advantage of this feature, the Configmap feature worker-shutdown-timeout new value is 240s instead of 10s. # | +| controller.livenessProbe.failureThreshold | int | `5` | | +| controller.livenessProbe.httpGet.path | string | `"/healthz"` | | +| controller.livenessProbe.httpGet.port | int | `10254` | | +| controller.livenessProbe.httpGet.scheme | string | `"HTTP"` | | +| controller.livenessProbe.initialDelaySeconds | int | `10` | | +| controller.livenessProbe.periodSeconds | int | `10` | | +| controller.livenessProbe.successThreshold | int | `1` | | +| controller.livenessProbe.timeoutSeconds | int | `1` | | +| controller.maxmindLicenseKey | string | `""` | Maxmind license key to download GeoLite2 Databases. # https://blog.maxmind.com/2019/12/18/significant-changes-to-accessing-and-using-geolite2-databases | +| controller.metrics.enabled | bool | `false` | | +| controller.metrics.port | int | `10254` | | +| controller.metrics.portName | string | `"metrics"` | | +| controller.metrics.prometheusRule.additionalLabels | object | `{}` | | +| controller.metrics.prometheusRule.enabled | bool | `false` | | +| controller.metrics.prometheusRule.rules | list | `[]` | | +| controller.metrics.service.annotations | object | `{}` | | +| controller.metrics.service.externalIPs | list | `[]` | List of IP addresses at which the stats-exporter service is available # Ref: https://kubernetes.io/docs/concepts/services-networking/service/#external-ips # | +| controller.metrics.service.labels | object | `{}` | Labels to be added to the metrics service resource | +| controller.metrics.service.loadBalancerSourceRanges | list | `[]` | | +| controller.metrics.service.servicePort | int | `10254` | | +| controller.metrics.service.type | string | `"ClusterIP"` | | +| controller.metrics.serviceMonitor.additionalLabels | object | `{}` | | +| controller.metrics.serviceMonitor.enabled | bool | `false` | | +| controller.metrics.serviceMonitor.metricRelabelings | list | `[]` | | +| controller.metrics.serviceMonitor.namespace | string | `""` | | +| controller.metrics.serviceMonitor.namespaceSelector | object | `{}` | | +| controller.metrics.serviceMonitor.relabelings | list | `[]` | | +| controller.metrics.serviceMonitor.scrapeInterval | string | `"30s"` | | +| controller.metrics.serviceMonitor.targetLabels | list | `[]` | | +| controller.minAvailable | int | `1` | Minimum available pods set in PodDisruptionBudget. Define either 'minAvailable' or 'maxUnavailable', never both. | +| controller.minReadySeconds | int | `0` | `minReadySeconds` to avoid killing pods before we are ready # | +| controller.name | string | `"controller"` | | +| controller.networkPolicy.enabled | bool | `false` | Enable 'networkPolicy' or not | +| controller.nodeSelector | object | `{"kubernetes.io/os":"linux"}` | Node labels for controller pod assignment # Ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/ # | +| controller.opentelemetry.containerSecurityContext.allowPrivilegeEscalation | bool | `false` | | +| controller.opentelemetry.containerSecurityContext.capabilities.drop[0] | string | `"ALL"` | | +| controller.opentelemetry.containerSecurityContext.readOnlyRootFilesystem | bool | `true` | | +| controller.opentelemetry.containerSecurityContext.runAsNonRoot | bool | `true` | | +| controller.opentelemetry.containerSecurityContext.runAsUser | int | `65532` | The image's default user, inherited from its base image `cgr.dev/chainguard/static`. | +| controller.opentelemetry.containerSecurityContext.seccompProfile.type | string | `"RuntimeDefault"` | | +| controller.opentelemetry.distroless | bool | `true` | | +| controller.opentelemetry.enabled | bool | `false` | | +| controller.opentelemetry.image | string | `"registry.k8s.io/ingress-nginx/opentelemetry:v20230721-3e2062ee5@sha256:13bee3f5223883d3ca62fee7309ad02d22ec00ff0d7033e3e9aca7a9f60fd472"` | | +| controller.opentelemetry.name | string | `"opentelemetry"` | | +| controller.opentelemetry.resources | object | `{}` | | +| controller.podAnnotations | object | `{}` | Annotations to be added to controller pods # | +| controller.podLabels | object | `{}` | Labels to add to the pod container metadata | +| controller.podSecurityContext | object | `{}` | Security context for controller pods | +| controller.priorityClassName | string | `""` | | +| controller.proxySetHeaders | object | `{}` | Will add custom headers before sending traffic to backends according to https://github.com/kubernetes/ingress-nginx/tree/main/docs/examples/customization/custom-headers | +| controller.publishService | object | `{"enabled":true,"pathOverride":""}` | Allows customization of the source of the IP address or FQDN to report in the ingress status field. By default, it reads the information provided by the service. If disable, the status field reports the IP address of the node or nodes where an ingress controller pod is running. | +| controller.publishService.enabled | bool | `true` | Enable 'publishService' or not | +| controller.publishService.pathOverride | string | `""` | Allows overriding of the publish service to bind to Must be / | +| controller.readinessProbe.failureThreshold | int | `3` | | +| controller.readinessProbe.httpGet.path | string | `"/healthz"` | | +| controller.readinessProbe.httpGet.port | int | `10254` | | +| controller.readinessProbe.httpGet.scheme | string | `"HTTP"` | | +| controller.readinessProbe.initialDelaySeconds | int | `10` | | +| controller.readinessProbe.periodSeconds | int | `10` | | +| controller.readinessProbe.successThreshold | int | `1` | | +| controller.readinessProbe.timeoutSeconds | int | `1` | | +| controller.replicaCount | int | `1` | | +| controller.reportNodeInternalIp | bool | `false` | Bare-metal considerations via the host network https://kubernetes.github.io/ingress-nginx/deploy/baremetal/#via-the-host-network Ingress status was blank because there is no Service exposing the Ingress-Nginx Controller in a configuration using the host network, the default --publish-service flag used in standard cloud setups does not apply | +| controller.resources.requests.cpu | string | `"100m"` | | +| controller.resources.requests.memory | string | `"90Mi"` | | +| controller.scope.enabled | bool | `false` | Enable 'scope' or not | +| controller.scope.namespace | string | `""` | Namespace to limit the controller to; defaults to $(POD_NAMESPACE) | +| controller.scope.namespaceSelector | string | `""` | When scope.enabled == false, instead of watching all namespaces, we watching namespaces whose labels only match with namespaceSelector. Format like foo=bar. Defaults to empty, means watching all namespaces. | +| controller.service.annotations | object | `{}` | Annotations are mandatory for the load balancer to come up. Varies with the cloud service. Values passed through helm tpl engine. | +| controller.service.appProtocol | bool | `true` | If enabled is adding an appProtocol option for Kubernetes service. An appProtocol field replacing annotations that were using for setting a backend protocol. Here is an example for AWS: service.beta.kubernetes.io/aws-load-balancer-backend-protocol: http It allows choosing the protocol for each backend specified in the Kubernetes service. See the following GitHub issue for more details about the purpose: https://github.com/kubernetes/kubernetes/issues/40244 Will be ignored for Kubernetes versions older than 1.20 # | +| controller.service.enableHttp | bool | `true` | | +| controller.service.enableHttps | bool | `true` | | +| controller.service.enabled | bool | `true` | | +| controller.service.external.enabled | bool | `true` | | +| controller.service.externalIPs | list | `[]` | List of IP addresses at which the controller services are available # Ref: https://kubernetes.io/docs/concepts/services-networking/service/#external-ips # | +| controller.service.internal.annotations | object | `{}` | Annotations are mandatory for the load balancer to come up. Varies with the cloud service. Values passed through helm tpl engine. | +| controller.service.internal.enabled | bool | `false` | Enables an additional internal load balancer (besides the external one). | +| controller.service.internal.loadBalancerIP | string | `""` | Used by cloud providers to connect the resulting internal LoadBalancer to a pre-existing static IP. Make sure to add to the service the needed annotation to specify the subnet which the static IP belongs to. For instance, `networking.gke.io/internal-load-balancer-subnet` for GCP and `service.beta.kubernetes.io/aws-load-balancer-subnets` for AWS. | +| controller.service.internal.loadBalancerSourceRanges | list | `[]` | Restrict access For LoadBalancer service. Defaults to 0.0.0.0/0. | +| controller.service.internal.ports | object | `{}` | Custom port mapping for internal service | +| controller.service.internal.targetPorts | object | `{}` | Custom target port mapping for internal service | +| controller.service.ipFamilies | list | `["IPv4"]` | List of IP families (e.g. IPv4, IPv6) assigned to the service. This field is usually assigned automatically based on cluster configuration and the ipFamilyPolicy field. # Ref: https://kubernetes.io/docs/concepts/services-networking/dual-stack/ | +| controller.service.ipFamilyPolicy | string | `"SingleStack"` | Represents the dual-stack-ness requested or required by this Service. Possible values are SingleStack, PreferDualStack or RequireDualStack. The ipFamilies and clusterIPs fields depend on the value of this field. # Ref: https://kubernetes.io/docs/concepts/services-networking/dual-stack/ | +| controller.service.labels | object | `{}` | | +| controller.service.loadBalancerClass | string | `""` | Used by cloud providers to select a load balancer implementation other than the cloud provider default. https://kubernetes.io/docs/concepts/services-networking/service/#load-balancer-class | +| controller.service.loadBalancerIP | string | `""` | Used by cloud providers to connect the resulting `LoadBalancer` to a pre-existing static IP according to https://kubernetes.io/docs/concepts/services-networking/service/#loadbalancer | +| controller.service.loadBalancerSourceRanges | list | `[]` | | +| controller.service.nodePorts.http | string | `""` | | +| controller.service.nodePorts.https | string | `""` | | +| controller.service.nodePorts.tcp | object | `{}` | | +| controller.service.nodePorts.udp | object | `{}` | | +| controller.service.ports.http | int | `80` | | +| controller.service.ports.https | int | `443` | | +| controller.service.targetPorts.http | string | `"http"` | | +| controller.service.targetPorts.https | string | `"https"` | | +| controller.service.type | string | `"LoadBalancer"` | | +| controller.shareProcessNamespace | bool | `false` | | +| controller.sysctls | object | `{}` | sysctls for controller pods # Ref: https://kubernetes.io/docs/tasks/administer-cluster/sysctl-cluster/ | +| controller.tcp.annotations | object | `{}` | Annotations to be added to the tcp config configmap | +| controller.tcp.configMapNamespace | string | `""` | Allows customization of the tcp-services-configmap; defaults to $(POD_NAMESPACE) | +| controller.terminationGracePeriodSeconds | int | `300` | `terminationGracePeriodSeconds` to avoid killing pods before we are ready # wait up to five minutes for the drain of connections # | +| controller.tolerations | list | `[]` | Node tolerations for server scheduling to nodes with taints # Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ # | +| controller.topologySpreadConstraints | list | `[]` | Topology spread constraints rely on node labels to identify the topology domain(s) that each Node is in. # Ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/ # | +| controller.udp.annotations | object | `{}` | Annotations to be added to the udp config configmap | +| controller.udp.configMapNamespace | string | `""` | Allows customization of the udp-services-configmap; defaults to $(POD_NAMESPACE) | +| controller.updateStrategy | object | `{}` | The update strategy to apply to the Deployment or DaemonSet # | +| controller.watchIngressWithoutClass | bool | `false` | Process Ingress objects without ingressClass annotation/ingressClassName field Overrides value for --watch-ingress-without-class flag of the controller binary Defaults to false | +| defaultBackend.affinity | object | `{}` | | +| defaultBackend.autoscaling.annotations | object | `{}` | | +| defaultBackend.autoscaling.enabled | bool | `false` | | +| defaultBackend.autoscaling.maxReplicas | int | `2` | | +| defaultBackend.autoscaling.minReplicas | int | `1` | | +| defaultBackend.autoscaling.targetCPUUtilizationPercentage | int | `50` | | +| defaultBackend.autoscaling.targetMemoryUtilizationPercentage | int | `50` | | +| defaultBackend.containerSecurityContext | object | `{}` | Security context for default backend containers | +| defaultBackend.enabled | bool | `false` | | +| defaultBackend.existingPsp | string | `""` | Use an existing PSP instead of creating one | +| defaultBackend.extraArgs | object | `{}` | | +| defaultBackend.extraConfigMaps | list | `[]` | | +| defaultBackend.extraEnvs | list | `[]` | Additional environment variables to set for defaultBackend pods | +| defaultBackend.extraVolumeMounts | list | `[]` | | +| defaultBackend.extraVolumes | list | `[]` | | +| defaultBackend.image.allowPrivilegeEscalation | bool | `false` | | +| defaultBackend.image.image | string | `"defaultbackend-amd64"` | | +| defaultBackend.image.pullPolicy | string | `"IfNotPresent"` | | +| defaultBackend.image.readOnlyRootFilesystem | bool | `true` | | +| defaultBackend.image.registry | string | `"registry.k8s.io"` | | +| defaultBackend.image.runAsNonRoot | bool | `true` | | +| defaultBackend.image.runAsUser | int | `65534` | | +| defaultBackend.image.seccompProfile.type | string | `"RuntimeDefault"` | | +| defaultBackend.image.tag | string | `"1.5"` | | +| defaultBackend.labels | object | `{}` | Labels to be added to the default backend resources | +| defaultBackend.livenessProbe.failureThreshold | int | `3` | | +| defaultBackend.livenessProbe.initialDelaySeconds | int | `30` | | +| defaultBackend.livenessProbe.periodSeconds | int | `10` | | +| defaultBackend.livenessProbe.successThreshold | int | `1` | | +| defaultBackend.livenessProbe.timeoutSeconds | int | `5` | | +| defaultBackend.minAvailable | int | `1` | | +| defaultBackend.minReadySeconds | int | `0` | `minReadySeconds` to avoid killing pods before we are ready # | +| defaultBackend.name | string | `"defaultbackend"` | | +| defaultBackend.networkPolicy.enabled | bool | `false` | Enable 'networkPolicy' or not | +| defaultBackend.nodeSelector | object | `{"kubernetes.io/os":"linux"}` | Node labels for default backend pod assignment # Ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/ # | +| defaultBackend.podAnnotations | object | `{}` | Annotations to be added to default backend pods # | +| defaultBackend.podLabels | object | `{}` | Labels to add to the pod container metadata | +| defaultBackend.podSecurityContext | object | `{}` | Security context for default backend pods | +| defaultBackend.port | int | `8080` | | +| defaultBackend.priorityClassName | string | `""` | | +| defaultBackend.readinessProbe.failureThreshold | int | `6` | | +| defaultBackend.readinessProbe.initialDelaySeconds | int | `0` | | +| defaultBackend.readinessProbe.periodSeconds | int | `5` | | +| defaultBackend.readinessProbe.successThreshold | int | `1` | | +| defaultBackend.readinessProbe.timeoutSeconds | int | `5` | | +| defaultBackend.replicaCount | int | `1` | | +| defaultBackend.resources | object | `{}` | | +| defaultBackend.service.annotations | object | `{}` | | +| defaultBackend.service.externalIPs | list | `[]` | List of IP addresses at which the default backend service is available # Ref: https://kubernetes.io/docs/concepts/services-networking/service/#external-ips # | +| defaultBackend.service.loadBalancerSourceRanges | list | `[]` | | +| defaultBackend.service.servicePort | int | `80` | | +| defaultBackend.service.type | string | `"ClusterIP"` | | +| defaultBackend.serviceAccount.automountServiceAccountToken | bool | `true` | | +| defaultBackend.serviceAccount.create | bool | `true` | | +| defaultBackend.serviceAccount.name | string | `""` | | +| defaultBackend.tolerations | list | `[]` | Node tolerations for server scheduling to nodes with taints # Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ # | +| defaultBackend.updateStrategy | object | `{}` | The update strategy to apply to the Deployment or DaemonSet # | +| dhParam | string | `""` | A base64-encoded Diffie-Hellman parameter. This can be generated with: `openssl dhparam 4096 2> /dev/null | base64` # Ref: https://github.com/kubernetes/ingress-nginx/tree/main/docs/examples/customization/ssl-dh-param | +| imagePullSecrets | list | `[]` | Optional array of imagePullSecrets containing private registry credentials # Ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ | +| namespaceOverride | string | `""` | Override the deployment namespace; defaults to .Release.Namespace | +| podSecurityPolicy.enabled | bool | `false` | | +| portNamePrefix | string | `""` | Prefix for TCP and UDP ports names in ingress controller service # Some cloud providers, like Yandex Cloud may have a requirements for a port name regex to support cloud load balancer integration | +| rbac.create | bool | `true` | | +| rbac.scope | bool | `false` | | +| revisionHistoryLimit | int | `10` | Rollback limit # | +| serviceAccount.annotations | object | `{}` | Annotations for the controller service account | +| serviceAccount.automountServiceAccountToken | bool | `true` | | +| serviceAccount.create | bool | `true` | | +| serviceAccount.name | string | `""` | | +| tcp | object | `{}` | TCP service key-value pairs # Ref: https://github.com/kubernetes/ingress-nginx/blob/main/docs/user-guide/exposing-tcp-udp-services.md # | +| udp | object | `{}` | UDP service key-value pairs # Ref: https://github.com/kubernetes/ingress-nginx/blob/main/docs/user-guide/exposing-tcp-udp-services.md # | diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/README.md.gotmpl b/packages/system/ingress-nginx/charts/ingress-nginx/README.md.gotmpl new file mode 100644 index 00000000..17b029bb --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/README.md.gotmpl @@ -0,0 +1,229 @@ +{{ template "chart.header" . }} +[ingress-nginx](https://github.com/kubernetes/ingress-nginx) Ingress controller for Kubernetes using NGINX as a reverse proxy and load balancer + +{{ template "chart.versionBadge" . }}{{ template "chart.typeBadge" . }}{{ template "chart.appVersionBadge" . }} + +To use, add `ingressClassName: nginx` spec field or the `kubernetes.io/ingress.class: nginx` annotation to your Ingress resources. + +This chart bootstraps an ingress-nginx deployment on a [Kubernetes](http://kubernetes.io) cluster using the [Helm](https://helm.sh) package manager. + +{{ template "chart.requirementsSection" . }} + +## Get Repo Info + +```console +helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx +helm repo update +``` + +## Install Chart + +**Important:** only helm3 is supported + +```console +helm install [RELEASE_NAME] ingress-nginx/ingress-nginx +``` + +The command deploys ingress-nginx on the Kubernetes cluster in the default configuration. + +_See [configuration](#configuration) below._ + +_See [helm install](https://helm.sh/docs/helm/helm_install/) for command documentation._ + +## Uninstall Chart + +```console +helm uninstall [RELEASE_NAME] +``` + +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._ + +## Upgrading Chart + +```console +helm upgrade [RELEASE_NAME] [CHART] --install +``` + +_See [helm upgrade](https://helm.sh/docs/helm/helm_upgrade/) for command documentation._ + +### Migrating from stable/nginx-ingress + +There are two main ways to migrate a release from `stable/nginx-ingress` to `ingress-nginx/ingress-nginx` chart: + +1. For Nginx Ingress controllers used for non-critical services, the easiest method is to [uninstall](#uninstall-chart) the old release and [install](#install-chart) the new one +1. For critical services in production that require zero-downtime, you will want to: + 1. [Install](#install-chart) a second Ingress controller + 1. Redirect your DNS traffic from the old controller to the new controller + 1. Log traffic from both controllers during this changeover + 1. [Uninstall](#uninstall-chart) the old controller once traffic has fully drained from it + +Note that there are some different and upgraded configurations between the two charts, described by Rimas Mocevicius from JFrog in the "Upgrading to ingress-nginx Helm chart" section of [Migrating from Helm chart nginx-ingress to ingress-nginx](https://rimusz.net/migrating-to-ingress-nginx). As the `ingress-nginx/ingress-nginx` chart continues to update, you will want to check current differences by running [helm configuration](#configuration) commands on both charts. + +## Configuration + +See [Customizing the Chart Before Installing](https://helm.sh/docs/intro/using_helm/#customizing-the-chart-before-installing). To see all configurable options with detailed comments, visit the chart's [values.yaml](./values.yaml), or run these configuration commands: + +```console +helm show values ingress-nginx/ingress-nginx +``` + +### PodDisruptionBudget + +Note that the PodDisruptionBudget resource will only be defined if the replicaCount is greater than one, +else it would make it impossible to evacuate a node. See [gh issue #7127](https://github.com/helm/charts/issues/7127) for more info. + +### Prometheus Metrics + +The Ingress-Nginx Controller can export Prometheus metrics, by setting `controller.metrics.enabled` to `true`. + +You can add Prometheus annotations to the metrics service using `controller.metrics.service.annotations`. +Alternatively, if you use the Prometheus Operator, you can enable ServiceMonitor creation using `controller.metrics.serviceMonitor.enabled`. And set `controller.metrics.serviceMonitor.additionalLabels.release="prometheus"`. "release=prometheus" should match the label configured in the prometheus servicemonitor ( see `kubectl get servicemonitor prometheus-kube-prom-prometheus -oyaml -n prometheus`) + +### ingress-nginx nginx\_status page/stats server + +Previous versions of this chart had a `controller.stats.*` configuration block, which is now obsolete due to the following changes in Ingress-Nginx Controller: + +- In [0.16.1](https://github.com/kubernetes/ingress-nginx/blob/main/Changelog.md#0161), the vts (virtual host traffic status) dashboard was removed +- In [0.23.0](https://github.com/kubernetes/ingress-nginx/blob/main/Changelog.md#0230), the status page at port 18080 is now a unix socket webserver only available at localhost. + You can use `curl --unix-socket /tmp/nginx-status-server.sock http://localhost/nginx_status` inside the controller container to access it locally, or use the snippet from [nginx-ingress changelog](https://github.com/kubernetes/ingress-nginx/blob/main/Changelog.md#0230) to re-enable the http server + +### ExternalDNS Service Configuration + +Add an [ExternalDNS](https://github.com/kubernetes-sigs/external-dns) annotation to the LoadBalancer service: + +```yaml +controller: + service: + annotations: + external-dns.alpha.kubernetes.io/hostname: kubernetes-example.com. +``` + +### AWS L7 ELB with SSL Termination + +Annotate the controller as shown in the [nginx-ingress l7 patch](https://github.com/kubernetes/ingress-nginx/blob/ab3a789caae65eec4ad6e3b46b19750b481b6bce/deploy/aws/l7/service-l7.yaml): + +```yaml +controller: + service: + targetPorts: + http: http + https: http + annotations: + service.beta.kubernetes.io/aws-load-balancer-ssl-cert: arn:aws:acm:XX-XXXX-X:XXXXXXXXX:certificate/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXX + service.beta.kubernetes.io/aws-load-balancer-backend-protocol: "http" + service.beta.kubernetes.io/aws-load-balancer-ssl-ports: "https" + service.beta.kubernetes.io/aws-load-balancer-connection-idle-timeout: '3600' +``` + +### Additional Internal Load Balancer + +This setup is useful when you need both external and internal load balancers but don't want to have multiple ingress controllers and multiple ingress objects per application. + +By default, the ingress object will point to the external load balancer address, but if correctly configured, you can make use of the internal one if the URL you are looking up resolves to the internal load balancer's URL. + +You'll need to set both the following values: + +`controller.service.internal.enabled` +`controller.service.internal.annotations` + +If one of them is missing the internal load balancer will not be deployed. Example you may have `controller.service.internal.enabled=true` but no annotations set, in this case no action will be taken. + +`controller.service.internal.annotations` varies with the cloud service you're using. + +Example for AWS: + +```yaml +controller: + service: + internal: + enabled: true + annotations: + # Create internal NLB + service.beta.kubernetes.io/aws-load-balancer-scheme: "internal" + # Create internal ELB(Deprecated) + # service.beta.kubernetes.io/aws-load-balancer-internal: "true" + # Any other annotation can be declared here. +``` + +Example for GCE: + +```yaml +controller: + service: + internal: + enabled: true + annotations: + # Create internal LB. More information: https://cloud.google.com/kubernetes-engine/docs/how-to/internal-load-balancing + # For GKE versions 1.17 and later + networking.gke.io/load-balancer-type: "Internal" + # For earlier versions + # cloud.google.com/load-balancer-type: "Internal" + + # Any other annotation can be declared here. +``` + +Example for Azure: + +```yaml +controller: + service: + annotations: + # Create internal LB + service.beta.kubernetes.io/azure-load-balancer-internal: "true" + # Any other annotation can be declared here. +``` + +Example for Oracle Cloud Infrastructure: + +```yaml +controller: + service: + annotations: + # Create internal LB + service.beta.kubernetes.io/oci-load-balancer-internal: "true" + # Any other annotation can be declared here. +``` + +The load balancer annotations of more cloud service providers can be found: [Internal load balancer](https://kubernetes.io/docs/concepts/services-networking/service/#internal-load-balancer). + +An use case for this scenario is having a split-view DNS setup where the public zone CNAME records point to the external balancer URL while the private zone CNAME records point to the internal balancer URL. This way, you only need one ingress kubernetes object. + +Optionally you can set `controller.service.loadBalancerIP` if you need a static IP for the resulting `LoadBalancer`. + +### Ingress Admission Webhooks + +With nginx-ingress-controller version 0.25+, the Ingress-Nginx Controller pod exposes an endpoint that will integrate with the `validatingwebhookconfiguration` Kubernetes feature to prevent bad ingress from being added to the cluster. +**This feature is enabled by default since 0.31.0.** + +With nginx-ingress-controller in 0.25.* work only with kubernetes 1.14+, 0.26 fix [this issue](https://github.com/kubernetes/ingress-nginx/pull/4521) + +#### How the Chart Configures the Hooks +A validating and configuration requires the endpoint to which the request is sent to use TLS. It is possible to set up custom certificates to do this, but in most cases, a self-signed certificate is enough. The setup of this component requires some more complex orchestration when using helm. The steps are created to be idempotent and to allow turning the feature on and off without running into helm quirks. + +1. A pre-install hook provisions a certificate into the same namespace using a format compatible with provisioning using end user certificates. If the certificate already exists, the hook exits. +2. The Ingress-Nginx Controller pod is configured to use a TLS proxy container, which will load that certificate. +3. Validating and Mutating webhook configurations are created in the cluster. +4. A post-install hook reads the CA from the secret created by step 1 and patches the Validating and Mutating webhook configurations. This process will allow a custom CA provisioned by some other process to also be patched into the webhook configurations. The chosen failure policy is also patched into the webhook configurations + +#### Alternatives +It should be possible to use [cert-manager/cert-manager](https://github.com/cert-manager/cert-manager) if a more complete solution is required. + +You can enable automatic self-signed TLS certificate provisioning via cert-manager by setting the `controller.admissionWebhooks.certManager.enabled` value to true. + +Please ensure that cert-manager is correctly installed and configured. + +### Helm Error When Upgrading: spec.clusterIP: Invalid value: "" + +If you are upgrading this chart from a version between 0.31.0 and 1.2.2 then you may get an error like this: + +```console +Error: UPGRADE FAILED: Service "?????-controller" is invalid: spec.clusterIP: Invalid value: "": field is immutable +``` + +Detail of how and why are in [this issue](https://github.com/helm/charts/pull/13646) but to resolve this you can set `xxxx.service.omitClusterIP` to `true` where `xxxx` is the service referenced in the error. + +As of version `1.26.0` of this chart, by simply not providing any clusterIP value, `invalid: spec.clusterIP: Invalid value: "": field is immutable` will no longer occur since `clusterIP: ""` will not be rendered. + +{{ template "chart.valuesSection" . }} diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/ci/controller-admission-tls-cert-manager-values.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/ci/controller-admission-tls-cert-manager-values.yaml new file mode 100644 index 00000000..a13241cd --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/ci/controller-admission-tls-cert-manager-values.yaml @@ -0,0 +1,6 @@ +controller: + admissionWebhooks: + certManager: + enabled: true + service: + type: ClusterIP diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/ci/controller-custom-ingressclass-flags.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/ci/controller-custom-ingressclass-flags.yaml new file mode 100644 index 00000000..b28a2326 --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/ci/controller-custom-ingressclass-flags.yaml @@ -0,0 +1,7 @@ +controller: + watchIngressWithoutClass: true + ingressClassResource: + name: custom-nginx + enabled: true + default: true + controllerValue: "k8s.io/custom-nginx" diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/ci/daemonset-customconfig-values.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/ci/daemonset-customconfig-values.yaml new file mode 100644 index 00000000..4393a5bc --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/ci/daemonset-customconfig-values.yaml @@ -0,0 +1,14 @@ +controller: + image: + repository: ingress-controller/controller + tag: 1.0.0-dev + digest: null + kind: DaemonSet + allowSnippetAnnotations: false + admissionWebhooks: + enabled: false + service: + type: ClusterIP + + config: + use-proxy-protocol: "true" diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/ci/daemonset-customnodeport-values.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/ci/daemonset-customnodeport-values.yaml new file mode 100644 index 00000000..1d94be21 --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/ci/daemonset-customnodeport-values.yaml @@ -0,0 +1,22 @@ +controller: + kind: DaemonSet + image: + repository: ingress-controller/controller + tag: 1.0.0-dev + digest: null + admissionWebhooks: + enabled: false + + service: + type: NodePort + nodePorts: + tcp: + 9000: 30090 + udp: + 9001: 30091 + +tcp: + 9000: "default/test:8080" + +udp: + 9001: "default/test:8080" diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/ci/daemonset-extra-modules.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/ci/daemonset-extra-modules.yaml new file mode 100644 index 00000000..f299dbf1 --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/ci/daemonset-extra-modules.yaml @@ -0,0 +1,10 @@ +controller: + kind: DaemonSet + image: + repository: ingress-controller/controller + tag: 1.0.0-dev + service: + type: ClusterIP + extraModules: + - name: opentelemetry + image: busybox diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/ci/daemonset-headers-values.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/ci/daemonset-headers-values.yaml new file mode 100644 index 00000000..ab7d47bd --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/ci/daemonset-headers-values.yaml @@ -0,0 +1,14 @@ +controller: + kind: DaemonSet + image: + repository: ingress-controller/controller + tag: 1.0.0-dev + digest: null + admissionWebhooks: + enabled: false + addHeaders: + X-Frame-Options: deny + proxySetHeaders: + X-Forwarded-Proto: https + service: + type: ClusterIP diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/ci/daemonset-internal-lb-values.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/ci/daemonset-internal-lb-values.yaml new file mode 100644 index 00000000..0a200a74 --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/ci/daemonset-internal-lb-values.yaml @@ -0,0 +1,14 @@ +controller: + kind: DaemonSet + image: + repository: ingress-controller/controller + tag: 1.0.0-dev + digest: null + admissionWebhooks: + enabled: false + service: + type: ClusterIP + internal: + enabled: true + annotations: + service.beta.kubernetes.io/aws-load-balancer-internal: "true" diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/ci/daemonset-nodeport-values.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/ci/daemonset-nodeport-values.yaml new file mode 100644 index 00000000..3b7aa2fc --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/ci/daemonset-nodeport-values.yaml @@ -0,0 +1,10 @@ +controller: + kind: DaemonSet + image: + repository: ingress-controller/controller + tag: 1.0.0-dev + digest: null + admissionWebhooks: + enabled: false + service: + type: NodePort diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/ci/daemonset-podannotations-values.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/ci/daemonset-podannotations-values.yaml new file mode 100644 index 00000000..0b55306a --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/ci/daemonset-podannotations-values.yaml @@ -0,0 +1,17 @@ +controller: + kind: DaemonSet + image: + repository: ingress-controller/controller + tag: 1.0.0-dev + digest: null + admissionWebhooks: + enabled: false + metrics: + enabled: true + service: + type: ClusterIP + podAnnotations: + prometheus.io/path: /metrics + prometheus.io/port: "10254" + prometheus.io/scheme: http + prometheus.io/scrape: "true" diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/ci/daemonset-tcp-udp-configMapNamespace-values.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/ci/daemonset-tcp-udp-configMapNamespace-values.yaml new file mode 100644 index 00000000..acd86a77 --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/ci/daemonset-tcp-udp-configMapNamespace-values.yaml @@ -0,0 +1,20 @@ +controller: + kind: DaemonSet + image: + repository: ingress-controller/controller + tag: 1.0.0-dev + digest: null + admissionWebhooks: + enabled: false + service: + type: ClusterIP + tcp: + configMapNamespace: default + udp: + configMapNamespace: default + +tcp: + 9000: "default/test:8080" + +udp: + 9001: "default/test:8080" diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/ci/daemonset-tcp-udp-portNamePrefix-values.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/ci/daemonset-tcp-udp-portNamePrefix-values.yaml new file mode 100644 index 00000000..90b0f57a --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/ci/daemonset-tcp-udp-portNamePrefix-values.yaml @@ -0,0 +1,18 @@ +controller: + kind: DaemonSet + image: + repository: ingress-controller/controller + tag: 1.0.0-dev + digest: null + admissionWebhooks: + enabled: false + service: + type: ClusterIP + +tcp: + 9000: "default/test:8080" + +udp: + 9001: "default/test:8080" + +portNamePrefix: "port" diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/ci/daemonset-tcp-udp-values.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/ci/daemonset-tcp-udp-values.yaml new file mode 100644 index 00000000..25ee64d8 --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/ci/daemonset-tcp-udp-values.yaml @@ -0,0 +1,16 @@ +controller: + kind: DaemonSet + image: + repository: ingress-controller/controller + tag: 1.0.0-dev + digest: null + admissionWebhooks: + enabled: false + service: + type: ClusterIP + +tcp: + 9000: "default/test:8080" + +udp: + 9001: "default/test:8080" diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/ci/daemonset-tcp-values.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/ci/daemonset-tcp-values.yaml new file mode 100644 index 00000000..380c8b4b --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/ci/daemonset-tcp-values.yaml @@ -0,0 +1,14 @@ +controller: + kind: DaemonSet + image: + repository: ingress-controller/controller + tag: 1.0.0-dev + digest: null + admissionWebhooks: + enabled: false + service: + type: ClusterIP + +tcp: + 9000: "default/test:8080" + 9001: "default/test:8080" diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/ci/deamonset-default-values.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/ci/deamonset-default-values.yaml new file mode 100644 index 00000000..82fa23e8 --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/ci/deamonset-default-values.yaml @@ -0,0 +1,10 @@ +controller: + kind: DaemonSet + image: + repository: ingress-controller/controller + tag: 1.0.0-dev + digest: null + admissionWebhooks: + enabled: false + service: + type: ClusterIP diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/ci/deamonset-metrics-values.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/ci/deamonset-metrics-values.yaml new file mode 100644 index 00000000..cb3cb54b --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/ci/deamonset-metrics-values.yaml @@ -0,0 +1,12 @@ +controller: + kind: DaemonSet + image: + repository: ingress-controller/controller + tag: 1.0.0-dev + digest: null + admissionWebhooks: + enabled: false + metrics: + enabled: true + service: + type: ClusterIP diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/ci/deamonset-psp-values.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/ci/deamonset-psp-values.yaml new file mode 100644 index 00000000..8026a635 --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/ci/deamonset-psp-values.yaml @@ -0,0 +1,13 @@ +controller: + kind: DaemonSet + image: + repository: ingress-controller/controller + tag: 1.0.0-dev + digest: null + admissionWebhooks: + enabled: false + service: + type: ClusterIP + +podSecurityPolicy: + enabled: true diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/ci/deamonset-webhook-and-psp-values.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/ci/deamonset-webhook-and-psp-values.yaml new file mode 100644 index 00000000..fccdb134 --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/ci/deamonset-webhook-and-psp-values.yaml @@ -0,0 +1,13 @@ +controller: + kind: DaemonSet + image: + repository: ingress-controller/controller + tag: 1.0.0-dev + digest: null + admissionWebhooks: + enabled: true + service: + type: ClusterIP + +podSecurityPolicy: + enabled: true diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/ci/deamonset-webhook-values.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/ci/deamonset-webhook-values.yaml new file mode 100644 index 00000000..54d364df --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/ci/deamonset-webhook-values.yaml @@ -0,0 +1,10 @@ +controller: + kind: DaemonSet + image: + repository: ingress-controller/controller + tag: 1.0.0-dev + digest: null + admissionWebhooks: + enabled: true + service: + type: ClusterIP diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-autoscaling-behavior-values.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-autoscaling-behavior-values.yaml new file mode 100644 index 00000000..dca3f35f --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-autoscaling-behavior-values.yaml @@ -0,0 +1,14 @@ +controller: + autoscaling: + enabled: true + behavior: + scaleDown: + stabilizationWindowSeconds: 300 + policies: + - type: Pods + value: 1 + periodSeconds: 180 + admissionWebhooks: + enabled: false + service: + type: ClusterIP diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-autoscaling-values.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-autoscaling-values.yaml new file mode 100644 index 00000000..b8b3ac68 --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-autoscaling-values.yaml @@ -0,0 +1,11 @@ +controller: + image: + repository: ingress-controller/controller + tag: 1.0.0-dev + digest: null + autoscaling: + enabled: true + admissionWebhooks: + enabled: false + service: + type: ClusterIP diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-customconfig-values.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-customconfig-values.yaml new file mode 100644 index 00000000..17494184 --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-customconfig-values.yaml @@ -0,0 +1,12 @@ +controller: + image: + repository: ingress-controller/controller + tag: 1.0.0-dev + digest: null + config: + use-proxy-protocol: "true" + allowSnippetAnnotations: false + admissionWebhooks: + enabled: false + service: + type: ClusterIP diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-customnodeport-values.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-customnodeport-values.yaml new file mode 100644 index 00000000..a564eaf9 --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-customnodeport-values.yaml @@ -0,0 +1,20 @@ +controller: + image: + repository: ingress-controller/controller + tag: 1.0.0-dev + digest: null + admissionWebhooks: + enabled: false + service: + type: NodePort + nodePorts: + tcp: + 9000: 30090 + udp: + 9001: 30091 + +tcp: + 9000: "default/test:8080" + +udp: + 9001: "default/test:8080" diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-default-values.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-default-values.yaml new file mode 100644 index 00000000..9f46b4e7 --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-default-values.yaml @@ -0,0 +1,8 @@ +# Left blank to test default values +controller: + image: + repository: ingress-controller/controller + tag: 1.0.0-dev + digest: null + service: + type: ClusterIP diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-extra-modules-default-container-sec-context.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-extra-modules-default-container-sec-context.yaml new file mode 100644 index 00000000..2310c344 --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-extra-modules-default-container-sec-context.yaml @@ -0,0 +1,12 @@ +controller: + image: + repository: ingress-controller/controller + tag: 1.0.0-dev + digest: null + service: + type: ClusterIP + containerSecurityContext: + allowPrivilegeEscalation: false + extraModules: + - name: opentelemetry + image: busybox diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-extra-modules-specific-container-sec-context.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-extra-modules-specific-container-sec-context.yaml new file mode 100644 index 00000000..bd2f011c --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-extra-modules-specific-container-sec-context.yaml @@ -0,0 +1,12 @@ +controller: + image: + repository: ingress-controller/controller + tag: 1.0.0-dev + digest: null + service: + type: ClusterIP + extraModules: + - name: opentelemetry + image: busybox + containerSecurityContext: + allowPrivilegeEscalation: false diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-extra-modules.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-extra-modules.yaml new file mode 100644 index 00000000..ec592354 --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-extra-modules.yaml @@ -0,0 +1,10 @@ +controller: + image: + repository: ingress-controller/controller + tag: 1.0.0-dev + digest: null + service: + type: ClusterIP + extraModules: + - name: opentelemetry + image: busybox diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-headers-values.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-headers-values.yaml new file mode 100644 index 00000000..17a11ac3 --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-headers-values.yaml @@ -0,0 +1,13 @@ +controller: + image: + repository: ingress-controller/controller + tag: 1.0.0-dev + digest: null + admissionWebhooks: + enabled: false + addHeaders: + X-Frame-Options: deny + proxySetHeaders: + X-Forwarded-Proto: https + service: + type: ClusterIP diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-internal-lb-values.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-internal-lb-values.yaml new file mode 100644 index 00000000..663ccb9d --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-internal-lb-values.yaml @@ -0,0 +1,19 @@ +controller: + image: + repository: ingress-controller/controller + tag: 1.0.0-dev + digest: null + admissionWebhooks: + enabled: false + service: + type: ClusterIP + internal: + enabled: true + annotations: + service.beta.kubernetes.io/aws-load-balancer-internal: "true" + ports: + http: 443 + https: 80 + targetPorts: + http: 443 + https: 80 diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-metrics-values.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-metrics-values.yaml new file mode 100644 index 00000000..9209ad5a --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-metrics-values.yaml @@ -0,0 +1,11 @@ +controller: + image: + repository: ingress-controller/controller + tag: 1.0.0-dev + digest: null + admissionWebhooks: + enabled: false + metrics: + enabled: true + service: + type: ClusterIP diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-nodeport-values.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-nodeport-values.yaml new file mode 100644 index 00000000..cd9b3235 --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-nodeport-values.yaml @@ -0,0 +1,9 @@ +controller: + image: + repository: ingress-controller/controller + tag: 1.0.0-dev + digest: null + admissionWebhooks: + enabled: false + service: + type: NodePort diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-podannotations-values.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-podannotations-values.yaml new file mode 100644 index 00000000..b48d93c4 --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-podannotations-values.yaml @@ -0,0 +1,16 @@ +controller: + image: + repository: ingress-controller/controller + tag: 1.0.0-dev + digest: null + admissionWebhooks: + enabled: false + metrics: + enabled: true + service: + type: ClusterIP + podAnnotations: + prometheus.io/path: /metrics + prometheus.io/port: "10254" + prometheus.io/scheme: http + prometheus.io/scrape: "true" diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-psp-values.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-psp-values.yaml new file mode 100644 index 00000000..2f332a7b --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-psp-values.yaml @@ -0,0 +1,10 @@ +controller: + image: + repository: ingress-controller/controller + tag: 1.0.0-dev + digest: null + service: + type: ClusterIP + +podSecurityPolicy: + enabled: true diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-tcp-udp-configMapNamespace-values.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-tcp-udp-configMapNamespace-values.yaml new file mode 100644 index 00000000..c51a4e91 --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-tcp-udp-configMapNamespace-values.yaml @@ -0,0 +1,19 @@ +controller: + image: + repository: ingress-controller/controller + tag: 1.0.0-dev + digest: null + admissionWebhooks: + enabled: false + service: + type: ClusterIP + tcp: + configMapNamespace: default + udp: + configMapNamespace: default + +tcp: + 9000: "default/test:8080" + +udp: + 9001: "default/test:8080" diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-tcp-udp-portNamePrefix-values.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-tcp-udp-portNamePrefix-values.yaml new file mode 100644 index 00000000..56323c5e --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-tcp-udp-portNamePrefix-values.yaml @@ -0,0 +1,17 @@ +controller: + image: + repository: ingress-controller/controller + tag: 1.0.0-dev + digest: null + admissionWebhooks: + enabled: false + service: + type: ClusterIP + +tcp: + 9000: "default/test:8080" + +udp: + 9001: "default/test:8080" + +portNamePrefix: "port" diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-tcp-udp-values.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-tcp-udp-values.yaml new file mode 100644 index 00000000..5b45b69d --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-tcp-udp-values.yaml @@ -0,0 +1,15 @@ +controller: + image: + repository: ingress-controller/controller + tag: 1.0.0-dev + digest: null + admissionWebhooks: + enabled: false + service: + type: ClusterIP + +tcp: + 9000: "default/test:8080" + +udp: + 9001: "default/test:8080" diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-tcp-values.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-tcp-values.yaml new file mode 100644 index 00000000..ac0b6e60 --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-tcp-values.yaml @@ -0,0 +1,11 @@ +controller: + image: + repository: ingress-controller/controller + tag: 1.0.0-dev + digest: null + service: + type: ClusterIP + +tcp: + 9000: "default/test:8080" + 9001: "default/test:8080" diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-webhook-and-psp-values.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-webhook-and-psp-values.yaml new file mode 100644 index 00000000..6195bb33 --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-webhook-and-psp-values.yaml @@ -0,0 +1,12 @@ +controller: + image: + repository: ingress-controller/controller + tag: 1.0.0-dev + digest: null + admissionWebhooks: + enabled: true + service: + type: ClusterIP + +podSecurityPolicy: + enabled: true diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-webhook-extraEnvs-values.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-webhook-extraEnvs-values.yaml new file mode 100644 index 00000000..95487b07 --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-webhook-extraEnvs-values.yaml @@ -0,0 +1,12 @@ +controller: + service: + type: ClusterIP + admissionWebhooks: + enabled: true + extraEnvs: + - name: FOO + value: foo + - name: TEST + value: test + patch: + enabled: true diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-webhook-resources-values.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-webhook-resources-values.yaml new file mode 100644 index 00000000..49ebbb02 --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-webhook-resources-values.yaml @@ -0,0 +1,23 @@ +controller: + service: + type: ClusterIP + admissionWebhooks: + enabled: true + createSecretJob: + resources: + limits: + cpu: 10m + memory: 20Mi + requests: + cpu: 10m + memory: 20Mi + patchWebhookJob: + resources: + limits: + cpu: 10m + memory: 20Mi + requests: + cpu: 10m + memory: 20Mi + patch: + enabled: true diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-webhook-values.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-webhook-values.yaml new file mode 100644 index 00000000..76669a53 --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-webhook-values.yaml @@ -0,0 +1,9 @@ +controller: + image: + repository: ingress-controller/controller + tag: 1.0.0-dev + digest: null + admissionWebhooks: + enabled: true + service: + type: ClusterIP diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/templates/NOTES.txt b/packages/system/ingress-nginx/charts/ingress-nginx/templates/NOTES.txt new file mode 100644 index 00000000..f4923007 --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/templates/NOTES.txt @@ -0,0 +1,73 @@ +The ingress-nginx controller has been installed. + +{{- if contains "NodePort" .Values.controller.service.type }} +Get the application URL by running these commands: + +{{- if (not (empty .Values.controller.service.nodePorts.http)) }} + export HTTP_NODE_PORT={{ .Values.controller.service.nodePorts.http }} +{{- else }} + export HTTP_NODE_PORT=$(kubectl get service --namespace {{ include "ingress-nginx.namespace" . }} {{ include "ingress-nginx.controller.fullname" . }} --output jsonpath="{.spec.ports[0].nodePort}") +{{- end }} +{{- if (not (empty .Values.controller.service.nodePorts.https)) }} + export HTTPS_NODE_PORT={{ .Values.controller.service.nodePorts.https }} +{{- else }} + export HTTPS_NODE_PORT=$(kubectl get service --namespace {{ include "ingress-nginx.namespace" . }} {{ include "ingress-nginx.controller.fullname" . }} --output jsonpath="{.spec.ports[1].nodePort}") +{{- end }} + export NODE_IP="$(kubectl get nodes --output jsonpath="{.items[0].status.addresses[1].address}")" + + echo "Visit http://${NODE_IP}:${HTTP_NODE_PORT} to access your application via HTTP." + echo "Visit https://${NODE_IP}:${HTTPS_NODE_PORT} to access your application via HTTPS." +{{- else if contains "LoadBalancer" .Values.controller.service.type }} +It may take a few minutes for the load balancer IP to be available. +You can watch the status by running 'kubectl get service --namespace {{ include "ingress-nginx.namespace" . }} {{ include "ingress-nginx.controller.fullname" . }} --output wide --watch' +{{- else if contains "ClusterIP" .Values.controller.service.type }} +Get the application URL by running these commands: + export POD_NAME="$(kubectl get pods --namespace {{ include "ingress-nginx.namespace" . }} --selector app.kubernetes.io/name={{ include "ingress-nginx.name" . }},app.kubernetes.io/instance={{ .Release.Name }},app.kubernetes.io/component=controller --output jsonpath="{.items[0].metadata.name}")" + kubectl port-forward --namespace {{ include "ingress-nginx.namespace" . }} "${POD_NAME}" 8080:80 + echo "Visit http://127.0.0.1:8080 to access your application." +{{- end }} + +An example Ingress that makes use of the controller: + +{{- $isV1 := semverCompare ">=1" .Chart.AppVersion}} + apiVersion: networking.k8s.io/v1 + kind: Ingress + metadata: + name: example + namespace: foo + {{- if eq $isV1 false }} + annotations: + kubernetes.io/ingress.class: {{ .Values.controller.ingressClass }} + {{- end }} + spec: + {{- if $isV1 }} + ingressClassName: {{ .Values.controller.ingressClassResource.name }} + {{- end }} + rules: + - host: www.example.com + http: + paths: + - pathType: Prefix + backend: + service: + name: exampleService + port: + number: 80 + path: / + # This section is only required if TLS is to be enabled for the Ingress + tls: + - hosts: + - www.example.com + secretName: example-tls + +If TLS is enabled for the Ingress, a Secret containing the certificate and key must also be provided: + + apiVersion: v1 + kind: Secret + metadata: + name: example-tls + namespace: foo + data: + tls.crt: + tls.key: + type: kubernetes.io/tls diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/templates/_helpers.tpl b/packages/system/ingress-nginx/charts/ingress-nginx/templates/_helpers.tpl new file mode 100644 index 00000000..c936dab7 --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/templates/_helpers.tpl @@ -0,0 +1,278 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "ingress-nginx.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "ingress-nginx.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | 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). +*/}} +{{- define "ingress-nginx.fullname" -}} +{{- if .Values.fullnameOverride -}} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- if contains $name .Release.Name -}} +{{- .Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Expand the namespace of the release. +Allows overriding it for multi-namespace deployments in combined charts. +*/}} +{{- define "ingress-nginx.namespace" -}} +{{- default .Release.Namespace .Values.namespaceOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Controller container security context. +*/}} +{{- define "ingress-nginx.controller.containerSecurityContext" -}} +{{- if .Values.controller.containerSecurityContext -}} +{{- toYaml .Values.controller.containerSecurityContext -}} +{{- else -}} +runAsNonRoot: {{ .Values.controller.image.runAsNonRoot }} +runAsUser: {{ .Values.controller.image.runAsUser }} +allowPrivilegeEscalation: {{ or .Values.controller.image.allowPrivilegeEscalation .Values.controller.image.chroot }} +{{- if .Values.controller.image.seccompProfile }} +seccompProfile: {{ toYaml .Values.controller.image.seccompProfile | nindent 2 }} +{{- end }} +capabilities: + drop: + - ALL + add: + - NET_BIND_SERVICE + {{- if .Values.controller.image.chroot }} + {{- if .Values.controller.image.seccompProfile }} + - SYS_ADMIN + {{- end }} + - SYS_CHROOT + {{- end }} +readOnlyRootFilesystem: {{ .Values.controller.image.readOnlyRootFilesystem }} +{{- end -}} +{{- end -}} + +{{/* +Get specific image +*/}} +{{- define "ingress-nginx.image" -}} +{{- if .chroot -}} +{{- printf "%s-chroot" .image -}} +{{- else -}} +{{- printf "%s" .image -}} +{{- end }} +{{- end -}} + +{{/* +Get specific image digest +*/}} +{{- define "ingress-nginx.imageDigest" -}} +{{- if .chroot -}} +{{- if .digestChroot -}} +{{- printf "@%s" .digestChroot -}} +{{- end }} +{{- else -}} +{{ if .digest -}} +{{- printf "@%s" .digest -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Create a default fully qualified controller name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +*/}} +{{- define "ingress-nginx.controller.fullname" -}} +{{- printf "%s-%s" (include "ingress-nginx.fullname" .) .Values.controller.name | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Construct a unique electionID. +Users can provide an override for an explicit electionID if they want via `.Values.controller.electionID` +*/}} +{{- define "ingress-nginx.controller.electionID" -}} +{{- $defElectionID := printf "%s-leader" (include "ingress-nginx.fullname" .) -}} +{{- $electionID := default $defElectionID .Values.controller.electionID -}} +{{- print $electionID -}} +{{- end -}} + +{{/* +Construct the path for the publish-service. + +By convention this will simply use the / to match the name of the +service generated. + +Users can provide an override for an explicit service they want bound via `.Values.controller.publishService.pathOverride` +*/}} +{{- define "ingress-nginx.controller.publishServicePath" -}} +{{- $defServiceName := printf "%s/%s" "$(POD_NAMESPACE)" (include "ingress-nginx.controller.fullname" .) -}} +{{- $servicePath := default $defServiceName .Values.controller.publishService.pathOverride }} +{{- print $servicePath | trimSuffix "-" -}} +{{- end -}} + +{{/* +Common labels +*/}} +{{- define "ingress-nginx.labels" -}} +helm.sh/chart: {{ include "ingress-nginx.chart" . }} +{{ include "ingress-nginx.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/part-of: {{ template "ingress-nginx.name" . }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- if .Values.commonLabels}} +{{ toYaml .Values.commonLabels }} +{{- end }} +{{- end -}} + +{{/* +Selector labels +*/}} +{{- define "ingress-nginx.selectorLabels" -}} +app.kubernetes.io/name: {{ include "ingress-nginx.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end -}} + +{{/* +Create the name of the controller service account to use +*/}} +{{- define "ingress-nginx.serviceAccountName" -}} +{{- if .Values.serviceAccount.create -}} + {{ default (include "ingress-nginx.fullname" .) .Values.serviceAccount.name }} +{{- else -}} + {{ default "default" .Values.serviceAccount.name }} +{{- end -}} +{{- end -}} + +{{/* +Create a default fully qualified admission webhook name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +*/}} +{{- define "ingress-nginx.admissionWebhooks.fullname" -}} +{{- printf "%s-%s" (include "ingress-nginx.fullname" .) .Values.controller.admissionWebhooks.name | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a default fully qualified admission webhook secret creation job name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +*/}} +{{- define "ingress-nginx.admissionWebhooks.createSecretJob.fullname" -}} +{{- printf "%s-%s" (include "ingress-nginx.admissionWebhooks.fullname" .) .Values.controller.admissionWebhooks.createSecretJob.name | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a default fully qualified admission webhook patch job name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +*/}} +{{- define "ingress-nginx.admissionWebhooks.patchWebhookJob.fullname" -}} +{{- printf "%s-%s" (include "ingress-nginx.admissionWebhooks.fullname" .) .Values.controller.admissionWebhooks.patchWebhookJob.name | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a default fully qualified default backend name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +*/}} +{{- define "ingress-nginx.defaultBackend.fullname" -}} +{{- printf "%s-%s" (include "ingress-nginx.fullname" .) .Values.defaultBackend.name | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create the name of the backend service account to use - only used when podsecuritypolicy is also enabled +*/}} +{{- define "ingress-nginx.defaultBackend.serviceAccountName" -}} +{{- if .Values.defaultBackend.serviceAccount.create -}} + {{ default (printf "%s-backend" (include "ingress-nginx.fullname" .)) .Values.defaultBackend.serviceAccount.name }} +{{- else -}} + {{ default "default-backend" .Values.defaultBackend.serviceAccount.name }} +{{- end -}} +{{- end -}} + +{{/* +Default backend container security context. +*/}} +{{- define "ingress-nginx.defaultBackend.containerSecurityContext" -}} +{{- if .Values.defaultBackend.containerSecurityContext -}} +{{- toYaml .Values.defaultBackend.containerSecurityContext -}} +{{- else -}} +runAsNonRoot: {{ .Values.defaultBackend.image.runAsNonRoot }} +runAsUser: {{ .Values.defaultBackend.image.runAsUser }} +allowPrivilegeEscalation: {{ .Values.defaultBackend.image.allowPrivilegeEscalation }} +{{- if .Values.defaultBackend.image.seccompProfile }} +seccompProfile: {{ toYaml .Values.defaultBackend.image.seccompProfile | nindent 2 }} +{{- end }} +capabilities: + drop: + - ALL +readOnlyRootFilesystem: {{ .Values.defaultBackend.image.readOnlyRootFilesystem }} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiGroup for PodSecurityPolicy. +*/}} +{{- define "podSecurityPolicy.apiGroup" -}} +{{- if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} +{{- print "policy" -}} +{{- else -}} +{{- print "extensions" -}} +{{- end -}} +{{- end -}} + +{{/* +Check the ingress controller version tag is at most three versions behind the last release +*/}} +{{- define "isControllerTagValid" -}} +{{- if not (semverCompare ">=0.27.0-0" .Values.controller.image.tag) -}} +{{- fail "Controller container image tag should be 0.27.0 or higher" -}} +{{- end -}} +{{- end -}} + +{{/* +IngressClass parameters. +*/}} +{{- define "ingressClass.parameters" -}} + {{- if .Values.controller.ingressClassResource.parameters -}} + parameters: +{{ toYaml .Values.controller.ingressClassResource.parameters | indent 4}} + {{ end }} +{{- end -}} + +{{/* +Extra modules. +*/}} +{{- define "extraModules" -}} +- name: {{ .name }} + image: {{ .image }} + command: + {{- if .distroless }} + - /init_module + {{- else }} + - sh + - -c + - /usr/local/bin/init_module.sh + {{- end }} + {{- if .containerSecurityContext }} + securityContext: {{ toYaml .containerSecurityContext | nindent 4 }} + {{- end }} + {{- if .resources }} + resources: {{ toYaml .resources | nindent 4 }} + {{- end }} + volumeMounts: + - name: modules + mountPath: /modules_mount +{{- end -}} diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/templates/_params.tpl b/packages/system/ingress-nginx/charts/ingress-nginx/templates/_params.tpl new file mode 100644 index 00000000..47d024e8 --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/templates/_params.tpl @@ -0,0 +1,68 @@ +{{- define "ingress-nginx.params" -}} +- /nginx-ingress-controller +{{- if .Values.controller.enableAnnotationValidations }} +- --enable-annotation-validation=true +{{- end }} +{{- if .Values.defaultBackend.enabled }} +- --default-backend-service=$(POD_NAMESPACE)/{{ include "ingress-nginx.defaultBackend.fullname" . }} +{{- end }} +{{- if and .Values.controller.publishService.enabled .Values.controller.service.enabled }} +{{- if .Values.controller.service.external.enabled }} +- --publish-service={{ template "ingress-nginx.controller.publishServicePath" . }} +{{- else if .Values.controller.service.internal.enabled }} +- --publish-service={{ template "ingress-nginx.controller.publishServicePath" . }}-internal +{{- end }} +{{- end }} +- --election-id={{ include "ingress-nginx.controller.electionID" . }} +- --controller-class={{ .Values.controller.ingressClassResource.controllerValue }} +{{- if .Values.controller.ingressClass }} +- --ingress-class={{ .Values.controller.ingressClass }} +{{- end }} +- --configmap={{ default "$(POD_NAMESPACE)" .Values.controller.configMapNamespace }}/{{ include "ingress-nginx.controller.fullname" . }} +{{- if .Values.tcp }} +- --tcp-services-configmap={{ default "$(POD_NAMESPACE)" .Values.controller.tcp.configMapNamespace }}/{{ include "ingress-nginx.fullname" . }}-tcp +{{- end }} +{{- if .Values.udp }} +- --udp-services-configmap={{ default "$(POD_NAMESPACE)" .Values.controller.udp.configMapNamespace }}/{{ include "ingress-nginx.fullname" . }}-udp +{{- end }} +{{- if .Values.controller.scope.enabled }} +- --watch-namespace={{ default "$(POD_NAMESPACE)" .Values.controller.scope.namespace }} +{{- end }} +{{- if and (not .Values.controller.scope.enabled) .Values.controller.scope.namespaceSelector }} +- --watch-namespace-selector={{ default "" .Values.controller.scope.namespaceSelector }} +{{- end }} +{{- if and .Values.controller.reportNodeInternalIp .Values.controller.hostNetwork }} +- --report-node-internal-ip-address={{ .Values.controller.reportNodeInternalIp }} +{{- end }} +{{- if .Values.controller.admissionWebhooks.enabled }} +- --validating-webhook=:{{ .Values.controller.admissionWebhooks.port }} +- --validating-webhook-certificate={{ .Values.controller.admissionWebhooks.certificate }} +- --validating-webhook-key={{ .Values.controller.admissionWebhooks.key }} +{{- end }} +{{- if .Values.controller.maxmindLicenseKey }} +- --maxmind-license-key={{ .Values.controller.maxmindLicenseKey }} +{{- end }} +{{- if .Values.controller.healthCheckHost }} +- --healthz-host={{ .Values.controller.healthCheckHost }} +{{- end }} +{{- if not (eq .Values.controller.healthCheckPath "/healthz") }} +- --health-check-path={{ .Values.controller.healthCheckPath }} +{{- end }} +{{- if .Values.controller.ingressClassByName }} +- --ingress-class-by-name=true +{{- end }} +{{- if .Values.controller.watchIngressWithoutClass }} +- --watch-ingress-without-class=true +{{- end }} +{{- if .Values.controller.enableTopologyAwareRouting }} +- --enable-topology-aware-routing=true +{{- end }} +{{- range $key, $value := .Values.controller.extraArgs }} +{{- /* Accept keys without values or with false as value */}} +{{- if eq ($value | quote | len) 2 }} +- --{{ $key }} +{{- else }} +- --{{ $key }}={{ $value }} +{{- end }} +{{- end }} +{{- end -}} diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/templates/admission-webhooks/cert-manager.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/templates/admission-webhooks/cert-manager.yaml new file mode 100644 index 00000000..db2946c3 --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/templates/admission-webhooks/cert-manager.yaml @@ -0,0 +1,63 @@ +{{- if and .Values.controller.admissionWebhooks.enabled .Values.controller.admissionWebhooks.certManager.enabled -}} +{{- if not .Values.controller.admissionWebhooks.certManager.issuerRef -}} +# Create a selfsigned Issuer, in order to create a root CA certificate for +# signing webhook serving certificates +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + name: {{ include "ingress-nginx.fullname" . }}-self-signed-issuer + namespace: {{ include "ingress-nginx.namespace" . }} +spec: + selfSigned: {} +--- +# Generate a CA Certificate used to sign certificates for the webhook +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: {{ include "ingress-nginx.fullname" . }}-root-cert + namespace: {{ include "ingress-nginx.namespace" . }} +spec: + secretName: {{ include "ingress-nginx.fullname" . }}-root-cert + duration: {{ .Values.controller.admissionWebhooks.certManager.rootCert.duration | default "43800h0m0s" | quote }} + issuerRef: + name: {{ include "ingress-nginx.fullname" . }}-self-signed-issuer + commonName: "ca.webhook.ingress-nginx" + isCA: true + subject: + organizations: + - ingress-nginx +--- +# Create an Issuer that uses the above generated CA certificate to issue certs +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + name: {{ include "ingress-nginx.fullname" . }}-root-issuer + namespace: {{ include "ingress-nginx.namespace" . }} +spec: + ca: + secretName: {{ include "ingress-nginx.fullname" . }}-root-cert +{{- end }} +--- +# generate a server certificate for the apiservices to use +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: {{ include "ingress-nginx.admissionWebhooks.fullname" . }} + namespace: {{ include "ingress-nginx.namespace" . }} +spec: + secretName: {{ include "ingress-nginx.admissionWebhooks.fullname" . }} + duration: {{ .Values.controller.admissionWebhooks.certManager.admissionCert.duration | default "8760h0m0s" | quote }} + issuerRef: + {{- if .Values.controller.admissionWebhooks.certManager.issuerRef }} + {{- toYaml .Values.controller.admissionWebhooks.certManager.issuerRef | nindent 4 }} + {{- else }} + name: {{ include "ingress-nginx.fullname" . }}-root-issuer + {{- end }} + dnsNames: + - {{ include "ingress-nginx.controller.fullname" . }}-admission + - {{ include "ingress-nginx.controller.fullname" . }}-admission.{{ include "ingress-nginx.namespace" . }} + - {{ include "ingress-nginx.controller.fullname" . }}-admission.{{ include "ingress-nginx.namespace" . }}.svc + subject: + organizations: + - ingress-nginx-admission +{{- end -}} diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/templates/admission-webhooks/job-patch/clusterrole.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/templates/admission-webhooks/job-patch/clusterrole.yaml new file mode 100644 index 00000000..8271dc40 --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/templates/admission-webhooks/job-patch/clusterrole.yaml @@ -0,0 +1,33 @@ +{{- if and .Values.controller.admissionWebhooks.enabled .Values.controller.admissionWebhooks.patch.enabled (not .Values.controller.admissionWebhooks.certManager.enabled) -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ include "ingress-nginx.admissionWebhooks.fullname" . }} + annotations: + "helm.sh/hook": pre-install,pre-upgrade,post-install,post-upgrade + "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded + labels: + {{- include "ingress-nginx.labels" . | nindent 4 }} + app.kubernetes.io/component: admission-webhook + {{- with .Values.controller.admissionWebhooks.patch.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +rules: + - apiGroups: + - admissionregistration.k8s.io + resources: + - validatingwebhookconfigurations + verbs: + - get + - update +{{- if .Values.podSecurityPolicy.enabled }} + - apiGroups: [{{ template "podSecurityPolicy.apiGroup" . }}] + resources: ['podsecuritypolicies'] + verbs: ['use'] + {{- with .Values.controller.admissionWebhooks.existingPsp }} + resourceNames: [{{ . }}] + {{- else }} + resourceNames: [{{ include "ingress-nginx.admissionWebhooks.fullname" . }}] + {{- end }} +{{- end }} +{{- end }} diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/templates/admission-webhooks/job-patch/clusterrolebinding.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/templates/admission-webhooks/job-patch/clusterrolebinding.yaml new file mode 100644 index 00000000..3fe842d1 --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/templates/admission-webhooks/job-patch/clusterrolebinding.yaml @@ -0,0 +1,23 @@ +{{- if and .Values.controller.admissionWebhooks.enabled .Values.controller.admissionWebhooks.patch.enabled (not .Values.controller.admissionWebhooks.certManager.enabled) -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ include "ingress-nginx.admissionWebhooks.fullname" . }} + annotations: + "helm.sh/hook": pre-install,pre-upgrade,post-install,post-upgrade + "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded + labels: + {{- include "ingress-nginx.labels" . | nindent 4 }} + app.kubernetes.io/component: admission-webhook + {{- with .Values.controller.admissionWebhooks.patch.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ include "ingress-nginx.admissionWebhooks.fullname" . }} +subjects: + - kind: ServiceAccount + name: {{ include "ingress-nginx.admissionWebhooks.fullname" . }} + namespace: {{ include "ingress-nginx.namespace" . }} +{{- end }} diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/templates/admission-webhooks/job-patch/job-createSecret.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/templates/admission-webhooks/job-patch/job-createSecret.yaml new file mode 100644 index 00000000..c29083f2 --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/templates/admission-webhooks/job-patch/job-createSecret.yaml @@ -0,0 +1,79 @@ +{{- if and .Values.controller.admissionWebhooks.enabled .Values.controller.admissionWebhooks.patch.enabled (not .Values.controller.admissionWebhooks.certManager.enabled) -}} +apiVersion: batch/v1 +kind: Job +metadata: + name: {{ include "ingress-nginx.admissionWebhooks.createSecretJob.fullname" . }} + namespace: {{ include "ingress-nginx.namespace" . }} + annotations: + "helm.sh/hook": pre-install,pre-upgrade + "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded + {{- with .Values.controller.admissionWebhooks.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} + labels: + {{- include "ingress-nginx.labels" . | nindent 4 }} + app.kubernetes.io/component: admission-webhook + {{- with .Values.controller.admissionWebhooks.patch.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: +{{- if .Capabilities.APIVersions.Has "batch/v1alpha1" }} + # Alpha feature since k8s 1.12 + ttlSecondsAfterFinished: 0 +{{- end }} + template: + metadata: + name: {{ include "ingress-nginx.admissionWebhooks.createSecretJob.fullname" . }} + {{- if .Values.controller.admissionWebhooks.patch.podAnnotations }} + annotations: {{ toYaml .Values.controller.admissionWebhooks.patch.podAnnotations | nindent 8 }} + {{- end }} + labels: + {{- include "ingress-nginx.labels" . | nindent 8 }} + app.kubernetes.io/component: admission-webhook + {{- with .Values.controller.admissionWebhooks.patch.labels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- if .Values.controller.admissionWebhooks.patch.priorityClassName }} + priorityClassName: {{ .Values.controller.admissionWebhooks.patch.priorityClassName }} + {{- end }} + {{- if .Values.imagePullSecrets }} + imagePullSecrets: {{ toYaml .Values.imagePullSecrets | nindent 8 }} + {{- end }} + containers: + - name: create + {{- with .Values.controller.admissionWebhooks.patch.image }} + image: "{{- if .repository -}}{{ .repository }}{{ else }}{{ .registry }}/{{ .image }}{{- end -}}:{{ .tag }}{{- if (.digest) -}} @{{.digest}} {{- end -}}" + {{- end }} + imagePullPolicy: {{ .Values.controller.admissionWebhooks.patch.image.pullPolicy }} + args: + - create + - --host={{ include "ingress-nginx.controller.fullname" . }}-admission,{{ include "ingress-nginx.controller.fullname" . }}-admission.$(POD_NAMESPACE).svc + - --namespace=$(POD_NAMESPACE) + - --secret-name={{ include "ingress-nginx.admissionWebhooks.fullname" . }} + env: + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + {{- if .Values.controller.admissionWebhooks.extraEnvs }} + {{- toYaml .Values.controller.admissionWebhooks.extraEnvs | nindent 12 }} + {{- end }} + {{- if .Values.controller.admissionWebhooks.createSecretJob.securityContext }} + securityContext: {{ toYaml .Values.controller.admissionWebhooks.createSecretJob.securityContext | nindent 12 }} + {{- end }} + {{- if .Values.controller.admissionWebhooks.createSecretJob.resources }} + resources: {{ toYaml .Values.controller.admissionWebhooks.createSecretJob.resources | nindent 12 }} + {{- end }} + restartPolicy: OnFailure + serviceAccountName: {{ include "ingress-nginx.admissionWebhooks.fullname" . }} + {{- if .Values.controller.admissionWebhooks.patch.nodeSelector }} + nodeSelector: {{ toYaml .Values.controller.admissionWebhooks.patch.nodeSelector | nindent 8 }} + {{- end }} + {{- if .Values.controller.admissionWebhooks.patch.tolerations }} + tolerations: {{ toYaml .Values.controller.admissionWebhooks.patch.tolerations | nindent 8 }} + {{- end }} + {{- if .Values.controller.admissionWebhooks.patch.securityContext }} + securityContext: {{ toYaml .Values.controller.admissionWebhooks.patch.securityContext | nindent 8 }} + {{- end }} +{{- end }} diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/templates/admission-webhooks/job-patch/job-patchWebhook.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/templates/admission-webhooks/job-patch/job-patchWebhook.yaml new file mode 100644 index 00000000..cbc4a761 --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/templates/admission-webhooks/job-patch/job-patchWebhook.yaml @@ -0,0 +1,81 @@ +{{- if and .Values.controller.admissionWebhooks.enabled .Values.controller.admissionWebhooks.patch.enabled (not .Values.controller.admissionWebhooks.certManager.enabled) -}} +apiVersion: batch/v1 +kind: Job +metadata: + name: {{ include "ingress-nginx.admissionWebhooks.patchWebhookJob.fullname" . }} + namespace: {{ include "ingress-nginx.namespace" . }} + annotations: + "helm.sh/hook": post-install,post-upgrade + "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded + {{- with .Values.controller.admissionWebhooks.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} + labels: + {{- include "ingress-nginx.labels" . | nindent 4 }} + app.kubernetes.io/component: admission-webhook + {{- with .Values.controller.admissionWebhooks.patch.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: +{{- if .Capabilities.APIVersions.Has "batch/v1alpha1" }} + # Alpha feature since k8s 1.12 + ttlSecondsAfterFinished: 0 +{{- end }} + template: + metadata: + name: {{ include "ingress-nginx.admissionWebhooks.patchWebhookJob.fullname" . }} + {{- if .Values.controller.admissionWebhooks.patch.podAnnotations }} + annotations: {{ toYaml .Values.controller.admissionWebhooks.patch.podAnnotations | nindent 8 }} + {{- end }} + labels: + {{- include "ingress-nginx.labels" . | nindent 8 }} + app.kubernetes.io/component: admission-webhook + {{- with .Values.controller.admissionWebhooks.patch.labels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- if .Values.controller.admissionWebhooks.patch.priorityClassName }} + priorityClassName: {{ .Values.controller.admissionWebhooks.patch.priorityClassName }} + {{- end }} + {{- if .Values.imagePullSecrets }} + imagePullSecrets: {{ toYaml .Values.imagePullSecrets | nindent 8 }} + {{- end }} + containers: + - name: patch + {{- with .Values.controller.admissionWebhooks.patch.image }} + image: "{{- if .repository -}}{{ .repository }}{{ else }}{{ .registry }}/{{ .image }}{{- end -}}:{{ .tag }}{{- if (.digest) -}} @{{.digest}} {{- end -}}" + {{- end }} + imagePullPolicy: {{ .Values.controller.admissionWebhooks.patch.image.pullPolicy }} + args: + - patch + - --webhook-name={{ include "ingress-nginx.admissionWebhooks.fullname" . }} + - --namespace=$(POD_NAMESPACE) + - --patch-mutating=false + - --secret-name={{ include "ingress-nginx.admissionWebhooks.fullname" . }} + - --patch-failure-policy={{ .Values.controller.admissionWebhooks.failurePolicy }} + env: + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + {{- if .Values.controller.admissionWebhooks.extraEnvs }} + {{- toYaml .Values.controller.admissionWebhooks.extraEnvs | nindent 12 }} + {{- end }} + {{- if .Values.controller.admissionWebhooks.patchWebhookJob.securityContext }} + securityContext: {{ toYaml .Values.controller.admissionWebhooks.patchWebhookJob.securityContext | nindent 12 }} + {{- end }} + {{- if .Values.controller.admissionWebhooks.patchWebhookJob.resources }} + resources: {{ toYaml .Values.controller.admissionWebhooks.patchWebhookJob.resources | nindent 12 }} + {{- end }} + restartPolicy: OnFailure + serviceAccountName: {{ include "ingress-nginx.admissionWebhooks.fullname" . }} + {{- if .Values.controller.admissionWebhooks.patch.nodeSelector }} + nodeSelector: {{ toYaml .Values.controller.admissionWebhooks.patch.nodeSelector | nindent 8 }} + {{- end }} + {{- if .Values.controller.admissionWebhooks.patch.tolerations }} + tolerations: {{ toYaml .Values.controller.admissionWebhooks.patch.tolerations | nindent 8 }} + {{- end }} + {{- if .Values.controller.admissionWebhooks.patch.securityContext }} + securityContext: {{ toYaml .Values.controller.admissionWebhooks.patch.securityContext | nindent 8 }} + {{- end }} +{{- end }} diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/templates/admission-webhooks/job-patch/networkpolicy.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/templates/admission-webhooks/job-patch/networkpolicy.yaml new file mode 100644 index 00000000..a8f38df9 --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/templates/admission-webhooks/job-patch/networkpolicy.yaml @@ -0,0 +1,26 @@ +{{- if and .Values.controller.admissionWebhooks.enabled .Values.controller.admissionWebhooks.patch.enabled .Values.controller.admissionWebhooks.patch.networkPolicy.enabled (not .Values.controller.admissionWebhooks.certManager.enabled) -}} +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: {{ include "ingress-nginx.admissionWebhooks.fullname" . }} + namespace: {{ include "ingress-nginx.namespace" . }} + annotations: + "helm.sh/hook": pre-install,pre-upgrade,post-install,post-upgrade + "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded + labels: + {{- include "ingress-nginx.labels" . | nindent 4 }} + app.kubernetes.io/component: admission-webhook + {{- with .Values.controller.admissionWebhooks.patch.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + podSelector: + matchLabels: + {{- include "ingress-nginx.selectorLabels" . | nindent 6 }} + app.kubernetes.io/component: admission-webhook + policyTypes: + - Ingress + - Egress + egress: + - {} +{{- end }} diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/templates/admission-webhooks/job-patch/psp.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/templates/admission-webhooks/job-patch/psp.yaml new file mode 100644 index 00000000..8e5dc72a --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/templates/admission-webhooks/job-patch/psp.yaml @@ -0,0 +1,52 @@ +{{- if (semverCompare "<1.25.0-0" .Capabilities.KubeVersion.Version) }} +{{- if and .Values.podSecurityPolicy.enabled .Values.controller.admissionWebhooks.enabled .Values.controller.admissionWebhooks.patch.enabled (empty .Values.controller.admissionWebhooks.existingPsp) -}} +apiVersion: policy/v1beta1 +kind: PodSecurityPolicy +metadata: + name: {{ include "ingress-nginx.admissionWebhooks.fullname" . }} + annotations: + "helm.sh/hook": pre-install,pre-upgrade,post-install,post-upgrade + "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded + seccomp.security.alpha.kubernetes.io/allowedProfileNames: "*" + labels: + {{- include "ingress-nginx.labels" . | nindent 4 }} + app.kubernetes.io/component: admission-webhook + {{- with .Values.controller.admissionWebhooks.patch.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + privileged: false + hostPID: false + hostIPC: false + hostNetwork: false + volumes: + - configMap + - downwardAPI + - emptyDir + - secret + - projected + fsGroup: + rule: MustRunAs + ranges: + - min: 1 + max: 65535 + readOnlyRootFilesystem: true + runAsUser: + rule: MustRunAsNonRoot + runAsGroup: + rule: MustRunAs + ranges: + - min: 1 + max: 65535 + supplementalGroups: + rule: MustRunAs + ranges: + - min: 1 + max: 65535 + allowPrivilegeEscalation: false + requiredDropCapabilities: + - ALL + seLinux: + rule: RunAsAny +{{- end }} +{{- end }} diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/templates/admission-webhooks/job-patch/role.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/templates/admission-webhooks/job-patch/role.yaml new file mode 100644 index 00000000..5b05d9b0 --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/templates/admission-webhooks/job-patch/role.yaml @@ -0,0 +1,24 @@ +{{- if and .Values.controller.admissionWebhooks.enabled .Values.controller.admissionWebhooks.patch.enabled (not .Values.controller.admissionWebhooks.certManager.enabled) -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ include "ingress-nginx.admissionWebhooks.fullname" . }} + namespace: {{ include "ingress-nginx.namespace" . }} + annotations: + "helm.sh/hook": pre-install,pre-upgrade,post-install,post-upgrade + "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded + labels: + {{- include "ingress-nginx.labels" . | nindent 4 }} + app.kubernetes.io/component: admission-webhook + {{- with .Values.controller.admissionWebhooks.patch.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +rules: + - apiGroups: + - "" + resources: + - secrets + verbs: + - get + - create +{{- end }} diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/templates/admission-webhooks/job-patch/rolebinding.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/templates/admission-webhooks/job-patch/rolebinding.yaml new file mode 100644 index 00000000..48a17556 --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/templates/admission-webhooks/job-patch/rolebinding.yaml @@ -0,0 +1,24 @@ +{{- if and .Values.controller.admissionWebhooks.enabled .Values.controller.admissionWebhooks.patch.enabled (not .Values.controller.admissionWebhooks.certManager.enabled) -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ include "ingress-nginx.admissionWebhooks.fullname" . }} + namespace: {{ include "ingress-nginx.namespace" . }} + annotations: + "helm.sh/hook": pre-install,pre-upgrade,post-install,post-upgrade + "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded + labels: + {{- include "ingress-nginx.labels" . | nindent 4 }} + app.kubernetes.io/component: admission-webhook + {{- with .Values.controller.admissionWebhooks.patch.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ include "ingress-nginx.admissionWebhooks.fullname" . }} +subjects: + - kind: ServiceAccount + name: {{ include "ingress-nginx.admissionWebhooks.fullname" . }} + namespace: {{ include "ingress-nginx.namespace" . }} +{{- end }} diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/templates/admission-webhooks/job-patch/serviceaccount.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/templates/admission-webhooks/job-patch/serviceaccount.yaml new file mode 100644 index 00000000..91bbf22b --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/templates/admission-webhooks/job-patch/serviceaccount.yaml @@ -0,0 +1,16 @@ +{{- if and .Values.controller.admissionWebhooks.enabled .Values.controller.admissionWebhooks.patch.enabled (not .Values.controller.admissionWebhooks.certManager.enabled) -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "ingress-nginx.admissionWebhooks.fullname" . }} + namespace: {{ include "ingress-nginx.namespace" . }} + annotations: + "helm.sh/hook": pre-install,pre-upgrade,post-install,post-upgrade + "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded + labels: + {{- include "ingress-nginx.labels" . | nindent 4 }} + app.kubernetes.io/component: admission-webhook + {{- with .Values.controller.admissionWebhooks.patch.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/templates/admission-webhooks/validating-webhook.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/templates/admission-webhooks/validating-webhook.yaml new file mode 100644 index 00000000..4cd36a62 --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/templates/admission-webhooks/validating-webhook.yaml @@ -0,0 +1,53 @@ +{{- if .Values.controller.admissionWebhooks.enabled -}} +# before changing this value, check the required kubernetes version +# https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#prerequisites +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingWebhookConfiguration +metadata: + annotations: + {{- if .Values.controller.admissionWebhooks.certManager.enabled }} + certmanager.k8s.io/inject-ca-from: {{ printf "%s/%s" (include "ingress-nginx.namespace" .) (include "ingress-nginx.admissionWebhooks.fullname" .) | quote }} + cert-manager.io/inject-ca-from: {{ printf "%s/%s" (include "ingress-nginx.namespace" .) (include "ingress-nginx.admissionWebhooks.fullname" .) | quote }} + {{- end }} + {{- if .Values.controller.admissionWebhooks.annotations }} + {{- toYaml .Values.controller.admissionWebhooks.annotations | nindent 4 }} + {{- end }} + labels: + {{- include "ingress-nginx.labels" . | nindent 4 }} + app.kubernetes.io/component: admission-webhook + {{- with .Values.controller.admissionWebhooks.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + name: {{ include "ingress-nginx.admissionWebhooks.fullname" . }} +webhooks: + - name: validate.nginx.ingress.kubernetes.io + matchPolicy: Equivalent + rules: + - apiGroups: + - networking.k8s.io + apiVersions: + - v1 + operations: + - CREATE + - UPDATE + resources: + - ingresses + failurePolicy: {{ .Values.controller.admissionWebhooks.failurePolicy | default "Fail" }} + sideEffects: None + admissionReviewVersions: + - v1 + clientConfig: + service: + name: {{ include "ingress-nginx.controller.fullname" . }}-admission + namespace: {{ include "ingress-nginx.namespace" . }} + path: /networking/v1/ingresses + {{- if .Values.controller.admissionWebhooks.timeoutSeconds }} + timeoutSeconds: {{ .Values.controller.admissionWebhooks.timeoutSeconds }} + {{- end }} + {{- if .Values.controller.admissionWebhooks.namespaceSelector }} + namespaceSelector: {{ toYaml .Values.controller.admissionWebhooks.namespaceSelector | nindent 6 }} + {{- end }} + {{- if .Values.controller.admissionWebhooks.objectSelector }} + objectSelector: {{ toYaml .Values.controller.admissionWebhooks.objectSelector | nindent 6 }} + {{- end }} +{{- end }} diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/templates/clusterrole.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/templates/clusterrole.yaml new file mode 100644 index 00000000..51bc5002 --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/templates/clusterrole.yaml @@ -0,0 +1,102 @@ +{{- if .Values.rbac.create }} + +{{- if and .Values.rbac.scope (not .Values.controller.scope.enabled) -}} + {{ required "Invalid configuration: 'rbac.scope' should be equal to 'controller.scope.enabled' (true/false)." (index (dict) ".") }} +{{- end }} + +{{- if not .Values.rbac.scope -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + {{- include "ingress-nginx.labels" . | nindent 4 }} + {{- with .Values.controller.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + name: {{ include "ingress-nginx.fullname" . }} +rules: + - apiGroups: + - "" + resources: + - configmaps + - endpoints + - nodes + - pods + - secrets +{{- if not .Values.controller.scope.enabled }} + - namespaces +{{- end}} + verbs: + - list + - watch + - apiGroups: + - coordination.k8s.io + resources: + - leases + verbs: + - list + - watch +{{- if and .Values.controller.scope.enabled .Values.controller.scope.namespace }} + - apiGroups: + - "" + resources: + - namespaces + resourceNames: + - "{{ .Values.controller.scope.namespace }}" + verbs: + - get +{{- end }} + - apiGroups: + - "" + resources: + - nodes + verbs: + - get + - apiGroups: + - "" + resources: + - services + verbs: + - get + - list + - watch + - apiGroups: + - networking.k8s.io + resources: + - ingresses + verbs: + - get + - list + - watch + - apiGroups: + - "" + resources: + - events + verbs: + - create + - patch + - apiGroups: + - networking.k8s.io + resources: + - ingresses/status + verbs: + - update + - apiGroups: + - networking.k8s.io + resources: + - ingressclasses + verbs: + - get + - list + - watch + - apiGroups: + - discovery.k8s.io + resources: + - endpointslices + verbs: + - list + - watch + - get +{{- end }} + +{{- end }} diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/templates/clusterrolebinding.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/templates/clusterrolebinding.yaml new file mode 100644 index 00000000..8f91aac8 --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/templates/clusterrolebinding.yaml @@ -0,0 +1,19 @@ +{{- if and .Values.rbac.create (not .Values.rbac.scope) -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + labels: + {{- include "ingress-nginx.labels" . | nindent 4 }} + {{- with .Values.controller.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + name: {{ include "ingress-nginx.fullname" . }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ include "ingress-nginx.fullname" . }} +subjects: + - kind: ServiceAccount + name: {{ template "ingress-nginx.serviceAccountName" . }} + namespace: {{ include "ingress-nginx.namespace" . }} +{{- end }} diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-configmap-addheaders.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-configmap-addheaders.yaml new file mode 100644 index 00000000..4e4bd131 --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-configmap-addheaders.yaml @@ -0,0 +1,14 @@ +{{- if .Values.controller.addHeaders -}} +apiVersion: v1 +kind: ConfigMap +metadata: + labels: + {{- include "ingress-nginx.labels" . | nindent 4 }} + app.kubernetes.io/component: controller + {{- with .Values.controller.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + name: {{ include "ingress-nginx.fullname" . }}-custom-add-headers + namespace: {{ include "ingress-nginx.namespace" . }} +data: {{ toYaml .Values.controller.addHeaders | nindent 2 }} +{{- end }} diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-configmap-proxyheaders.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-configmap-proxyheaders.yaml new file mode 100644 index 00000000..0a22600d --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-configmap-proxyheaders.yaml @@ -0,0 +1,14 @@ +{{- if .Values.controller.proxySetHeaders -}} +apiVersion: v1 +kind: ConfigMap +metadata: + labels: + {{- include "ingress-nginx.labels" . | nindent 4 }} + app.kubernetes.io/component: controller + {{- with .Values.controller.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + name: {{ include "ingress-nginx.fullname" . }}-custom-proxy-headers + namespace: {{ include "ingress-nginx.namespace" . }} +data: {{ toYaml .Values.controller.proxySetHeaders | nindent 2 }} +{{- end }} diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-configmap-tcp.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-configmap-tcp.yaml new file mode 100644 index 00000000..131a9ad5 --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-configmap-tcp.yaml @@ -0,0 +1,17 @@ +{{- if .Values.tcp -}} +apiVersion: v1 +kind: ConfigMap +metadata: + labels: + {{- include "ingress-nginx.labels" . | nindent 4 }} + app.kubernetes.io/component: controller + {{- with .Values.controller.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +{{- if .Values.controller.tcp.annotations }} + annotations: {{ toYaml .Values.controller.tcp.annotations | nindent 4 }} +{{- end }} + name: {{ include "ingress-nginx.fullname" . }}-tcp + namespace: {{ include "ingress-nginx.namespace" . }} +data: {{ tpl (toYaml .Values.tcp) . | nindent 2 }} +{{- end }} diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-configmap-udp.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-configmap-udp.yaml new file mode 100644 index 00000000..7137da9a --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-configmap-udp.yaml @@ -0,0 +1,17 @@ +{{- if .Values.udp -}} +apiVersion: v1 +kind: ConfigMap +metadata: + labels: + {{- include "ingress-nginx.labels" . | nindent 4 }} + app.kubernetes.io/component: controller + {{- with .Values.controller.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +{{- if .Values.controller.udp.annotations }} + annotations: {{ toYaml .Values.controller.udp.annotations | nindent 4 }} +{{- end }} + name: {{ include "ingress-nginx.fullname" . }}-udp + namespace: {{ include "ingress-nginx.namespace" . }} +data: {{ tpl (toYaml .Values.udp) . | nindent 2 }} +{{- end }} diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-configmap.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-configmap.yaml new file mode 100644 index 00000000..662a1620 --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-configmap.yaml @@ -0,0 +1,28 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + labels: + {{- include "ingress-nginx.labels" . | nindent 4 }} + app.kubernetes.io/component: controller + {{- with .Values.controller.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +{{- if .Values.controller.configAnnotations }} + annotations: {{ toYaml .Values.controller.configAnnotations | nindent 4 }} +{{- end }} + name: {{ include "ingress-nginx.controller.fullname" . }} + namespace: {{ include "ingress-nginx.namespace" . }} +data: + allow-snippet-annotations: "{{ .Values.controller.allowSnippetAnnotations }}" +{{- if .Values.controller.addHeaders }} + add-headers: {{ include "ingress-nginx.namespace" . }}/{{ include "ingress-nginx.fullname" . }}-custom-add-headers +{{- end }} +{{- if .Values.controller.proxySetHeaders }} + proxy-set-headers: {{ include "ingress-nginx.namespace" . }}/{{ include "ingress-nginx.fullname" . }}-custom-proxy-headers +{{- end }} +{{- if .Values.dhParam }} + ssl-dh-param: {{ include "ingress-nginx.namespace" . }}/{{ include "ingress-nginx.controller.fullname" . }} +{{- end }} +{{- range $key, $value := .Values.controller.config }} + {{- $key | nindent 2 }}: {{ $value | quote }} +{{- end }} diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-daemonset.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-daemonset.yaml new file mode 100644 index 00000000..887d7a20 --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-daemonset.yaml @@ -0,0 +1,246 @@ +{{- if eq .Values.controller.kind "DaemonSet" -}} +{{- include "isControllerTagValid" . -}} +apiVersion: apps/v1 +kind: DaemonSet +metadata: + labels: + {{- include "ingress-nginx.labels" . | nindent 4 }} + app.kubernetes.io/component: controller + {{- with .Values.controller.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + name: {{ include "ingress-nginx.controller.fullname" . }} + namespace: {{ include "ingress-nginx.namespace" . }} + {{- if .Values.controller.annotations }} + annotations: {{ toYaml .Values.controller.annotations | nindent 4 }} + {{- end }} +spec: + selector: + matchLabels: + {{- include "ingress-nginx.selectorLabels" . | nindent 6 }} + app.kubernetes.io/component: controller + revisionHistoryLimit: {{ .Values.revisionHistoryLimit }} + {{- if .Values.controller.updateStrategy }} + updateStrategy: {{ toYaml .Values.controller.updateStrategy | nindent 4 }} + {{- end }} + minReadySeconds: {{ .Values.controller.minReadySeconds }} + template: + metadata: + {{- if .Values.controller.podAnnotations }} + annotations: + {{- range $key, $value := .Values.controller.podAnnotations }} + {{ $key }}: {{ $value | quote }} + {{- end }} + {{- end }} + labels: + {{- include "ingress-nginx.labels" . | nindent 8 }} + app.kubernetes.io/component: controller + {{- with .Values.controller.labels }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if .Values.controller.podLabels }} + {{- toYaml .Values.controller.podLabels | nindent 8 }} + {{- end }} + spec: + {{- if .Values.controller.dnsConfig }} + dnsConfig: {{ toYaml .Values.controller.dnsConfig | nindent 8 }} + {{- end }} + {{- if .Values.controller.hostAliases }} + hostAliases: {{ tpl (toYaml .Values.controller.hostAliases) $ | nindent 8 }} + {{- end }} + {{- if .Values.controller.hostname }} + hostname: {{ toYaml .Values.controller.hostname | nindent 8 }} + {{- end }} + dnsPolicy: {{ .Values.controller.dnsPolicy }} + {{- if .Values.imagePullSecrets }} + imagePullSecrets: {{ toYaml .Values.imagePullSecrets | nindent 8 }} + {{- end }} + {{- if .Values.controller.priorityClassName }} + priorityClassName: {{ .Values.controller.priorityClassName | quote }} + {{- end }} + {{- if or .Values.controller.podSecurityContext .Values.controller.sysctls }} + securityContext: + {{- if .Values.controller.podSecurityContext }} + {{- toYaml .Values.controller.podSecurityContext | nindent 8 }} + {{- end }} + {{- if .Values.controller.sysctls }} + sysctls: + {{- range $sysctl, $value := .Values.controller.sysctls }} + - name: {{ $sysctl | quote }} + value: {{ $value | quote }} + {{- end }} + {{- end }} + {{- end }} + {{- if .Values.controller.shareProcessNamespace }} + shareProcessNamespace: {{ .Values.controller.shareProcessNamespace }} + {{- end }} + containers: + - name: {{ .Values.controller.containerName }} + {{- with .Values.controller.image }} + image: "{{- if .repository -}}{{ .repository }}{{ else }}{{ .registry }}/{{ include "ingress-nginx.image" . }}{{- end -}}:{{ .tag }}{{ include "ingress-nginx.imageDigest" . }}" + {{- end }} + imagePullPolicy: {{ .Values.controller.image.pullPolicy }} + {{- if .Values.controller.lifecycle }} + lifecycle: {{ toYaml .Values.controller.lifecycle | nindent 12 }} + {{- end }} + args: {{ include "ingress-nginx.params" . | nindent 12 }} + securityContext: {{ include "ingress-nginx.controller.containerSecurityContext" . | nindent 12 }} + env: + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + {{- if .Values.controller.enableMimalloc }} + - name: LD_PRELOAD + value: /usr/local/lib/libmimalloc.so + {{- end }} + {{- if .Values.controller.extraEnvs }} + {{- toYaml .Values.controller.extraEnvs | nindent 12 }} + {{- end }} + {{- if .Values.controller.startupProbe }} + startupProbe: {{ toYaml .Values.controller.startupProbe | nindent 12 }} + {{- end }} + {{- if .Values.controller.livenessProbe }} + livenessProbe: {{ toYaml .Values.controller.livenessProbe | nindent 12 }} + {{- end }} + {{- if .Values.controller.readinessProbe }} + readinessProbe: {{ toYaml .Values.controller.readinessProbe | nindent 12 }} + {{- end }} + ports: + {{- range $key, $value := .Values.controller.containerPort }} + - name: {{ $key }} + containerPort: {{ $value }} + protocol: TCP + {{- if $.Values.controller.hostPort.enabled }} + hostPort: {{ index $.Values.controller.hostPort.ports $key | default $value }} + {{- end }} + {{- end }} + {{- if .Values.controller.metrics.enabled }} + - name: {{ .Values.controller.metrics.portName }} + containerPort: {{ .Values.controller.metrics.port }} + protocol: TCP + - name: metrics2 + containerPort: 9091 + protocol: TCP + {{- end }} + {{- if .Values.controller.admissionWebhooks.enabled }} + - name: webhook + containerPort: {{ .Values.controller.admissionWebhooks.port }} + protocol: TCP + {{- end }} + {{- range $key, $value := .Values.tcp }} + - name: {{ if $.Values.portNamePrefix }}{{ $.Values.portNamePrefix }}-{{ end }}{{ $key }}-tcp + containerPort: {{ $key }} + protocol: TCP + {{- if $.Values.controller.hostPort.enabled }} + hostPort: {{ $key }} + {{- end }} + {{- end }} + {{- range $key, $value := .Values.udp }} + - name: {{ if $.Values.portNamePrefix }}{{ $.Values.portNamePrefix }}-{{ end }}{{ $key }}-udp + containerPort: {{ $key }} + protocol: UDP + {{- if $.Values.controller.hostPort.enabled }} + hostPort: {{ $key }} + {{- end }} + {{- end }} + {{- if (or .Values.controller.customTemplate.configMapName .Values.controller.extraVolumeMounts .Values.controller.admissionWebhooks.enabled .Values.controller.extraModules .Values.controller.opentelemetry.enabled) }} + volumeMounts: + {{- if (or .Values.controller.extraModules .Values.controller.opentelemetry.enabled) }} + - name: modules + {{- if .Values.controller.image.chroot }} + mountPath: /chroot/modules_mount + {{- else }} + mountPath: /modules_mount + {{- end }} + {{- end }} + {{- if .Values.controller.customTemplate.configMapName }} + - mountPath: /etc/nginx/template + name: nginx-template-volume + readOnly: true + {{- end }} + {{- if .Values.controller.admissionWebhooks.enabled }} + - name: webhook-cert + mountPath: /usr/local/certificates/ + readOnly: true + {{- end }} + {{- if .Values.controller.extraVolumeMounts }} + {{- toYaml .Values.controller.extraVolumeMounts | nindent 12 }} + {{- end }} + {{- end }} + {{- if .Values.controller.resources }} + resources: {{ toYaml .Values.controller.resources | nindent 12 }} + {{- end }} + {{- if .Values.controller.extraContainers }} + {{- toYaml .Values.controller.extraContainers | nindent 8 }} + {{- end }} + {{- if (or .Values.controller.extraInitContainers .Values.controller.extraModules .Values.controller.opentelemetry.enabled) }} + initContainers: + {{- if .Values.controller.extraInitContainers }} + {{- toYaml .Values.controller.extraInitContainers | nindent 8 }} + {{- end }} + {{- if .Values.controller.extraModules }} + {{- range .Values.controller.extraModules }} + {{- $containerSecurityContext := .containerSecurityContext | default $.Values.controller.containerSecurityContext }} + {{- include "extraModules" (dict "name" .name "image" .image "distroless" .distroless "containerSecurityContext" $containerSecurityContext "resources" .resources) | nindent 8 }} + {{- end }} + {{- end }} + {{- if .Values.controller.opentelemetry.enabled }} + {{- with .Values.controller.opentelemetry }} + {{- $containerSecurityContext := .containerSecurityContext | default $.Values.controller.containerSecurityContext }} + {{- include "extraModules" (dict "name" .name "image" .image "distroless" .distroless "containerSecurityContext" $containerSecurityContext "resources" .resources) | nindent 8 }} + {{- end }} + {{- end }} + {{- end }} + {{- if .Values.controller.hostNetwork }} + hostNetwork: {{ .Values.controller.hostNetwork }} + {{- end }} + {{- if .Values.controller.nodeSelector }} + nodeSelector: {{ toYaml .Values.controller.nodeSelector | nindent 8 }} + {{- end }} + {{- if .Values.controller.tolerations }} + tolerations: {{ toYaml .Values.controller.tolerations | nindent 8 }} + {{- end }} + {{- if .Values.controller.affinity }} + affinity: {{ toYaml .Values.controller.affinity | nindent 8 }} + {{- end }} + {{- if .Values.controller.topologySpreadConstraints }} + topologySpreadConstraints: {{ tpl (toYaml .Values.controller.topologySpreadConstraints) $ | nindent 8 }} + {{- end }} + serviceAccountName: {{ template "ingress-nginx.serviceAccountName" . }} + terminationGracePeriodSeconds: {{ .Values.controller.terminationGracePeriodSeconds }} + {{- if (or .Values.controller.customTemplate.configMapName .Values.controller.extraVolumeMounts .Values.controller.admissionWebhooks.enabled .Values.controller.extraVolumes .Values.controller.extraModules .Values.controller.opentelemetry.enabled) }} + volumes: + {{- if (or .Values.controller.extraModules .Values.controller.opentelemetry.enabled)}} + - name: modules + emptyDir: {} + {{- end }} + {{- if .Values.controller.customTemplate.configMapName }} + - name: nginx-template-volume + configMap: + name: {{ .Values.controller.customTemplate.configMapName }} + items: + - key: {{ .Values.controller.customTemplate.configMapKey }} + path: nginx.tmpl + {{- end }} + {{- if .Values.controller.admissionWebhooks.enabled }} + - name: webhook-cert + secret: + secretName: {{ include "ingress-nginx.admissionWebhooks.fullname" . }} + {{- if .Values.controller.admissionWebhooks.certManager.enabled }} + items: + - key: tls.crt + path: cert + - key: tls.key + path: key + {{- end }} + {{- end }} + {{- if .Values.controller.extraVolumes }} + {{ toYaml .Values.controller.extraVolumes | nindent 8 }} + {{- end }} + {{- end }} +{{- end }} diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-daemonset.yaml.orig b/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-daemonset.yaml.orig new file mode 100644 index 00000000..3aaa9250 --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-daemonset.yaml.orig @@ -0,0 +1,243 @@ +{{- if eq .Values.controller.kind "DaemonSet" -}} +{{- include "isControllerTagValid" . -}} +apiVersion: apps/v1 +kind: DaemonSet +metadata: + labels: + {{- include "ingress-nginx.labels" . | nindent 4 }} + app.kubernetes.io/component: controller + {{- with .Values.controller.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + name: {{ include "ingress-nginx.controller.fullname" . }} + namespace: {{ include "ingress-nginx.namespace" . }} + {{- if .Values.controller.annotations }} + annotations: {{ toYaml .Values.controller.annotations | nindent 4 }} + {{- end }} +spec: + selector: + matchLabels: + {{- include "ingress-nginx.selectorLabels" . | nindent 6 }} + app.kubernetes.io/component: controller + revisionHistoryLimit: {{ .Values.revisionHistoryLimit }} + {{- if .Values.controller.updateStrategy }} + updateStrategy: {{ toYaml .Values.controller.updateStrategy | nindent 4 }} + {{- end }} + minReadySeconds: {{ .Values.controller.minReadySeconds }} + template: + metadata: + {{- if .Values.controller.podAnnotations }} + annotations: + {{- range $key, $value := .Values.controller.podAnnotations }} + {{ $key }}: {{ $value | quote }} + {{- end }} + {{- end }} + labels: + {{- include "ingress-nginx.labels" . | nindent 8 }} + app.kubernetes.io/component: controller + {{- with .Values.controller.labels }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if .Values.controller.podLabels }} + {{- toYaml .Values.controller.podLabels | nindent 8 }} + {{- end }} + spec: + {{- if .Values.controller.dnsConfig }} + dnsConfig: {{ toYaml .Values.controller.dnsConfig | nindent 8 }} + {{- end }} + {{- if .Values.controller.hostAliases }} + hostAliases: {{ tpl (toYaml .Values.controller.hostAliases) $ | nindent 8 }} + {{- end }} + {{- if .Values.controller.hostname }} + hostname: {{ toYaml .Values.controller.hostname | nindent 8 }} + {{- end }} + dnsPolicy: {{ .Values.controller.dnsPolicy }} + {{- if .Values.imagePullSecrets }} + imagePullSecrets: {{ toYaml .Values.imagePullSecrets | nindent 8 }} + {{- end }} + {{- if .Values.controller.priorityClassName }} + priorityClassName: {{ .Values.controller.priorityClassName | quote }} + {{- end }} + {{- if or .Values.controller.podSecurityContext .Values.controller.sysctls }} + securityContext: + {{- if .Values.controller.podSecurityContext }} + {{- toYaml .Values.controller.podSecurityContext | nindent 8 }} + {{- end }} + {{- if .Values.controller.sysctls }} + sysctls: + {{- range $sysctl, $value := .Values.controller.sysctls }} + - name: {{ $sysctl | quote }} + value: {{ $value | quote }} + {{- end }} + {{- end }} + {{- end }} + {{- if .Values.controller.shareProcessNamespace }} + shareProcessNamespace: {{ .Values.controller.shareProcessNamespace }} + {{- end }} + containers: + - name: {{ .Values.controller.containerName }} + {{- with .Values.controller.image }} + image: "{{- if .repository -}}{{ .repository }}{{ else }}{{ .registry }}/{{ include "ingress-nginx.image" . }}{{- end -}}:{{ .tag }}{{ include "ingress-nginx.imageDigest" . }}" + {{- end }} + imagePullPolicy: {{ .Values.controller.image.pullPolicy }} + {{- if .Values.controller.lifecycle }} + lifecycle: {{ toYaml .Values.controller.lifecycle | nindent 12 }} + {{- end }} + args: {{ include "ingress-nginx.params" . | nindent 12 }} + securityContext: {{ include "ingress-nginx.controller.containerSecurityContext" . | nindent 12 }} + env: + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + {{- if .Values.controller.enableMimalloc }} + - name: LD_PRELOAD + value: /usr/local/lib/libmimalloc.so + {{- end }} + {{- if .Values.controller.extraEnvs }} + {{- toYaml .Values.controller.extraEnvs | nindent 12 }} + {{- end }} + {{- if .Values.controller.startupProbe }} + startupProbe: {{ toYaml .Values.controller.startupProbe | nindent 12 }} + {{- end }} + {{- if .Values.controller.livenessProbe }} + livenessProbe: {{ toYaml .Values.controller.livenessProbe | nindent 12 }} + {{- end }} + {{- if .Values.controller.readinessProbe }} + readinessProbe: {{ toYaml .Values.controller.readinessProbe | nindent 12 }} + {{- end }} + ports: + {{- range $key, $value := .Values.controller.containerPort }} + - name: {{ $key }} + containerPort: {{ $value }} + protocol: TCP + {{- if $.Values.controller.hostPort.enabled }} + hostPort: {{ index $.Values.controller.hostPort.ports $key | default $value }} + {{- end }} + {{- end }} + {{- if .Values.controller.metrics.enabled }} + - name: {{ .Values.controller.metrics.portName }} + containerPort: {{ .Values.controller.metrics.port }} + protocol: TCP + {{- end }} + {{- if .Values.controller.admissionWebhooks.enabled }} + - name: webhook + containerPort: {{ .Values.controller.admissionWebhooks.port }} + protocol: TCP + {{- end }} + {{- range $key, $value := .Values.tcp }} + - name: {{ if $.Values.portNamePrefix }}{{ $.Values.portNamePrefix }}-{{ end }}{{ $key }}-tcp + containerPort: {{ $key }} + protocol: TCP + {{- if $.Values.controller.hostPort.enabled }} + hostPort: {{ $key }} + {{- end }} + {{- end }} + {{- range $key, $value := .Values.udp }} + - name: {{ if $.Values.portNamePrefix }}{{ $.Values.portNamePrefix }}-{{ end }}{{ $key }}-udp + containerPort: {{ $key }} + protocol: UDP + {{- if $.Values.controller.hostPort.enabled }} + hostPort: {{ $key }} + {{- end }} + {{- end }} + {{- if (or .Values.controller.customTemplate.configMapName .Values.controller.extraVolumeMounts .Values.controller.admissionWebhooks.enabled .Values.controller.extraModules .Values.controller.opentelemetry.enabled) }} + volumeMounts: + {{- if (or .Values.controller.extraModules .Values.controller.opentelemetry.enabled) }} + - name: modules + {{- if .Values.controller.image.chroot }} + mountPath: /chroot/modules_mount + {{- else }} + mountPath: /modules_mount + {{- end }} + {{- end }} + {{- if .Values.controller.customTemplate.configMapName }} + - mountPath: /etc/nginx/template + name: nginx-template-volume + readOnly: true + {{- end }} + {{- if .Values.controller.admissionWebhooks.enabled }} + - name: webhook-cert + mountPath: /usr/local/certificates/ + readOnly: true + {{- end }} + {{- if .Values.controller.extraVolumeMounts }} + {{- toYaml .Values.controller.extraVolumeMounts | nindent 12 }} + {{- end }} + {{- end }} + {{- if .Values.controller.resources }} + resources: {{ toYaml .Values.controller.resources | nindent 12 }} + {{- end }} + {{- if .Values.controller.extraContainers }} + {{- toYaml .Values.controller.extraContainers | nindent 8 }} + {{- end }} + {{- if (or .Values.controller.extraInitContainers .Values.controller.extraModules .Values.controller.opentelemetry.enabled) }} + initContainers: + {{- if .Values.controller.extraInitContainers }} + {{- toYaml .Values.controller.extraInitContainers | nindent 8 }} + {{- end }} + {{- if .Values.controller.extraModules }} + {{- range .Values.controller.extraModules }} + {{- $containerSecurityContext := .containerSecurityContext | default $.Values.controller.containerSecurityContext }} + {{- include "extraModules" (dict "name" .name "image" .image "distroless" .distroless "containerSecurityContext" $containerSecurityContext "resources" .resources) | nindent 8 }} + {{- end }} + {{- end }} + {{- if .Values.controller.opentelemetry.enabled }} + {{- with .Values.controller.opentelemetry }} + {{- $containerSecurityContext := .containerSecurityContext | default $.Values.controller.containerSecurityContext }} + {{- include "extraModules" (dict "name" .name "image" .image "distroless" .distroless "containerSecurityContext" $containerSecurityContext "resources" .resources) | nindent 8 }} + {{- end }} + {{- end }} + {{- end }} + {{- if .Values.controller.hostNetwork }} + hostNetwork: {{ .Values.controller.hostNetwork }} + {{- end }} + {{- if .Values.controller.nodeSelector }} + nodeSelector: {{ toYaml .Values.controller.nodeSelector | nindent 8 }} + {{- end }} + {{- if .Values.controller.tolerations }} + tolerations: {{ toYaml .Values.controller.tolerations | nindent 8 }} + {{- end }} + {{- if .Values.controller.affinity }} + affinity: {{ toYaml .Values.controller.affinity | nindent 8 }} + {{- end }} + {{- if .Values.controller.topologySpreadConstraints }} + topologySpreadConstraints: {{ tpl (toYaml .Values.controller.topologySpreadConstraints) $ | nindent 8 }} + {{- end }} + serviceAccountName: {{ template "ingress-nginx.serviceAccountName" . }} + terminationGracePeriodSeconds: {{ .Values.controller.terminationGracePeriodSeconds }} + {{- if (or .Values.controller.customTemplate.configMapName .Values.controller.extraVolumeMounts .Values.controller.admissionWebhooks.enabled .Values.controller.extraVolumes .Values.controller.extraModules .Values.controller.opentelemetry.enabled) }} + volumes: + {{- if (or .Values.controller.extraModules .Values.controller.opentelemetry.enabled)}} + - name: modules + emptyDir: {} + {{- end }} + {{- if .Values.controller.customTemplate.configMapName }} + - name: nginx-template-volume + configMap: + name: {{ .Values.controller.customTemplate.configMapName }} + items: + - key: {{ .Values.controller.customTemplate.configMapKey }} + path: nginx.tmpl + {{- end }} + {{- if .Values.controller.admissionWebhooks.enabled }} + - name: webhook-cert + secret: + secretName: {{ include "ingress-nginx.admissionWebhooks.fullname" . }} + {{- if .Values.controller.admissionWebhooks.certManager.enabled }} + items: + - key: tls.crt + path: cert + - key: tls.key + path: key + {{- end }} + {{- end }} + {{- if .Values.controller.extraVolumes }} + {{ toYaml .Values.controller.extraVolumes | nindent 8 }} + {{- end }} + {{- end }} +{{- end }} diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-deployment.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-deployment.yaml new file mode 100644 index 00000000..b504faec --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-deployment.yaml @@ -0,0 +1,249 @@ +{{- if eq .Values.controller.kind "Deployment" -}} +{{- include "isControllerTagValid" . -}} +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + {{- include "ingress-nginx.labels" . | nindent 4 }} + app.kubernetes.io/component: controller + {{- with .Values.controller.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + name: {{ include "ingress-nginx.controller.fullname" . }} + namespace: {{ include "ingress-nginx.namespace" . }} + {{- if .Values.controller.annotations }} + annotations: {{ toYaml .Values.controller.annotations | nindent 4 }} + {{- end }} +spec: + selector: + matchLabels: + {{- include "ingress-nginx.selectorLabels" . | nindent 6 }} + app.kubernetes.io/component: controller + {{- if not (or .Values.controller.autoscaling.enabled .Values.controller.keda.enabled) }} + replicas: {{ .Values.controller.replicaCount }} + {{- end }} + revisionHistoryLimit: {{ .Values.revisionHistoryLimit }} + {{- if .Values.controller.updateStrategy }} + strategy: {{ toYaml .Values.controller.updateStrategy | nindent 4 }} + {{- end }} + minReadySeconds: {{ .Values.controller.minReadySeconds }} + template: + metadata: + {{- if .Values.controller.podAnnotations }} + annotations: + {{- range $key, $value := .Values.controller.podAnnotations }} + {{ $key }}: {{ $value | quote }} + {{- end }} + {{- end }} + labels: + {{- include "ingress-nginx.labels" . | nindent 8 }} + app.kubernetes.io/component: controller + {{- with .Values.controller.labels }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if .Values.controller.podLabels }} + {{- toYaml .Values.controller.podLabels | nindent 8 }} + {{- end }} + spec: + {{- if .Values.controller.dnsConfig }} + dnsConfig: {{ toYaml .Values.controller.dnsConfig | nindent 8 }} + {{- end }} + {{- if .Values.controller.hostAliases }} + hostAliases: {{ tpl (toYaml .Values.controller.hostAliases) $ | nindent 8 }} + {{- end }} + {{- if .Values.controller.hostname }} + hostname: {{ toYaml .Values.controller.hostname | nindent 8 }} + {{- end }} + dnsPolicy: {{ .Values.controller.dnsPolicy }} + {{- if .Values.imagePullSecrets }} + imagePullSecrets: {{ toYaml .Values.imagePullSecrets | nindent 8 }} + {{- end }} + {{- if .Values.controller.priorityClassName }} + priorityClassName: {{ .Values.controller.priorityClassName | quote }} + {{- end }} + {{- if or .Values.controller.podSecurityContext .Values.controller.sysctls }} + securityContext: + {{- if .Values.controller.podSecurityContext }} + {{- toYaml .Values.controller.podSecurityContext | nindent 8 }} + {{- end }} + {{- if .Values.controller.sysctls }} + sysctls: + {{- range $sysctl, $value := .Values.controller.sysctls }} + - name: {{ $sysctl | quote }} + value: {{ $value | quote }} + {{- end }} + {{- end }} + {{- end }} + {{- if .Values.controller.shareProcessNamespace }} + shareProcessNamespace: {{ .Values.controller.shareProcessNamespace }} + {{- end }} + containers: + - name: {{ .Values.controller.containerName }} + {{- with .Values.controller.image }} + image: "{{- if .repository -}}{{ .repository }}{{ else }}{{ .registry }}/{{ include "ingress-nginx.image" . }}{{- end -}}:{{ .tag }}{{ include "ingress-nginx.imageDigest" . }}" + {{- end }} + imagePullPolicy: {{ .Values.controller.image.pullPolicy }} + {{- if .Values.controller.lifecycle }} + lifecycle: {{ toYaml .Values.controller.lifecycle | nindent 12 }} + {{- end }} + args: {{ include "ingress-nginx.params" . | nindent 12 }} + securityContext: {{ include "ingress-nginx.controller.containerSecurityContext" . | nindent 12 }} + env: + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + {{- if .Values.controller.enableMimalloc }} + - name: LD_PRELOAD + value: /usr/local/lib/libmimalloc.so + {{- end }} + {{- if .Values.controller.extraEnvs }} + {{- toYaml .Values.controller.extraEnvs | nindent 12 }} + {{- end }} + {{- if .Values.controller.startupProbe }} + startupProbe: {{ toYaml .Values.controller.startupProbe | nindent 12 }} + {{- end }} + {{- if .Values.controller.livenessProbe }} + livenessProbe: {{ toYaml .Values.controller.livenessProbe | nindent 12 }} + {{- end }} + {{- if .Values.controller.readinessProbe }} + readinessProbe: {{ toYaml .Values.controller.readinessProbe | nindent 12 }} + {{- end }} + ports: + {{- range $key, $value := .Values.controller.containerPort }} + - name: {{ $key }} + containerPort: {{ $value }} + protocol: TCP + {{- if $.Values.controller.hostPort.enabled }} + hostPort: {{ index $.Values.controller.hostPort.ports $key | default $value }} + {{- end }} + {{- end }} + {{- if .Values.controller.metrics.enabled }} + - name: {{ .Values.controller.metrics.portName }} + containerPort: {{ .Values.controller.metrics.port }} + protocol: TCP + - name: metrics2 + containerPort: 9091 + protocol: TCP + {{- end }} + {{- if .Values.controller.admissionWebhooks.enabled }} + - name: webhook + containerPort: {{ .Values.controller.admissionWebhooks.port }} + protocol: TCP + {{- end }} + {{- range $key, $value := .Values.tcp }} + - name: {{ if $.Values.portNamePrefix }}{{ $.Values.portNamePrefix }}-{{ end }}{{ $key }}-tcp + containerPort: {{ $key }} + protocol: TCP + {{- if $.Values.controller.hostPort.enabled }} + hostPort: {{ $key }} + {{- end }} + {{- end }} + {{- range $key, $value := .Values.udp }} + - name: {{ if $.Values.portNamePrefix }}{{ $.Values.portNamePrefix }}-{{ end }}{{ $key }}-udp + containerPort: {{ $key }} + protocol: UDP + {{- if $.Values.controller.hostPort.enabled }} + hostPort: {{ $key }} + {{- end }} + {{- end }} + {{- if (or .Values.controller.customTemplate.configMapName .Values.controller.extraVolumeMounts .Values.controller.admissionWebhooks.enabled .Values.controller.extraModules .Values.controller.opentelemetry.enabled) }} + volumeMounts: + {{- if (or .Values.controller.extraModules .Values.controller.opentelemetry.enabled) }} + - name: modules + {{- if .Values.controller.image.chroot }} + mountPath: /chroot/modules_mount + {{- else }} + mountPath: /modules_mount + {{- end }} + {{- end }} + {{- if .Values.controller.customTemplate.configMapName }} + - mountPath: /etc/nginx/template + name: nginx-template-volume + readOnly: true + {{- end }} + {{- if .Values.controller.admissionWebhooks.enabled }} + - name: webhook-cert + mountPath: /usr/local/certificates/ + readOnly: true + {{- end }} + {{- if .Values.controller.extraVolumeMounts }} + {{- toYaml .Values.controller.extraVolumeMounts | nindent 12 }} + {{- end }} + {{- end }} + {{- if .Values.controller.resources }} + resources: {{ toYaml .Values.controller.resources | nindent 12 }} + {{- end }} + {{- if .Values.controller.extraContainers }} + {{- toYaml .Values.controller.extraContainers | nindent 8 }} + {{- end }} + {{- if (or .Values.controller.extraInitContainers .Values.controller.extraModules .Values.controller.opentelemetry.enabled) }} + initContainers: + {{- if .Values.controller.extraInitContainers }} + {{- toYaml .Values.controller.extraInitContainers | nindent 8 }} + {{- end }} + {{- if .Values.controller.extraModules }} + {{- range .Values.controller.extraModules }} + {{- $containerSecurityContext := .containerSecurityContext | default $.Values.controller.containerSecurityContext }} + {{- include "extraModules" (dict "name" .name "image" .image "distroless" .distroless "containerSecurityContext" $containerSecurityContext "resources" .resources) | nindent 8 }} + {{- end }} + {{- end }} + {{- if .Values.controller.opentelemetry.enabled }} + {{- with .Values.controller.opentelemetry }} + {{- $containerSecurityContext := .containerSecurityContext | default $.Values.controller.containerSecurityContext }} + {{- include "extraModules" (dict "name" .name "image" .image "distroless" .distroless "containerSecurityContext" $containerSecurityContext "resources" .resources) | nindent 8 }} + {{- end }} + {{- end }} + {{- end }} + {{- if .Values.controller.hostNetwork }} + hostNetwork: {{ .Values.controller.hostNetwork }} + {{- end }} + {{- if .Values.controller.nodeSelector }} + nodeSelector: {{ toYaml .Values.controller.nodeSelector | nindent 8 }} + {{- end }} + {{- if .Values.controller.tolerations }} + tolerations: {{ toYaml .Values.controller.tolerations | nindent 8 }} + {{- end }} + {{- if .Values.controller.affinity }} + affinity: {{ toYaml .Values.controller.affinity | nindent 8 }} + {{- end }} + {{- if .Values.controller.topologySpreadConstraints }} + topologySpreadConstraints: {{ tpl (toYaml .Values.controller.topologySpreadConstraints) $ | nindent 8 }} + {{- end }} + serviceAccountName: {{ template "ingress-nginx.serviceAccountName" . }} + terminationGracePeriodSeconds: {{ .Values.controller.terminationGracePeriodSeconds }} + {{- if (or .Values.controller.customTemplate.configMapName .Values.controller.extraVolumeMounts .Values.controller.admissionWebhooks.enabled .Values.controller.extraVolumes .Values.controller.extraModules .Values.controller.opentelemetry.enabled) }} + volumes: + {{- if (or .Values.controller.extraModules .Values.controller.opentelemetry.enabled)}} + - name: modules + emptyDir: {} + {{- end }} + {{- if .Values.controller.customTemplate.configMapName }} + - name: nginx-template-volume + configMap: + name: {{ .Values.controller.customTemplate.configMapName }} + items: + - key: {{ .Values.controller.customTemplate.configMapKey }} + path: nginx.tmpl + {{- end }} + {{- if .Values.controller.admissionWebhooks.enabled }} + - name: webhook-cert + secret: + secretName: {{ include "ingress-nginx.admissionWebhooks.fullname" . }} + {{- if .Values.controller.admissionWebhooks.certManager.enabled }} + items: + - key: tls.crt + path: cert + - key: tls.key + path: key + {{- end }} + {{- end }} + {{- if .Values.controller.extraVolumes }} + {{ toYaml .Values.controller.extraVolumes | nindent 8 }} + {{- end }} + {{- end }} +{{- end }} diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-hpa.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-hpa.yaml new file mode 100644 index 00000000..ec9ad738 --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-hpa.yaml @@ -0,0 +1,47 @@ +{{- if and (eq .Values.controller.kind "Deployment") .Values.controller.autoscaling.enabled (not .Values.controller.keda.enabled) -}} +apiVersion: {{ ternary "autoscaling/v2" "autoscaling/v2beta2" (.Capabilities.APIVersions.Has "autoscaling/v2") }} +kind: HorizontalPodAutoscaler +metadata: + {{- with .Values.controller.autoscaling.annotations }} + annotations: {{ toYaml . | nindent 4 }} + {{- end }} + labels: + {{- include "ingress-nginx.labels" . | nindent 4 }} + app.kubernetes.io/component: controller + {{- with .Values.controller.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + name: {{ include "ingress-nginx.controller.fullname" . }} + namespace: {{ include "ingress-nginx.namespace" . }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ include "ingress-nginx.controller.fullname" . }} + minReplicas: {{ .Values.controller.autoscaling.minReplicas }} + maxReplicas: {{ .Values.controller.autoscaling.maxReplicas }} + metrics: + {{- with .Values.controller.autoscaling.targetMemoryUtilizationPercentage }} + - type: Resource + resource: + name: memory + target: + type: Utilization + averageUtilization: {{ . }} + {{- end }} + {{- with .Values.controller.autoscaling.targetCPUUtilizationPercentage }} + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: {{ . }} + {{- end }} + {{- with .Values.controller.autoscalingTemplate }} + {{- toYaml . | nindent 2 }} + {{- end }} + {{- with .Values.controller.autoscaling.behavior }} + behavior: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-ingressclass.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-ingressclass.yaml new file mode 100644 index 00000000..9492784a --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-ingressclass.yaml @@ -0,0 +1,21 @@ +{{- if .Values.controller.ingressClassResource.enabled -}} +# We don't support namespaced ingressClass yet +# So a ClusterRole and a ClusterRoleBinding is required +apiVersion: networking.k8s.io/v1 +kind: IngressClass +metadata: + labels: + {{- include "ingress-nginx.labels" . | nindent 4 }} + app.kubernetes.io/component: controller + {{- with .Values.controller.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + name: {{ .Values.controller.ingressClassResource.name }} +{{- if .Values.controller.ingressClassResource.default }} + annotations: + ingressclass.kubernetes.io/is-default-class: "true" +{{- end }} +spec: + controller: {{ .Values.controller.ingressClassResource.controllerValue }} + {{ template "ingressClass.parameters" . }} +{{- end }} diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-keda.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-keda.yaml new file mode 100644 index 00000000..6ff9c0b2 --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-keda.yaml @@ -0,0 +1,46 @@ +{{- if and .Values.controller.keda.enabled (eq .Values.controller.kind "Deployment") -}} +apiVersion: {{ .Values.controller.keda.apiVersion }} +kind: ScaledObject +metadata: + labels: + {{- include "ingress-nginx.labels" . | nindent 4 }} + app.kubernetes.io/component: controller + {{- with .Values.controller.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + name: {{ include "ingress-nginx.controller.fullname" . }} + namespace: {{ include "ingress-nginx.namespace" . }} + {{- if .Values.controller.keda.scaledObject.annotations }} + annotations: {{ toYaml .Values.controller.keda.scaledObject.annotations | nindent 4 }} + {{- end }} +spec: + scaleTargetRef: +{{- if eq .Values.controller.keda.apiVersion "keda.k8s.io/v1alpha1" }} + deploymentName: {{ include "ingress-nginx.controller.fullname" . }} +{{- else if eq .Values.controller.keda.apiVersion "keda.sh/v1alpha1" }} + name: {{ include "ingress-nginx.controller.fullname" . }} +{{- end }} + pollingInterval: {{ .Values.controller.keda.pollingInterval }} + cooldownPeriod: {{ .Values.controller.keda.cooldownPeriod }} + minReplicaCount: {{ .Values.controller.keda.minReplicas }} + maxReplicaCount: {{ .Values.controller.keda.maxReplicas }} +{{- with .Values.controller.keda.fallback }} + fallback: + failureThreshold: {{ .failureThreshold | default 3 }} + replicas: {{ .replicas | default $.Values.controller.keda.maxReplicas }} +{{- end }} + triggers: +{{- with .Values.controller.keda.triggers }} +{{ toYaml . | indent 2 }} +{{ end }} + advanced: + restoreToOriginalReplicaCount: {{ .Values.controller.keda.restoreToOriginalReplicaCount }} +{{- if .Values.controller.keda.behavior }} + horizontalPodAutoscalerConfig: + behavior: +{{ with .Values.controller.keda.behavior -}} +{{ toYaml . | indent 8 }} +{{ end }} + +{{- end }} +{{- end }} diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-networkpolicy.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-networkpolicy.yaml new file mode 100644 index 00000000..e68f9916 --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-networkpolicy.yaml @@ -0,0 +1,45 @@ +{{- if .Values.controller.networkPolicy.enabled }} +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + labels: + {{- include "ingress-nginx.labels" . | nindent 4 }} + app.kubernetes.io/component: controller + {{- with .Values.controller.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + name: {{ include "ingress-nginx.controller.fullname" . }} + namespace: {{ include "ingress-nginx.namespace" . }} +spec: + podSelector: + matchLabels: + {{- include "ingress-nginx.selectorLabels" . | nindent 6 }} + app.kubernetes.io/component: controller + policyTypes: + - Ingress + - Egress + ingress: + - ports: + {{- range $key, $value := .Values.controller.containerPort }} + - protocol: TCP + port: {{ $value }} + {{- end }} + {{- if .Values.controller.metrics.enabled }} + - protocol: TCP + port: {{ .Values.controller.metrics.port }} + {{- end }} + {{- if .Values.controller.admissionWebhooks.enabled }} + - protocol: TCP + port: {{ .Values.controller.admissionWebhooks.port }} + {{- end }} + {{- range $key, $value := .Values.tcp }} + - protocol: TCP + port: {{ $key }} + {{- end }} + {{- range $key, $value := .Values.udp }} + - protocol: UDP + port: {{ $key }} + {{- end }} + egress: + - {} +{{- end }} diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-poddisruptionbudget.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-poddisruptionbudget.yaml new file mode 100644 index 00000000..8cb7d4b9 --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-poddisruptionbudget.yaml @@ -0,0 +1,26 @@ +{{- if or (and .Values.controller.autoscaling.enabled (gt (.Values.controller.autoscaling.minReplicas | int) 1)) (and (not .Values.controller.autoscaling.enabled) (gt (.Values.controller.replicaCount | int) 1)) }} +apiVersion: {{ ternary "policy/v1" "policy/v1beta1" (semverCompare ">=1.21.0-0" .Capabilities.KubeVersion.Version) }} +kind: PodDisruptionBudget +metadata: + labels: + {{- include "ingress-nginx.labels" . | nindent 4 }} + app.kubernetes.io/component: controller + {{- with .Values.controller.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + name: {{ include "ingress-nginx.controller.fullname" . }} + namespace: {{ include "ingress-nginx.namespace" . }} + {{- if .Values.controller.annotations }} + annotations: {{ toYaml .Values.controller.annotations | nindent 4 }} + {{- end }} +spec: + selector: + matchLabels: + {{- include "ingress-nginx.selectorLabels" . | nindent 6 }} + app.kubernetes.io/component: controller + {{- if and .Values.controller.minAvailable (not (hasKey .Values.controller "maxUnavailable")) }} + minAvailable: {{ .Values.controller.minAvailable }} + {{- else if .Values.controller.maxUnavailable }} + maxUnavailable: {{ .Values.controller.maxUnavailable }} + {{- end }} +{{- end }} diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-prometheusrules.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-prometheusrules.yaml new file mode 100644 index 00000000..f0b93cc8 --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-prometheusrules.yaml @@ -0,0 +1,23 @@ +{{- if and ( .Values.controller.metrics.enabled ) ( .Values.controller.metrics.prometheusRule.enabled ) ( .Capabilities.APIVersions.Has "monitoring.coreos.com/v1" ) -}} +apiVersion: monitoring.coreos.com/v1 +kind: PrometheusRule +metadata: + name: {{ include "ingress-nginx.controller.fullname" . }} +{{- if .Values.controller.metrics.prometheusRule.namespace }} + namespace: {{ .Values.controller.metrics.prometheusRule.namespace }} +{{- else }} + namespace: {{ include "ingress-nginx.namespace" . }} +{{- end }} + labels: + {{- include "ingress-nginx.labels" . | nindent 4 }} + app.kubernetes.io/component: controller + {{- if .Values.controller.metrics.prometheusRule.additionalLabels }} + {{- toYaml .Values.controller.metrics.prometheusRule.additionalLabels | nindent 4 }} + {{- end }} +spec: +{{- if .Values.controller.metrics.prometheusRule.rules }} + groups: + - name: {{ template "ingress-nginx.name" . }} + rules: {{- toYaml .Values.controller.metrics.prometheusRule.rules | nindent 4 }} +{{- end }} +{{- end }} diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-psp.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-psp.yaml new file mode 100644 index 00000000..aad1d273 --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-psp.yaml @@ -0,0 +1,100 @@ +{{- if (semverCompare "<1.25.0-0" .Capabilities.KubeVersion.Version) }} +{{- if and .Values.podSecurityPolicy.enabled (empty .Values.controller.existingPsp) -}} +apiVersion: policy/v1beta1 +kind: PodSecurityPolicy +metadata: + name: {{ include "ingress-nginx.fullname" . }} + annotations: + seccomp.security.alpha.kubernetes.io/allowedProfileNames: "*" + labels: + {{- include "ingress-nginx.labels" . | nindent 4 }} + app.kubernetes.io/component: controller + {{- with .Values.controller.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + privileged: false + hostPID: false + hostIPC: false + hostNetwork: {{ .Values.controller.hostNetwork }} +{{- if or .Values.controller.hostNetwork .Values.controller.hostPort.enabled }} + hostPorts: + {{- if .Values.controller.hostNetwork }} + {{- range $key, $value := .Values.controller.containerPort }} + # controller.containerPort.{{ $key }} + - min: {{ $value }} + max: {{ $value }} + {{- end }} + {{- else if .Values.controller.hostPort.enabled }} + {{- range $key, $value := .Values.controller.hostPort.ports }} + # controller.hostPort.ports.{{ $key }} + - min: {{ $value }} + max: {{ $value }} + {{- end }} + {{- end }} + {{- if .Values.controller.metrics.enabled }} + # controller.metrics.port + - min: {{ .Values.controller.metrics.port }} + max: {{ .Values.controller.metrics.port }} + {{- end }} + {{- if .Values.controller.admissionWebhooks.enabled }} + # controller.admissionWebhooks.port + - min: {{ .Values.controller.admissionWebhooks.port }} + max: {{ .Values.controller.admissionWebhooks.port }} + {{- end }} + {{- range $key, $value := .Values.tcp }} + # tcp.{{ $key }} + - min: {{ $key }} + max: {{ $key }} + {{- end }} + {{- range $key, $value := .Values.udp }} + # udp.{{ $key }} + - min: {{ $key }} + max: {{ $key }} + {{- end }} +{{- end }} + volumes: + - configMap + - downwardAPI + - emptyDir + - secret + - projected + fsGroup: + rule: MustRunAs + ranges: + - min: 1 + max: 65535 + readOnlyRootFilesystem: false + runAsUser: + rule: MustRunAsNonRoot + runAsGroup: + rule: MustRunAs + ranges: + - min: 1 + max: 65535 + supplementalGroups: + rule: MustRunAs + ranges: + - min: 1 + max: 65535 + allowPrivilegeEscalation: {{ or .Values.controller.image.allowPrivilegeEscalation .Values.controller.image.chroot }} + requiredDropCapabilities: + - ALL + allowedCapabilities: + - NET_BIND_SERVICE + {{- if .Values.controller.image.chroot }} + {{- if .Values.controller.image.seccompProfile }} + - SYS_ADMIN + {{- end }} + - SYS_CHROOT + {{- end }} + seLinux: + rule: RunAsAny +{{- if .Values.controller.sysctls }} + allowedUnsafeSysctls: + {{- range $sysctl, $value := .Values.controller.sysctls }} + - {{ $sysctl }} + {{- end }} +{{- end }} +{{- end }} +{{- end }} diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-role.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-role.yaml new file mode 100644 index 00000000..f6217a29 --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-role.yaml @@ -0,0 +1,101 @@ +{{- if .Values.rbac.create -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + labels: + {{- include "ingress-nginx.labels" . | nindent 4 }} + app.kubernetes.io/component: controller + {{- with .Values.controller.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + name: {{ include "ingress-nginx.fullname" . }} + namespace: {{ include "ingress-nginx.namespace" . }} +rules: + - apiGroups: + - "" + resources: + - namespaces + verbs: + - get + - apiGroups: + - "" + resources: + - configmaps + - pods + - secrets + - endpoints + verbs: + - get + - list + - watch + - apiGroups: + - "" + resources: + - services + verbs: + - get + - list + - watch + - apiGroups: + - networking.k8s.io + resources: + - ingresses + verbs: + - get + - list + - watch + - apiGroups: + - networking.k8s.io + resources: + - ingresses/status + verbs: + - update + - apiGroups: + - networking.k8s.io + resources: + - ingressclasses + verbs: + - get + - list + - watch + - apiGroups: + - coordination.k8s.io + resources: + - leases + resourceNames: + - {{ include "ingress-nginx.controller.electionID" . }} + verbs: + - get + - update + - apiGroups: + - coordination.k8s.io + resources: + - leases + verbs: + - create + - apiGroups: + - "" + resources: + - events + verbs: + - create + - patch + - apiGroups: + - discovery.k8s.io + resources: + - endpointslices + verbs: + - list + - watch + - get +{{- if .Values.podSecurityPolicy.enabled }} + - apiGroups: [{{ template "podSecurityPolicy.apiGroup" . }}] + resources: ['podsecuritypolicies'] + verbs: ['use'] + {{- with .Values.controller.existingPsp }} + resourceNames: [{{ . }}] + {{- else }} + resourceNames: [{{ include "ingress-nginx.fullname" . }}] + {{- end }} +{{- end }} +{{- end }} diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-rolebinding.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-rolebinding.yaml new file mode 100644 index 00000000..153430aa --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-rolebinding.yaml @@ -0,0 +1,21 @@ +{{- if .Values.rbac.create -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + labels: + {{- include "ingress-nginx.labels" . | nindent 4 }} + app.kubernetes.io/component: controller + {{- with .Values.controller.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + name: {{ include "ingress-nginx.fullname" . }} + namespace: {{ include "ingress-nginx.namespace" . }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ include "ingress-nginx.fullname" . }} +subjects: + - kind: ServiceAccount + name: {{ template "ingress-nginx.serviceAccountName" . }} + namespace: {{ include "ingress-nginx.namespace" . }} +{{- end }} diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-secret.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-secret.yaml new file mode 100644 index 00000000..f20f5346 --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-secret.yaml @@ -0,0 +1,15 @@ +{{- if .Values.dhParam -}} +apiVersion: v1 +kind: Secret +metadata: + labels: + {{- include "ingress-nginx.labels" . | nindent 4 }} + app.kubernetes.io/component: controller + {{- with .Values.controller.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + name: {{ include "ingress-nginx.controller.fullname" . }} + namespace: {{ include "ingress-nginx.namespace" . }} +data: + dhparam.pem: {{ .Values.dhParam }} +{{- end }} diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-service-internal.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-service-internal.yaml new file mode 100644 index 00000000..b69a09f6 --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-service-internal.yaml @@ -0,0 +1,82 @@ +{{- if and .Values.controller.service.enabled .Values.controller.service.internal.enabled .Values.controller.service.internal.annotations}} +apiVersion: v1 +kind: Service +metadata: + annotations: + {{- range $key, $value := .Values.controller.service.internal.annotations }} + {{ $key }}: {{ tpl ($value | toString) $ | quote }} + {{- end }} + labels: + {{- include "ingress-nginx.labels" . | nindent 4 }} + app.kubernetes.io/component: controller + {{- if .Values.controller.service.labels }} + {{- toYaml .Values.controller.service.labels | nindent 4 }} + {{- end }} + name: {{ include "ingress-nginx.controller.fullname" . }}-internal + namespace: {{ include "ingress-nginx.namespace" . }} +spec: + type: "{{ .Values.controller.service.type }}" +{{- if hasKey .Values.controller.service.internal "allocateLoadBalancerNodePorts" }} + allocateLoadBalancerNodePorts: {{ .Values.controller.service.internal.allocateLoadBalancerNodePorts }} +{{- end }} +{{- if .Values.controller.service.internal.loadBalancerIP }} + loadBalancerIP: {{ .Values.controller.service.internal.loadBalancerIP }} +{{- end }} +{{- if .Values.controller.service.internal.loadBalancerSourceRanges }} + loadBalancerSourceRanges: {{ toYaml .Values.controller.service.internal.loadBalancerSourceRanges | nindent 4 }} +{{- end }} +{{- if .Values.controller.service.internal.externalTrafficPolicy }} + externalTrafficPolicy: {{ .Values.controller.service.internal.externalTrafficPolicy }} +{{- end }} + ports: + {{- $setNodePorts := (or (eq .Values.controller.service.type "NodePort") (eq .Values.controller.service.type "LoadBalancer")) }} + {{- if .Values.controller.service.enableHttp }} + - name: http + port: {{ .Values.controller.service.internal.ports.http | default .Values.controller.service.ports.http }} + protocol: TCP + targetPort: {{ .Values.controller.service.internal.targetPorts.http | default .Values.controller.service.targetPorts.http }} + {{- if semverCompare ">=1.20" .Capabilities.KubeVersion.Version }} + appProtocol: http + {{- end }} + {{- if (and $setNodePorts (not (empty .Values.controller.service.nodePorts.http))) }} + nodePort: {{ .Values.controller.service.nodePorts.http }} + {{- end }} + {{- end }} + {{- if .Values.controller.service.enableHttps }} + - name: https + port: {{ .Values.controller.service.internal.ports.https | default .Values.controller.service.ports.https }} + protocol: TCP + targetPort: {{ .Values.controller.service.internal.targetPorts.https | default .Values.controller.service.targetPorts.https }} + {{- if semverCompare ">=1.20" .Capabilities.KubeVersion.Version }} + appProtocol: https + {{- end }} + {{- if (and $setNodePorts (not (empty .Values.controller.service.nodePorts.https))) }} + nodePort: {{ .Values.controller.service.nodePorts.https }} + {{- end }} + {{- end }} + {{- range $key, $value := .Values.tcp }} + - name: {{ if $.Values.portNamePrefix }}{{ $.Values.portNamePrefix }}-{{ end }}{{ $key }}-tcp + port: {{ $key }} + protocol: TCP + targetPort: {{ if $.Values.portNamePrefix }}{{ $.Values.portNamePrefix }}-{{ end }}{{ $key }}-tcp + {{- if $.Values.controller.service.nodePorts.tcp }} + {{- if index $.Values.controller.service.nodePorts.tcp $key }} + nodePort: {{ index $.Values.controller.service.nodePorts.tcp $key }} + {{- end }} + {{- end }} + {{- end }} + {{- range $key, $value := .Values.udp }} + - name: {{ if $.Values.portNamePrefix }}{{ $.Values.portNamePrefix }}-{{ end }}{{ $key }}-udp + port: {{ $key }} + protocol: UDP + targetPort: {{ if $.Values.portNamePrefix }}{{ $.Values.portNamePrefix }}-{{ end }}{{ $key }}-udp + {{- if $.Values.controller.service.nodePorts.udp }} + {{- if index $.Values.controller.service.nodePorts.udp $key }} + nodePort: {{ index $.Values.controller.service.nodePorts.udp $key }} + {{- end }} + {{- end }} + {{- end }} + selector: + {{- include "ingress-nginx.selectorLabels" . | nindent 4 }} + app.kubernetes.io/component: controller +{{- end }} diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-service-metrics.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-service-metrics.yaml new file mode 100644 index 00000000..7c153295 --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-service-metrics.yaml @@ -0,0 +1,45 @@ +{{- if .Values.controller.metrics.enabled -}} +apiVersion: v1 +kind: Service +metadata: +{{- if .Values.controller.metrics.service.annotations }} + annotations: {{ toYaml .Values.controller.metrics.service.annotations | nindent 4 }} +{{- end }} + labels: + {{- include "ingress-nginx.labels" . | nindent 4 }} + app.kubernetes.io/component: controller + {{- if .Values.controller.metrics.service.labels }} + {{- toYaml .Values.controller.metrics.service.labels | nindent 4 }} + {{- end }} + name: {{ include "ingress-nginx.controller.fullname" . }}-metrics + namespace: {{ include "ingress-nginx.namespace" . }} +spec: + type: {{ .Values.controller.metrics.service.type }} +{{- if .Values.controller.metrics.service.clusterIP }} + clusterIP: {{ .Values.controller.metrics.service.clusterIP }} +{{- end }} +{{- if .Values.controller.metrics.service.externalIPs }} + externalIPs: {{ toYaml .Values.controller.metrics.service.externalIPs | nindent 4 }} +{{- end }} +{{- if .Values.controller.metrics.service.loadBalancerIP }} + loadBalancerIP: {{ .Values.controller.metrics.service.loadBalancerIP }} +{{- end }} +{{- if .Values.controller.metrics.service.loadBalancerSourceRanges }} + loadBalancerSourceRanges: {{ toYaml .Values.controller.metrics.service.loadBalancerSourceRanges | nindent 4 }} +{{- end }} +{{- if .Values.controller.metrics.service.externalTrafficPolicy }} + externalTrafficPolicy: {{ .Values.controller.metrics.service.externalTrafficPolicy }} +{{- end }} + ports: + - name: {{ .Values.controller.metrics.portName }} + port: {{ .Values.controller.metrics.service.servicePort }} + protocol: TCP + targetPort: {{ .Values.controller.metrics.portName }} + {{- $setNodePorts := (or (eq .Values.controller.metrics.service.type "NodePort") (eq .Values.controller.metrics.service.type "LoadBalancer")) }} + {{- if (and $setNodePorts (not (empty .Values.controller.metrics.service.nodePort))) }} + nodePort: {{ .Values.controller.metrics.service.nodePort }} + {{- end }} + selector: + {{- include "ingress-nginx.selectorLabels" . | nindent 4 }} + app.kubernetes.io/component: controller +{{- end }} diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-service-webhook.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-service-webhook.yaml new file mode 100644 index 00000000..2d02e23a --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-service-webhook.yaml @@ -0,0 +1,40 @@ +{{- if .Values.controller.admissionWebhooks.enabled -}} +apiVersion: v1 +kind: Service +metadata: +{{- if .Values.controller.admissionWebhooks.service.annotations }} + annotations: {{ toYaml .Values.controller.admissionWebhooks.service.annotations | nindent 4 }} +{{- end }} + labels: + {{- include "ingress-nginx.labels" . | nindent 4 }} + app.kubernetes.io/component: controller + {{- with .Values.controller.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + name: {{ include "ingress-nginx.controller.fullname" . }}-admission + namespace: {{ include "ingress-nginx.namespace" . }} +spec: + type: {{ .Values.controller.admissionWebhooks.service.type }} +{{- if .Values.controller.admissionWebhooks.service.clusterIP }} + clusterIP: {{ .Values.controller.admissionWebhooks.service.clusterIP }} +{{- end }} +{{- if .Values.controller.admissionWebhooks.service.externalIPs }} + externalIPs: {{ toYaml .Values.controller.admissionWebhooks.service.externalIPs | nindent 4 }} +{{- end }} +{{- if .Values.controller.admissionWebhooks.service.loadBalancerIP }} + loadBalancerIP: {{ .Values.controller.admissionWebhooks.service.loadBalancerIP }} +{{- end }} +{{- if .Values.controller.admissionWebhooks.service.loadBalancerSourceRanges }} + loadBalancerSourceRanges: {{ toYaml .Values.controller.admissionWebhooks.service.loadBalancerSourceRanges | nindent 4 }} +{{- end }} + ports: + - name: https-webhook + port: 443 + targetPort: webhook + {{- if semverCompare ">=1.20" .Capabilities.KubeVersion.Version }} + appProtocol: https + {{- end }} + selector: + {{- include "ingress-nginx.selectorLabels" . | nindent 4 }} + app.kubernetes.io/component: controller +{{- end }} diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-service.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-service.yaml new file mode 100644 index 00000000..d8163501 --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-service.yaml @@ -0,0 +1,107 @@ +{{- if and .Values.controller.service.enabled .Values.controller.service.external.enabled -}} +apiVersion: v1 +kind: Service +metadata: + annotations: + {{- range $key, $value := .Values.controller.service.annotations }} + {{ $key }}: {{ tpl ($value | toString) $ | quote }} + {{- end }} + labels: + {{- include "ingress-nginx.labels" . | nindent 4 }} + app.kubernetes.io/component: controller + {{- if .Values.controller.service.labels }} + {{- toYaml .Values.controller.service.labels | nindent 4 }} + {{- end }} + name: {{ include "ingress-nginx.controller.fullname" . }} + namespace: {{ include "ingress-nginx.namespace" . }} +spec: + type: {{ .Values.controller.service.type }} +{{- if hasKey .Values.controller.service "allocateLoadBalancerNodePorts" }} + allocateLoadBalancerNodePorts: {{ .Values.controller.service.allocateLoadBalancerNodePorts }} +{{- end }} +{{- if .Values.controller.service.clusterIP }} + clusterIP: {{ .Values.controller.service.clusterIP }} +{{- end }} +{{- if .Values.controller.service.externalIPs }} + externalIPs: {{ toYaml .Values.controller.service.externalIPs | nindent 4 }} +{{- end }} +{{- if .Values.controller.service.loadBalancerIP }} + loadBalancerIP: {{ .Values.controller.service.loadBalancerIP }} +{{- end }} +{{- if .Values.controller.service.loadBalancerSourceRanges }} + loadBalancerSourceRanges: {{ toYaml .Values.controller.service.loadBalancerSourceRanges | nindent 4 }} +{{- end }} +{{- if .Values.controller.service.loadBalancerClass }} + loadBalancerClass: {{ .Values.controller.service.loadBalancerClass }} +{{- end }} +{{- if .Values.controller.service.externalTrafficPolicy }} + externalTrafficPolicy: {{ .Values.controller.service.externalTrafficPolicy }} +{{- end }} +{{- if .Values.controller.service.sessionAffinity }} + sessionAffinity: {{ .Values.controller.service.sessionAffinity }} +{{- end }} +{{- if .Values.controller.service.healthCheckNodePort }} + healthCheckNodePort: {{ .Values.controller.service.healthCheckNodePort }} +{{- end }} +{{- if semverCompare ">=1.21.0-0" .Capabilities.KubeVersion.Version -}} +{{- if .Values.controller.service.ipFamilyPolicy }} + ipFamilyPolicy: {{ .Values.controller.service.ipFamilyPolicy }} +{{- end }} +{{- end }} +{{- if semverCompare ">=1.21.0-0" .Capabilities.KubeVersion.Version -}} +{{- if .Values.controller.service.ipFamilies }} + ipFamilies: {{ toYaml .Values.controller.service.ipFamilies | nindent 4 }} +{{- end }} +{{- end }} + ports: + {{- $setNodePorts := (or (eq .Values.controller.service.type "NodePort") (eq .Values.controller.service.type "LoadBalancer")) }} + {{- if .Values.controller.service.enableHttp }} + - name: http + port: {{ .Values.controller.service.ports.http }} + protocol: TCP + targetPort: {{ .Values.controller.service.targetPorts.http }} + {{- if and (semverCompare ">=1.20" .Capabilities.KubeVersion.Version) (.Values.controller.service.appProtocol) }} + appProtocol: http + {{- end }} + {{- if (and $setNodePorts (not (empty .Values.controller.service.nodePorts.http))) }} + nodePort: {{ .Values.controller.service.nodePorts.http }} + {{- end }} + {{- end }} + {{- if .Values.controller.service.enableHttps }} + - name: https + port: {{ .Values.controller.service.ports.https }} + protocol: TCP + targetPort: {{ .Values.controller.service.targetPorts.https }} + {{- if and (semverCompare ">=1.20" .Capabilities.KubeVersion.Version) (.Values.controller.service.appProtocol) }} + appProtocol: https + {{- end }} + {{- if (and $setNodePorts (not (empty .Values.controller.service.nodePorts.https))) }} + nodePort: {{ .Values.controller.service.nodePorts.https }} + {{- end }} + {{- end }} + {{- range $key, $value := .Values.tcp }} + - name: {{ if $.Values.portNamePrefix }}{{ $.Values.portNamePrefix }}-{{ end }}{{ $key }}-tcp + port: {{ $key }} + protocol: TCP + targetPort: {{ if $.Values.portNamePrefix }}{{ $.Values.portNamePrefix }}-{{ end }}{{ $key }}-tcp + {{- if $.Values.controller.service.nodePorts.tcp }} + {{- if index $.Values.controller.service.nodePorts.tcp $key }} + nodePort: {{ index $.Values.controller.service.nodePorts.tcp $key }} + {{- end }} + {{- end }} + {{- end }} + {{- range $key, $value := .Values.udp }} + - name: {{ if $.Values.portNamePrefix }}{{ $.Values.portNamePrefix }}-{{ end }}{{ $key }}-udp + port: {{ $key }} + protocol: UDP + targetPort: {{ if $.Values.portNamePrefix }}{{ $.Values.portNamePrefix }}-{{ end }}{{ $key }}-udp + {{- if $.Values.controller.service.nodePorts.udp }} + {{- if index $.Values.controller.service.nodePorts.udp $key }} + nodePort: {{ index $.Values.controller.service.nodePorts.udp $key }} + {{- end }} + {{- end }} + {{- end }} + selector: + {{- include "ingress-nginx.selectorLabels" . | nindent 4 }} + app.kubernetes.io/component: controller +{{- end }} diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-serviceaccount.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-serviceaccount.yaml new file mode 100644 index 00000000..df83de3d --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-serviceaccount.yaml @@ -0,0 +1,17 @@ +{{- if or .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + labels: + {{- include "ingress-nginx.labels" . | nindent 4 }} + app.kubernetes.io/component: controller + {{- with .Values.controller.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + name: {{ template "ingress-nginx.serviceAccountName" . }} + namespace: {{ include "ingress-nginx.namespace" . }} + {{- if .Values.serviceAccount.annotations }} + annotations: {{ toYaml .Values.serviceAccount.annotations | nindent 4 }} + {{- end }} +automountServiceAccountToken: {{ .Values.serviceAccount.automountServiceAccountToken }} +{{- end }} diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-servicemonitor.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-servicemonitor.yaml new file mode 100644 index 00000000..585fd0cb --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-servicemonitor.yaml @@ -0,0 +1,50 @@ +{{- if and .Values.controller.metrics.enabled .Values.controller.metrics.serviceMonitor.enabled -}} +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ include "ingress-nginx.controller.fullname" . }} +{{- if .Values.controller.metrics.serviceMonitor.namespace }} + namespace: {{ .Values.controller.metrics.serviceMonitor.namespace }} +{{- else }} + namespace: {{ include "ingress-nginx.namespace" . }} +{{- end }} + labels: + {{- include "ingress-nginx.labels" . | nindent 4 }} + app.kubernetes.io/component: controller + {{- if .Values.controller.metrics.serviceMonitor.additionalLabels }} + {{- toYaml .Values.controller.metrics.serviceMonitor.additionalLabels | nindent 4 }} + {{- end }} +spec: + endpoints: + - port: {{ .Values.controller.metrics.portName }} + interval: {{ .Values.controller.metrics.serviceMonitor.scrapeInterval }} + {{- if .Values.controller.metrics.serviceMonitor.honorLabels }} + honorLabels: true + {{- end }} + {{- if .Values.controller.metrics.serviceMonitor.relabelings }} + relabelings: {{ toYaml .Values.controller.metrics.serviceMonitor.relabelings | nindent 8 }} + {{- end }} + {{- if .Values.controller.metrics.serviceMonitor.metricRelabelings }} + metricRelabelings: {{ toYaml .Values.controller.metrics.serviceMonitor.metricRelabelings | nindent 8 }} + {{- end }} +{{- if .Values.controller.metrics.serviceMonitor.jobLabel }} + jobLabel: {{ .Values.controller.metrics.serviceMonitor.jobLabel | quote }} +{{- end }} +{{- if .Values.controller.metrics.serviceMonitor.namespaceSelector }} + namespaceSelector: {{ toYaml .Values.controller.metrics.serviceMonitor.namespaceSelector | nindent 4 }} +{{- else }} + namespaceSelector: + matchNames: + - {{ include "ingress-nginx.namespace" . }} +{{- end }} +{{- if .Values.controller.metrics.serviceMonitor.targetLabels }} + targetLabels: + {{- range .Values.controller.metrics.serviceMonitor.targetLabels }} + - {{ . }} + {{- end }} +{{- end }} + selector: + matchLabels: + {{- include "ingress-nginx.selectorLabels" . | nindent 6 }} + app.kubernetes.io/component: controller +{{- end }} diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/templates/default-backend-deployment.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/templates/default-backend-deployment.yaml new file mode 100644 index 00000000..ed88e6bc --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/templates/default-backend-deployment.yaml @@ -0,0 +1,116 @@ +{{- if .Values.defaultBackend.enabled -}} +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + {{- include "ingress-nginx.labels" . | nindent 4 }} + app.kubernetes.io/component: default-backend + {{- with .Values.defaultBackend.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + name: {{ include "ingress-nginx.defaultBackend.fullname" . }} + namespace: {{ include "ingress-nginx.namespace" . }} +spec: + selector: + matchLabels: + {{- include "ingress-nginx.selectorLabels" . | nindent 6 }} + app.kubernetes.io/component: default-backend +{{- if not .Values.defaultBackend.autoscaling.enabled }} + replicas: {{ .Values.defaultBackend.replicaCount }} +{{- end }} + revisionHistoryLimit: {{ .Values.revisionHistoryLimit }} + {{- if .Values.defaultBackend.updateStrategy }} + strategy: + {{ toYaml .Values.defaultBackend.updateStrategy | nindent 4 }} + {{- end }} + minReadySeconds: {{ .Values.defaultBackend.minReadySeconds }} + template: + metadata: + {{- if .Values.defaultBackend.podAnnotations }} + annotations: {{ toYaml .Values.defaultBackend.podAnnotations | nindent 8 }} + {{- end }} + labels: + {{- include "ingress-nginx.selectorLabels" . | nindent 8 }} + app.kubernetes.io/component: default-backend + {{- with .Values.defaultBackend.labels }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if .Values.defaultBackend.podLabels }} + {{- toYaml .Values.defaultBackend.podLabels | nindent 8 }} + {{- end }} + spec: + {{- if .Values.imagePullSecrets }} + imagePullSecrets: {{ toYaml .Values.imagePullSecrets | nindent 8 }} + {{- end }} + {{- if .Values.defaultBackend.priorityClassName }} + priorityClassName: {{ .Values.defaultBackend.priorityClassName }} + {{- end }} + {{- if .Values.defaultBackend.podSecurityContext }} + securityContext: {{ toYaml .Values.defaultBackend.podSecurityContext | nindent 8 }} + {{- end }} + containers: + - name: {{ template "ingress-nginx.name" . }}-default-backend + {{- with .Values.defaultBackend.image }} + image: "{{- if .repository -}}{{ .repository }}{{ else }}{{ .registry }}/{{ .image }}{{- end -}}:{{ .tag }}{{- if (.digest) -}} @{{.digest}} {{- end -}}" + {{- end }} + imagePullPolicy: {{ .Values.defaultBackend.image.pullPolicy }} + {{- if .Values.defaultBackend.extraArgs }} + args: + {{- range $key, $value := .Values.defaultBackend.extraArgs }} + {{- /* Accept keys without values or with false as value */}} + {{- if eq ($value | quote | len) 2 }} + - --{{ $key }} + {{- else }} + - --{{ $key }}={{ $value }} + {{- end }} + {{- end }} + {{- end }} + securityContext: {{ include "ingress-nginx.defaultBackend.containerSecurityContext" . | nindent 12 }} + {{- if .Values.defaultBackend.extraEnvs }} + env: {{ toYaml .Values.defaultBackend.extraEnvs | nindent 12 }} + {{- end }} + livenessProbe: + httpGet: + path: /healthz + port: {{ .Values.defaultBackend.port }} + scheme: HTTP + initialDelaySeconds: {{ .Values.defaultBackend.livenessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.defaultBackend.livenessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.defaultBackend.livenessProbe.timeoutSeconds }} + successThreshold: {{ .Values.defaultBackend.livenessProbe.successThreshold }} + failureThreshold: {{ .Values.defaultBackend.livenessProbe.failureThreshold }} + readinessProbe: + httpGet: + path: /healthz + port: {{ .Values.defaultBackend.port }} + scheme: HTTP + initialDelaySeconds: {{ .Values.defaultBackend.readinessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.defaultBackend.readinessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.defaultBackend.readinessProbe.timeoutSeconds }} + successThreshold: {{ .Values.defaultBackend.readinessProbe.successThreshold }} + failureThreshold: {{ .Values.defaultBackend.readinessProbe.failureThreshold }} + ports: + - name: http + containerPort: {{ .Values.defaultBackend.port }} + protocol: TCP + {{- if .Values.defaultBackend.extraVolumeMounts }} + volumeMounts: {{- toYaml .Values.defaultBackend.extraVolumeMounts | nindent 12 }} + {{- end }} + {{- if .Values.defaultBackend.resources }} + resources: {{ toYaml .Values.defaultBackend.resources | nindent 12 }} + {{- end }} + {{- if .Values.defaultBackend.nodeSelector }} + nodeSelector: {{ toYaml .Values.defaultBackend.nodeSelector | nindent 8 }} + {{- end }} + serviceAccountName: {{ template "ingress-nginx.defaultBackend.serviceAccountName" . }} + {{- if .Values.defaultBackend.tolerations }} + tolerations: {{ toYaml .Values.defaultBackend.tolerations | nindent 8 }} + {{- end }} + {{- if .Values.defaultBackend.affinity }} + affinity: {{ toYaml .Values.defaultBackend.affinity | nindent 8 }} + {{- end }} + terminationGracePeriodSeconds: 60 + {{- if .Values.defaultBackend.extraVolumes }} + volumes: {{ toYaml .Values.defaultBackend.extraVolumes | nindent 8 }} + {{- end }} +{{- end }} diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/templates/default-backend-extra-configmaps.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/templates/default-backend-extra-configmaps.yaml new file mode 100644 index 00000000..88b59280 --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/templates/default-backend-extra-configmaps.yaml @@ -0,0 +1,23 @@ +{{- if .Values.defaultBackend.enabled }} + {{- range .Values.defaultBackend.extraConfigMaps }} +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ .name }} + namespace: {{ include "ingress-nginx.namespace" $ | quote }} + labels: + {{- include "ingress-nginx.labels" $ | nindent 4 }} + {{- with $.Values.defaultBackend.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +data: + {{- with .data }} + {{- toYaml . | nindent 2 }} + {{- end }} + {{- end }} +{{- end }} + diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/templates/default-backend-hpa.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/templates/default-backend-hpa.yaml new file mode 100644 index 00000000..69932389 --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/templates/default-backend-hpa.yaml @@ -0,0 +1,40 @@ +{{- if and .Values.defaultBackend.enabled .Values.defaultBackend.autoscaling.enabled }} +apiVersion: {{ ternary "autoscaling/v2" "autoscaling/v2beta2" (.Capabilities.APIVersions.Has "autoscaling/v2") }} +kind: HorizontalPodAutoscaler +metadata: + {{- with .Values.defaultBackend.autoscaling.annotations }} + annotations: {{ toYaml . | nindent 4 }} + {{- end }} + labels: + {{- include "ingress-nginx.labels" . | nindent 4 }} + app.kubernetes.io/component: default-backend + {{- with .Values.defaultBackend.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + name: {{ include "ingress-nginx.defaultBackend.fullname" . }} + namespace: {{ include "ingress-nginx.namespace" . }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ include "ingress-nginx.defaultBackend.fullname" . }} + minReplicas: {{ .Values.defaultBackend.autoscaling.minReplicas }} + maxReplicas: {{ .Values.defaultBackend.autoscaling.maxReplicas }} + metrics: + {{- with .Values.defaultBackend.autoscaling.targetCPUUtilizationPercentage }} + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: {{ . }} + {{- end }} + {{- with .Values.defaultBackend.autoscaling.targetMemoryUtilizationPercentage }} + - type: Resource + resource: + name: memory + target: + type: Utilization + averageUtilization: {{ . }} + {{- end }} +{{- end }} diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/templates/default-backend-networkpolicy.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/templates/default-backend-networkpolicy.yaml new file mode 100644 index 00000000..90b3c2ba --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/templates/default-backend-networkpolicy.yaml @@ -0,0 +1,25 @@ +{{- if and .Values.defaultBackend.enabled .Values.defaultBackend.networkPolicy.enabled }} +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + labels: + {{- include "ingress-nginx.labels" . | nindent 4 }} + app.kubernetes.io/component: default-backend + {{- with .Values.defaultBackend.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + name: {{ include "ingress-nginx.defaultBackend.fullname" . }} + namespace: {{ include "ingress-nginx.namespace" . }} +spec: + podSelector: + matchLabels: + {{- include "ingress-nginx.selectorLabels" . | nindent 6 }} + app.kubernetes.io/component: default-backend + policyTypes: + - Ingress + - Egress + ingress: + - ports: + - protocol: TCP + port: {{ .Values.defaultBackend.port }} +{{- end }} diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/templates/default-backend-poddisruptionbudget.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/templates/default-backend-poddisruptionbudget.yaml new file mode 100644 index 00000000..f869e453 --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/templates/default-backend-poddisruptionbudget.yaml @@ -0,0 +1,21 @@ +{{- if .Values.defaultBackend.enabled -}} +{{- if or (gt (.Values.defaultBackend.replicaCount | int) 1) (gt (.Values.defaultBackend.autoscaling.minReplicas | int) 1) }} +apiVersion: {{ ternary "policy/v1" "policy/v1beta1" (semverCompare ">=1.21.0-0" .Capabilities.KubeVersion.Version) }} +kind: PodDisruptionBudget +metadata: + labels: + {{- include "ingress-nginx.labels" . | nindent 4 }} + app.kubernetes.io/component: default-backend + {{- with .Values.defaultBackend.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + name: {{ include "ingress-nginx.defaultBackend.fullname" . }} + namespace: {{ include "ingress-nginx.namespace" . }} +spec: + selector: + matchLabels: + {{- include "ingress-nginx.selectorLabels" . | nindent 6 }} + app.kubernetes.io/component: default-backend + minAvailable: {{ .Values.defaultBackend.minAvailable }} +{{- end }} +{{- end }} diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/templates/default-backend-psp.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/templates/default-backend-psp.yaml new file mode 100644 index 00000000..42410910 --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/templates/default-backend-psp.yaml @@ -0,0 +1,50 @@ +{{- if (semverCompare "<1.25.0-0" .Capabilities.KubeVersion.Version) }} +{{- if and .Values.podSecurityPolicy.enabled .Values.defaultBackend.enabled (empty .Values.defaultBackend.existingPsp) -}} +apiVersion: policy/v1beta1 +kind: PodSecurityPolicy +metadata: + name: {{ include "ingress-nginx.fullname" . }}-backend + annotations: + seccomp.security.alpha.kubernetes.io/allowedProfileNames: "*" + labels: + {{- include "ingress-nginx.labels" . | nindent 4 }} + app.kubernetes.io/component: default-backend + {{- with .Values.defaultBackend.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + privileged: false + hostPID: false + hostIPC: false + hostNetwork: false + volumes: + - configMap + - downwardAPI + - emptyDir + - secret + - projected + fsGroup: + rule: MustRunAs + ranges: + - min: 1 + max: 65535 + readOnlyRootFilesystem: true + runAsUser: + rule: MustRunAsNonRoot + runAsGroup: + rule: MustRunAs + ranges: + - min: 1 + max: 65535 + supplementalGroups: + rule: MustRunAs + ranges: + - min: 1 + max: 65535 + allowPrivilegeEscalation: false + requiredDropCapabilities: + - ALL + seLinux: + rule: RunAsAny +{{- end }} +{{- end }} diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/templates/default-backend-role.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/templates/default-backend-role.yaml new file mode 100644 index 00000000..dd7868aa --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/templates/default-backend-role.yaml @@ -0,0 +1,22 @@ +{{- if and .Values.rbac.create .Values.podSecurityPolicy.enabled .Values.defaultBackend.enabled -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + labels: + {{- include "ingress-nginx.labels" . | nindent 4 }} + app.kubernetes.io/component: default-backend + {{- with .Values.defaultBackend.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + name: {{ include "ingress-nginx.fullname" . }}-backend + namespace: {{ include "ingress-nginx.namespace" . }} +rules: + - apiGroups: [{{ template "podSecurityPolicy.apiGroup" . }}] + resources: ['podsecuritypolicies'] + verbs: ['use'] + {{- with .Values.defaultBackend.existingPsp }} + resourceNames: [{{ . }}] + {{- else }} + resourceNames: [{{ include "ingress-nginx.fullname" . }}-backend] + {{- end }} +{{- end }} diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/templates/default-backend-rolebinding.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/templates/default-backend-rolebinding.yaml new file mode 100644 index 00000000..3203b6f5 --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/templates/default-backend-rolebinding.yaml @@ -0,0 +1,21 @@ +{{- if and .Values.rbac.create .Values.podSecurityPolicy.enabled .Values.defaultBackend.enabled -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + labels: + {{- include "ingress-nginx.labels" . | nindent 4 }} + app.kubernetes.io/component: default-backend + {{- with .Values.defaultBackend.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + name: {{ include "ingress-nginx.fullname" . }}-backend + namespace: {{ include "ingress-nginx.namespace" . }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ include "ingress-nginx.fullname" . }}-backend +subjects: + - kind: ServiceAccount + name: {{ template "ingress-nginx.defaultBackend.serviceAccountName" . }} + namespace: {{ include "ingress-nginx.namespace" . }} +{{- end }} diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/templates/default-backend-service.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/templates/default-backend-service.yaml new file mode 100644 index 00000000..2cccd6e9 --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/templates/default-backend-service.yaml @@ -0,0 +1,41 @@ +{{- if .Values.defaultBackend.enabled -}} +apiVersion: v1 +kind: Service +metadata: +{{- if .Values.defaultBackend.service.annotations }} + annotations: {{ toYaml .Values.defaultBackend.service.annotations | nindent 4 }} +{{- end }} + labels: + {{- include "ingress-nginx.labels" . | nindent 4 }} + app.kubernetes.io/component: default-backend + {{- with .Values.defaultBackend.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + name: {{ include "ingress-nginx.defaultBackend.fullname" . }} + namespace: {{ include "ingress-nginx.namespace" . }} +spec: + type: {{ .Values.defaultBackend.service.type }} +{{- if .Values.defaultBackend.service.clusterIP }} + clusterIP: {{ .Values.defaultBackend.service.clusterIP }} +{{- end }} +{{- if .Values.defaultBackend.service.externalIPs }} + externalIPs: {{ toYaml .Values.defaultBackend.service.externalIPs | nindent 4 }} +{{- end }} +{{- if .Values.defaultBackend.service.loadBalancerIP }} + loadBalancerIP: {{ .Values.defaultBackend.service.loadBalancerIP }} +{{- end }} +{{- if .Values.defaultBackend.service.loadBalancerSourceRanges }} + loadBalancerSourceRanges: {{ toYaml .Values.defaultBackend.service.loadBalancerSourceRanges | nindent 4 }} +{{- end }} + ports: + - name: http + port: {{ .Values.defaultBackend.service.servicePort }} + protocol: TCP + targetPort: http + {{- if semverCompare ">=1.20" .Capabilities.KubeVersion.Version }} + appProtocol: http + {{- end }} + selector: + {{- include "ingress-nginx.selectorLabels" . | nindent 4 }} + app.kubernetes.io/component: default-backend +{{- end }} diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/templates/default-backend-serviceaccount.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/templates/default-backend-serviceaccount.yaml new file mode 100644 index 00000000..2afaf0c0 --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/templates/default-backend-serviceaccount.yaml @@ -0,0 +1,14 @@ +{{- if and .Values.defaultBackend.enabled .Values.defaultBackend.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + labels: + {{- include "ingress-nginx.labels" . | nindent 4 }} + app.kubernetes.io/component: default-backend + {{- with .Values.defaultBackend.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + name: {{ template "ingress-nginx.defaultBackend.serviceAccountName" . }} + namespace: {{ include "ingress-nginx.namespace" . }} +automountServiceAccountToken: {{ .Values.defaultBackend.serviceAccount.automountServiceAccountToken }} +{{- end }} diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/tests/default-backend-extra-configmaps_test.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/tests/default-backend-extra-configmaps_test.yaml new file mode 100644 index 00000000..b18ceedf --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/tests/default-backend-extra-configmaps_test.yaml @@ -0,0 +1,49 @@ +suite: test default backend extra ConfigMaps +templates: + - default-backend-extra-configmaps.yaml + +tests: + - it: should not create any ConfigMap by default + set: + Release.Namespace: default + defaultBackend.enabled: true + asserts: + - hasDocuments: + count: 0 + + - it: should create one ConfigMap + set: + Release.Namespace: default + defaultBackend.enabled: true + defaultBackend.extraConfigMaps: + - name: my-configmap-1 + data: + key1: value1 + asserts: + - hasDocuments: + count: 1 + - isKind: + of: ConfigMap + - equal: + path: metadata.name + value: my-configmap-1 + + - it: should correctly render multiple ConfigMaps + set: + Release.Namespace: nginx + defaultBackend.enabled: true + defaultBackend.extraConfigMaps: + - name: my-configmap-1 + data: + key1: value1 + - name: my-configmap-2 + data: + key2: value2 + asserts: + - hasDocuments: + count: 2 + - isKind: + of: ConfigMap + - matchRegex: + path: metadata.name + pattern: "my-configmap-\\d+" diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/values.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/values.yaml new file mode 100644 index 00000000..c1e89d77 --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/values.yaml @@ -0,0 +1,1013 @@ +## nginx configuration +## Ref: https://github.com/kubernetes/ingress-nginx/blob/main/docs/user-guide/nginx-configuration/index.md +## + +## Overrides for generated resource names +# See templates/_helpers.tpl +# nameOverride: +# fullnameOverride: + +# -- Override the deployment namespace; defaults to .Release.Namespace +namespaceOverride: "" + +## Labels to apply to all resources +## +commonLabels: {} +# scmhash: abc123 +# myLabel: aakkmd + +controller: + name: controller + enableAnnotationValidations: false + image: + ## Keep false as default for now! + chroot: false + registry: registry.k8s.io + image: ingress-nginx/controller + ## for backwards compatibility consider setting the full image url via the repository value below + ## use *either* current default registry/image or repository format or installing chart by providing the values.yaml will fail + ## repository: + tag: "v1.9.4" + digest: sha256:5b161f051d017e55d358435f295f5e9a297e66158f136321d9b04520ec6c48a3 + digestChroot: sha256:5976b1067cfbca8a21d0ba53d71f83543a73316a61ea7f7e436d6cf84ddf9b26 + pullPolicy: IfNotPresent + runAsNonRoot: true + # www-data -> uid 101 + runAsUser: 101 + allowPrivilegeEscalation: false + seccompProfile: + type: RuntimeDefault + readOnlyRootFilesystem: false + # -- Use an existing PSP instead of creating one + existingPsp: "" + # -- Configures the controller container name + containerName: controller + # -- Configures the ports that the nginx-controller listens on + containerPort: + http: 80 + https: 443 + # -- Will add custom configuration options to Nginx https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/configmap/ + config: {} + # -- Annotations to be added to the controller config configuration configmap. + configAnnotations: {} + # -- Will add custom headers before sending traffic to backends according to https://github.com/kubernetes/ingress-nginx/tree/main/docs/examples/customization/custom-headers + proxySetHeaders: {} + # -- Will add custom headers before sending response traffic to the client according to: https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/configmap/#add-headers + addHeaders: {} + # -- Optionally customize the pod dnsConfig. + dnsConfig: {} + # -- Optionally customize the pod hostAliases. + hostAliases: [] + # - ip: 127.0.0.1 + # hostnames: + # - foo.local + # - bar.local + # - ip: 10.1.2.3 + # hostnames: + # - foo.remote + # - bar.remote + # -- Optionally customize the pod hostname. + hostname: {} + # -- Optionally change this to ClusterFirstWithHostNet in case you have 'hostNetwork: true'. + # By default, while using host network, name resolution uses the host's DNS. If you wish nginx-controller + # to keep resolving names inside the k8s network, use ClusterFirstWithHostNet. + dnsPolicy: ClusterFirst + # -- Bare-metal considerations via the host network https://kubernetes.github.io/ingress-nginx/deploy/baremetal/#via-the-host-network + # Ingress status was blank because there is no Service exposing the Ingress-Nginx Controller in a configuration using the host network, the default --publish-service flag used in standard cloud setups does not apply + reportNodeInternalIp: false + # -- Process Ingress objects without ingressClass annotation/ingressClassName field + # Overrides value for --watch-ingress-without-class flag of the controller binary + # Defaults to false + watchIngressWithoutClass: false + # -- Process IngressClass per name (additionally as per spec.controller). + ingressClassByName: false + # -- This configuration enables Topology Aware Routing feature, used together with service annotation service.kubernetes.io/topology-mode="auto" + # Defaults to false + enableTopologyAwareRouting: false + # -- This configuration defines if Ingress Controller should allow users to set + # their own *-snippet annotations, otherwise this is forbidden / dropped + # when users add those annotations. + # Global snippets in ConfigMap are still respected + allowSnippetAnnotations: false + # -- Required for use with CNI based kubernetes installations (such as ones set up by kubeadm), + # since CNI and hostport don't mix yet. Can be deprecated once https://github.com/kubernetes/kubernetes/issues/23920 + # is merged + hostNetwork: false + ## Use host ports 80 and 443 + ## Disabled by default + hostPort: + # -- Enable 'hostPort' or not + enabled: false + ports: + # -- 'hostPort' http port + http: 80 + # -- 'hostPort' https port + https: 443 + # NetworkPolicy for controller component. + networkPolicy: + # -- Enable 'networkPolicy' or not + enabled: false + # -- Election ID to use for status update, by default it uses the controller name combined with a suffix of 'leader' + electionID: "" + ## This section refers to the creation of the IngressClass resource + ## IngressClass resources are supported since k8s >= 1.18 and required since k8s >= 1.19 + ingressClassResource: + # -- Name of the ingressClass + name: nginx + # -- Is this ingressClass enabled or not + enabled: true + # -- Is this the default ingressClass for the cluster + default: false + # -- Controller-value of the controller that is processing this ingressClass + controllerValue: "k8s.io/ingress-nginx" + # -- Parameters is a link to a custom resource containing additional + # configuration for the controller. This is optional if the controller + # does not require extra parameters. + parameters: {} + # -- For backwards compatibility with ingress.class annotation, use ingressClass. + # Algorithm is as follows, first ingressClassName is considered, if not present, controller looks for ingress.class annotation + ingressClass: nginx + # -- Labels to add to the pod container metadata + podLabels: {} + # key: value + + # -- Security context for controller pods + podSecurityContext: {} + # -- sysctls for controller pods + ## Ref: https://kubernetes.io/docs/tasks/administer-cluster/sysctl-cluster/ + sysctls: {} + # sysctls: + # "net.core.somaxconn": "8192" + # -- Security context for controller containers + containerSecurityContext: {} + + # -- Allows customization of the source of the IP address or FQDN to report + # in the ingress status field. By default, it reads the information provided + # by the service. If disable, the status field reports the IP address of the + # node or nodes where an ingress controller pod is running. + publishService: + # -- Enable 'publishService' or not + enabled: true + # -- Allows overriding of the publish service to bind to + # Must be / + pathOverride: "" + # Limit the scope of the controller to a specific namespace + scope: + # -- Enable 'scope' or not + enabled: false + # -- Namespace to limit the controller to; defaults to $(POD_NAMESPACE) + namespace: "" + # -- When scope.enabled == false, instead of watching all namespaces, we watching namespaces whose labels + # only match with namespaceSelector. Format like foo=bar. Defaults to empty, means watching all namespaces. + namespaceSelector: "" + # -- Allows customization of the configmap / nginx-configmap namespace; defaults to $(POD_NAMESPACE) + configMapNamespace: "" + tcp: + # -- Allows customization of the tcp-services-configmap; defaults to $(POD_NAMESPACE) + configMapNamespace: "" + # -- Annotations to be added to the tcp config configmap + annotations: {} + udp: + # -- Allows customization of the udp-services-configmap; defaults to $(POD_NAMESPACE) + configMapNamespace: "" + # -- Annotations to be added to the udp config configmap + annotations: {} + # -- Maxmind license key to download GeoLite2 Databases. + ## https://blog.maxmind.com/2019/12/18/significant-changes-to-accessing-and-using-geolite2-databases + maxmindLicenseKey: "" + # -- Additional command line arguments to pass to Ingress-Nginx Controller + # E.g. to specify the default SSL certificate you can use + extraArgs: {} + ## extraArgs: + ## default-ssl-certificate: "/" + ## time-buckets: "0.005,0.01,0.025,0.05,0.1,0.25,0.5,1,2.5,5,10" + ## length-buckets: "10,20,30,40,50,60,70,80,90,100" + ## size-buckets: "10,100,1000,10000,100000,1e+06,1e+07" + + # -- Additional environment variables to set + extraEnvs: [] + # extraEnvs: + # - name: FOO + # valueFrom: + # secretKeyRef: + # key: FOO + # name: secret-resource + + # -- Use a `DaemonSet` or `Deployment` + kind: Deployment + # -- Annotations to be added to the controller Deployment or DaemonSet + ## + annotations: {} + # keel.sh/pollSchedule: "@every 60m" + + # -- Labels to be added to the controller Deployment or DaemonSet and other resources that do not have option to specify labels + ## + labels: {} + # keel.sh/policy: patch + # keel.sh/trigger: poll + + # -- The update strategy to apply to the Deployment or DaemonSet + ## + updateStrategy: {} + # rollingUpdate: + # maxUnavailable: 1 + # type: RollingUpdate + + # -- `minReadySeconds` to avoid killing pods before we are ready + ## + minReadySeconds: 0 + # -- Node tolerations for server scheduling to nodes with taints + ## Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ + ## + tolerations: [] + # - key: "key" + # operator: "Equal|Exists" + # value: "value" + # effect: "NoSchedule|PreferNoSchedule|NoExecute(1.6 only)" + + # -- Affinity and anti-affinity rules for server scheduling to nodes + ## Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity + ## + affinity: {} + # # An example of preferred pod anti-affinity, weight is in the range 1-100 + # podAntiAffinity: + # preferredDuringSchedulingIgnoredDuringExecution: + # - weight: 100 + # podAffinityTerm: + # labelSelector: + # matchExpressions: + # - key: app.kubernetes.io/name + # operator: In + # values: + # - ingress-nginx + # - key: app.kubernetes.io/instance + # operator: In + # values: + # - ingress-nginx + # - key: app.kubernetes.io/component + # operator: In + # values: + # - controller + # topologyKey: kubernetes.io/hostname + + # # An example of required pod anti-affinity + # podAntiAffinity: + # requiredDuringSchedulingIgnoredDuringExecution: + # - labelSelector: + # matchExpressions: + # - key: app.kubernetes.io/name + # operator: In + # values: + # - ingress-nginx + # - key: app.kubernetes.io/instance + # operator: In + # values: + # - ingress-nginx + # - key: app.kubernetes.io/component + # operator: In + # values: + # - controller + # topologyKey: "kubernetes.io/hostname" + + # -- Topology spread constraints rely on node labels to identify the topology domain(s) that each Node is in. + ## Ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/ + ## + topologySpreadConstraints: [] + # - labelSelector: + # matchLabels: + # app.kubernetes.io/name: '{{ include "ingress-nginx.name" . }}' + # app.kubernetes.io/instance: '{{ .Release.Name }}' + # app.kubernetes.io/component: controller + # topologyKey: topology.kubernetes.io/zone + # maxSkew: 1 + # whenUnsatisfiable: ScheduleAnyway + # - labelSelector: + # matchLabels: + # app.kubernetes.io/name: '{{ include "ingress-nginx.name" . }}' + # app.kubernetes.io/instance: '{{ .Release.Name }}' + # app.kubernetes.io/component: controller + # topologyKey: kubernetes.io/hostname + # maxSkew: 1 + # whenUnsatisfiable: ScheduleAnyway + + # -- `terminationGracePeriodSeconds` to avoid killing pods before we are ready + ## wait up to five minutes for the drain of connections + ## + terminationGracePeriodSeconds: 300 + # -- Node labels for controller pod assignment + ## Ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/ + ## + nodeSelector: + kubernetes.io/os: linux + ## Liveness and readiness probe values + ## Ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes + ## + ## startupProbe: + ## httpGet: + ## # should match container.healthCheckPath + ## path: "/healthz" + ## port: 10254 + ## scheme: HTTP + ## initialDelaySeconds: 5 + ## periodSeconds: 5 + ## timeoutSeconds: 2 + ## successThreshold: 1 + ## failureThreshold: 5 + livenessProbe: + httpGet: + # should match container.healthCheckPath + path: "/healthz" + port: 10254 + scheme: HTTP + initialDelaySeconds: 10 + periodSeconds: 10 + timeoutSeconds: 1 + successThreshold: 1 + failureThreshold: 5 + readinessProbe: + httpGet: + # should match container.healthCheckPath + path: "/healthz" + port: 10254 + scheme: HTTP + initialDelaySeconds: 10 + periodSeconds: 10 + timeoutSeconds: 1 + successThreshold: 1 + failureThreshold: 3 + # -- Path of the health check endpoint. All requests received on the port defined by + # the healthz-port parameter are forwarded internally to this path. + healthCheckPath: "/healthz" + # -- Address to bind the health check endpoint. + # It is better to set this option to the internal node address + # if the Ingress-Nginx Controller is running in the `hostNetwork: true` mode. + healthCheckHost: "" + # -- Annotations to be added to controller pods + ## + podAnnotations: {} + replicaCount: 1 + # -- Minimum available pods set in PodDisruptionBudget. + # Define either 'minAvailable' or 'maxUnavailable', never both. + minAvailable: 1 + # -- Maximum unavailable pods set in PodDisruptionBudget. If set, 'minAvailable' is ignored. + # maxUnavailable: 1 + + ## Define requests resources to avoid probe issues due to CPU utilization in busy nodes + ## ref: https://github.com/kubernetes/ingress-nginx/issues/4735#issuecomment-551204903 + ## Ideally, there should be no limits. + ## https://engineering.indeedblog.com/blog/2019/12/cpu-throttling-regression-fix/ + resources: + ## limits: + ## cpu: 100m + ## memory: 90Mi + requests: + cpu: 100m + memory: 90Mi + # Mutually exclusive with keda autoscaling + autoscaling: + enabled: false + annotations: {} + minReplicas: 1 + maxReplicas: 11 + targetCPUUtilizationPercentage: 50 + targetMemoryUtilizationPercentage: 50 + behavior: {} + # scaleDown: + # stabilizationWindowSeconds: 300 + # policies: + # - type: Pods + # value: 1 + # periodSeconds: 180 + # scaleUp: + # stabilizationWindowSeconds: 300 + # policies: + # - type: Pods + # value: 2 + # periodSeconds: 60 + autoscalingTemplate: [] + # Custom or additional autoscaling metrics + # ref: https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/#support-for-custom-metrics + # - type: Pods + # pods: + # metric: + # name: nginx_ingress_controller_nginx_process_requests_total + # target: + # type: AverageValue + # averageValue: 10000m + + # Mutually exclusive with hpa autoscaling + keda: + apiVersion: "keda.sh/v1alpha1" + ## apiVersion changes with keda 1.x vs 2.x + ## 2.x = keda.sh/v1alpha1 + ## 1.x = keda.k8s.io/v1alpha1 + enabled: false + minReplicas: 1 + maxReplicas: 11 + pollingInterval: 30 + cooldownPeriod: 300 + # fallback: + # failureThreshold: 3 + # replicas: 11 + restoreToOriginalReplicaCount: false + scaledObject: + annotations: {} + # Custom annotations for ScaledObject resource + # annotations: + # key: value + triggers: [] + # - type: prometheus + # metadata: + # serverAddress: http://:9090 + # metricName: http_requests_total + # threshold: '100' + # query: sum(rate(http_requests_total{deployment="my-deployment"}[2m])) + + behavior: {} + # scaleDown: + # stabilizationWindowSeconds: 300 + # policies: + # - type: Pods + # value: 1 + # periodSeconds: 180 + # scaleUp: + # stabilizationWindowSeconds: 300 + # policies: + # - type: Pods + # value: 2 + # periodSeconds: 60 + # -- Enable mimalloc as a drop-in replacement for malloc. + ## ref: https://github.com/microsoft/mimalloc + ## + enableMimalloc: true + ## Override NGINX template + customTemplate: + configMapName: "" + configMapKey: "" + service: + enabled: true + # -- If enabled is adding an appProtocol option for Kubernetes service. An appProtocol field replacing annotations that were + # using for setting a backend protocol. Here is an example for AWS: service.beta.kubernetes.io/aws-load-balancer-backend-protocol: http + # It allows choosing the protocol for each backend specified in the Kubernetes service. + # See the following GitHub issue for more details about the purpose: https://github.com/kubernetes/kubernetes/issues/40244 + # Will be ignored for Kubernetes versions older than 1.20 + ## + appProtocol: true + # -- Annotations are mandatory for the load balancer to come up. Varies with the cloud service. Values passed through helm tpl engine. + annotations: {} + labels: {} + # clusterIP: "" + + # -- List of IP addresses at which the controller services are available + ## Ref: https://kubernetes.io/docs/concepts/services-networking/service/#external-ips + ## + externalIPs: [] + # -- Set to false to disable loadbalancer node port allocation + # See https://kubernetes.io/docs/concepts/services-networking/service/#load-balancer-nodeport-allocation + # allocateLoadBalancerNodePorts: true + # -- Used by cloud providers to connect the resulting `LoadBalancer` to a pre-existing static IP according to https://kubernetes.io/docs/concepts/services-networking/service/#loadbalancer + loadBalancerIP: "" + loadBalancerSourceRanges: [] + # -- Used by cloud providers to select a load balancer implementation other than the cloud provider default. https://kubernetes.io/docs/concepts/services-networking/service/#load-balancer-class + loadBalancerClass: "" + enableHttp: true + enableHttps: true + ## Set external traffic policy to: "Local" to preserve source IP on providers supporting it. + ## Ref: https://kubernetes.io/docs/tutorials/services/source-ip/#source-ip-for-services-with-typeloadbalancer + # externalTrafficPolicy: "" + + ## Must be either "None" or "ClientIP" if set. Kubernetes will default to "None". + ## Ref: https://kubernetes.io/docs/concepts/services-networking/service/#virtual-ips-and-service-proxies + # sessionAffinity: "" + + ## Specifies the health check node port (numeric port number) for the service. If healthCheckNodePort isn’t specified, + ## the service controller allocates a port from your cluster’s NodePort range. + ## Ref: https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip + # healthCheckNodePort: 0 + + # -- Represents the dual-stack-ness requested or required by this Service. Possible values are + # SingleStack, PreferDualStack or RequireDualStack. + # The ipFamilies and clusterIPs fields depend on the value of this field. + ## Ref: https://kubernetes.io/docs/concepts/services-networking/dual-stack/ + ipFamilyPolicy: "SingleStack" + # -- List of IP families (e.g. IPv4, IPv6) assigned to the service. This field is usually assigned automatically + # based on cluster configuration and the ipFamilyPolicy field. + ## Ref: https://kubernetes.io/docs/concepts/services-networking/dual-stack/ + ipFamilies: + - IPv4 + ports: + http: 80 + https: 443 + targetPorts: + http: http + https: https + type: LoadBalancer + ## type: NodePort + ## nodePorts: + ## http: 32080 + ## https: 32443 + ## tcp: + ## 8080: 32808 + nodePorts: + http: "" + https: "" + tcp: {} + udp: {} + external: + enabled: true + internal: + # -- Enables an additional internal load balancer (besides the external one). + enabled: false + # -- Annotations are mandatory for the load balancer to come up. Varies with the cloud service. Values passed through helm tpl engine. + annotations: {} + # -- Set to false to disable loadbalancer node port allocation + # See https://kubernetes.io/docs/concepts/services-networking/service/#load-balancer-nodeport-allocation + # allocateLoadBalancerNodePorts: true + # -- Used by cloud providers to connect the resulting internal LoadBalancer to a pre-existing static IP. Make sure to add to the service the needed annotation to specify the subnet which the static IP belongs to. For instance, `networking.gke.io/internal-load-balancer-subnet` for GCP and `service.beta.kubernetes.io/aws-load-balancer-subnets` for AWS. + loadBalancerIP: "" + # -- Restrict access For LoadBalancer service. Defaults to 0.0.0.0/0. + loadBalancerSourceRanges: [] + ## Set external traffic policy to: "Local" to preserve source IP on + ## providers supporting it + ## Ref: https://kubernetes.io/docs/tutorials/services/source-ip/#source-ip-for-services-with-typeloadbalancer + # externalTrafficPolicy: "" + + # -- Custom port mapping for internal service + ports: {} + # http: 80 + # https: 443 + + # -- Custom target port mapping for internal service + targetPorts: {} + # http: http + # https: https + # shareProcessNamespace enables process namespace sharing within the pod. + # This can be used for example to signal log rotation using `kill -USR1` from a sidecar. + shareProcessNamespace: false + # -- Additional containers to be added to the controller pod. + # See https://github.com/lemonldap-ng-controller/lemonldap-ng-controller as example. + extraContainers: [] + # - name: my-sidecar + # image: nginx:latest + # - name: lemonldap-ng-controller + # image: lemonldapng/lemonldap-ng-controller:0.2.0 + # args: + # - /lemonldap-ng-controller + # - --alsologtostderr + # - --configmap=$(POD_NAMESPACE)/lemonldap-ng-configuration + # env: + # - name: POD_NAME + # valueFrom: + # fieldRef: + # fieldPath: metadata.name + # - name: POD_NAMESPACE + # valueFrom: + # fieldRef: + # fieldPath: metadata.namespace + # volumeMounts: + # - name: copy-portal-skins + # mountPath: /srv/var/lib/lemonldap-ng/portal/skins + + # -- Additional volumeMounts to the controller main container. + extraVolumeMounts: [] + # - name: copy-portal-skins + # mountPath: /var/lib/lemonldap-ng/portal/skins + + # -- Additional volumes to the controller pod. + extraVolumes: [] + # - name: copy-portal-skins + # emptyDir: {} + + # -- Containers, which are run before the app containers are started. + extraInitContainers: [] + # - name: init-myservice + # image: busybox + # command: ['sh', '-c', 'until nslookup myservice; do echo waiting for myservice; sleep 2; done;'] + + # -- Modules, which are mounted into the core nginx image. See values.yaml for a sample to add opentelemetry module + extraModules: [] + # - name: mytestmodule + # image: registry.k8s.io/ingress-nginx/mytestmodule + # distroless: false + # containerSecurityContext: + # runAsNonRoot: true + # runAsUser: + # allowPrivilegeEscalation: false + # seccompProfile: + # type: RuntimeDefault + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # resources: {} + # + # The image must contain a `/usr/local/bin/init_module.sh` executable, which + # will be executed as initContainers, to move its config files within the + # mounted volume. + + opentelemetry: + enabled: false + name: opentelemetry + image: registry.k8s.io/ingress-nginx/opentelemetry:v20230721-3e2062ee5@sha256:13bee3f5223883d3ca62fee7309ad02d22ec00ff0d7033e3e9aca7a9f60fd472 + distroless: true + containerSecurityContext: + runAsNonRoot: true + # -- The image's default user, inherited from its base image `cgr.dev/chainguard/static`. + runAsUser: 65532 + allowPrivilegeEscalation: false + seccompProfile: + type: RuntimeDefault + capabilities: + drop: + - ALL + readOnlyRootFilesystem: true + resources: {} + admissionWebhooks: + name: admission + annotations: {} + # ignore-check.kube-linter.io/no-read-only-rootfs: "This deployment needs write access to root filesystem". + + ## Additional annotations to the admission webhooks. + ## These annotations will be added to the ValidatingWebhookConfiguration and + ## the Jobs Spec of the admission webhooks. + enabled: true + # -- Additional environment variables to set + extraEnvs: [] + # extraEnvs: + # - name: FOO + # valueFrom: + # secretKeyRef: + # key: FOO + # name: secret-resource + # -- Admission Webhook failure policy to use + failurePolicy: Fail + # timeoutSeconds: 10 + port: 8443 + certificate: "/usr/local/certificates/cert" + key: "/usr/local/certificates/key" + namespaceSelector: {} + objectSelector: {} + # -- Labels to be added to admission webhooks + labels: {} + # -- Use an existing PSP instead of creating one + existingPsp: "" + service: + annotations: {} + # clusterIP: "" + externalIPs: [] + # loadBalancerIP: "" + loadBalancerSourceRanges: [] + servicePort: 443 + type: ClusterIP + createSecretJob: + name: create + # -- Security context for secret creation containers + securityContext: + runAsNonRoot: true + runAsUser: 65532 + allowPrivilegeEscalation: false + seccompProfile: + type: RuntimeDefault + capabilities: + drop: + - ALL + readOnlyRootFilesystem: true + resources: {} + # limits: + # cpu: 10m + # memory: 20Mi + # requests: + # cpu: 10m + # memory: 20Mi + patchWebhookJob: + name: patch + # -- Security context for webhook patch containers + securityContext: + runAsNonRoot: true + runAsUser: 65532 + allowPrivilegeEscalation: false + seccompProfile: + type: RuntimeDefault + capabilities: + drop: + - ALL + readOnlyRootFilesystem: true + resources: {} + patch: + enabled: true + image: + registry: registry.k8s.io + image: ingress-nginx/kube-webhook-certgen + ## for backwards compatibility consider setting the full image url via the repository value below + ## use *either* current default registry/image or repository format or installing chart by providing the values.yaml will fail + ## repository: + tag: v20231011-8b53cabe0 + digest: sha256:a7943503b45d552785aa3b5e457f169a5661fb94d82b8a3373bcd9ebaf9aac80 + pullPolicy: IfNotPresent + # -- Provide a priority class name to the webhook patching job + ## + priorityClassName: "" + podAnnotations: {} + # NetworkPolicy for webhook patch + networkPolicy: + # -- Enable 'networkPolicy' or not + enabled: false + nodeSelector: + kubernetes.io/os: linux + tolerations: [] + # -- Labels to be added to patch job resources + labels: {} + # -- Security context for secret creation & webhook patch pods + securityContext: {} + # Use certmanager to generate webhook certs + certManager: + enabled: false + # self-signed root certificate + rootCert: + # default to be 5y + duration: "" + admissionCert: + # default to be 1y + duration: "" + # issuerRef: + # name: "issuer" + # kind: "ClusterIssuer" + metrics: + port: 10254 + portName: metrics + # if this port is changed, change healthz-port: in extraArgs: accordingly + enabled: false + service: + annotations: {} + # prometheus.io/scrape: "true" + # prometheus.io/port: "10254" + # -- Labels to be added to the metrics service resource + labels: {} + # clusterIP: "" + + # -- List of IP addresses at which the stats-exporter service is available + ## Ref: https://kubernetes.io/docs/concepts/services-networking/service/#external-ips + ## + externalIPs: [] + # loadBalancerIP: "" + loadBalancerSourceRanges: [] + servicePort: 10254 + type: ClusterIP + # externalTrafficPolicy: "" + # nodePort: "" + serviceMonitor: + enabled: false + additionalLabels: {} + ## The label to use to retrieve the job name from. + ## jobLabel: "app.kubernetes.io/name" + namespace: "" + namespaceSelector: {} + ## Default: scrape .Release.Namespace or namespaceOverride only + ## To scrape all, use the following: + ## namespaceSelector: + ## any: true + scrapeInterval: 30s + # honorLabels: true + targetLabels: [] + relabelings: [] + metricRelabelings: [] + prometheusRule: + enabled: false + additionalLabels: {} + # namespace: "" + rules: [] + # # These are just examples rules, please adapt them to your needs + # - alert: NGINXConfigFailed + # expr: count(nginx_ingress_controller_config_last_reload_successful == 0) > 0 + # for: 1s + # labels: + # severity: critical + # annotations: + # description: bad ingress config - nginx config test failed + # summary: uninstall the latest ingress changes to allow config reloads to resume + # # By default a fake self-signed certificate is generated as default and + # # it is fine if it expires. If `--default-ssl-certificate` flag is used + # # and a valid certificate passed please do not filter for `host` label! + # # (i.e. delete `{host!="_"}` so also the default SSL certificate is + # # checked for expiration) + # - alert: NGINXCertificateExpiry + # expr: (avg(nginx_ingress_controller_ssl_expire_time_seconds{host!="_"}) by (host) - time()) < 604800 + # for: 1s + # labels: + # severity: critical + # annotations: + # description: ssl certificate(s) will expire in less then a week + # summary: renew expiring certificates to avoid downtime + # - alert: NGINXTooMany500s + # expr: 100 * ( sum( nginx_ingress_controller_requests{status=~"5.+"} ) / sum(nginx_ingress_controller_requests) ) > 5 + # for: 1m + # labels: + # severity: warning + # annotations: + # description: Too many 5XXs + # summary: More than 5% of all requests returned 5XX, this requires your attention + # - alert: NGINXTooMany400s + # expr: 100 * ( sum( nginx_ingress_controller_requests{status=~"4.+"} ) / sum(nginx_ingress_controller_requests) ) > 5 + # for: 1m + # labels: + # severity: warning + # annotations: + # description: Too many 4XXs + # summary: More than 5% of all requests returned 4XX, this requires your attention + # -- Improve connection draining when ingress controller pod is deleted using a lifecycle hook: + # With this new hook, we increased the default terminationGracePeriodSeconds from 30 seconds + # to 300, allowing the draining of connections up to five minutes. + # If the active connections end before that, the pod will terminate gracefully at that time. + # To effectively take advantage of this feature, the Configmap feature + # worker-shutdown-timeout new value is 240s instead of 10s. + ## + lifecycle: + preStop: + exec: + command: + - /wait-shutdown + priorityClassName: "" +# -- Rollback limit +## +revisionHistoryLimit: 10 +## Default 404 backend +## +defaultBackend: + ## + enabled: false + name: defaultbackend + image: + registry: registry.k8s.io + image: defaultbackend-amd64 + ## for backwards compatibility consider setting the full image url via the repository value below + ## use *either* current default registry/image or repository format or installing chart by providing the values.yaml will fail + ## repository: + tag: "1.5" + pullPolicy: IfNotPresent + runAsNonRoot: true + # nobody user -> uid 65534 + runAsUser: 65534 + allowPrivilegeEscalation: false + seccompProfile: + type: RuntimeDefault + readOnlyRootFilesystem: true + # -- Use an existing PSP instead of creating one + existingPsp: "" + extraArgs: {} + serviceAccount: + create: true + name: "" + automountServiceAccountToken: true + # -- Additional environment variables to set for defaultBackend pods + extraEnvs: [] + port: 8080 + ## Readiness and liveness probes for default backend + ## Ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/ + ## + livenessProbe: + failureThreshold: 3 + initialDelaySeconds: 30 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 5 + readinessProbe: + failureThreshold: 6 + initialDelaySeconds: 0 + periodSeconds: 5 + successThreshold: 1 + timeoutSeconds: 5 + # -- The update strategy to apply to the Deployment or DaemonSet + ## + updateStrategy: {} + # rollingUpdate: + # maxUnavailable: 1 + # type: RollingUpdate + + # -- `minReadySeconds` to avoid killing pods before we are ready + ## + minReadySeconds: 0 + # -- Node tolerations for server scheduling to nodes with taints + ## Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ + ## + tolerations: [] + # - key: "key" + # operator: "Equal|Exists" + # value: "value" + # effect: "NoSchedule|PreferNoSchedule|NoExecute(1.6 only)" + + affinity: {} + # -- Security context for default backend pods + podSecurityContext: {} + # -- Security context for default backend containers + containerSecurityContext: {} + # -- Labels to add to the pod container metadata + podLabels: {} + # key: value + + # -- Node labels for default backend pod assignment + ## Ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/ + ## + nodeSelector: + kubernetes.io/os: linux + # -- Annotations to be added to default backend pods + ## + podAnnotations: {} + replicaCount: 1 + minAvailable: 1 + resources: {} + # limits: + # cpu: 10m + # memory: 20Mi + # requests: + # cpu: 10m + # memory: 20Mi + + extraVolumeMounts: [] + ## Additional volumeMounts to the default backend container. + # - name: copy-portal-skins + # mountPath: /var/lib/lemonldap-ng/portal/skins + + extraVolumes: [] + ## Additional volumes to the default backend pod. + # - name: copy-portal-skins + # emptyDir: {} + extraConfigMaps: [] + ## Additional configmaps to the default backend pod. + # Example ConfigMap, uncomment and configure as needed + # - name: my-extra-configmap-1 + # labels: + # type: config-1 + # data: + # extra_file_1.html: | + # + # - name: my-extra-configmap-2 + # labels: + # type: config-2 + # data: + # extra_file_2.html: | + # + + autoscaling: + annotations: {} + enabled: false + minReplicas: 1 + maxReplicas: 2 + targetCPUUtilizationPercentage: 50 + targetMemoryUtilizationPercentage: 50 + # NetworkPolicy for default backend component. + networkPolicy: + # -- Enable 'networkPolicy' or not + enabled: false + service: + annotations: {} + # clusterIP: "" + + # -- List of IP addresses at which the default backend service is available + ## Ref: https://kubernetes.io/docs/concepts/services-networking/service/#external-ips + ## + externalIPs: [] + # loadBalancerIP: "" + loadBalancerSourceRanges: [] + servicePort: 80 + type: ClusterIP + priorityClassName: "" + # -- Labels to be added to the default backend resources + labels: {} +## Enable RBAC as per https://github.com/kubernetes/ingress-nginx/blob/main/docs/deploy/rbac.md and https://github.com/kubernetes/ingress-nginx/issues/266 +rbac: + create: true + scope: false +## If true, create & use Pod Security Policy resources +## https://kubernetes.io/docs/concepts/policy/pod-security-policy/ +podSecurityPolicy: + enabled: false +serviceAccount: + create: true + name: "" + automountServiceAccountToken: true + # -- Annotations for the controller service account + annotations: {} +# -- Optional array of imagePullSecrets containing private registry credentials +## Ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ +imagePullSecrets: [] +# - name: secretName + +# -- TCP service key-value pairs +## Ref: https://github.com/kubernetes/ingress-nginx/blob/main/docs/user-guide/exposing-tcp-udp-services.md +## +tcp: {} +# 8080: "default/example-tcp-svc:9000" + +# -- UDP service key-value pairs +## Ref: https://github.com/kubernetes/ingress-nginx/blob/main/docs/user-guide/exposing-tcp-udp-services.md +## +udp: {} +# 53: "kube-system/kube-dns:53" + +# -- Prefix for TCP and UDP ports names in ingress controller service +## Some cloud providers, like Yandex Cloud may have a requirements for a port name regex to support cloud load balancer integration +portNamePrefix: "" +# -- (string) A base64-encoded Diffie-Hellman parameter. +# This can be generated with: `openssl dhparam 4096 2> /dev/null | base64` +## Ref: https://github.com/kubernetes/ingress-nginx/tree/main/docs/examples/customization/ssl-dh-param +dhParam: "" diff --git a/packages/system/ingress-nginx/patches/add-metrics2.patch b/packages/system/ingress-nginx/patches/add-metrics2.patch new file mode 100644 index 00000000..93bdc324 --- /dev/null +++ b/packages/system/ingress-nginx/patches/add-metrics2.patch @@ -0,0 +1,28 @@ +diff --git a/apps/ingress-nginx/charts/ingress-nginx/templates/controller-daemonset.yaml b/apps/ingress-nginx/charts/ingress-nginx/templates/controller-daemonset.yaml +index 82abe75..148d930 100644 +--- a/apps/ingress-nginx/charts/ingress-nginx/templates/controller-daemonset.yaml ++++ b/apps/ingress-nginx/charts/ingress-nginx/templates/controller-daemonset.yaml +@@ -121,6 +121,9 @@ spec: + - name: {{ .Values.controller.metrics.portName }} + containerPort: {{ .Values.controller.metrics.port }} + protocol: TCP ++ - name: metrics2 ++ containerPort: 9091 ++ protocol: TCP + {{- end }} + {{- if .Values.controller.admissionWebhooks.enabled }} + - name: webhook +diff --git a/apps/ingress-nginx/charts/ingress-nginx/templates/controller-deployment.yaml b/apps/ingress-nginx/charts/ingress-nginx/templates/controller-deployment.yaml +index 7fe8804..9fe0142 100644 +--- a/apps/ingress-nginx/charts/ingress-nginx/templates/controller-deployment.yaml ++++ b/apps/ingress-nginx/charts/ingress-nginx/templates/controller-deployment.yaml +@@ -125,6 +125,9 @@ spec: + - name: {{ .Values.controller.metrics.portName }} + containerPort: {{ .Values.controller.metrics.port }} + protocol: TCP ++ - name: metrics2 ++ containerPort: 9091 ++ protocol: TCP + {{- end }} + {{- if .Values.controller.admissionWebhooks.enabled }} + - name: webhook diff --git a/packages/system/ingress-nginx/values.yaml b/packages/system/ingress-nginx/values.yaml new file mode 100644 index 00000000..1390e725 --- /dev/null +++ b/packages/system/ingress-nginx/values.yaml @@ -0,0 +1,47 @@ +ingress-nginx: + controller: + extraArgs: + enable-ssl-passthrough: true + image: + registry: ghcr.io + image: kvaps/ingress-nginx-with-protobuf-exporter/controller + tag: v1.8.1 + digest: "sha256:7933a0729c716a8bf879218451ff43ee9c1a8f4850feffb12f81eb9439aefc23" + allowSnippetAnnotations: true + replicaCount: 2 + admissionWebhooks: + certManager: + enabled: true + metrics: + enabled: true + extraContainers: + - name: protobuf-exporter + image: ghcr.io/kvaps/ingress-nginx-with-protobuf-exporter/protobuf-exporter:v1.8.1@sha256:9b6f3f2688592a0f25038bc15e107642d7374359cbd87442920df1c45f27fe4d + args: + - --server.telemetry-address=0.0.0.0:9090 + - --server.exporter-address=0.0.0.0:9091 + service: + #type: NodePort # ClusterIP + externalTrafficPolicy: "Local" + #allocateLoadBalancerNodePorts: false + config: + ## proxy protocol + #use-proxy-protocol: "true" + #use-forwarded-headers: "true" + #compute-full-forwarded-for: "true" + #real-ip-header: "proxy_protocol" + #enable-real-ip: "true" + # keep-alive + proxy-connect-timeout: "10s" + proxy-read-timeout: "10s" + keep-alive-requests: "1000000" + upstream-keepalive-requests: "100000" + upstream-keepalive-time: '1m' + upstream-keepalive-timeout: "60" + upstream-keepalive-connections: "320" + ssl-session-tickets: "true" + + + defaultBackend: + ## + enabled: true diff --git a/packages/system/kamaji-etcd/.helmignore b/packages/system/kamaji-etcd/.helmignore new file mode 100644 index 00000000..216b462f --- /dev/null +++ b/packages/system/kamaji-etcd/.helmignore @@ -0,0 +1,2 @@ +images +hack diff --git a/packages/system/kamaji-etcd/Chart.yaml b/packages/system/kamaji-etcd/Chart.yaml new file mode 100644 index 00000000..c67b97e3 --- /dev/null +++ b/packages/system/kamaji-etcd/Chart.yaml @@ -0,0 +1,2 @@ +name: cozy-kamaji-etcd +version: 1.0.0 diff --git a/packages/system/kamaji-etcd/Makefile b/packages/system/kamaji-etcd/Makefile new file mode 100644 index 00000000..25d7155d --- /dev/null +++ b/packages/system/kamaji-etcd/Makefile @@ -0,0 +1,8 @@ +update: + rm -rf charts + helm repo add clastix https://clastix.github.io/charts + helm repo update clastix + helm pull clastix/kamaji-etcd --untar --untardir charts + sed -i 's/hook-failed/before-hook-creation,hook-failed/' `grep -rl hook-failed charts` + patch -p4 < patches/fix-svc.diff + patch -p4 < patches/fullnameOverride.diff diff --git a/packages/system/kamaji-etcd/charts/kamaji-etcd/.helmignore b/packages/system/kamaji-etcd/charts/kamaji-etcd/.helmignore new file mode 100644 index 00000000..0e8a0eb3 --- /dev/null +++ b/packages/system/kamaji-etcd/charts/kamaji-etcd/.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/packages/system/kamaji-etcd/charts/kamaji-etcd/Chart.yaml b/packages/system/kamaji-etcd/charts/kamaji-etcd/Chart.yaml new file mode 100644 index 00000000..ae934ae6 --- /dev/null +++ b/packages/system/kamaji-etcd/charts/kamaji-etcd/Chart.yaml @@ -0,0 +1,15 @@ +apiVersion: v2 +appVersion: 3.5.6 +description: Helm chart for deploying a multi-tenant `etcd` cluster. +home: https://github.com/clastix/kamaji-etcd +kubeVersion: '>=1.22.0-0' +maintainers: +- email: me@bsctl.io + name: Adriano Pezzuto +- email: dario@tranchitella.eu + name: Dario Tranchitella +name: kamaji-etcd +sources: +- https://github.com/clastix/kamaji-etcd +type: application +version: 0.5.1 diff --git a/packages/system/kamaji-etcd/charts/kamaji-etcd/Makefile b/packages/system/kamaji-etcd/charts/kamaji-etcd/Makefile new file mode 100644 index 00000000..94f47498 --- /dev/null +++ b/packages/system/kamaji-etcd/charts/kamaji-etcd/Makefile @@ -0,0 +1,9 @@ +docs: HELMDOCS_VERSION := v1.8.1 +docs: docker + @docker run --rm -v "$$(pwd):/helm-docs" -u $$(id -u) jnorwood/helm-docs:$(HELMDOCS_VERSION) + +docker: + @hash docker 2>/dev/null || {\ + echo "You need docker" &&\ + exit 1;\ + } \ No newline at end of file diff --git a/packages/system/kamaji-etcd/charts/kamaji-etcd/README.md b/packages/system/kamaji-etcd/charts/kamaji-etcd/README.md new file mode 100644 index 00000000..d23b1b23 --- /dev/null +++ b/packages/system/kamaji-etcd/charts/kamaji-etcd/README.md @@ -0,0 +1,133 @@ +# kamaji-etcd + +![Version: 0.5.1](https://img.shields.io/badge/Version-0.5.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 3.5.6](https://img.shields.io/badge/AppVersion-3.5.6-informational?style=flat-square) + +Helm chart for deploying a multi-tenant `etcd` cluster. + +[Kamaji](https://github.com/clastix/kamaji) turns any Kubernetes cluster into an _admin cluster_ to orchestrate other Kubernetes clusters called _tenant clusters_. +The Control Plane of a _tenant cluster_ is made of regular pods running in a namespace of the _admin cluster_ instead of a dedicated set of Virtual Machines. +This solution makes running control planes at scale cheaper and easier to deploy and operate. + +As of any Kubernetes cluster, a _tenant cluster_ needs a datastore where to save the state and be able to retrieve data. +This chart provides a multi-tenant `etcd` as datastore for Kamaji as well as a standalone multi-tenant `etcd` cluster. + +## Install kamaji-etcd + +To install the Chart with the release name `kamaji-etcd`: + + helm repo add clastix https://clastix.github.io/charts + helm repo update + helm install kamaji-etcd clastix/kamaji-etcd -n kamaji-etcd --create-namespace + +Show the status: + + helm status kamaji-etcd -n kamaji-etcd + +Upgrade the Chart + + helm upgrade kamaji-etcd -n kamaji-etcd clastix/kamaji-etcd + +Uninstall the Chart + + helm uninstall kamaji-etcd -n kamaji-etcd + +## Customize the installation + +There are two methods for specifying overrides of values during Chart installation: `--values` and `--set`. + +The `--values` option is the preferred method because it allows you to keep your overrides in a YAML file, rather than specifying them all on the command line. +Create a copy of the YAML file `values.yaml` and add your overrides to it. + +Specify your overrides file when you install the Chart: + + helm upgrade kamaji-etcd --install --namespace kamaji-etcd --create-namespacekamaji-etcd --values myvalues.yaml + +The values in your overrides file `myvalues.yaml` will override their counterparts in the Chart's values.yaml file. +Any values in `values.yaml` that weren't overridden will keep their defaults. + +If you only need to make minor customizations, you can specify them on the command line by using the `--set` option. For example: + + helm upgrade kamaji-etcd --install --namespace kamaji-etcd --create-namespace kamaji-etcd --set replicas=5 + +Here the values you can override: + +## Values + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| affinity | object | `{}` | Kubernetes affinity rules to apply to etcd controller pods | +| alerts.annotations | object | `{}` | Assign additional Annotations | +| alerts.enabled | bool | `false` | Enable alerts for Alertmanager | +| alerts.labels | object | `{}` | Assign additional labels according to Prometheus' Alerts matching labels | +| alerts.namespace | string | `""` | Install the Alerts into a different Namespace, as the monitoring stack one (default: the release one) | +| alerts.rules | list | `[]` | The rules for alerts | +| autoCompactionMode | string | `"periodic"` | Interpret 'auto-compaction-retention' one of: periodic|revision. Use 'periodic' for duration based retention, 'revision' for revision number based retention. | +| autoCompactionRetention | string | `"5m"` | Auto compaction retention length. 0 means disable auto compaction. | +| backup | object | `{"all":false,"enabled":false,"s3":{"accessKey":{"value":"","valueFrom":{}},"bucket":"mybucket","image":{"pullPolicy":"IfNotPresent","repository":"minio/mc","tag":"RELEASE.2022-11-07T23-47-39Z"},"retention":"","secretKey":{"value":"","valueFrom":{}},"url":"http://mys3storage:9000"},"schedule":"20 3 * * *","snapshotDateFormat":"$(date +%Y%m%d)","snapshotNamePrefix":"mysnapshot"}` | Enable storage backup | +| backup.all | bool | `false` | Enable backup for all endpoints. When disabled, only the leader will be taken | +| backup.enabled | bool | `false` | Enable scheduling backup job | +| backup.s3 | object | `{"accessKey":{"value":"","valueFrom":{}},"bucket":"mybucket","image":{"pullPolicy":"IfNotPresent","repository":"minio/mc","tag":"RELEASE.2022-11-07T23-47-39Z"},"retention":"","secretKey":{"value":"","valueFrom":{}},"url":"http://mys3storage:9000"}` | The S3 storage config section | +| backup.s3.accessKey | object | `{"value":"","valueFrom":{}}` | The S3 storage ACCESS KEY credential. The plain value has precedence over the valueFrom that can be used to retrieve the value from a Secret. | +| backup.s3.bucket | string | `"mybucket"` | The S3 storage bucket | +| backup.s3.image | object | `{"pullPolicy":"IfNotPresent","repository":"minio/mc","tag":"RELEASE.2022-11-07T23-47-39Z"}` | The S3 client image config section | +| backup.s3.image.pullPolicy | string | `"IfNotPresent"` | Pull policy to use | +| backup.s3.image.repository | string | `"minio/mc"` | Install image from specific repo | +| backup.s3.image.tag | string | `"RELEASE.2022-11-07T23-47-39Z"` | Install image with specific tag | +| backup.s3.retention | string | `""` | The S3 storage object lifecycle management rules; N.B. enabling this option will delete previously set lifecycle rules | +| backup.s3.secretKey | object | `{"value":"","valueFrom":{}}` | The S3 storage SECRET KEY credential. The plain value has precedence over the valueFrom that can be used to retrieve the value from a Secret. | +| backup.s3.url | string | `"http://mys3storage:9000"` | The S3 storage url | +| backup.schedule | string | `"20 3 * * *"` | The job scheduled maintenance time for backup | +| backup.snapshotDateFormat | string | `"$(date +%Y%m%d)"` | The backup file date format (bash) | +| backup.snapshotNamePrefix | string | `"mysnapshot"` | The backup file name prefix | +| clientPort | int | `2379` | The client request port. | +| datastore.enabled | bool | `false` | Create a datastore custom resource for Kamaji | +| defragmentation | object | `{"schedule":"*/15 * * * *"}` | Enable storage defragmentation | +| defragmentation.schedule | string | `"*/15 * * * *"` | The job scheduled maintenance time for defrag (empty to disable) | +| extraArgs | list | `[]` | A list of extra arguments to add to the etcd default ones | +| image.pullPolicy | string | `"IfNotPresent"` | Pull policy to use | +| image.repository | string | `"quay.io/coreos/etcd"` | Install image from specific repo | +| image.tag | string | `""` | Install image with specific tag, overwrite the tag in the chart | +| livenessProbe | object | `{}` | The livenessProbe for the etcd container | +| metricsPort | int | `2381` | The port where etcd exposes metrics. | +| nodeSelector | object | `{"kubernetes.io/os":"linux"}` | Kubernetes node selector rules to schedule etcd | +| peerApiPort | int | `2380` | The peer API port which servers are listening to. | +| persistentVolumeClaim.accessModes | list | `["ReadWriteOnce"]` | The Access Mode to storage | +| persistentVolumeClaim.customAnnotations | object | `{}` | The custom annotations to add to the PVC | +| persistentVolumeClaim.size | string | `"10Gi"` | The size of persistent storage for etcd data | +| persistentVolumeClaim.storageClassName | string | `""` | A specific storage class | +| podAnnotations | object | `{}` | Annotations to add to all etcd pods | +| podLabels | object | `{"application":"kamaji-etcd"}` | Labels to add to all etcd pods | +| priorityClassName | string | `"system-cluster-critical"` | The priorityClassName to apply to etcd | +| quotaBackendBytes | string | `"8589934592"` | Raise alarms when backend size exceeds the given quota. It will put the cluster into a maintenance mode which only accepts key reads and deletes. | +| replicas | int | `3` | Size of the etcd cluster | +| resources | object | `{"limits":{},"requests":{}}` | Resources assigned to the etcd containers | +| securityContext | object | `{"allowPrivilegeEscalation":false}` | The securityContext to apply to etcd | +| serviceAccount | object | `{"create":true,"name":""}` | Install an etcd with enabled multi-tenancy | +| serviceAccount.create | bool | `true` | Create a ServiceAccount, required to install and provision the etcd backing storage (default: true) | +| serviceAccount.name | string | `""` | Define the ServiceAccount name to use during the setup and provision of the etcd backing storage (default: "") | +| serviceMonitor.annotations | object | `{}` | Assign additional Annotations | +| serviceMonitor.enabled | bool | `false` | Enable ServiceMonitor for Prometheus | +| serviceMonitor.endpoint.interval | string | `"15s"` | Set the scrape interval for the endpoint of the serviceMonitor | +| serviceMonitor.endpoint.metricRelabelings | list | `[]` | Set metricRelabelings for the endpoint of the serviceMonitor | +| serviceMonitor.endpoint.relabelings | list | `[]` | Set relabelings for the endpoint of the serviceMonitor | +| serviceMonitor.endpoint.scrapeTimeout | string | `""` | Set the scrape timeout for the endpoint of the serviceMonitor | +| serviceMonitor.labels | object | `{}` | Assign additional labels according to Prometheus' serviceMonitorSelector matching labels | +| serviceMonitor.matchLabels | object | `{}` | Change matching labels | +| serviceMonitor.namespace | string | `""` | Install the ServiceMonitor into a different Namespace, as the monitoring stack one (default: the release one) | +| serviceMonitor.serviceAccount.name | string | `"etcd"` | ServiceAccount for Metrics RBAC | +| serviceMonitor.serviceAccount.namespace | string | `"etcd-system"` | ServiceAccount Namespace for Metrics RBAC | +| serviceMonitor.targetLabels | list | `[]` | Set targetLabels for the serviceMonitor | +| snapshotCount | string | `"10000"` | Number of committed transactions to trigger a snapshot to disk. | +| tolerations | list | `[]` | Kubernetes node taints that the etcd pods would tolerate | +| topologySpreadConstraints | list | `[]` | Kubernetes topology spread constraints to apply to etcd controller pods | + +## Maintainers + +| Name | Email | Url | +| ---- | ------ | --- | +| Adriano Pezzuto | | | +| Dario Tranchitella | | | + +## Source Code + +* diff --git a/packages/system/kamaji-etcd/charts/kamaji-etcd/README.md.gotmpl b/packages/system/kamaji-etcd/charts/kamaji-etcd/README.md.gotmpl new file mode 100644 index 00000000..04c36a53 --- /dev/null +++ b/packages/system/kamaji-etcd/charts/kamaji-etcd/README.md.gotmpl @@ -0,0 +1,59 @@ +{{ template "chart.header" . }} +{{ template "chart.deprecationWarning" . }} + +{{ template "chart.badgesSection" . }} + +{{ template "chart.description" . }} + +[Kamaji](https://github.com/clastix/kamaji) turns any Kubernetes cluster into an _admin cluster_ to orchestrate other Kubernetes clusters called _tenant clusters_. +The Control Plane of a _tenant cluster_ is made of regular pods running in a namespace of the _admin cluster_ instead of a dedicated set of Virtual Machines. +This solution makes running control planes at scale cheaper and easier to deploy and operate. + +As of any Kubernetes cluster, a _tenant cluster_ needs a datastore where to save the state and be able to retrieve data. +This chart provides a multi-tenant `etcd` as datastore for Kamaji as well as a standalone multi-tenant `etcd` cluster. + +## Install kamaji-etcd + +To install the Chart with the release name `kamaji-etcd`: + + helm repo add clastix https://clastix.github.io/charts + helm repo update + helm install kamaji-etcd clastix/kamaji-etcd -n kamaji-etcd --create-namespace + +Show the status: + + helm status kamaji-etcd -n kamaji-etcd + +Upgrade the Chart + + helm upgrade kamaji-etcd -n kamaji-etcd clastix/kamaji-etcd + +Uninstall the Chart + + helm uninstall kamaji-etcd -n kamaji-etcd + +## Customize the installation + +There are two methods for specifying overrides of values during Chart installation: `--values` and `--set`. + +The `--values` option is the preferred method because it allows you to keep your overrides in a YAML file, rather than specifying them all on the command line. +Create a copy of the YAML file `values.yaml` and add your overrides to it. + +Specify your overrides file when you install the Chart: + + helm upgrade kamaji-etcd --install --namespace kamaji-etcd --create-namespacekamaji-etcd --values myvalues.yaml + +The values in your overrides file `myvalues.yaml` will override their counterparts in the Chart's values.yaml file. +Any values in `values.yaml` that weren't overridden will keep their defaults. + +If you only need to make minor customizations, you can specify them on the command line by using the `--set` option. For example: + + helm upgrade kamaji-etcd --install --namespace kamaji-etcd --create-namespace kamaji-etcd --set replicas=5 + +Here the values you can override: + +{{ template "chart.valuesSection" . }} + +{{ template "chart.maintainersSection" . }} + +{{ template "chart.sourcesSection" . }} diff --git a/packages/system/kamaji-etcd/charts/kamaji-etcd/templates/_helpers.tpl b/packages/system/kamaji-etcd/charts/kamaji-etcd/templates/_helpers.tpl new file mode 100644 index 00000000..403e187a --- /dev/null +++ b/packages/system/kamaji-etcd/charts/kamaji-etcd/templates/_helpers.tpl @@ -0,0 +1,168 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "etcd.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified etcd name. +*/}} +{{- define "etcd.fullname" -}} +{{- if .Values.fullnameOverride -}} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- if contains $name .Release.Name -}} +{{- .Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "etcd.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create the etcd fully-qualified Docker image to use +*/}} +{{- define "etcd.fullyQualifiedDockerImage" -}} +{{- printf "%s:%s" .Values.image.repository ( .Values.image.tag | default (printf "v%s" .Chart.AppVersion) ) -}} +{{- end }} + +{{/* +Create the name of the Service to use +*/}} +{{- define "etcd.serviceName" -}} +{{- printf "%s" (include "etcd.fullname" .) | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "etcd.labels" -}} +helm.sh/chart: {{ include "etcd.chart" . }} +{{ include "etcd.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "etcd.selectorLabels" -}} +app.kubernetes.io/name: {{ include "etcd.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "etcd.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "etcd.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} + +{{/* +Name of the Stateful Set. +*/}} +{{- define "etcd.stsName" }} +{{- printf "%s" (include "etcd.fullname" .) | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Name of the etcd CA secret. +*/}} +{{- define "etcd.caSecretName" }} +{{- printf "%s-%s" (include "etcd.fullname" .) "certs" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Name of the certificate signing requests for the certificates required by etcd. +*/}} +{{- define "etcd.csrConfigMapName" }} +{{- printf "%s-csr" (include "etcd.fullname" .) }} +{{- end }} + +{{/* +Name of the etcd role +*/}} +{{- define "etcd.roleName" }} +{{- printf "%s-gen-certs-role" (include "etcd.fullname" .) }} +{{- end }} + +{{/* +Name of the etcd role binding +*/}} +{{- define "etcd.roleBindingName" }} +{{- printf "%s-gen-certs-rolebiding" (include "etcd.fullname" .) }} +{{- end }} + +{{/* +Name of the etcd root-client secret. +*/}} +{{- define "etcd.clientSecretName" }} +{{- printf "%s-root-client-certs" ( include "etcd.fullname" . ) }} +{{- end }} + +{{/* +Retrieve the current Kubernetes version to launch a kubectl container with the minimum version skew possible. +*/}} +{{- define "etcd.jobsTagKubeVersion" -}} +{{- if contains "-eks-" .Capabilities.KubeVersion.GitVersion }} +{{- print "v" .Capabilities.KubeVersion.Major "." (.Capabilities.KubeVersion.Minor | replace "+" "") -}} +{{- else }} +{{- print "v" .Capabilities.KubeVersion.Major "." .Capabilities.KubeVersion.Minor -}} +{{- end }} +{{- end }} + +{{/* +Comma separated list of etcd cluster peers. +*/}} +{{- define "etcd.initialCluster" }} +{{- $outer := . -}} +{{- $list := list -}} +{{- range $i, $count := until (int $.Values.replicas) -}} + {{- $list = append $list ( printf "%s-%d=https://%s-%d.%s.%s.svc.cluster.local:%d" ( include "etcd.stsName" $outer ) $i ( include "etcd.fullname" $outer ) $count ( include "etcd.serviceName" $outer ) $.Release.Namespace (int $.Values.peerApiPort) ) -}} +{{- end }} +{{- join "," $list -}} +{{- end }} + +{{/* +Space separated list of etcd cluster endpoints. +*/}} +{{- define "etcd.endpoints" }} +{{- $outer := . -}} +{{- $list := list -}} +{{- range $i, $count := until (int $.Values.replicas) -}} + {{- $list = append $list ( printf "%s-%d.%s.%s.svc.cluster.local:%d" ( include "etcd.stsName" $outer ) $count ( include "etcd.serviceName" $outer ) $.Release.Namespace (int $.Values.clientPort) ) -}} +{{- end }} +{{- join " " $list -}} +{{- end }} + +{{/* +Space separated list of etcd cluster endpoints. +*/}} +{{- define "etcd.endpointsYAML" }} +{{- $outer := . -}} +{{- range $i, $count := until (int $.Values.replicas) -}} + {{ printf "- %s-%d.%s.%s.svc.cluster.local:%d\n" ( include "etcd.stsName" $outer ) $count ( include "etcd.serviceName" $outer ) $.Release.Namespace (int $.Values.clientPort) }} +{{- end }} +{{- end }} + +{{/* +Create the minio-client fully-qualified Docker image to use +*/}} +{{- define "minio-client.fullyQualifiedDockerImage" -}} +{{- printf "%s:%s" .Values.backup.s3.image.repository .Values.backup.s3.image.tag -}} +{{- end }} diff --git a/packages/system/kamaji-etcd/charts/kamaji-etcd/templates/etcd_alerts.yaml b/packages/system/kamaji-etcd/charts/kamaji-etcd/templates/etcd_alerts.yaml new file mode 100644 index 00000000..30bc6f43 --- /dev/null +++ b/packages/system/kamaji-etcd/charts/kamaji-etcd/templates/etcd_alerts.yaml @@ -0,0 +1,22 @@ +{{- if .Values.alerts.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: PrometheusRule +metadata: + name: {{ include "etcd.fullname" . }}-alerts + namespace: {{ .Values.alerts.namespace | default .Release.Namespace }} + labels: + {{- include "etcd.labels" . | nindent 4 }} + {{- with .Values.alerts.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.alerts.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + groups: + - name: kamaji-etcd + {{- with .Values.alerts.rules }} + rules: {{- toYaml . | nindent 6 }} + {{- end }} +{{- end }} \ No newline at end of file diff --git a/packages/system/kamaji-etcd/charts/kamaji-etcd/templates/etcd_cm.yaml b/packages/system/kamaji-etcd/charts/kamaji-etcd/templates/etcd_cm.yaml new file mode 100644 index 00000000..bd8ddcb9 --- /dev/null +++ b/packages/system/kamaji-etcd/charts/kamaji-etcd/templates/etcd_cm.yaml @@ -0,0 +1,98 @@ +{{- $outer := $ -}} +apiVersion: v1 +kind: ConfigMap +metadata: + annotations: + "helm.sh/hook": pre-install + "helm.sh/hook-weight": "5" + labels: + {{- include "etcd.labels" . | nindent 4 }} + name: {{ include "etcd.csrConfigMapName" . }} + namespace: {{ .Release.Namespace }} +data: + ca-csr.json: |- + { + "CN": "Clastix CA", + "key": { + "algo": "rsa", + "size": 2048 + }, + "names": [ + { + "C": "IT", + "ST": "Italy", + "L": "Milan" + } + ] + } + config.json: |- + { + "signing": { + "default": { + "expiry": "8760h" + }, + "profiles": { + "server-authentication": { + "usages": ["signing", "key encipherment", "server auth"], + "expiry": "8760h" + }, + "client-authentication": { + "usages": ["signing", "key encipherment", "client auth"], + "expiry": "8760h" + }, + "peer-authentication": { + "usages": ["signing", "key encipherment", "server auth", "client auth"], + "expiry": "8760h" + } + } + } + } + server-csr.json: |- + { + "CN": "etcd", + "key": { + "algo": "rsa", + "size": 2048 + }, + "hosts": [ +{{- range $count := until (int $.Values.replicas) -}} + {{ printf "\"%s-%d.%s.%s.svc.cluster.local\"," ( include "etcd.fullname" $outer ) $count (include "etcd.serviceName" $outer) $.Release.Namespace }} + {{ printf "\"%s-%d.%s.%s.svc\"," ( include "etcd.fullname" $outer ) $count (include "etcd.serviceName" $outer) $.Release.Namespace }} +{{- end }} + "etcd-server.{{ .Release.Namespace }}.svc.cluster.local", + "etcd-server.{{ .Release.Namespace }}.svc", + "etcd-server", + "127.0.0.1" + ] + } + peer-csr.json: |- + { + "CN": "etcd", + "key": { + "algo": "rsa", + "size": 2048 + }, + "hosts": [ +{{- range $count := until (int $.Values.replicas) -}} + {{ printf "\"%s-%d\"," ( include "etcd.stsName" $outer ) $count }} + {{ printf "\"%s-%d.%s\"," ( include "etcd.stsName" $outer ) $count (include "etcd.serviceName" $outer) }} + {{ printf "\"%s-%d.%s.%s.svc\"," ( include "etcd.stsName" $outer ) $count (include "etcd.serviceName" $outer) $.Release.Namespace }} + {{ printf "\"%s-%d.%s.%s.svc.cluster.local\"," ( include "etcd.stsName" $outer ) $count (include "etcd.serviceName" $outer) $.Release.Namespace }} +{{- end }} + "127.0.0.1" + ] + } + root-client-csr.json: |- + { + "CN": "root", + "key": { + "algo": "rsa", + "size": 2048 + }, + "names": [ + { + "O": "system:masters" + } + ] + } + diff --git a/packages/system/kamaji-etcd/charts/kamaji-etcd/templates/etcd_cronjob_backup.yaml b/packages/system/kamaji-etcd/charts/kamaji-etcd/templates/etcd_cronjob_backup.yaml new file mode 100644 index 00000000..034bbac2 --- /dev/null +++ b/packages/system/kamaji-etcd/charts/kamaji-etcd/templates/etcd_cronjob_backup.yaml @@ -0,0 +1,115 @@ +{{- if .Values.backup.enabled -}} +apiVersion: batch/v1 +kind: CronJob +metadata: + labels: + {{- include "etcd.labels" . | nindent 4 }} + name: "{{ .Release.Name }}-backup" + namespace: {{ .Release.Namespace }} +spec: + schedule: "{{ .Values.backup.schedule }}" + successfulJobsHistoryLimit: 7 + jobTemplate: + spec: + template: + spec: + serviceAccountName: {{ include "etcd.serviceAccountName" . }} + restartPolicy: OnFailure + initContainers: + - name: etcd-client + image: {{ include "etcd.fullyQualifiedDockerImage" . }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + command: + - bash + - -c + - |- + cd /opt/etcd-dump; + for ENDPOINT in {{ include "etcd.endpoints" . }}; do + isLeader=$(etcdctl --endpoints=${ENDPOINT} endpoint status | awk '{ print $6 }' | tr -d ',' ) + if ! {{ .Values.backup.all }} && ! ${isLeader} ; then + continue + elif ! {{ .Values.backup.all }} && ${isLeader} ; then + POD="etcd-leader" + else + POD=${ENDPOINT#*//} + POD=${POD%.{{ include "etcd.serviceName" . }}*} + fi + SNAPSHOT={{ .Values.backup.snapshotNamePrefix }}_${POD}_{{ .Values.backup.snapshotDateFormat }}.db + etcdctl --endpoints=${ENDPOINT} snapshot save ${SNAPSHOT} + etcdutl --write-out=table snapshot status ${SNAPSHOT} + md5sum ${SNAPSHOT}; + done; + env: + - name: ETCDCTL_CACERT + value: /opt/certs/ca/ca.crt + - name: ETCDCTL_CERT + value: /opt/certs/root-client-certs/tls.crt + - name: ETCDCTL_KEY + value: /opt/certs/root-client-certs/tls.key + volumeMounts: + - name: root-client-certs + mountPath: /opt/certs/root-client-certs + - name: certs + mountPath: /opt/certs/ca + - name: shared-data + mountPath: /opt/etcd-dump + containers: + - name: minio-client + image: {{ include "minio-client.fullyQualifiedDockerImage" . }} + imagePullPolicy: {{ .Values.backup.s3.image.pullPolicy }} + command: + - bash + - -c + - |- + cd /opt/etcd-dump + if $MC alias set myminio ${S3_URL} ${S3_ACCESS_KEY} ${S3_SECRET_KEY} \ + && $MC ping myminio -c 3 -e 3 ; then + echo -e "\nUploading snapshot(s):" + $MC cp {{ .Values.backup.snapshotNamePrefix }}_*.db myminio/{{ .Values.backup.s3.bucket }} + else + echo -e "\nERROR: S3 storage could not be configured;\nCheck your S3 URL/Credentials or network connectivity" + exit 1 + fi + env: + - name: S3_URL + value: {{ .Values.backup.s3.url | quote }} + - name: S3_ACCESS_KEY + {{- if .Values.backup.s3.accessKey.value }} + value: {{ .Values.backup.s3.accessKey.value | quote }} + {{- else }} + valueFrom: + {{- toYaml .Values.backup.s3.accessKey.valueFrom | nindent 16 }} + {{- end }} + - name: S3_SECRET_KEY + {{- if .Values.backup.s3.secretKey.value }} + value: {{ .Values.backup.s3.secretKey.value | quote }} + {{- else }} + valueFrom: + {{- toYaml .Values.backup.s3.secretKey.valueFrom | nindent 16 }} + {{- end }} + - name: MC_CONFIG_DIR + value: /tmp + - name: MC + value: "/usr/bin/mc --config-dir ${MC_CONFIG_DIR}" + volumeMounts: + - name: shared-data + mountPath: /opt/etcd-dump + securityContext: + runAsUser: 1000 + runAsGroup: 1000 + fsGroup: 1000 + {{- with .Values.tolerations }} + tolerations: {{- toYaml . | nindent 12 }} + {{- end }} + volumes: + - name: shared-data + emptyDir: {} + - name: root-client-certs + secret: + secretName: {{ include "etcd.clientSecretName" . }} + optional: true + - name: certs + secret: + secretName: {{ include "etcd.caSecretName" . }} + optional: true +{{- end }} diff --git a/packages/system/kamaji-etcd/charts/kamaji-etcd/templates/etcd_cronjob_defrag.yaml b/packages/system/kamaji-etcd/charts/kamaji-etcd/templates/etcd_cronjob_defrag.yaml new file mode 100644 index 00000000..ef5ca25d --- /dev/null +++ b/packages/system/kamaji-etcd/charts/kamaji-etcd/templates/etcd_cronjob_defrag.yaml @@ -0,0 +1,62 @@ +{{- if .Values.defragmentation.schedule -}} +apiVersion: batch/v1 +kind: CronJob +metadata: + labels: + {{- include "etcd.labels" . | nindent 4 }} + name: "{{ .Release.Name }}-defrag" + namespace: {{ .Release.Namespace }} +spec: + schedule: "{{ .Values.defragmentation.schedule }}" + successfulJobsHistoryLimit: 4 + jobTemplate: + spec: + template: + spec: + serviceAccountName: {{ include "etcd.serviceAccountName" . }} + restartPolicy: OnFailure + containers: + - name: etcd-client + image: {{ include "etcd.fullyQualifiedDockerImage" . }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + command: + - bash + - -c + - |- + for ENDPOINT in {{ include "etcd.endpoints" . }}; do + etcdctl --endpoints=https://${ENDPOINT} defrag; + etcdctl --endpoints=https://${ENDPOINT} alarm disarm; + etcdctl --endpoints=https://${ENDPOINT} alarm list; + etcdctl --endpoints=https://${ENDPOINT} endpoint status -w table; + etcdctl --endpoints=https://${ENDPOINT} member list -w table; + sleep 15; + done; + env: + - name: ETCDCTL_CACERT + value: /opt/certs/ca/ca.crt + - name: ETCDCTL_CERT + value: /opt/certs/root-client-certs/tls.crt + - name: ETCDCTL_KEY + value: /opt/certs/root-client-certs/tls.key + volumeMounts: + - name: root-client-certs + mountPath: /opt/certs/root-client-certs + - name: certs + mountPath: /opt/certs/ca + securityContext: + runAsUser: 1000 + runAsGroup: 1000 + fsGroup: 1000 + {{- with .Values.tolerations }} + tolerations: {{- toYaml . | nindent 12 }} + {{- end }} + volumes: + - name: root-client-certs + secret: + secretName: {{ include "etcd.clientSecretName" . }} + optional: true + - name: certs + secret: + secretName: {{ include "etcd.caSecretName" . }} + optional: true +{{- end }} diff --git a/packages/system/kamaji-etcd/charts/kamaji-etcd/templates/etcd_datastore.yaml b/packages/system/kamaji-etcd/charts/kamaji-etcd/templates/etcd_datastore.yaml new file mode 100644 index 00000000..edf155c3 --- /dev/null +++ b/packages/system/kamaji-etcd/charts/kamaji-etcd/templates/etcd_datastore.yaml @@ -0,0 +1,35 @@ +{{- if .Values.datastore.enabled }} +apiVersion: kamaji.clastix.io/v1alpha1 +kind: DataStore +metadata: + name: {{ include "etcd.fullname" . }} + labels: + {{- include "etcd.labels" . | nindent 4 }} +spec: + driver: etcd + endpoints: + {{- include "etcd.endpointsYAML" . | nindent 4 }} + tlsConfig: + certificateAuthority: + certificate: + secretReference: + keyPath: ca.crt + name: {{ include "etcd.caSecretName" . }} + namespace: {{ .Release.Namespace }} + privateKey: + secretReference: + keyPath: ca.key + name: {{ include "etcd.caSecretName" . }} + namespace: {{ .Release.Namespace }} + clientCertificate: + certificate: + secretReference: + keyPath: tls.crt + name: {{ include "etcd.clientSecretName" . }} + namespace: {{ .Release.Namespace }} + privateKey: + secretReference: + keyPath: tls.key + name: {{ include "etcd.clientSecretName" . }} + namespace: {{ .Release.Namespace }} +{{ end }} \ No newline at end of file diff --git a/packages/system/kamaji-etcd/charts/kamaji-etcd/templates/etcd_job_postdelete.yaml b/packages/system/kamaji-etcd/charts/kamaji-etcd/templates/etcd_job_postdelete.yaml new file mode 100644 index 00000000..71a9d5cc --- /dev/null +++ b/packages/system/kamaji-etcd/charts/kamaji-etcd/templates/etcd_job_postdelete.yaml @@ -0,0 +1,32 @@ +apiVersion: batch/v1 +kind: Job +metadata: + labels: + {{- include "etcd.labels" . | nindent 4 }} + annotations: + "helm.sh/hook": pre-delete + "helm.sh/hook-weight": "10" + "helm.sh/hook-delete-policy": "hook-succeeded,before-hook-creation,hook-failed" + name: "{{ .Release.Name }}-etcd-teardown" + namespace: {{ .Release.Namespace }} +spec: + template: + metadata: + name: "{{ .Release.Name }}" + spec: + serviceAccountName: {{ include "etcd.serviceAccountName" . }} + restartPolicy: Never + containers: + - name: kubectl + image: {{ printf "clastix/kubectl:%s" (include "etcd.jobsTagKubeVersion" .) }} + command: + - kubectl + - --namespace={{ .Release.Namespace }} + - delete + - secret + - --ignore-not-found=true + - {{ include "etcd.caSecretName" . }} + - {{ include "etcd.clientSecretName" . }} + {{- with .Values.tolerations }} + tolerations: {{- toYaml . | nindent 8 }} + {{- end }} diff --git a/packages/system/kamaji-etcd/charts/kamaji-etcd/templates/etcd_job_preinstall_1.yaml b/packages/system/kamaji-etcd/charts/kamaji-etcd/templates/etcd_job_preinstall_1.yaml new file mode 100644 index 00000000..7fa78ce1 --- /dev/null +++ b/packages/system/kamaji-etcd/charts/kamaji-etcd/templates/etcd_job_preinstall_1.yaml @@ -0,0 +1,69 @@ +apiVersion: batch/v1 +kind: Job +metadata: + labels: + {{- include "etcd.labels" . | nindent 4 }} + annotations: + "helm.sh/hook": pre-install + "helm.sh/hook-weight": "10" + "helm.sh/hook-delete-policy": "hook-succeeded,before-hook-creation,hook-failed" + name: "{{ .Release.Name }}-etcd-setup-1" + namespace: {{ .Release.Namespace }} +spec: + template: + metadata: + name: "{{ .Release.Name }}" + spec: + serviceAccountName: {{ include "etcd.serviceAccountName" . }} + restartPolicy: Never + initContainers: + - name: cfssl + image: cfssl/cfssl:latest + command: + - bash + - -c + - |- + cfssl gencert -initca /csr/ca-csr.json | cfssljson -bare /certs/ca && + mv /certs/ca.pem /certs/ca.crt && mv /certs/ca-key.pem /certs/ca.key && + cfssl gencert -ca=/certs/ca.crt -ca-key=/certs/ca.key -config=/csr/config.json -profile=peer-authentication /csr/peer-csr.json | cfssljson -bare /certs/peer && + cfssl gencert -ca=/certs/ca.crt -ca-key=/certs/ca.key -config=/csr/config.json -profile=peer-authentication /csr/server-csr.json | cfssljson -bare /certs/server && + cfssl gencert -ca=/certs/ca.crt -ca-key=/certs/ca.key -config=/csr/config.json -profile=client-authentication /csr/root-client-csr.json | cfssljson -bare /certs/root-client + volumeMounts: + - mountPath: /certs + name: certs + - mountPath: /csr + name: csr + containers: + - name: kubectl + image: {{ printf "clastix/kubectl:%s" (include "etcd.jobsTagKubeVersion" .) }} + command: ["/bin/sh", "-c"] + args: + - | + if kubectl get secret {{ include "etcd.caSecretName" . }} --namespace={{ .Release.Namespace }} &>/dev/null; then + echo "Secret {{ include "etcd.caSecretName" . }} already exists" + else + echo "Creating secret {{ include "etcd.caSecretName" . }}" + kubectl --namespace={{ .Release.Namespace }} create secret generic {{ include "etcd.caSecretName" . }} --from-file=/certs/ca.crt --from-file=/certs/ca.key --from-file=/certs/peer-key.pem --from-file=/certs/peer.pem --from-file=/certs/server-key.pem --from-file=/certs/server.pem + fi + if kubectl get secret {{ include "etcd.clientSecretName" . }} --namespace={{ .Release.Namespace }} &>/dev/null; then + echo "Secret {{ include "etcd.clientSecretName" . }} already exists" + else + echo "Creating secret {{ include "etcd.clientSecretName" . }}" + kubectl --namespace={{ .Release.Namespace }} create secret tls {{ include "etcd.clientSecretName" . }} --key=/certs/root-client-key.pem --cert=/certs/root-client.pem + fi + volumeMounts: + - mountPath: /certs + name: certs + securityContext: + runAsUser: 1000 + runAsGroup: 1000 + fsGroup: 1000 + {{- with .Values.tolerations }} + tolerations: {{- toYaml . | nindent 8 }} + {{- end }} + volumes: + - name: csr + configMap: + name: {{ include "etcd.csrConfigMapName" . }} + - name: certs + emptyDir: {} diff --git a/packages/system/kamaji-etcd/charts/kamaji-etcd/templates/etcd_job_preinstall_2.yaml b/packages/system/kamaji-etcd/charts/kamaji-etcd/templates/etcd_job_preinstall_2.yaml new file mode 100644 index 00000000..be55cddc --- /dev/null +++ b/packages/system/kamaji-etcd/charts/kamaji-etcd/templates/etcd_job_preinstall_2.yaml @@ -0,0 +1,71 @@ +apiVersion: batch/v1 +kind: Job +metadata: + labels: + {{- include "etcd.labels" . | nindent 4 }} + annotations: + "helm.sh/hook": post-install + "helm.sh/hook-weight": "10" + "helm.sh/hook-delete-policy": "hook-succeeded,before-hook-creation,hook-failed" + name: "{{ .Release.Name }}-etcd-setup-2" + namespace: {{ .Release.Namespace }} +spec: + backoffLimit: 12 + template: + metadata: + name: "{{ .Release.Name }}" + spec: + serviceAccountName: {{ include "etcd.serviceAccountName" . }} + restartPolicy: Never + initContainers: + - name: kubectl + image: {{ printf "clastix/kubectl:%s" (include "etcd.jobsTagKubeVersion" .) }} + command: + - sh + - -c + - kubectl --namespace={{ .Release.Namespace }} rollout status sts/{{ include "etcd.stsName" . }} --timeout=300s + containers: + - command: + - bash + - -c + - |- + etcdctl member list -w table + if etcdctl user get root &>/dev/null; then + echo "User already exists, nothing to do" + else + etcdctl user add --no-password=true root && + etcdctl role add root && + etcdctl user grant-role root root && + etcdctl auth enable + fi + env: + - name: ETCDCTL_ENDPOINTS + value: https://{{ include "etcd.fullname" . }}-0.{{ include "etcd.serviceName" . }}.{{ .Release.Namespace }}.svc.cluster.local:{{ .Values.clientPort }} + - name: ETCDCTL_CACERT + value: /opt/certs/ca/ca.crt + - name: ETCDCTL_CERT + value: /opt/certs/root-certs/tls.crt + - name: ETCDCTL_KEY + value: /opt/certs/root-certs/tls.key + image: {{ include "etcd.fullyQualifiedDockerImage" . }} + imagePullPolicy: IfNotPresent + name: etcd-client + volumeMounts: + - name: root-certs + mountPath: /opt/certs/root-certs + - name: ca + mountPath: /opt/certs/ca + securityContext: + runAsUser: 1000 + runAsGroup: 1000 + fsGroup: 1000 + {{- with .Values.tolerations }} + tolerations: {{- toYaml . | nindent 8 }} + {{- end }} + volumes: + - name: root-certs + secret: + secretName: {{ include "etcd.clientSecretName" . }} + - name: ca + secret: + secretName: {{ include "etcd.caSecretName" . }} diff --git a/packages/system/kamaji-etcd/charts/kamaji-etcd/templates/etcd_job_s3retention.yaml b/packages/system/kamaji-etcd/charts/kamaji-etcd/templates/etcd_job_s3retention.yaml new file mode 100644 index 00000000..cebe79f0 --- /dev/null +++ b/packages/system/kamaji-etcd/charts/kamaji-etcd/templates/etcd_job_s3retention.yaml @@ -0,0 +1,77 @@ +{{- if .Values.backup.enabled -}} +{{- if .Values.backup.s3.retention -}} +apiVersion: batch/v1 +kind: Job +metadata: + labels: + {{- include "etcd.labels" . | nindent 4 }} + annotations: + "helm.sh/hook": post-install,post-upgrade,post-rollback + "helm.sh/hook-weight": "5" + "helm.sh/hook-delete-policy": "hook-succeeded,before-hook-creation,hook-failed" + name: "{{ .Release.Name }}-s3-retention" + namespace: {{ .Release.Namespace }} +spec: + template: + metadata: + name: "{{ .Release.Name }}" + spec: + serviceAccountName: {{ include "etcd.serviceAccountName" . }} + restartPolicy: OnFailure + containers: + - name: minio-client + image: {{ include "minio-client.fullyQualifiedDockerImage" . }} + imagePullPolicy: {{ .Values.backup.s3.image.pullPolicy }} + command: + - bash + - -c + - |- + cd ${MC_CONFIG_DIR} + if $MC alias set myminio ${S3_URL} ${S3_ACCESS_KEY} ${S3_SECRET_KEY} \ + && $MC ping myminio -c 3 -e 3 ; then + echo -e "\nCheck for already created object lifecycle management rule(s):" + if $MC ilm ls myminio/${S3_BUCKET} ; then + echo -e "\nObject lifecycle management rule(s) found - Clean up:" + $MC ilm rm --all --force myminio/${S3_BUCKET} + else + echo -e "\nNo object lifecycle management rule(s) found - Continue" + fi + echo -e "\nAdding object lifecycle management rule(s):" + $MC ilm add {{ .Values.backup.s3.retention }} myminio/${S3_BUCKET} + $MC ilm ls myminio/${S3_BUCKET} + else + echo -e "\nERROR: S3 storage could not be configured;\nCheck your S3 URL/Credentials or network connectivity" + exit 1 + fi + env: + - name: S3_URL + value: {{ .Values.backup.s3.url | quote }} + - name: S3_ACCESS_KEY + {{- if .Values.backup.s3.accessKey.value }} + value: {{ .Values.backup.s3.accessKey.value | quote }} + {{- else }} + valueFrom: + {{- toYaml .Values.backup.s3.accessKey.valueFrom | nindent 12 }} + {{- end }} + - name: S3_SECRET_KEY + {{- if .Values.backup.s3.secretKey.value }} + value: {{ .Values.backup.s3.secretKey.value | quote }} + {{- else }} + valueFrom: + {{- toYaml .Values.backup.s3.secretKey.valueFrom | nindent 12 }} + {{- end }} + - name: S3_BUCKET + value: {{ .Values.backup.s3.bucket | quote }} + - name: MC_CONFIG_DIR + value: /tmp + - name: MC + value: "/usr/bin/mc --config-dir ${MC_CONFIG_DIR}" + {{- with .Values.tolerations }} + tolerations: {{- toYaml . | nindent 8 }} + {{- end }} + securityContext: + runAsUser: 1000 + runAsGroup: 1000 + fsGroup: 1000 +{{- end }} +{{- end }} diff --git a/packages/system/kamaji-etcd/charts/kamaji-etcd/templates/etcd_metrics_rbac.yaml b/packages/system/kamaji-etcd/charts/kamaji-etcd/templates/etcd_metrics_rbac.yaml new file mode 100644 index 00000000..fb6996fc --- /dev/null +++ b/packages/system/kamaji-etcd/charts/kamaji-etcd/templates/etcd_metrics_rbac.yaml @@ -0,0 +1,46 @@ +{{- if .Values.serviceMonitor.enabled }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + labels: + {{- include "etcd.labels" . | nindent 4 }} + {{- if .Values.serviceMonitor.labels }} + {{- toYaml .Values.serviceMonitor.labels | nindent 4 }} + {{- end }} + {{- with .Values.customAnnotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} + name: {{ include "etcd.fullname" . }}-metrics-role + namespace: {{ .Values.serviceMonitor.namespace | default .Release.Namespace }} +rules: +- apiGroups: + - "" + resources: + - services + - endpoints + - pods + verbs: + - get + - list + - watch +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + labels: + {{- include "etcd.labels" . | nindent 4 }} + {{- if .Values.serviceMonitor.labels }} + {{- toYaml .Values.serviceMonitor.labels | nindent 4 }} + {{- end }} + name: {{ include "etcd.fullname" . }}-metrics-rolebinding + namespace: {{ .Values.serviceMonitor.namespace | default .Release.Namespace }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ include "etcd.fullname" . }}-metrics-role +subjects: +- kind: ServiceAccount + name: {{ .Values.serviceMonitor.serviceAccount.name }} + namespace: {{ .Values.serviceMonitor.serviceAccount.namespace | default .Release.Namespace }} +{{- end }} diff --git a/packages/system/kamaji-etcd/charts/kamaji-etcd/templates/etcd_rbac.yaml b/packages/system/kamaji-etcd/charts/kamaji-etcd/templates/etcd_rbac.yaml new file mode 100644 index 00000000..bdd41be1 --- /dev/null +++ b/packages/system/kamaji-etcd/charts/kamaji-etcd/templates/etcd_rbac.yaml @@ -0,0 +1,60 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + annotations: + "helm.sh/hook": pre-install,post-install,pre-delete + "helm.sh/hook-delete-policy": "hook-succeeded,before-hook-creation,hook-failed" + "helm.sh/hook-weight": "5" + labels: + {{- include "etcd.labels" . | nindent 4 }} + name: {{ include "etcd.roleName" . }} + namespace: {{ .Release.Namespace }} +rules: + - apiGroups: + - "" + resources: + - secrets + verbs: + - get + - patch + - delete + resourceNames: + - {{ include "etcd.caSecretName" . }} + - {{ include "etcd.clientSecretName" . }} + - apiGroups: + - "" + resources: + - secrets + verbs: + - create + - apiGroups: + - apps + resources: + - statefulsets + verbs: + - get + - list + - watch + - patch + resourceNames: + - {{ include "etcd.stsName" . }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + annotations: + "helm.sh/hook": pre-install,post-install,pre-delete + "helm.sh/hook-delete-policy": "hook-succeeded,before-hook-creation,hook-failed" + "helm.sh/hook-weight": "5" + labels: + {{- include "etcd.labels" . | nindent 4 }} + name: {{ include "etcd.roleBindingName" . }} + namespace: {{ .Release.Namespace }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ include "etcd.roleName" . }} +subjects: + - kind: ServiceAccount + name: {{ include "etcd.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} diff --git a/packages/system/kamaji-etcd/charts/kamaji-etcd/templates/etcd_sa.yaml b/packages/system/kamaji-etcd/charts/kamaji-etcd/templates/etcd_sa.yaml new file mode 100644 index 00000000..99061ba7 --- /dev/null +++ b/packages/system/kamaji-etcd/charts/kamaji-etcd/templates/etcd_sa.yaml @@ -0,0 +1,15 @@ +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "etcd.serviceAccountName" . }} + labels: + {{- include "etcd.labels" . | nindent 4 }} + annotations: + "helm.sh/hook": pre-install + "helm.sh/hook-delete-policy": "before-hook-creation,hook-failed" + "helm.sh/hook-weight": "0" + {{- with .Values.serviceAccount.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/packages/system/kamaji-etcd/charts/kamaji-etcd/templates/etcd_service.yaml b/packages/system/kamaji-etcd/charts/kamaji-etcd/templates/etcd_service.yaml new file mode 100644 index 00000000..8b739e87 --- /dev/null +++ b/packages/system/kamaji-etcd/charts/kamaji-etcd/templates/etcd_service.yaml @@ -0,0 +1,18 @@ +apiVersion: v1 +kind: Service +metadata: + labels: + {{- include "etcd.labels" . | nindent 4 }} + name: {{ include "etcd.serviceName" . }} + namespace: {{ .Release.Namespace }} +spec: + clusterIP: None + ports: + - port: {{ .Values.clientPort }} + name: client + - port: {{ .Values.peerApiPort }} + name: peer + - port: {{ .Values.metricsPort }} + name: metrics + selector: + {{- include "etcd.selectorLabels" . | nindent 4 }} diff --git a/packages/system/kamaji-etcd/charts/kamaji-etcd/templates/etcd_service_monitor.yaml b/packages/system/kamaji-etcd/charts/kamaji-etcd/templates/etcd_service_monitor.yaml new file mode 100644 index 00000000..8b9c1aa3 --- /dev/null +++ b/packages/system/kamaji-etcd/charts/kamaji-etcd/templates/etcd_service_monitor.yaml @@ -0,0 +1,47 @@ +{{- if .Values.serviceMonitor.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ include "etcd.fullname" . }}-monitor + namespace: {{ .Values.serviceMonitor.namespace | default .Release.Namespace }} + labels: + {{- include "etcd.labels" . | nindent 4 }} + {{- with .Values.serviceMonitor.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.serviceMonitor.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + endpoints: + {{- with .Values.serviceMonitor.endpoint }} + - interval: {{ .interval }} + port: metrics + path: /metrics + {{- with .scrapeTimeout }} + scrapeTimeout: {{ . }} + {{- end }} + {{- with .metricRelabelings }} + metricRelabelings: {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .relabelings }} + relabelings: {{- toYaml . | nindent 6 }} + {{- end }} + {{- end }} + jobLabel: app.kubernetes.io/name + {{- with .Values.serviceMonitor.targetLabels }} + targetLabels: {{- toYaml . | nindent 4 }} + {{- end }} + selector: + matchLabels: + {{- if .Values.serviceMonitor.matchLabels }} + {{- toYaml .Values.serviceMonitor.matchLabels | nindent 6 }} + {{- else }} + {{- include "etcd.labels" . | nindent 6 }} + {{- end }} + namespaceSelector: + matchNames: + - {{ .Release.Namespace }} +{{- end }} + diff --git a/packages/system/kamaji-etcd/charts/kamaji-etcd/templates/etcd_sts.yaml b/packages/system/kamaji-etcd/charts/kamaji-etcd/templates/etcd_sts.yaml new file mode 100644 index 00000000..16b84e9e --- /dev/null +++ b/packages/system/kamaji-etcd/charts/kamaji-etcd/templates/etcd_sts.yaml @@ -0,0 +1,117 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + labels: + {{- include "etcd.labels" . | nindent 4 }} + name: {{ include "etcd.stsName" . }} + namespace: {{ .Release.Namespace }} +spec: + serviceName: {{ include "etcd.serviceName" . }} + selector: + matchLabels: + {{- include "etcd.selectorLabels" . | nindent 6 }} + replicas: {{ .Values.replicas }} + template: + metadata: + name: etcd + labels: + {{- include "etcd.selectorLabels" . | nindent 8 }} + {{- if .Values.podLabels }} + {{- toYaml .Values.podLabels | nindent 8 }} + {{- end }} + annotations: + {{- if .Values.podAnnotations }} + {{- toYaml .Values.podAnnotations | nindent 8 }} + {{- end }} + spec: + volumes: + - name: certs + secret: + secretName: {{ include "etcd.caSecretName" . }} + containers: + - name: etcd + image: {{ include "etcd.fullyQualifiedDockerImage" . }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 12 }} + ports: + - containerPort: {{ .Values.clientPort }} + name: client + - containerPort: {{ .Values.peerApiPort }} + name: peer + - containerPort: {{ .Values.metricsPort }} + name: metrics + volumeMounts: + - name: data + mountPath: /var/run/etcd + - name: certs + mountPath: /etc/etcd/pki + command: + - etcd + - --data-dir=/var/run/etcd + - --name=$(POD_NAME) + - --initial-cluster-state=new + - --initial-cluster={{ include "etcd.initialCluster" . }} + - --initial-advertise-peer-urls=https://$(POD_NAME).{{ include "etcd.serviceName" . }}.$(POD_NAMESPACE).svc.cluster.local:{{ .Values.peerApiPort }} + - --advertise-client-urls=https://$(POD_NAME).{{ include "etcd.serviceName" . }}.$(POD_NAMESPACE).svc.cluster.local:{{ .Values.clientPort }} + - --initial-cluster-token=kamaji + - --listen-client-urls=https://0.0.0.0:{{ .Values.clientPort }} + - --listen-metrics-urls=http://0.0.0.0:{{ .Values.metricsPort }} + - --listen-peer-urls=https://0.0.0.0:{{ .Values.peerApiPort }} + - --client-cert-auth=true + - --peer-client-cert-auth=true + - --trusted-ca-file=/etc/etcd/pki/ca.crt + - --cert-file=/etc/etcd/pki/server.pem + - --key-file=/etc/etcd/pki/server-key.pem + - --peer-trusted-ca-file=/etc/etcd/pki/ca.crt + - --peer-cert-file=/etc/etcd/pki/peer.pem + - --peer-key-file=/etc/etcd/pki/peer-key.pem + - --auto-compaction-mode={{ .Values.autoCompactionMode }} + - --auto-compaction-retention={{ .Values.autoCompactionRetention }} + - --snapshot-count={{ .Values.snapshotCount }} + - --quota-backend-bytes={{ .Values.quotaBackendBytes }} + {{- with .Values.extraArgs }} + {{- toYaml . | nindent 12 }} + {{- end }} + env: + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + {{- with .Values.livenessProbe }} + livenessProbe: + {{- toYaml . | nindent 12 }} + {{- end }} + priorityClassName: {{- toYaml .Values.priorityClassName | nindent 8 }} + {{- with .Values.nodeSelector }} + nodeSelector: {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.topologySpreadConstraints }} + topologySpreadConstraints: {{- toYaml . | nindent 8 }} + {{- end }} + volumeClaimTemplates: + - metadata: + name: data + {{- with .Values.persistentVolumeClaim.customAnnotations }} + annotations: + {{- toYaml . | nindent 10 }} + {{- end }} + spec: + storageClassName: {{ .Values.persistentVolumeClaim.storageClassName }} + accessModes: + {{- range .Values.persistentVolumeClaim.accessModes }} + - {{ . | quote }} + {{- end }} + resources: + requests: + storage: {{ .Values.persistentVolumeClaim.size }} diff --git a/packages/system/kamaji-etcd/charts/kamaji-etcd/values.yaml b/packages/system/kamaji-etcd/charts/kamaji-etcd/values.yaml new file mode 100644 index 00000000..ca7a1c08 --- /dev/null +++ b/packages/system/kamaji-etcd/charts/kamaji-etcd/values.yaml @@ -0,0 +1,223 @@ +# Default values for kamaji-crane. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +# -- Size of the etcd cluster +replicas: 3 + +# -- Install an etcd with enabled multi-tenancy +serviceAccount: + # -- Create a ServiceAccount, required to install and provision the etcd backing storage (default: true) + create: true + # -- Define the ServiceAccount name to use during the setup and provision of the etcd backing storage (default: "") + name: "" + +image: + # -- Install image from specific repo + repository: quay.io/coreos/etcd + # -- Install image with specific tag, overwrite the tag in the chart + tag: "" + # -- Pull policy to use + pullPolicy: IfNotPresent + +# -- The peer API port which servers are listening to. +peerApiPort: 2380 + +# -- The client request port. +clientPort: 2379 + +# -- The port where etcd exposes metrics. +metricsPort: 2381 + +# -- The livenessProbe for the etcd container +livenessProbe: {} +# failureThreshold: 8 +# httpGet: +# path: /health?serializable=true +# port: 2381 +# scheme: HTTP +# initialDelaySeconds: 10 +# periodSeconds: 10 +# timeoutSeconds: 15 + +# -- A list of extra arguments to add to the etcd default ones +extraArgs: [] +#- --log-level=warn +#- --logger=zap + +# -- Interpret 'auto-compaction-retention' one of: periodic|revision. Use 'periodic' for duration based retention, 'revision' for revision number based retention. +autoCompactionMode: periodic + +# -- Auto compaction retention length. 0 means disable auto compaction. +autoCompactionRetention: 5m + +# -- Number of committed transactions to trigger a snapshot to disk. +snapshotCount: "10000" + +# -- Raise alarms when backend size exceeds the given quota. It will put the cluster into a maintenance mode which only accepts key reads and deletes. +quotaBackendBytes: "8589934592" # 8Gi + +persistentVolumeClaim: + # -- The size of persistent storage for etcd data + size: 10Gi + # -- A specific storage class + storageClassName: "" + # -- The Access Mode to storage + accessModes: + - ReadWriteOnce + # -- The custom annotations to add to the PVC + customAnnotations: {} + # volumeType: local + +# -- Enable storage defragmentation +defragmentation: + # -- The job scheduled maintenance time for defrag (empty to disable) + schedule: "*/15 * * * *" # https://crontab.guru/ + +# -- Enable storage backup +backup: + # -- Enable scheduling backup job + enabled: false + # -- Enable backup for all endpoints. When disabled, only the leader will be taken + all: false + # -- The job scheduled maintenance time for backup + schedule: "20 3 * * *" # https://crontab.guru/ + # -- The backup file name prefix + snapshotNamePrefix: mysnapshot + # -- The backup file date format (bash) + snapshotDateFormat: $(date +%Y%m%d) + # -- The S3 storage config section + s3: + # -- The S3 storage url + url: http://mys3storage:9000 + # -- The S3 storage bucket + bucket: mybucket + # -- The S3 storage object lifecycle management rules; N.B. enabling this option will delete previously set lifecycle rules + retention: "" #"--expiry-days 7" + # -- The S3 storage ACCESS KEY credential. The plain value has precedence over the valueFrom that can be used to retrieve the value from a Secret. + accessKey: + value: "" + valueFrom: {} + # secretKeyRef: + # key: access_key + # name: minio-key + # -- The S3 storage SECRET KEY credential. The plain value has precedence over the valueFrom that can be used to retrieve the value from a Secret. + secretKey: + value: "" + valueFrom: {} + # secretKeyRef: + # key: secret_key + # name: minio-key + # -- The S3 client image config section + image: + # -- Install image from specific repo + repository: minio/mc + # -- Install image with specific tag + tag: "RELEASE.2022-11-07T23-47-39Z" + # -- Pull policy to use + pullPolicy: IfNotPresent + +# -- Labels to add to all etcd pods +podLabels: + application: kamaji-etcd + +# -- Annotations to add to all etcd pods +podAnnotations: {} + +# -- The securityContext to apply to etcd +securityContext: + allowPrivilegeEscalation: false + +# -- The priorityClassName to apply to etcd +priorityClassName: system-cluster-critical + +# -- Resources assigned to the etcd containers +resources: + limits: {} + requests: {} + +# -- Kubernetes node selector rules to schedule etcd +nodeSelector: + kubernetes.io/os: linux + +# -- Kubernetes node taints that the etcd pods would tolerate +tolerations: [] + +# -- Kubernetes affinity rules to apply to etcd controller pods +affinity: {} + +# -- Kubernetes topology spread constraints to apply to etcd controller pods +topologySpreadConstraints: [] +#- maxSkew: 1 +# topologyKey: topology.kubernetes.io/zone +# whenUnsatisfiable: DoNotSchedule +# labelSelector: +# matchLabels: +# application: kamaji-etcd + +datastore: + # -- Create a datastore custom resource for Kamaji + enabled: false + +serviceMonitor: + # -- Enable ServiceMonitor for Prometheus + enabled: false + # -- Install the ServiceMonitor into a different Namespace, as the monitoring stack one (default: the release one) + namespace: '' + # -- Assign additional labels according to Prometheus' serviceMonitorSelector matching labels + labels: {} + # -- Assign additional Annotations + annotations: {} + # -- Change matching labels + matchLabels: {} + # -- Set targetLabels for the serviceMonitor + targetLabels: [] + serviceAccount: + # -- ServiceAccount for Metrics RBAC + name: etcd + # -- ServiceAccount Namespace for Metrics RBAC + namespace: etcd-system + endpoint: + # -- Set the scrape interval for the endpoint of the serviceMonitor + interval: "15s" + # -- Set the scrape timeout for the endpoint of the serviceMonitor + scrapeTimeout: "" + # -- Set metricRelabelings for the endpoint of the serviceMonitor + metricRelabelings: [] + # -- Set relabelings for the endpoint of the serviceMonitor + relabelings: [] + #- action: replace + # regex: (.+) + # replacement: $1 + # sourceLabels: + # - __meta_kubernetes_pod_name + # targetLabel: member + # + +alerts: + # -- Enable alerts for Alertmanager + enabled: false + # -- Install the Alerts into a different Namespace, as the monitoring stack one (default: the release one) + namespace: '' + # -- Assign additional labels according to Prometheus' Alerts matching labels + labels: {} + # -- Assign additional Annotations + annotations: {} + # -- The rules for alerts + rules: [] + # - alert: etcdNoLeader + # annotations: + # message: 'etcd cluster: member {{ $labels.instance }} has no leader.' + # expr: count(etcd_server_has_leader{job=~".*etcd.*"}) == 0 + # for: 1m + # labels: + # severity: critical + # - alert: EtcdDataBaseSize + # annotations: + # message: 'etcd cluster: "member {{ $labels.instance }} db has almost exceeded 8GB".' + # expr: |- + # etcd_mvcc_db_total_size_in_bytes{job=~".*etcd.*"} >= 8589934592 + # for: 15m + # labels: + # severity: critical + # diff --git a/packages/system/kamaji-etcd/patches/fix-svc.diff b/packages/system/kamaji-etcd/patches/fix-svc.diff new file mode 100644 index 00000000..a94ebf96 --- /dev/null +++ b/packages/system/kamaji-etcd/patches/fix-svc.diff @@ -0,0 +1,12 @@ +diff --git a/packages/system/kamaji-etcd/charts/kamaji-etcd/templates/etcd_cm.yaml b/packages/system/kamaji-etcd/charts/kamaji-etcd/templates/etcd_cm.yaml +index 95a2671..bd8ddcb 100644 +--- a/packages/system/kamaji-etcd/charts/kamaji-etcd/templates/etcd_cm.yaml ++++ b/packages/system/kamaji-etcd/charts/kamaji-etcd/templates/etcd_cm.yaml +@@ -57,6 +57,7 @@ data: + "hosts": [ + {{- range $count := until (int $.Values.replicas) -}} + {{ printf "\"%s-%d.%s.%s.svc.cluster.local\"," ( include "etcd.fullname" $outer ) $count (include "etcd.serviceName" $outer) $.Release.Namespace }} ++ {{ printf "\"%s-%d.%s.%s.svc\"," ( include "etcd.fullname" $outer ) $count (include "etcd.serviceName" $outer) $.Release.Namespace }} + {{- end }} + "etcd-server.{{ .Release.Namespace }}.svc.cluster.local", + "etcd-server.{{ .Release.Namespace }}.svc", diff --git a/packages/system/kamaji-etcd/patches/fullnameOverride.diff b/packages/system/kamaji-etcd/patches/fullnameOverride.diff new file mode 100644 index 00000000..29a1a7ed --- /dev/null +++ b/packages/system/kamaji-etcd/patches/fullnameOverride.diff @@ -0,0 +1,31 @@ +diff --git a/packages/system/kamaji-etcd/charts/kamaji-etcd/templates/_helpers.tpl b/packages/system/kamaji-etcd/charts/kamaji-etcd/templates/_helpers.tpl +index 4f7014e..403e187 100644 +--- a/packages/system/kamaji-etcd/charts/kamaji-etcd/templates/_helpers.tpl ++++ b/packages/system/kamaji-etcd/charts/kamaji-etcd/templates/_helpers.tpl +@@ -9,8 +9,17 @@ Expand the name of the chart. + Create a default fully qualified etcd name. + */}} + {{- define "etcd.fullname" -}} +-{{- .Release.Name }} +-{{- end }} ++{{- if .Values.fullnameOverride -}} ++{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} ++{{- else -}} ++{{- $name := default .Chart.Name .Values.nameOverride -}} ++{{- if contains $name .Release.Name -}} ++{{- .Release.Name | trunc 63 | trimSuffix "-" -}} ++{{- else -}} ++{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} ++{{- end -}} ++{{- end -}} ++{{- end -}} + + {{/* + Create chart name and version as used by the chart label. +@@ -156,4 +165,4 @@ Create the minio-client fully-qualified Docker image to use + */}} + {{- define "minio-client.fullyQualifiedDockerImage" -}} + {{- printf "%s:%s" .Values.backup.s3.image.repository .Values.backup.s3.image.tag -}} +-{{- end }} +\ No newline at end of file ++{{- end }} diff --git a/packages/system/kamaji-etcd/templates/datastore.yaml b/packages/system/kamaji-etcd/templates/datastore.yaml new file mode 100644 index 00000000..9ca2ffee --- /dev/null +++ b/packages/system/kamaji-etcd/templates/datastore.yaml @@ -0,0 +1,33 @@ +apiVersion: kamaji.clastix.io/v1alpha1 +kind: DataStore +metadata: + name: {{ .Release.Namespace }} +spec: + driver: etcd + endpoints: + - etcd-0.etcd.{{ .Release.Namespace }}.svc:2379 + - etcd-1.etcd.{{ .Release.Namespace }}.svc:2379 + - etcd-2.etcd.{{ .Release.Namespace }}.svc:2379 + tlsConfig: + certificateAuthority: + certificate: + secretReference: + keyPath: ca.crt + name: etcd-certs + namespace: {{ .Release.Namespace }} + privateKey: + secretReference: + keyPath: ca.key + name: etcd-certs + namespace: {{ .Release.Namespace }} + clientCertificate: + certificate: + secretReference: + keyPath: tls.crt + name: etcd-root-client-certs + namespace: {{ .Release.Namespace }} + privateKey: + secretReference: + keyPath: tls.key + name: etcd-root-client-certs + namespace: {{ .Release.Namespace }} diff --git a/packages/system/kamaji/.helmignore b/packages/system/kamaji/.helmignore new file mode 100644 index 00000000..216b462f --- /dev/null +++ b/packages/system/kamaji/.helmignore @@ -0,0 +1,2 @@ +images +hack diff --git a/packages/system/kamaji/Chart.yaml b/packages/system/kamaji/Chart.yaml new file mode 100644 index 00000000..330dcfc4 --- /dev/null +++ b/packages/system/kamaji/Chart.yaml @@ -0,0 +1,2 @@ +name: cozy-kamaji +version: 1.0.0 diff --git a/packages/system/kamaji/Makefile b/packages/system/kamaji/Makefile new file mode 100644 index 00000000..79e6787c --- /dev/null +++ b/packages/system/kamaji/Makefile @@ -0,0 +1,18 @@ +NAME=kamaji +NAMESPACE=cozy-kamaji + +show: + helm template --dry-run=server -n $(NAMESPACE) $(NAME) . + +apply: + flux suspend hr kamaji -n cozy-kamaji || true + helm upgrade -i -n $(NAMESPACE) $(NAME) . + +diff: + helm diff upgrade --allow-unreleased --normalize-manifests -n $(NAMESPACE) $(NAME) . + +update: + rm -rf charts + helm repo add clastix https://clastix.github.io/charts + helm repo update clastix + helm pull clastix/kamaji --untar --untardir charts diff --git a/packages/system/kamaji/charts/kamaji/.helmignore b/packages/system/kamaji/charts/kamaji/.helmignore new file mode 100644 index 00000000..0e8a0eb3 --- /dev/null +++ b/packages/system/kamaji/charts/kamaji/.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/packages/system/kamaji/charts/kamaji/Chart.yaml b/packages/system/kamaji/charts/kamaji/Chart.yaml new file mode 100644 index 00000000..f2fb9252 --- /dev/null +++ b/packages/system/kamaji/charts/kamaji/Chart.yaml @@ -0,0 +1,22 @@ +annotations: + catalog.cattle.io/certified: partner + catalog.cattle.io/display-name: Kamaji + catalog.cattle.io/release-name: kamaji +apiVersion: v2 +appVersion: v0.4.1 +description: Kamaji is a Kubernetes Control Plane Manager. +home: https://github.com/clastix/kamaji +icon: https://github.com/clastix/kamaji/raw/master/assets/logo-colored.png +kubeVersion: '>=1.21.0-0' +maintainers: +- email: dario@tranchitella.eu + name: Dario Tranchitella +- email: me@maxgio.it + name: Massimiliano Giovagnoli +- email: me@bsctl.io + name: Adriano Pezzuto +name: kamaji +sources: +- https://github.com/clastix/kamaji +type: application +version: 0.14.1 diff --git a/packages/system/kamaji/charts/kamaji/Makefile b/packages/system/kamaji/charts/kamaji/Makefile new file mode 100644 index 00000000..a191fe4c --- /dev/null +++ b/packages/system/kamaji/charts/kamaji/Makefile @@ -0,0 +1,9 @@ +docs: HELMDOCS_VERSION := v1.8.1 +docs: docker + @docker run --rm -v "$$(pwd):/helm-docs" -u $$(id -u) jnorwood/helm-docs:$(HELMDOCS_VERSION) + +docker: + @hash docker 2>/dev/null || {\ + echo "You need docker" &&\ + exit 1;\ + } diff --git a/packages/system/kamaji/charts/kamaji/README.md b/packages/system/kamaji/charts/kamaji/README.md new file mode 100644 index 00000000..70e77a0b --- /dev/null +++ b/packages/system/kamaji/charts/kamaji/README.md @@ -0,0 +1,141 @@ +# kamaji + +![Version: 0.14.1](https://img.shields.io/badge/Version-0.14.1-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: v0.4.1](https://img.shields.io/badge/AppVersion-v0.4.1-informational?style=flat-square) + +Kamaji is a Kubernetes Control Plane Manager. + +## Maintainers + +| Name | Email | Url | +| ---- | ------ | --- | +| Dario Tranchitella | | | +| Massimiliano Giovagnoli | | | +| Adriano Pezzuto | | | + +## Source Code + +* + +## Requirements + +Kubernetes: `>=1.21.0-0` + +[Kamaji](https://github.com/clastix/kamaji) requires a [multi-tenant `etcd`](https://github.com/clastix/kamaji-internal/blob/master/deploy/getting-started-with-kamaji.md#setup-internal-multi-tenant-etcd) cluster. +This Helm Chart starting from v0.1.1 provides the installation of an internal `etcd` in order to streamline the local test. If you'd like to use an externally managed etcd instance, you can specify the overrides and by setting the value `etcd.deploy=false`. + +> For production use an externally managed `etcd` is highly recommended, the `etcd` addon offered by this Chart is not considered production-grade. + +## Install Kamaji + +To install the Chart with the release name `kamaji`: + + helm upgrade --install --namespace kamaji-system --create-namespace clastix/kamaji + +Show the status: + + helm status kamaji -n kamaji-system + +Upgrade the Chart + + helm upgrade kamaji -n kamaji-system clastix/kamaji + +Uninstall the Chart + + helm uninstall kamaji -n kamaji-system + +## Customize the installation + +There are two methods for specifying overrides of values during Chart installation: `--values` and `--set`. + +The `--values` option is the preferred method because it allows you to keep your overrides in a YAML file, rather than specifying them all on the command line. Create a copy of the YAML file `values.yaml` and add your overrides to it. + +Specify your overrides file when you install the Chart: + + helm upgrade kamaji --install --namespace kamaji-system --create-namespace clastix/kamaji --values myvalues.yaml + +The values in your overrides file `myvalues.yaml` will override their counterparts in the Chart's values.yaml file. Any values in `values.yaml` that weren’t overridden will keep their defaults. + +If you only need to make minor customizations, you can specify them on the command line by using the `--set` option. For example: + + helm upgrade kamaji --install --namespace kamaji-system --create-namespace clastix/kamaji --set etcd.deploy=false + +Here the values you can override: + +## Values + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| affinity | object | `{}` | Kubernetes affinity rules to apply to Kamaji controller pods | +| datastore.basicAuth.passwordSecret.keyPath | string | `nil` | The Secret key where the data is stored. | +| datastore.basicAuth.passwordSecret.name | string | `nil` | The name of the Secret containing the password used to connect to the relational database. | +| datastore.basicAuth.passwordSecret.namespace | string | `nil` | The namespace of the Secret containing the password used to connect to the relational database. | +| datastore.basicAuth.usernameSecret.keyPath | string | `nil` | The Secret key where the data is stored. | +| datastore.basicAuth.usernameSecret.name | string | `nil` | The name of the Secret containing the username used to connect to the relational database. | +| datastore.basicAuth.usernameSecret.namespace | string | `nil` | The namespace of the Secret containing the username used to connect to the relational database. | +| datastore.driver | string | `"etcd"` | (string) The Kamaji Datastore driver, supported: etcd, MySQL, PostgreSQL (defaults=etcd). | +| datastore.enabled | bool | `true` | (bool) Enable the Kamaji Datastore creation (default=true) | +| datastore.endpoints | list | `[]` | (array) List of endpoints of the selected Datastore. When letting the Chart install the etcd datastore, this field is populated automatically. | +| datastore.nameOverride | string | `nil` | The Datastore name override, if empty and enabled=true defaults to `default`, if enabled=false, this is the name of the Datastore to connect to. | +| datastore.tlsConfig.certificateAuthority.certificate.keyPath | string | `nil` | Key of the Secret which contains the content of the certificate. | +| datastore.tlsConfig.certificateAuthority.certificate.name | string | `nil` | Name of the Secret containing the CA required to establish the mandatory SSL/TLS connection to the datastore. | +| datastore.tlsConfig.certificateAuthority.certificate.namespace | string | `nil` | Namespace of the Secret containing the CA required to establish the mandatory SSL/TLS connection to the datastore. | +| datastore.tlsConfig.certificateAuthority.privateKey.keyPath | string | `nil` | Key of the Secret which contains the content of the private key. | +| datastore.tlsConfig.certificateAuthority.privateKey.name | string | `nil` | Name of the Secret containing the CA private key required to establish the mandatory SSL/TLS connection to the datastore. | +| datastore.tlsConfig.certificateAuthority.privateKey.namespace | string | `nil` | Namespace of the Secret containing the CA private key required to establish the mandatory SSL/TLS connection to the datastore. | +| datastore.tlsConfig.clientCertificate.certificate.keyPath | string | `nil` | Key of the Secret which contains the content of the certificate. | +| datastore.tlsConfig.clientCertificate.certificate.name | string | `nil` | Name of the Secret containing the client certificate required to establish the mandatory SSL/TLS connection to the datastore. | +| datastore.tlsConfig.clientCertificate.certificate.namespace | string | `nil` | Namespace of the Secret containing the client certificate required to establish the mandatory SSL/TLS connection to the datastore. | +| datastore.tlsConfig.clientCertificate.privateKey.keyPath | string | `nil` | Key of the Secret which contains the content of the private key. | +| datastore.tlsConfig.clientCertificate.privateKey.name | string | `nil` | Name of the Secret containing the client certificate private key required to establish the mandatory SSL/TLS connection to the datastore. | +| datastore.tlsConfig.clientCertificate.privateKey.namespace | string | `nil` | Namespace of the Secret containing the client certificate private key required to establish the mandatory SSL/TLS connection to the datastore. | +| etcd.compactionInterval | int | `0` | ETCD Compaction interval (e.g. "5m0s"). (default: "0" (disabled)) | +| etcd.deploy | bool | `true` | Install an etcd with enabled multi-tenancy along with Kamaji | +| etcd.image | object | `{"pullPolicy":"IfNotPresent","repository":"quay.io/coreos/etcd","tag":"v3.5.6"}` | Install specific etcd image | +| etcd.livenessProbe | object | `{"failureThreshold":8,"httpGet":{"path":"/health?serializable=true","port":2381,"scheme":"HTTP"},"initialDelaySeconds":10,"periodSeconds":10,"timeoutSeconds":15}` | The livenessProbe for the etcd container | +| etcd.overrides.caSecret.name | string | `"etcd-certs"` | Name of the secret which contains CA's certificate and private key. (default: "etcd-certs") | +| etcd.overrides.caSecret.namespace | string | `"kamaji-system"` | Namespace of the secret which contains CA's certificate and private key. (default: "kamaji-system") | +| etcd.overrides.clientSecret.name | string | `"root-client-certs"` | Name of the secret which contains ETCD client certificates. (default: "root-client-certs") | +| etcd.overrides.clientSecret.namespace | string | `"kamaji-system"` | Name of the namespace where the secret which contains ETCD client certificates is. (default: "kamaji-system") | +| etcd.overrides.endpoints | object | `{"etcd-0":"etcd-0.etcd.kamaji-system.svc.cluster.local","etcd-1":"etcd-1.etcd.kamaji-system.svc.cluster.local","etcd-2":"etcd-2.etcd.kamaji-system.svc.cluster.local"}` | (map) Dictionary of the endpoints for the etcd cluster's members, key is the name of the etcd server. Don't define the protocol (TLS is automatically inflected), or any port, inflected from .etcd.peerApiPort value. | +| etcd.peerApiPort | int | `2380` | The peer API port which servers are listening to. | +| etcd.persistence.accessModes[0] | string | `"ReadWriteOnce"` | | +| etcd.persistence.customAnnotations | object | `{}` | The custom annotations to add to the PVC | +| etcd.persistence.size | string | `"10Gi"` | | +| etcd.persistence.storageClassName | string | `""` | | +| etcd.port | int | `2379` | The client request port. | +| etcd.serviceAccount.create | bool | `true` | Create a ServiceAccount, required to install and provision the etcd backing storage (default: true) | +| etcd.serviceAccount.name | string | `""` | Define the ServiceAccount name to use during the setup and provision of the etcd backing storage (default: "") | +| etcd.tolerations | list | `[]` | (array) Kubernetes affinity rules to apply to Kamaji etcd pods | +| extraArgs | list | `[]` | A list of extra arguments to add to the kamaji controller default ones | +| fullnameOverride | string | `""` | | +| healthProbeBindAddress | string | `":8081"` | The address the probe endpoint binds to. (default ":8081") | +| image.pullPolicy | string | `"Always"` | | +| image.repository | string | `"clastix/kamaji"` | The container image of the Kamaji controller. | +| image.tag | string | `nil` | Overrides the image tag whose default is the chart appVersion. | +| imagePullSecrets | list | `[]` | | +| livenessProbe | object | `{"httpGet":{"path":"/healthz","port":"healthcheck"},"initialDelaySeconds":15,"periodSeconds":20}` | The livenessProbe for the controller container | +| loggingDevel.enable | bool | `false` | (string) Development Mode defaults(encoder=consoleEncoder,logLevel=Debug,stackTraceLevel=Warn). Production Mode defaults(encoder=jsonEncoder,logLevel=Info,stackTraceLevel=Error) (default false) | +| metricsBindAddress | string | `":8080"` | (string) The address the metric endpoint binds to. (default ":8080") | +| nameOverride | string | `""` | | +| nodeSelector | object | `{}` | Kubernetes node selector rules to schedule Kamaji controller | +| podAnnotations | object | `{}` | The annotations to apply to the Kamaji controller pods. | +| podSecurityContext | object | `{"runAsNonRoot":true}` | The securityContext to apply to the Kamaji controller pods. | +| readinessProbe | object | `{"httpGet":{"path":"/readyz","port":"healthcheck"},"initialDelaySeconds":5,"periodSeconds":10}` | The readinessProbe for the controller container | +| replicaCount | int | `1` | The number of the pod replicas for the Kamaji controller. | +| resources.limits.cpu | string | `"200m"` | | +| resources.limits.memory | string | `"100Mi"` | | +| resources.requests.cpu | string | `"100m"` | | +| resources.requests.memory | string | `"20Mi"` | | +| securityContext | object | `{"allowPrivilegeEscalation":false}` | The securityContext to apply to the Kamaji controller container only. It does not apply to the Kamaji RBAC proxy container. | +| serviceAccount.annotations | object | `{}` | | +| serviceAccount.create | bool | `true` | | +| serviceAccount.name | string | `"kamaji-controller-manager"` | | +| serviceMonitor.enabled | bool | `false` | Toggle the ServiceMonitor true if you have Prometheus Operator installed and configured | +| temporaryDirectoryPath | string | `"/tmp/kamaji"` | Directory which will be used to work with temporary files. (default "/tmp/kamaji") | +| tolerations | list | `[]` | Kubernetes node taints that the Kamaji controller pods would tolerate | + +## Installing and managing etcd as DataStore + +Kamaji supports multiple data store, although `etcd` is the default one: thus, an initial cluster will be created upon the Chart installation. + +The `DataStore` resource can be configured with the proper values in case of overrides when using a different driver, otherwise all the required data will be inherited by the Chart values. diff --git a/packages/system/kamaji/charts/kamaji/README.md.gotmpl b/packages/system/kamaji/charts/kamaji/README.md.gotmpl new file mode 100644 index 00000000..709b0eb3 --- /dev/null +++ b/packages/system/kamaji/charts/kamaji/README.md.gotmpl @@ -0,0 +1,62 @@ +{{ template "chart.header" . }} +{{ template "chart.deprecationWarning" . }} + +{{ template "chart.badgesSection" . }} + +{{ template "chart.description" . }} + +{{ template "chart.maintainersSection" . }} + +{{ template "chart.sourcesSection" . }} + +{{ template "chart.requirementsSection" . }} + +[Kamaji](https://github.com/clastix/kamaji) requires a [multi-tenant `etcd`](https://github.com/clastix/kamaji-internal/blob/master/deploy/getting-started-with-kamaji.md#setup-internal-multi-tenant-etcd) cluster. +This Helm Chart starting from v0.1.1 provides the installation of an internal `etcd` in order to streamline the local test. If you'd like to use an externally managed etcd instance, you can specify the overrides and by setting the value `etcd.deploy=false`. + +> For production use an externally managed `etcd` is highly recommended, the `etcd` addon offered by this Chart is not considered production-grade. + +## Install Kamaji + +To install the Chart with the release name `kamaji`: + + + helm upgrade --install --namespace kamaji-system --create-namespace clastix/kamaji + +Show the status: + + helm status kamaji -n kamaji-system + +Upgrade the Chart + + helm upgrade kamaji -n kamaji-system clastix/kamaji + +Uninstall the Chart + + helm uninstall kamaji -n kamaji-system + +## Customize the installation + +There are two methods for specifying overrides of values during Chart installation: `--values` and `--set`. + +The `--values` option is the preferred method because it allows you to keep your overrides in a YAML file, rather than specifying them all on the command line. Create a copy of the YAML file `values.yaml` and add your overrides to it. + +Specify your overrides file when you install the Chart: + + helm upgrade kamaji --install --namespace kamaji-system --create-namespace clastix/kamaji --values myvalues.yaml + +The values in your overrides file `myvalues.yaml` will override their counterparts in the Chart's values.yaml file. Any values in `values.yaml` that weren’t overridden will keep their defaults. + +If you only need to make minor customizations, you can specify them on the command line by using the `--set` option. For example: + + helm upgrade kamaji --install --namespace kamaji-system --create-namespace clastix/kamaji --set etcd.deploy=false + +Here the values you can override: + +{{ template "chart.valuesSection" . }} + +## Installing and managing etcd as DataStore + +Kamaji supports multiple data store, although `etcd` is the default one: thus, an initial cluster will be created upon the Chart installation. + +The `DataStore` resource can be configured with the proper values in case of overrides when using a different driver, otherwise all the required data will be inherited by the Chart values. diff --git a/packages/system/kamaji/charts/kamaji/app-readme.md b/packages/system/kamaji/charts/kamaji/app-readme.md new file mode 100644 index 00000000..a87e8b7b --- /dev/null +++ b/packages/system/kamaji/charts/kamaji/app-readme.md @@ -0,0 +1,12 @@ +# Kamaji + +Kamaji deploys and operates Kubernetes at scale with a fraction of the operational burden. + +Useful links: +- [Kamaji Github repository](https://github.com/clastix/kamaji) +- [Kamaji Documentation](https://kamaji.clastix.io) + +## Requirements + +* Kubernetes v1.22+ +* Helm v3 \ No newline at end of file diff --git a/packages/system/kamaji/charts/kamaji/crds/datastore.yaml b/packages/system/kamaji/charts/kamaji/crds/datastore.yaml new file mode 100644 index 00000000..fade41f2 --- /dev/null +++ b/packages/system/kamaji/charts/kamaji/crds/datastore.yaml @@ -0,0 +1,239 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + cert-manager.io/inject-ca-from: kamaji-system/kamaji-serving-cert + controller-gen.kubebuilder.io/version: v0.11.4 + name: datastores.kamaji.clastix.io +spec: + group: kamaji.clastix.io + names: + kind: DataStore + listKind: DataStoreList + plural: datastores + singular: datastore + scope: Cluster + versions: + - additionalPrinterColumns: + - description: Kamaji data store driver + jsonPath: .spec.driver + name: Driver + type: string + - description: Age + jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + description: DataStore is the Schema for the datastores 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: DataStoreSpec defines the desired state of DataStore. + properties: + basicAuth: + description: In case of authentication enabled for the given data store, specifies the username and password pair. This value is optional. + properties: + password: + properties: + content: + description: Bare content of the file, base64 encoded. It has precedence over the SecretReference value. + format: byte + type: string + secretReference: + properties: + keyPath: + description: Name of the key for the given Secret reference where the content is stored. This value is mandatory. + minLength: 1 + type: string + name: + description: name is unique within a namespace to reference a secret resource. + type: string + namespace: + description: namespace defines the space within which the secret name must be unique. + type: string + required: + - keyPath + type: object + x-kubernetes-map-type: atomic + type: object + username: + properties: + content: + description: Bare content of the file, base64 encoded. It has precedence over the SecretReference value. + format: byte + type: string + secretReference: + properties: + keyPath: + description: Name of the key for the given Secret reference where the content is stored. This value is mandatory. + minLength: 1 + type: string + name: + description: name is unique within a namespace to reference a secret resource. + type: string + namespace: + description: namespace defines the space within which the secret name must be unique. + type: string + required: + - keyPath + type: object + x-kubernetes-map-type: atomic + type: object + required: + - password + - username + type: object + driver: + description: The driver to use to connect to the shared datastore. + enum: + - etcd + - MySQL + - PostgreSQL + type: string + endpoints: + description: List of the endpoints to connect to the shared datastore. No need for protocol, just bare IP/FQDN and port. + items: + type: string + minItems: 1 + type: array + tlsConfig: + description: Defines the TLS/SSL configuration required to connect to the data store in a secure way. + properties: + certificateAuthority: + description: Retrieve the Certificate Authority certificate and private key, such as bare content of the file, or a SecretReference. The key reference is required since etcd authentication is based on certificates, and Kamaji is responsible in creating this. + properties: + certificate: + properties: + content: + description: Bare content of the file, base64 encoded. It has precedence over the SecretReference value. + format: byte + type: string + secretReference: + properties: + keyPath: + description: Name of the key for the given Secret reference where the content is stored. This value is mandatory. + minLength: 1 + type: string + name: + description: name is unique within a namespace to reference a secret resource. + type: string + namespace: + description: namespace defines the space within which the secret name must be unique. + type: string + required: + - keyPath + type: object + x-kubernetes-map-type: atomic + type: object + privateKey: + properties: + content: + description: Bare content of the file, base64 encoded. It has precedence over the SecretReference value. + format: byte + type: string + secretReference: + properties: + keyPath: + description: Name of the key for the given Secret reference where the content is stored. This value is mandatory. + minLength: 1 + type: string + name: + description: name is unique within a namespace to reference a secret resource. + type: string + namespace: + description: namespace defines the space within which the secret name must be unique. + type: string + required: + - keyPath + type: object + x-kubernetes-map-type: atomic + type: object + required: + - certificate + type: object + clientCertificate: + description: Specifies the SSL/TLS key and private key pair used to connect to the data store. + properties: + certificate: + properties: + content: + description: Bare content of the file, base64 encoded. It has precedence over the SecretReference value. + format: byte + type: string + secretReference: + properties: + keyPath: + description: Name of the key for the given Secret reference where the content is stored. This value is mandatory. + minLength: 1 + type: string + name: + description: name is unique within a namespace to reference a secret resource. + type: string + namespace: + description: namespace defines the space within which the secret name must be unique. + type: string + required: + - keyPath + type: object + x-kubernetes-map-type: atomic + type: object + privateKey: + properties: + content: + description: Bare content of the file, base64 encoded. It has precedence over the SecretReference value. + format: byte + type: string + secretReference: + properties: + keyPath: + description: Name of the key for the given Secret reference where the content is stored. This value is mandatory. + minLength: 1 + type: string + name: + description: name is unique within a namespace to reference a secret resource. + type: string + namespace: + description: namespace defines the space within which the secret name must be unique. + type: string + required: + - keyPath + type: object + x-kubernetes-map-type: atomic + type: object + required: + - certificate + - privateKey + type: object + required: + - certificateAuthority + - clientCertificate + type: object + required: + - driver + - endpoints + - tlsConfig + type: object + status: + description: DataStoreStatus defines the observed state of DataStore. + properties: + usedBy: + description: List of the Tenant Control Planes, namespaced named, using this data store. + items: + type: string + type: array + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/packages/system/kamaji/charts/kamaji/crds/tenantcontrolplane.yaml b/packages/system/kamaji/charts/kamaji/crds/tenantcontrolplane.yaml new file mode 100644 index 00000000..e4746204 --- /dev/null +++ b/packages/system/kamaji/charts/kamaji/crds/tenantcontrolplane.yaml @@ -0,0 +1,7736 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + cert-manager.io/inject-ca-from: kamaji-system/kamaji-serving-cert + controller-gen.kubebuilder.io/version: v0.11.4 + name: tenantcontrolplanes.kamaji.clastix.io +spec: + conversion: + strategy: Webhook + webhook: + clientConfig: + service: + name: kamaji-webhook-service + namespace: kamaji-system + path: /convert + conversionReviewVersions: + - v1 + group: kamaji.clastix.io + names: + kind: TenantControlPlane + listKind: TenantControlPlaneList + plural: tenantcontrolplanes + shortNames: + - tcp + singular: tenantcontrolplane + scope: Namespaced + versions: + - additionalPrinterColumns: + - description: Kubernetes version + jsonPath: .spec.kubernetes.version + name: Version + type: string + - description: Status + jsonPath: .status.kubernetesResources.version.status + name: Status + type: string + - description: Tenant Control Plane Endpoint (API server) + jsonPath: .status.controlPlaneEndpoint + name: Control-Plane endpoint + type: string + - description: Secret which contains admin kubeconfig + jsonPath: .status.kubeconfig.admin.secretName + name: Kubeconfig + type: string + - description: DataStore actually used + jsonPath: .status.storage.dataStoreName + name: Datastore + type: string + - description: Age + jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + description: TenantControlPlane is the Schema for the tenantcontrolplanes + 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: TenantControlPlaneSpec defines the desired state of TenantControlPlane. + properties: + addons: + description: Addons contain which addons are enabled + properties: + coreDNS: + description: Enables the DNS addon in the Tenant Cluster. The + registry and the tag are configurable, the image is hard-coded + to `coredns`. + properties: + imageRepository: + description: ImageRepository sets the container registry to + pull images from. if not set, the default ImageRepository + will be used instead. + type: string + imageTag: + description: ImageTag allows to specify a tag for the image. + In case this value is set, kubeadm does not change automatically + the version of the above components during upgrades. + type: string + type: object + konnectivity: + description: Enables the Konnectivity addon in the Tenant Cluster, + required if the worker nodes are in a different network. + properties: + agent: + default: + image: registry.k8s.io/kas-network-proxy/proxy-agent + version: v0.0.32 + properties: + extraArgs: + description: ExtraArgs allows adding additional arguments + to said component. + items: + type: string + type: array + image: + default: registry.k8s.io/kas-network-proxy/proxy-agent + description: AgentImage defines the container image for + Konnectivity's agent. + type: string + version: + default: v0.0.32 + description: Version for Konnectivity agent. + type: string + type: object + server: + default: + image: registry.k8s.io/kas-network-proxy/proxy-server + port: 8132 + version: v0.0.32 + properties: + extraArgs: + description: ExtraArgs allows adding additional arguments + to said component. + items: + type: string + type: array + image: + default: registry.k8s.io/kas-network-proxy/proxy-server + description: Container image used by the Konnectivity + server. + type: string + port: + description: The port which Konnectivity server is listening + to. + format: int32 + type: integer + resources: + description: Resources define the amount of CPU and memory + to allocate to the Konnectivity server. + properties: + claims: + description: "Claims lists the names of resources, + defined in spec.resourceClaims, that are used by + this container. \n This is an alpha field and requires + enabling the DynamicResourceAllocation feature gate. + \n 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 + 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 + version: + default: v0.0.32 + description: Container image version of the Konnectivity + server. + type: string + required: + - port + type: object + type: object + kubeProxy: + description: Enables the kube-proxy addon in the Tenant Cluster. + The registry and the tag are configurable, the image is hard-coded + to `kube-proxy`. + properties: + imageRepository: + description: ImageRepository sets the container registry to + pull images from. if not set, the default ImageRepository + will be used instead. + type: string + imageTag: + description: ImageTag allows to specify a tag for the image. + In case this value is set, kubeadm does not change automatically + the version of the above components during upgrades. + type: string + type: object + type: object + controlPlane: + description: ControlPlane defines how the Tenant Control Plane Kubernetes + resources must be created in the Admin Cluster, such as the number + of Pod replicas, the Service resource, or the Ingress. + properties: + deployment: + description: Defining the options for the deployed Tenant Control + Plane as Deployment resource. + properties: + additionalContainers: + description: AdditionalContainers allows adding additional + containers to the Control Plane deployment. + items: + description: A single application container that you want + to run within a pod. + properties: + args: + description: 'Arguments to the entrypoint. The container + image''s CMD is used if this is not provided. Variable + references $(VAR_NAME) are expanded using the container''s + environment. 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. Cannot be updated. More info: + https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell' + items: + type: string + type: array + command: + description: 'Entrypoint array. Not executed within + a shell. The container image''s ENTRYPOINT is used + if this is not provided. Variable references $(VAR_NAME) + are expanded using the container''s environment. 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. Cannot be updated. More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell' + items: + type: string + type: array + env: + description: List of environment variables to set in + the container. Cannot be updated. + 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: + description: 'Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + 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: + description: 'Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + 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 + envFrom: + description: List of sources to populate environment + variables in the container. The keys defined within + a source must be a C_IDENTIFIER. All invalid keys + will be reported as an event when the container is + starting. 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. Cannot be updated. + items: + description: EnvFromSource represents the source of + a set of ConfigMaps + properties: + configMapRef: + description: The ConfigMap to select from + properties: + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + optional: + description: Specify whether the ConfigMap + must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + description: An optional identifier to prepend + to each key in the ConfigMap. Must be a C_IDENTIFIER. + type: string + secretRef: + description: The Secret to select from + properties: + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + optional: + description: Specify whether the Secret must + be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + image: + description: 'Container image name. More info: https://kubernetes.io/docs/concepts/containers/images + This field is optional to allow higher level config + management to default or override container images + in workload controllers like Deployments and StatefulSets.' + type: string + imagePullPolicy: + description: 'Image pull policy. One of Always, Never, + IfNotPresent. Defaults to Always if :latest tag is + specified, or IfNotPresent otherwise. Cannot be updated. + More info: https://kubernetes.io/docs/concepts/containers/images#updating-images' + type: string + lifecycle: + description: Actions that the management system should + take in response to container lifecycle events. Cannot + be updated. + properties: + postStart: + description: 'PostStart is called immediately after + a container is created. If the handler fails, + the container is terminated and restarted according + to its restart policy. Other management of the + container blocks until the hook completes. More + info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks' + properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line + to execute inside the container, the working + directory for the command is root ('/') + in the container's filesystem. The command + is simply exec'd, it is not run inside + a shell, so traditional shell instructions + ('|', etc) won't work. To use a shell, + you need to explicitly call out to that + shell. Exit status of 0 is treated as + live/healthy and non-zero is unhealthy. + items: + type: string + type: array + type: object + httpGet: + description: HTTPGet specifies the http request + to perform. + properties: + host: + description: Host name to connect to, defaults + to the pod IP. You probably want to set + "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the + request. HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom + header to be used in HTTP probes + properties: + name: + description: The header field name. + This will be canonicalized upon + output, so case-variant names will + be understood as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP + server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port + to access on the container. Number must + be in the range 1 to 65535. Name must + be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting + to the host. Defaults to HTTP. + type: string + required: + - port + type: object + sleep: + description: Sleep represents the duration that + the container should sleep before being terminated. + properties: + seconds: + description: Seconds is the number of seconds + to sleep. + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + description: Deprecated. TCPSocket is NOT supported + as a LifecycleHandler and kept for the backward + compatibility. There are no validation of + this field and lifecycle hooks will fail in + runtime when tcp handler is specified. + properties: + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port + to access on the container. Number must + be in the range 1 to 65535. Name must + be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + preStop: + description: 'PreStop is called immediately before + a container is terminated due to an API request + or management event such as liveness/startup probe + failure, preemption, resource contention, etc. + The handler is not called if the container crashes + or exits. The Pod''s termination grace period + countdown begins before the PreStop hook is executed. + Regardless of the outcome of the handler, the + container will eventually terminate within the + Pod''s termination grace period (unless delayed + by finalizers). Other management of the container + blocks until the hook completes or until the termination + grace period is reached. More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks' + properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line + to execute inside the container, the working + directory for the command is root ('/') + in the container's filesystem. The command + is simply exec'd, it is not run inside + a shell, so traditional shell instructions + ('|', etc) won't work. To use a shell, + you need to explicitly call out to that + shell. Exit status of 0 is treated as + live/healthy and non-zero is unhealthy. + items: + type: string + type: array + type: object + httpGet: + description: HTTPGet specifies the http request + to perform. + properties: + host: + description: Host name to connect to, defaults + to the pod IP. You probably want to set + "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the + request. HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom + header to be used in HTTP probes + properties: + name: + description: The header field name. + This will be canonicalized upon + output, so case-variant names will + be understood as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP + server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port + to access on the container. Number must + be in the range 1 to 65535. Name must + be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting + to the host. Defaults to HTTP. + type: string + required: + - port + type: object + sleep: + description: Sleep represents the duration that + the container should sleep before being terminated. + properties: + seconds: + description: Seconds is the number of seconds + to sleep. + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + description: Deprecated. TCPSocket is NOT supported + as a LifecycleHandler and kept for the backward + compatibility. There are no validation of + this field and lifecycle hooks will fail in + runtime when tcp handler is specified. + properties: + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port + to access on the container. Number must + be in the range 1 to 65535. Name must + be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + type: object + livenessProbe: + description: 'Periodic probe of container liveness. + Container will be restarted if the probe fails. Cannot + be updated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to + execute inside the container, the working + directory for the command is root ('/') in + the container's filesystem. The command is + simply exec'd, it is not run inside a shell, + so traditional shell instructions ('|', etc) + won't work. To use a shell, you need to explicitly + call out to that shell. Exit status of 0 is + treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + type: object + failureThreshold: + description: Minimum consecutive failures for the + probe to be considered failed after having succeeded. + Defaults to 3. Minimum value is 1. + format: int32 + type: integer + grpc: + description: GRPC specifies an action involving + a GRPC port. + properties: + port: + description: Port number of the gRPC service. + Number must be in the range 1 to 65535. + format: int32 + type: integer + service: + description: "Service is the name of the service + to place in the gRPC HealthCheckRequest (see + https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + \n If this is not specified, the default behavior + is defined by gRPC." + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies the http request + to perform. + properties: + host: + description: Host name to connect to, defaults + to the pod IP. You probably want to set "Host" + in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the request. + HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom + header to be used in HTTP probes + properties: + name: + description: The header field name. This + will be canonicalized upon output, so + case-variant names will be understood + as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to + the host. Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: 'Number of seconds after the container + has started before liveness probes are initiated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + periodSeconds: + description: How often (in seconds) to perform the + probe. Default to 10 seconds. Minimum value is + 1. + format: int32 + type: integer + successThreshold: + description: Minimum consecutive successes for the + probe to be considered successful after having + failed. Defaults to 1. Must be 1 for liveness + and startup. Minimum value is 1. + format: int32 + type: integer + tcpSocket: + description: TCPSocket specifies an action involving + a TCP port. + properties: + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: Optional duration in seconds the pod + needs to terminate gracefully upon probe failure. + The grace period is the duration in seconds after + the processes running in the pod are sent a termination + signal and the time when the processes are forcibly + halted with a kill signal. Set this value longer + than the expected cleanup time for your process. + If this value is nil, the pod's terminationGracePeriodSeconds + will be used. Otherwise, this value overrides + the value provided by the pod spec. Value must + be non-negative integer. The value zero indicates + stop immediately via the kill signal (no opportunity + to shut down). This is a beta field and requires + enabling ProbeTerminationGracePeriod feature gate. + Minimum value is 1. spec.terminationGracePeriodSeconds + is used if unset. + format: int64 + type: integer + timeoutSeconds: + description: 'Number of seconds after which the + probe times out. Defaults to 1 second. Minimum + value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + type: object + name: + description: Name of the container specified as a DNS_LABEL. + Each container in a pod must have a unique name (DNS_LABEL). + Cannot be updated. + type: string + ports: + description: List of ports to expose from the container. + Not specifying a port here DOES NOT prevent that port + from being exposed. Any port which is listening on + the default "0.0.0.0" address inside a container will + be accessible from the network. Modifying this array + with strategic merge patch may corrupt the data. For + more information See https://github.com/kubernetes/kubernetes/issues/108255. + Cannot be updated. + items: + description: ContainerPort represents a network port + in a single container. + properties: + containerPort: + description: Number of port to expose on the pod's + IP address. This must be a valid port number, + 0 < x < 65536. + format: int32 + type: integer + hostIP: + description: What host IP to bind the external + port to. + type: string + hostPort: + description: Number of port to expose on the host. + If specified, this must be a valid port number, + 0 < x < 65536. If HostNetwork is specified, + this must match ContainerPort. Most containers + do not need this. + format: int32 + type: integer + name: + description: If specified, this must be an IANA_SVC_NAME + and unique within the pod. Each named port in + a pod must have a unique name. Name for the + port that can be referred to by services. + type: string + protocol: + default: TCP + description: Protocol for port. Must be UDP, TCP, + or SCTP. Defaults to "TCP". + type: string + required: + - containerPort + type: object + type: array + x-kubernetes-list-map-keys: + - containerPort + - protocol + x-kubernetes-list-type: map + readinessProbe: + description: 'Periodic probe of container service readiness. + Container will be removed from service endpoints if + the probe fails. Cannot be updated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to + execute inside the container, the working + directory for the command is root ('/') in + the container's filesystem. The command is + simply exec'd, it is not run inside a shell, + so traditional shell instructions ('|', etc) + won't work. To use a shell, you need to explicitly + call out to that shell. Exit status of 0 is + treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + type: object + failureThreshold: + description: Minimum consecutive failures for the + probe to be considered failed after having succeeded. + Defaults to 3. Minimum value is 1. + format: int32 + type: integer + grpc: + description: GRPC specifies an action involving + a GRPC port. + properties: + port: + description: Port number of the gRPC service. + Number must be in the range 1 to 65535. + format: int32 + type: integer + service: + description: "Service is the name of the service + to place in the gRPC HealthCheckRequest (see + https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + \n If this is not specified, the default behavior + is defined by gRPC." + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies the http request + to perform. + properties: + host: + description: Host name to connect to, defaults + to the pod IP. You probably want to set "Host" + in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the request. + HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom + header to be used in HTTP probes + properties: + name: + description: The header field name. This + will be canonicalized upon output, so + case-variant names will be understood + as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to + the host. Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: 'Number of seconds after the container + has started before liveness probes are initiated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + periodSeconds: + description: How often (in seconds) to perform the + probe. Default to 10 seconds. Minimum value is + 1. + format: int32 + type: integer + successThreshold: + description: Minimum consecutive successes for the + probe to be considered successful after having + failed. Defaults to 1. Must be 1 for liveness + and startup. Minimum value is 1. + format: int32 + type: integer + tcpSocket: + description: TCPSocket specifies an action involving + a TCP port. + properties: + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: Optional duration in seconds the pod + needs to terminate gracefully upon probe failure. + The grace period is the duration in seconds after + the processes running in the pod are sent a termination + signal and the time when the processes are forcibly + halted with a kill signal. Set this value longer + than the expected cleanup time for your process. + If this value is nil, the pod's terminationGracePeriodSeconds + will be used. Otherwise, this value overrides + the value provided by the pod spec. Value must + be non-negative integer. The value zero indicates + stop immediately via the kill signal (no opportunity + to shut down). This is a beta field and requires + enabling ProbeTerminationGracePeriod feature gate. + Minimum value is 1. spec.terminationGracePeriodSeconds + is used if unset. + format: int64 + type: integer + timeoutSeconds: + description: 'Number of seconds after which the + probe times out. Defaults to 1 second. Minimum + value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + type: object + resizePolicy: + description: Resources resize policy for the container. + items: + description: ContainerResizePolicy represents resource + resize policy for the container. + properties: + resourceName: + description: 'Name of the resource to which this + resource resize policy applies. Supported values: + cpu, memory.' + type: string + restartPolicy: + description: Restart policy to apply when specified + resource is resized. If not specified, it defaults + to NotRequired. + type: string + required: + - resourceName + - restartPolicy + type: object + type: array + x-kubernetes-list-type: atomic + resources: + description: 'Compute Resources required by this container. + Cannot be updated. More info: 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. \n This is an alpha field and + requires enabling the DynamicResourceAllocation + feature gate. \n 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 + 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 + restartPolicy: + description: 'RestartPolicy defines the restart behavior + of individual containers in a pod. This field may + only be set for init containers, and the only allowed + value is "Always". For non-init containers or when + this field is not specified, the restart behavior + is defined by the Pod''s restart policy and the container + type. Setting the RestartPolicy as "Always" for the + init container will have the following effect: this + init container will be continually restarted on exit + until all regular containers have terminated. Once + all regular containers have completed, all init containers + with restartPolicy "Always" will be shut down. This + lifecycle differs from normal init containers and + is often referred to as a "sidecar" container. Although + this init container still starts in the init container + sequence, it does not wait for the container to complete + before proceeding to the next init container. Instead, + the next init container starts immediately after this + init container is started, or after any startupProbe + has successfully completed.' + type: string + securityContext: + description: 'SecurityContext defines the security options + the container should be run with. If set, the fields + of SecurityContext override the equivalent fields + of PodSecurityContext. More info: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/' + properties: + allowPrivilegeEscalation: + description: 'AllowPrivilegeEscalation controls + whether a process can gain more privileges than + its parent process. This bool directly controls + if the no_new_privs flag will be set on the container + process. AllowPrivilegeEscalation is true always + when the container is: 1) run as Privileged 2) + has CAP_SYS_ADMIN Note that this field cannot + be set when spec.os.name is windows.' + type: boolean + capabilities: + description: The capabilities to add/drop when running + containers. Defaults to the default set of capabilities + granted by the container runtime. Note that this + field cannot be set when spec.os.name is windows. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + type: object + privileged: + description: Run container in privileged mode. Processes + in privileged containers are essentially equivalent + to root on the host. Defaults to false. Note that + this field cannot be set when spec.os.name is + windows. + type: boolean + procMount: + description: procMount denotes the type of proc + mount to use for the containers. The default is + DefaultProcMount which uses the container runtime + defaults for readonly paths and masked paths. + This requires the ProcMountType feature flag to + be enabled. Note that this field cannot be set + when spec.os.name is windows. + type: string + readOnlyRootFilesystem: + description: Whether this container has a read-only + root filesystem. Default is false. Note that this + field cannot be set when spec.os.name is windows. + type: boolean + runAsGroup: + description: The GID to run the entrypoint of the + container process. Uses runtime default if unset. + May also be set in PodSecurityContext. If set + in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name + is windows. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run + as a non-root user. If true, the Kubelet will + validate the image at runtime to ensure that it + does not run as UID 0 (root) and fail to start + the container if it does. If unset or false, no + such validation will be performed. May also be + set in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in + SecurityContext takes precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the + container process. Defaults to user specified + in image metadata if unspecified. May also be + set in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in + SecurityContext takes precedence. Note that this + field cannot be set when spec.os.name is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to + the container. If unspecified, the container runtime + will allocate a random SELinux context for each + container. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name + is windows. + properties: + level: + description: Level is SELinux level label that + applies to the container. + type: string + role: + description: Role is a SELinux role label that + applies to the container. + type: string + type: + description: Type is a SELinux type label that + applies to the container. + type: string + user: + description: User is a SELinux user label that + applies to the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by this + container. If seccomp options are provided at + both the pod & container level, the container + options override the pod options. Note that this + field cannot be set when spec.os.name is windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile + defined in a file on the node should be used. + The profile must be preconfigured on the node + to work. Must be a descending path, relative + to the kubelet's configured seccomp profile + location. Must be set if type is "Localhost". + Must NOT be set for any other type. + type: string + type: + description: "type indicates which kind of seccomp + profile will be applied. Valid options are: + \n Localhost - a profile defined in a file + on the node should be used. RuntimeDefault + - the container runtime default profile should + be used. Unconfined - no profile should be + applied." + type: string + required: + - type + type: object + windowsOptions: + description: The Windows specific settings applied + to all containers. If unspecified, the options + from the PodSecurityContext will be used. If set + in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name + is linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the + GMSA admission webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential + spec named by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name + of the GMSA credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container + should be run as a 'Host Process' container. + All of a Pod's containers must have the same + effective HostProcess value (it is not allowed + to have a mix of HostProcess containers and + non-HostProcess containers). In addition, + if HostProcess is true then HostNetwork must + also be set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run + the entrypoint of the container process. Defaults + to the user specified in image metadata if + unspecified. May also be set in PodSecurityContext. + If set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes + precedence. + type: string + type: object + type: object + startupProbe: + description: 'StartupProbe indicates that the Pod has + successfully initialized. If specified, no other probes + are executed until this completes successfully. If + this probe fails, the Pod will be restarted, just + as if the livenessProbe failed. This can be used to + provide different probe parameters at the beginning + of a Pod''s lifecycle, when it might take a long time + to load data or warm a cache, than during steady-state + operation. This cannot be updated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to + execute inside the container, the working + directory for the command is root ('/') in + the container's filesystem. The command is + simply exec'd, it is not run inside a shell, + so traditional shell instructions ('|', etc) + won't work. To use a shell, you need to explicitly + call out to that shell. Exit status of 0 is + treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + type: object + failureThreshold: + description: Minimum consecutive failures for the + probe to be considered failed after having succeeded. + Defaults to 3. Minimum value is 1. + format: int32 + type: integer + grpc: + description: GRPC specifies an action involving + a GRPC port. + properties: + port: + description: Port number of the gRPC service. + Number must be in the range 1 to 65535. + format: int32 + type: integer + service: + description: "Service is the name of the service + to place in the gRPC HealthCheckRequest (see + https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + \n If this is not specified, the default behavior + is defined by gRPC." + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies the http request + to perform. + properties: + host: + description: Host name to connect to, defaults + to the pod IP. You probably want to set "Host" + in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the request. + HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom + header to be used in HTTP probes + properties: + name: + description: The header field name. This + will be canonicalized upon output, so + case-variant names will be understood + as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to + the host. Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: 'Number of seconds after the container + has started before liveness probes are initiated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + periodSeconds: + description: How often (in seconds) to perform the + probe. Default to 10 seconds. Minimum value is + 1. + format: int32 + type: integer + successThreshold: + description: Minimum consecutive successes for the + probe to be considered successful after having + failed. Defaults to 1. Must be 1 for liveness + and startup. Minimum value is 1. + format: int32 + type: integer + tcpSocket: + description: TCPSocket specifies an action involving + a TCP port. + properties: + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: Optional duration in seconds the pod + needs to terminate gracefully upon probe failure. + The grace period is the duration in seconds after + the processes running in the pod are sent a termination + signal and the time when the processes are forcibly + halted with a kill signal. Set this value longer + than the expected cleanup time for your process. + If this value is nil, the pod's terminationGracePeriodSeconds + will be used. Otherwise, this value overrides + the value provided by the pod spec. Value must + be non-negative integer. The value zero indicates + stop immediately via the kill signal (no opportunity + to shut down). This is a beta field and requires + enabling ProbeTerminationGracePeriod feature gate. + Minimum value is 1. spec.terminationGracePeriodSeconds + is used if unset. + format: int64 + type: integer + timeoutSeconds: + description: 'Number of seconds after which the + probe times out. Defaults to 1 second. Minimum + value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + type: object + stdin: + description: Whether this container should allocate + a buffer for stdin in the container runtime. If this + is not set, reads from stdin in the container will + always result in EOF. Default is false. + type: boolean + stdinOnce: + description: Whether the container runtime should close + the stdin channel after it has been opened by a single + attach. When stdin is true the stdin stream will remain + open across multiple attach sessions. If stdinOnce + is set to true, stdin is opened on container start, + is empty until the first client attaches to stdin, + and then remains open and accepts data until the client + disconnects, at which time stdin is closed and remains + closed until the container is restarted. If this flag + is false, a container processes that reads from stdin + will never receive an EOF. Default is false + type: boolean + terminationMessagePath: + description: 'Optional: Path at which the file to which + the container''s termination message will be written + is mounted into the container''s filesystem. Message + written is intended to be brief final status, such + as an assertion failure message. Will be truncated + by the node if greater than 4096 bytes. The total + message length across all containers will be limited + to 12kb. Defaults to /dev/termination-log. Cannot + be updated.' + type: string + terminationMessagePolicy: + description: Indicate how the termination message should + be populated. File will use the contents of terminationMessagePath + to populate the container status message on both success + and failure. FallbackToLogsOnError will use the last + chunk of container log output if the termination message + file is empty and the container exited with an error. + The log output is limited to 2048 bytes or 80 lines, + whichever is smaller. Defaults to File. Cannot be + updated. + type: string + tty: + description: Whether this container should allocate + a TTY for itself, also requires 'stdin' to be true. + Default is false. + type: boolean + volumeDevices: + description: volumeDevices is the list of block devices + to be used by the container. + items: + description: volumeDevice describes a mapping of a + raw block device within a container. + properties: + devicePath: + description: devicePath is the path inside of + the container that the device will be mapped + to. + type: string + name: + description: name must match the name of a persistentVolumeClaim + in the pod + type: string + required: + - devicePath + - name + type: object + type: array + volumeMounts: + description: Pod volumes to mount into the container's + filesystem. Cannot be updated. + items: + description: VolumeMount describes a mounting of a + Volume within a container. + properties: + mountPath: + description: Path within the container at which + the volume should be mounted. Must not contain + ':'. + type: string + mountPropagation: + description: mountPropagation determines how mounts + are propagated from the host to container and + the other way around. When not set, MountPropagationNone + is used. This field is beta in 1.10. + type: string + name: + description: This must match the Name of a Volume. + type: string + readOnly: + description: Mounted read-only if true, read-write + otherwise (false or unspecified). Defaults to + false. + type: boolean + subPath: + description: Path within the volume from which + the container's volume should be mounted. Defaults + to "" (volume's root). + type: string + subPathExpr: + description: Expanded path within the volume from + which the container's volume should be mounted. + Behaves similarly to SubPath but environment + variable references $(VAR_NAME) are expanded + using the container's environment. Defaults + to "" (volume's root). SubPathExpr and SubPath + are mutually exclusive. + type: string + required: + - mountPath + - name + type: object + type: array + workingDir: + description: Container's working directory. If not specified, + the container runtime's default will be used, which + might be configured in the container image. Cannot + be updated. + type: string + required: + - name + type: object + type: array + additionalInitContainers: + description: AdditionalInitContainers allows adding additional + init containers to the Control Plane deployment. + items: + description: A single application container that you want + to run within a pod. + properties: + args: + description: 'Arguments to the entrypoint. The container + image''s CMD is used if this is not provided. Variable + references $(VAR_NAME) are expanded using the container''s + environment. 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. Cannot be updated. More info: + https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell' + items: + type: string + type: array + command: + description: 'Entrypoint array. Not executed within + a shell. The container image''s ENTRYPOINT is used + if this is not provided. Variable references $(VAR_NAME) + are expanded using the container''s environment. 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. Cannot be updated. More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell' + items: + type: string + type: array + env: + description: List of environment variables to set in + the container. Cannot be updated. + 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: + description: 'Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + 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: + description: 'Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + 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 + envFrom: + description: List of sources to populate environment + variables in the container. The keys defined within + a source must be a C_IDENTIFIER. All invalid keys + will be reported as an event when the container is + starting. 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. Cannot be updated. + items: + description: EnvFromSource represents the source of + a set of ConfigMaps + properties: + configMapRef: + description: The ConfigMap to select from + properties: + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + optional: + description: Specify whether the ConfigMap + must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + description: An optional identifier to prepend + to each key in the ConfigMap. Must be a C_IDENTIFIER. + type: string + secretRef: + description: The Secret to select from + properties: + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + optional: + description: Specify whether the Secret must + be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + image: + description: 'Container image name. More info: https://kubernetes.io/docs/concepts/containers/images + This field is optional to allow higher level config + management to default or override container images + in workload controllers like Deployments and StatefulSets.' + type: string + imagePullPolicy: + description: 'Image pull policy. One of Always, Never, + IfNotPresent. Defaults to Always if :latest tag is + specified, or IfNotPresent otherwise. Cannot be updated. + More info: https://kubernetes.io/docs/concepts/containers/images#updating-images' + type: string + lifecycle: + description: Actions that the management system should + take in response to container lifecycle events. Cannot + be updated. + properties: + postStart: + description: 'PostStart is called immediately after + a container is created. If the handler fails, + the container is terminated and restarted according + to its restart policy. Other management of the + container blocks until the hook completes. More + info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks' + properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line + to execute inside the container, the working + directory for the command is root ('/') + in the container's filesystem. The command + is simply exec'd, it is not run inside + a shell, so traditional shell instructions + ('|', etc) won't work. To use a shell, + you need to explicitly call out to that + shell. Exit status of 0 is treated as + live/healthy and non-zero is unhealthy. + items: + type: string + type: array + type: object + httpGet: + description: HTTPGet specifies the http request + to perform. + properties: + host: + description: Host name to connect to, defaults + to the pod IP. You probably want to set + "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the + request. HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom + header to be used in HTTP probes + properties: + name: + description: The header field name. + This will be canonicalized upon + output, so case-variant names will + be understood as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP + server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port + to access on the container. Number must + be in the range 1 to 65535. Name must + be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting + to the host. Defaults to HTTP. + type: string + required: + - port + type: object + sleep: + description: Sleep represents the duration that + the container should sleep before being terminated. + properties: + seconds: + description: Seconds is the number of seconds + to sleep. + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + description: Deprecated. TCPSocket is NOT supported + as a LifecycleHandler and kept for the backward + compatibility. There are no validation of + this field and lifecycle hooks will fail in + runtime when tcp handler is specified. + properties: + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port + to access on the container. Number must + be in the range 1 to 65535. Name must + be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + preStop: + description: 'PreStop is called immediately before + a container is terminated due to an API request + or management event such as liveness/startup probe + failure, preemption, resource contention, etc. + The handler is not called if the container crashes + or exits. The Pod''s termination grace period + countdown begins before the PreStop hook is executed. + Regardless of the outcome of the handler, the + container will eventually terminate within the + Pod''s termination grace period (unless delayed + by finalizers). Other management of the container + blocks until the hook completes or until the termination + grace period is reached. More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks' + properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line + to execute inside the container, the working + directory for the command is root ('/') + in the container's filesystem. The command + is simply exec'd, it is not run inside + a shell, so traditional shell instructions + ('|', etc) won't work. To use a shell, + you need to explicitly call out to that + shell. Exit status of 0 is treated as + live/healthy and non-zero is unhealthy. + items: + type: string + type: array + type: object + httpGet: + description: HTTPGet specifies the http request + to perform. + properties: + host: + description: Host name to connect to, defaults + to the pod IP. You probably want to set + "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the + request. HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom + header to be used in HTTP probes + properties: + name: + description: The header field name. + This will be canonicalized upon + output, so case-variant names will + be understood as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP + server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port + to access on the container. Number must + be in the range 1 to 65535. Name must + be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting + to the host. Defaults to HTTP. + type: string + required: + - port + type: object + sleep: + description: Sleep represents the duration that + the container should sleep before being terminated. + properties: + seconds: + description: Seconds is the number of seconds + to sleep. + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + description: Deprecated. TCPSocket is NOT supported + as a LifecycleHandler and kept for the backward + compatibility. There are no validation of + this field and lifecycle hooks will fail in + runtime when tcp handler is specified. + properties: + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port + to access on the container. Number must + be in the range 1 to 65535. Name must + be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + type: object + livenessProbe: + description: 'Periodic probe of container liveness. + Container will be restarted if the probe fails. Cannot + be updated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to + execute inside the container, the working + directory for the command is root ('/') in + the container's filesystem. The command is + simply exec'd, it is not run inside a shell, + so traditional shell instructions ('|', etc) + won't work. To use a shell, you need to explicitly + call out to that shell. Exit status of 0 is + treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + type: object + failureThreshold: + description: Minimum consecutive failures for the + probe to be considered failed after having succeeded. + Defaults to 3. Minimum value is 1. + format: int32 + type: integer + grpc: + description: GRPC specifies an action involving + a GRPC port. + properties: + port: + description: Port number of the gRPC service. + Number must be in the range 1 to 65535. + format: int32 + type: integer + service: + description: "Service is the name of the service + to place in the gRPC HealthCheckRequest (see + https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + \n If this is not specified, the default behavior + is defined by gRPC." + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies the http request + to perform. + properties: + host: + description: Host name to connect to, defaults + to the pod IP. You probably want to set "Host" + in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the request. + HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom + header to be used in HTTP probes + properties: + name: + description: The header field name. This + will be canonicalized upon output, so + case-variant names will be understood + as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to + the host. Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: 'Number of seconds after the container + has started before liveness probes are initiated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + periodSeconds: + description: How often (in seconds) to perform the + probe. Default to 10 seconds. Minimum value is + 1. + format: int32 + type: integer + successThreshold: + description: Minimum consecutive successes for the + probe to be considered successful after having + failed. Defaults to 1. Must be 1 for liveness + and startup. Minimum value is 1. + format: int32 + type: integer + tcpSocket: + description: TCPSocket specifies an action involving + a TCP port. + properties: + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: Optional duration in seconds the pod + needs to terminate gracefully upon probe failure. + The grace period is the duration in seconds after + the processes running in the pod are sent a termination + signal and the time when the processes are forcibly + halted with a kill signal. Set this value longer + than the expected cleanup time for your process. + If this value is nil, the pod's terminationGracePeriodSeconds + will be used. Otherwise, this value overrides + the value provided by the pod spec. Value must + be non-negative integer. The value zero indicates + stop immediately via the kill signal (no opportunity + to shut down). This is a beta field and requires + enabling ProbeTerminationGracePeriod feature gate. + Minimum value is 1. spec.terminationGracePeriodSeconds + is used if unset. + format: int64 + type: integer + timeoutSeconds: + description: 'Number of seconds after which the + probe times out. Defaults to 1 second. Minimum + value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + type: object + name: + description: Name of the container specified as a DNS_LABEL. + Each container in a pod must have a unique name (DNS_LABEL). + Cannot be updated. + type: string + ports: + description: List of ports to expose from the container. + Not specifying a port here DOES NOT prevent that port + from being exposed. Any port which is listening on + the default "0.0.0.0" address inside a container will + be accessible from the network. Modifying this array + with strategic merge patch may corrupt the data. For + more information See https://github.com/kubernetes/kubernetes/issues/108255. + Cannot be updated. + items: + description: ContainerPort represents a network port + in a single container. + properties: + containerPort: + description: Number of port to expose on the pod's + IP address. This must be a valid port number, + 0 < x < 65536. + format: int32 + type: integer + hostIP: + description: What host IP to bind the external + port to. + type: string + hostPort: + description: Number of port to expose on the host. + If specified, this must be a valid port number, + 0 < x < 65536. If HostNetwork is specified, + this must match ContainerPort. Most containers + do not need this. + format: int32 + type: integer + name: + description: If specified, this must be an IANA_SVC_NAME + and unique within the pod. Each named port in + a pod must have a unique name. Name for the + port that can be referred to by services. + type: string + protocol: + default: TCP + description: Protocol for port. Must be UDP, TCP, + or SCTP. Defaults to "TCP". + type: string + required: + - containerPort + type: object + type: array + x-kubernetes-list-map-keys: + - containerPort + - protocol + x-kubernetes-list-type: map + readinessProbe: + description: 'Periodic probe of container service readiness. + Container will be removed from service endpoints if + the probe fails. Cannot be updated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to + execute inside the container, the working + directory for the command is root ('/') in + the container's filesystem. The command is + simply exec'd, it is not run inside a shell, + so traditional shell instructions ('|', etc) + won't work. To use a shell, you need to explicitly + call out to that shell. Exit status of 0 is + treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + type: object + failureThreshold: + description: Minimum consecutive failures for the + probe to be considered failed after having succeeded. + Defaults to 3. Minimum value is 1. + format: int32 + type: integer + grpc: + description: GRPC specifies an action involving + a GRPC port. + properties: + port: + description: Port number of the gRPC service. + Number must be in the range 1 to 65535. + format: int32 + type: integer + service: + description: "Service is the name of the service + to place in the gRPC HealthCheckRequest (see + https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + \n If this is not specified, the default behavior + is defined by gRPC." + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies the http request + to perform. + properties: + host: + description: Host name to connect to, defaults + to the pod IP. You probably want to set "Host" + in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the request. + HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom + header to be used in HTTP probes + properties: + name: + description: The header field name. This + will be canonicalized upon output, so + case-variant names will be understood + as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to + the host. Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: 'Number of seconds after the container + has started before liveness probes are initiated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + periodSeconds: + description: How often (in seconds) to perform the + probe. Default to 10 seconds. Minimum value is + 1. + format: int32 + type: integer + successThreshold: + description: Minimum consecutive successes for the + probe to be considered successful after having + failed. Defaults to 1. Must be 1 for liveness + and startup. Minimum value is 1. + format: int32 + type: integer + tcpSocket: + description: TCPSocket specifies an action involving + a TCP port. + properties: + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: Optional duration in seconds the pod + needs to terminate gracefully upon probe failure. + The grace period is the duration in seconds after + the processes running in the pod are sent a termination + signal and the time when the processes are forcibly + halted with a kill signal. Set this value longer + than the expected cleanup time for your process. + If this value is nil, the pod's terminationGracePeriodSeconds + will be used. Otherwise, this value overrides + the value provided by the pod spec. Value must + be non-negative integer. The value zero indicates + stop immediately via the kill signal (no opportunity + to shut down). This is a beta field and requires + enabling ProbeTerminationGracePeriod feature gate. + Minimum value is 1. spec.terminationGracePeriodSeconds + is used if unset. + format: int64 + type: integer + timeoutSeconds: + description: 'Number of seconds after which the + probe times out. Defaults to 1 second. Minimum + value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + type: object + resizePolicy: + description: Resources resize policy for the container. + items: + description: ContainerResizePolicy represents resource + resize policy for the container. + properties: + resourceName: + description: 'Name of the resource to which this + resource resize policy applies. Supported values: + cpu, memory.' + type: string + restartPolicy: + description: Restart policy to apply when specified + resource is resized. If not specified, it defaults + to NotRequired. + type: string + required: + - resourceName + - restartPolicy + type: object + type: array + x-kubernetes-list-type: atomic + resources: + description: 'Compute Resources required by this container. + Cannot be updated. More info: 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. \n This is an alpha field and + requires enabling the DynamicResourceAllocation + feature gate. \n 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 + 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 + restartPolicy: + description: 'RestartPolicy defines the restart behavior + of individual containers in a pod. This field may + only be set for init containers, and the only allowed + value is "Always". For non-init containers or when + this field is not specified, the restart behavior + is defined by the Pod''s restart policy and the container + type. Setting the RestartPolicy as "Always" for the + init container will have the following effect: this + init container will be continually restarted on exit + until all regular containers have terminated. Once + all regular containers have completed, all init containers + with restartPolicy "Always" will be shut down. This + lifecycle differs from normal init containers and + is often referred to as a "sidecar" container. Although + this init container still starts in the init container + sequence, it does not wait for the container to complete + before proceeding to the next init container. Instead, + the next init container starts immediately after this + init container is started, or after any startupProbe + has successfully completed.' + type: string + securityContext: + description: 'SecurityContext defines the security options + the container should be run with. If set, the fields + of SecurityContext override the equivalent fields + of PodSecurityContext. More info: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/' + properties: + allowPrivilegeEscalation: + description: 'AllowPrivilegeEscalation controls + whether a process can gain more privileges than + its parent process. This bool directly controls + if the no_new_privs flag will be set on the container + process. AllowPrivilegeEscalation is true always + when the container is: 1) run as Privileged 2) + has CAP_SYS_ADMIN Note that this field cannot + be set when spec.os.name is windows.' + type: boolean + capabilities: + description: The capabilities to add/drop when running + containers. Defaults to the default set of capabilities + granted by the container runtime. Note that this + field cannot be set when spec.os.name is windows. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + type: object + privileged: + description: Run container in privileged mode. Processes + in privileged containers are essentially equivalent + to root on the host. Defaults to false. Note that + this field cannot be set when spec.os.name is + windows. + type: boolean + procMount: + description: procMount denotes the type of proc + mount to use for the containers. The default is + DefaultProcMount which uses the container runtime + defaults for readonly paths and masked paths. + This requires the ProcMountType feature flag to + be enabled. Note that this field cannot be set + when spec.os.name is windows. + type: string + readOnlyRootFilesystem: + description: Whether this container has a read-only + root filesystem. Default is false. Note that this + field cannot be set when spec.os.name is windows. + type: boolean + runAsGroup: + description: The GID to run the entrypoint of the + container process. Uses runtime default if unset. + May also be set in PodSecurityContext. If set + in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name + is windows. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run + as a non-root user. If true, the Kubelet will + validate the image at runtime to ensure that it + does not run as UID 0 (root) and fail to start + the container if it does. If unset or false, no + such validation will be performed. May also be + set in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in + SecurityContext takes precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the + container process. Defaults to user specified + in image metadata if unspecified. May also be + set in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in + SecurityContext takes precedence. Note that this + field cannot be set when spec.os.name is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to + the container. If unspecified, the container runtime + will allocate a random SELinux context for each + container. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name + is windows. + properties: + level: + description: Level is SELinux level label that + applies to the container. + type: string + role: + description: Role is a SELinux role label that + applies to the container. + type: string + type: + description: Type is a SELinux type label that + applies to the container. + type: string + user: + description: User is a SELinux user label that + applies to the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by this + container. If seccomp options are provided at + both the pod & container level, the container + options override the pod options. Note that this + field cannot be set when spec.os.name is windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile + defined in a file on the node should be used. + The profile must be preconfigured on the node + to work. Must be a descending path, relative + to the kubelet's configured seccomp profile + location. Must be set if type is "Localhost". + Must NOT be set for any other type. + type: string + type: + description: "type indicates which kind of seccomp + profile will be applied. Valid options are: + \n Localhost - a profile defined in a file + on the node should be used. RuntimeDefault + - the container runtime default profile should + be used. Unconfined - no profile should be + applied." + type: string + required: + - type + type: object + windowsOptions: + description: The Windows specific settings applied + to all containers. If unspecified, the options + from the PodSecurityContext will be used. If set + in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name + is linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the + GMSA admission webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential + spec named by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name + of the GMSA credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container + should be run as a 'Host Process' container. + All of a Pod's containers must have the same + effective HostProcess value (it is not allowed + to have a mix of HostProcess containers and + non-HostProcess containers). In addition, + if HostProcess is true then HostNetwork must + also be set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run + the entrypoint of the container process. Defaults + to the user specified in image metadata if + unspecified. May also be set in PodSecurityContext. + If set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes + precedence. + type: string + type: object + type: object + startupProbe: + description: 'StartupProbe indicates that the Pod has + successfully initialized. If specified, no other probes + are executed until this completes successfully. If + this probe fails, the Pod will be restarted, just + as if the livenessProbe failed. This can be used to + provide different probe parameters at the beginning + of a Pod''s lifecycle, when it might take a long time + to load data or warm a cache, than during steady-state + operation. This cannot be updated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to + execute inside the container, the working + directory for the command is root ('/') in + the container's filesystem. The command is + simply exec'd, it is not run inside a shell, + so traditional shell instructions ('|', etc) + won't work. To use a shell, you need to explicitly + call out to that shell. Exit status of 0 is + treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + type: object + failureThreshold: + description: Minimum consecutive failures for the + probe to be considered failed after having succeeded. + Defaults to 3. Minimum value is 1. + format: int32 + type: integer + grpc: + description: GRPC specifies an action involving + a GRPC port. + properties: + port: + description: Port number of the gRPC service. + Number must be in the range 1 to 65535. + format: int32 + type: integer + service: + description: "Service is the name of the service + to place in the gRPC HealthCheckRequest (see + https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + \n If this is not specified, the default behavior + is defined by gRPC." + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies the http request + to perform. + properties: + host: + description: Host name to connect to, defaults + to the pod IP. You probably want to set "Host" + in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the request. + HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom + header to be used in HTTP probes + properties: + name: + description: The header field name. This + will be canonicalized upon output, so + case-variant names will be understood + as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to + the host. Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: 'Number of seconds after the container + has started before liveness probes are initiated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + periodSeconds: + description: How often (in seconds) to perform the + probe. Default to 10 seconds. Minimum value is + 1. + format: int32 + type: integer + successThreshold: + description: Minimum consecutive successes for the + probe to be considered successful after having + failed. Defaults to 1. Must be 1 for liveness + and startup. Minimum value is 1. + format: int32 + type: integer + tcpSocket: + description: TCPSocket specifies an action involving + a TCP port. + properties: + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: Optional duration in seconds the pod + needs to terminate gracefully upon probe failure. + The grace period is the duration in seconds after + the processes running in the pod are sent a termination + signal and the time when the processes are forcibly + halted with a kill signal. Set this value longer + than the expected cleanup time for your process. + If this value is nil, the pod's terminationGracePeriodSeconds + will be used. Otherwise, this value overrides + the value provided by the pod spec. Value must + be non-negative integer. The value zero indicates + stop immediately via the kill signal (no opportunity + to shut down). This is a beta field and requires + enabling ProbeTerminationGracePeriod feature gate. + Minimum value is 1. spec.terminationGracePeriodSeconds + is used if unset. + format: int64 + type: integer + timeoutSeconds: + description: 'Number of seconds after which the + probe times out. Defaults to 1 second. Minimum + value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + type: object + stdin: + description: Whether this container should allocate + a buffer for stdin in the container runtime. If this + is not set, reads from stdin in the container will + always result in EOF. Default is false. + type: boolean + stdinOnce: + description: Whether the container runtime should close + the stdin channel after it has been opened by a single + attach. When stdin is true the stdin stream will remain + open across multiple attach sessions. If stdinOnce + is set to true, stdin is opened on container start, + is empty until the first client attaches to stdin, + and then remains open and accepts data until the client + disconnects, at which time stdin is closed and remains + closed until the container is restarted. If this flag + is false, a container processes that reads from stdin + will never receive an EOF. Default is false + type: boolean + terminationMessagePath: + description: 'Optional: Path at which the file to which + the container''s termination message will be written + is mounted into the container''s filesystem. Message + written is intended to be brief final status, such + as an assertion failure message. Will be truncated + by the node if greater than 4096 bytes. The total + message length across all containers will be limited + to 12kb. Defaults to /dev/termination-log. Cannot + be updated.' + type: string + terminationMessagePolicy: + description: Indicate how the termination message should + be populated. File will use the contents of terminationMessagePath + to populate the container status message on both success + and failure. FallbackToLogsOnError will use the last + chunk of container log output if the termination message + file is empty and the container exited with an error. + The log output is limited to 2048 bytes or 80 lines, + whichever is smaller. Defaults to File. Cannot be + updated. + type: string + tty: + description: Whether this container should allocate + a TTY for itself, also requires 'stdin' to be true. + Default is false. + type: boolean + volumeDevices: + description: volumeDevices is the list of block devices + to be used by the container. + items: + description: volumeDevice describes a mapping of a + raw block device within a container. + properties: + devicePath: + description: devicePath is the path inside of + the container that the device will be mapped + to. + type: string + name: + description: name must match the name of a persistentVolumeClaim + in the pod + type: string + required: + - devicePath + - name + type: object + type: array + volumeMounts: + description: Pod volumes to mount into the container's + filesystem. Cannot be updated. + items: + description: VolumeMount describes a mounting of a + Volume within a container. + properties: + mountPath: + description: Path within the container at which + the volume should be mounted. Must not contain + ':'. + type: string + mountPropagation: + description: mountPropagation determines how mounts + are propagated from the host to container and + the other way around. When not set, MountPropagationNone + is used. This field is beta in 1.10. + type: string + name: + description: This must match the Name of a Volume. + type: string + readOnly: + description: Mounted read-only if true, read-write + otherwise (false or unspecified). Defaults to + false. + type: boolean + subPath: + description: Path within the volume from which + the container's volume should be mounted. Defaults + to "" (volume's root). + type: string + subPathExpr: + description: Expanded path within the volume from + which the container's volume should be mounted. + Behaves similarly to SubPath but environment + variable references $(VAR_NAME) are expanded + using the container's environment. Defaults + to "" (volume's root). SubPathExpr and SubPath + are mutually exclusive. + type: string + required: + - mountPath + - name + type: object + type: array + workingDir: + description: Container's working directory. If not specified, + the container runtime's default will be used, which + might be configured in the container image. Cannot + be updated. + type: string + required: + - name + type: object + type: array + additionalMetadata: + description: AdditionalMetadata defines which additional metadata, + such as labels and annotations, must be attached to the + created resource. + properties: + annotations: + additionalProperties: + type: string + type: object + labels: + additionalProperties: + type: string + type: object + type: object + additionalVolumeMounts: + description: AdditionalVolumeMounts allows to mount an additional + volume into each component of the Control Plane (kube-apiserver, + controller-manager, and scheduler). + properties: + apiServer: + items: + description: VolumeMount describes a mounting of a Volume + within a container. + properties: + mountPath: + description: Path within the container at which + the volume should be mounted. Must not contain + ':'. + type: string + mountPropagation: + description: mountPropagation determines how mounts + are propagated from the host to container and + the other way around. When not set, MountPropagationNone + is used. This field is beta in 1.10. + type: string + name: + description: This must match the Name of a Volume. + type: string + readOnly: + description: Mounted read-only if true, read-write + otherwise (false or unspecified). Defaults to + false. + type: boolean + subPath: + description: Path within the volume from which the + container's volume should be mounted. Defaults + to "" (volume's root). + type: string + subPathExpr: + description: Expanded path within the volume from + which the container's volume should be mounted. + Behaves similarly to SubPath but environment variable + references $(VAR_NAME) are expanded using the + container's environment. Defaults to "" (volume's + root). SubPathExpr and SubPath are mutually exclusive. + type: string + required: + - mountPath + - name + type: object + type: array + controllerManager: + items: + description: VolumeMount describes a mounting of a Volume + within a container. + properties: + mountPath: + description: Path within the container at which + the volume should be mounted. Must not contain + ':'. + type: string + mountPropagation: + description: mountPropagation determines how mounts + are propagated from the host to container and + the other way around. When not set, MountPropagationNone + is used. This field is beta in 1.10. + type: string + name: + description: This must match the Name of a Volume. + type: string + readOnly: + description: Mounted read-only if true, read-write + otherwise (false or unspecified). Defaults to + false. + type: boolean + subPath: + description: Path within the volume from which the + container's volume should be mounted. Defaults + to "" (volume's root). + type: string + subPathExpr: + description: Expanded path within the volume from + which the container's volume should be mounted. + Behaves similarly to SubPath but environment variable + references $(VAR_NAME) are expanded using the + container's environment. Defaults to "" (volume's + root). SubPathExpr and SubPath are mutually exclusive. + type: string + required: + - mountPath + - name + type: object + type: array + scheduler: + items: + description: VolumeMount describes a mounting of a Volume + within a container. + properties: + mountPath: + description: Path within the container at which + the volume should be mounted. Must not contain + ':'. + type: string + mountPropagation: + description: mountPropagation determines how mounts + are propagated from the host to container and + the other way around. When not set, MountPropagationNone + is used. This field is beta in 1.10. + type: string + name: + description: This must match the Name of a Volume. + type: string + readOnly: + description: Mounted read-only if true, read-write + otherwise (false or unspecified). Defaults to + false. + type: boolean + subPath: + description: Path within the volume from which the + container's volume should be mounted. Defaults + to "" (volume's root). + type: string + subPathExpr: + description: Expanded path within the volume from + which the container's volume should be mounted. + Behaves similarly to SubPath but environment variable + references $(VAR_NAME) are expanded using the + container's environment. Defaults to "" (volume's + root). SubPathExpr and SubPath are mutually exclusive. + type: string + required: + - mountPath + - name + type: object + type: array + type: object + additionalVolumes: + description: AdditionalVolumes allows to add additional volumes + to the Control Plane deployment. + items: + description: Volume represents a named volume in a pod that + may be accessed by any container in the pod. + properties: + awsElasticBlockStore: + description: 'awsElasticBlockStore represents an AWS + Disk resource that is attached to a kubelet''s host + machine and then exposed to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' + properties: + fsType: + description: 'fsType is the filesystem type of the + volume that you want to mount. Tip: Ensure that + the filesystem type is supported by the host operating + system. Examples: "ext4", "xfs", "ntfs". Implicitly + inferred to be "ext4" if unspecified. More info: + https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore + TODO: how do we prevent errors in the filesystem + from compromising the machine' + type: string + partition: + description: 'partition is the partition in the + volume that you want to mount. If omitted, the + default is to mount by volume name. Examples: + For volume /dev/sda1, you specify the partition + as "1". Similarly, the volume partition for /dev/sda + is "0" (or you can leave the property empty).' + format: int32 + type: integer + readOnly: + description: 'readOnly value true will force the + readOnly setting in VolumeMounts. More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' + type: boolean + volumeID: + description: 'volumeID is unique ID of the persistent + disk resource in AWS (Amazon EBS volume). More + info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' + type: string + required: + - volumeID + type: object + azureDisk: + description: azureDisk represents an Azure Data Disk + mount on the host and bind mount to the pod. + properties: + cachingMode: + description: 'cachingMode is the Host Caching mode: + None, Read Only, Read Write.' + type: string + diskName: + description: diskName is the Name of the data disk + in the blob storage + type: string + diskURI: + description: diskURI is the URI of data disk in + the blob storage + type: string + fsType: + description: fsType is Filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". Implicitly + inferred to be "ext4" if unspecified. + type: string + kind: + description: 'kind expected values are Shared: multiple + blob disks per storage account Dedicated: single + blob disk per storage account Managed: azure + managed data disk (only in managed availability + set). defaults to shared' + type: string + readOnly: + description: readOnly Defaults to false (read/write). + ReadOnly here will force the ReadOnly setting + in VolumeMounts. + type: boolean + required: + - diskName + - diskURI + type: object + azureFile: + description: azureFile represents an Azure File Service + mount on the host and bind mount to the pod. + properties: + readOnly: + description: readOnly defaults to false (read/write). + ReadOnly here will force the ReadOnly setting + in VolumeMounts. + type: boolean + secretName: + description: secretName is the name of secret that + contains Azure Storage Account Name and Key + type: string + shareName: + description: shareName is the azure share Name + type: string + required: + - secretName + - shareName + type: object + cephfs: + description: cephFS represents a Ceph FS mount on the + host that shares a pod's lifetime + properties: + monitors: + description: 'monitors is Required: Monitors is + a collection of Ceph monitors More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + items: + type: string + type: array + path: + description: 'path is Optional: Used as the mounted + root, rather than the full Ceph tree, default + is /' + type: string + readOnly: + description: 'readOnly is Optional: Defaults to + false (read/write). ReadOnly here will force the + ReadOnly setting in VolumeMounts. More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + type: boolean + secretFile: + description: 'secretFile is Optional: SecretFile + is the path to key ring for User, default is /etc/ceph/user.secret + More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + type: string + secretRef: + description: 'secretRef is Optional: SecretRef is + reference to the authentication secret for User, + default is empty. More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + properties: + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + type: object + x-kubernetes-map-type: atomic + user: + description: 'user is optional: User is the rados + user name, default is admin More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + type: string + required: + - monitors + type: object + cinder: + description: 'cinder represents a cinder volume attached + and mounted on kubelets host machine. More info: https://examples.k8s.io/mysql-cinder-pd/README.md' + properties: + fsType: + description: 'fsType is the filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Examples: "ext4", "xfs", "ntfs". + Implicitly inferred to be "ext4" if unspecified. + More info: https://examples.k8s.io/mysql-cinder-pd/README.md' + type: string + readOnly: + description: 'readOnly defaults to false (read/write). + ReadOnly here will force the ReadOnly setting + in VolumeMounts. More info: https://examples.k8s.io/mysql-cinder-pd/README.md' + type: boolean + secretRef: + description: 'secretRef is optional: points to a + secret object containing parameters used to connect + to OpenStack.' + properties: + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + type: object + x-kubernetes-map-type: atomic + volumeID: + description: 'volumeID used to identify the volume + in cinder. More info: https://examples.k8s.io/mysql-cinder-pd/README.md' + type: string + required: + - volumeID + type: object + configMap: + description: configMap represents a configMap that should + populate this volume + properties: + defaultMode: + description: 'defaultMode is optional: mode bits + used to set permissions on created files by default. + Must be an octal value between 0000 and 0777 or + a decimal value between 0 and 511. YAML accepts + both octal and decimal values, JSON requires decimal + values for mode bits. Defaults to 0644. Directories + within the path are not affected by this setting. + This might be in conflict with other options that + affect the file mode, like fsGroup, and the result + can be other mode bits set.' + format: int32 + type: integer + items: + description: items if unspecified, each key-value + pair in the Data field of the referenced ConfigMap + will be projected into the volume as a file whose + name is the key and content is the value. If specified, + the listed keys will be projected into the specified + paths, and unlisted keys will not be present. + If a key is specified which is not present in + the ConfigMap, the volume setup will error unless + it is marked optional. Paths must be relative + and may not contain the '..' path or start with + '..'. + items: + description: Maps a string key to a path within + a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: mode bits + used to set permissions on this file. Must + be an octal value between 0000 and 0777 + or a decimal value between 0 and 511. YAML + accepts both octal and decimal values, JSON + requires decimal values for mode bits. If + not specified, the volume defaultMode will + be used. This might be in conflict with + other options that affect the file mode, + like fsGroup, and the result can be other + mode bits set.' + format: int32 + type: integer + path: + description: path is the relative path of + the file to map the key to. May not be an + absolute path. May not contain the path + element '..'. May not start with the string + '..'. + type: string + required: + - key + - path + type: object + type: array + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: optional specify whether the ConfigMap + or its keys must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + csi: + description: csi (Container Storage Interface) represents + ephemeral storage that is handled by certain external + CSI drivers (Beta feature). + properties: + driver: + description: driver is the name of the CSI driver + that handles this volume. Consult with your admin + for the correct name as registered in the cluster. + type: string + fsType: + description: fsType to mount. Ex. "ext4", "xfs", + "ntfs". If not provided, the empty value is passed + to the associated CSI driver which will determine + the default filesystem to apply. + type: string + nodePublishSecretRef: + description: nodePublishSecretRef is a reference + to the secret object containing sensitive information + to pass to the CSI driver to complete the CSI + NodePublishVolume and NodeUnpublishVolume calls. + This field is optional, and may be empty if no + secret is required. If the secret object contains + more than one secret, all secret references are + passed. + properties: + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + type: object + x-kubernetes-map-type: atomic + readOnly: + description: readOnly specifies a read-only configuration + for the volume. Defaults to false (read/write). + type: boolean + volumeAttributes: + additionalProperties: + type: string + description: volumeAttributes stores driver-specific + properties that are passed to the CSI driver. + Consult your driver's documentation for supported + values. + type: object + required: + - driver + type: object + downwardAPI: + description: downwardAPI represents downward API about + the pod that should populate this volume + properties: + defaultMode: + description: 'Optional: mode bits to use on created + files by default. Must be a Optional: mode bits + used to set permissions on created files by default. + Must be an octal value between 0000 and 0777 or + a decimal value between 0 and 511. YAML accepts + both octal and decimal values, JSON requires decimal + values for mode bits. Defaults to 0644. Directories + within the path are not affected by this setting. + This might be in conflict with other options that + affect the file mode, like fsGroup, and the result + can be other mode bits set.' + format: int32 + type: integer + items: + description: Items is a list of downward API volume + file + items: + description: DownwardAPIVolumeFile represents + information to create the file containing the + pod field + properties: + fieldRef: + description: 'Required: Selects a field of + the pod: only annotations, labels, name + and namespace are supported.' + 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 + mode: + description: 'Optional: mode bits used to + set permissions on this file, must be an + octal value between 0000 and 0777 or a decimal + value between 0 and 511. YAML accepts both + octal and decimal values, JSON requires + decimal values for mode bits. If not specified, + the volume defaultMode will be used. This + might be in conflict with other options + that affect the file mode, like fsGroup, + and the result can be other mode bits set.' + format: int32 + type: integer + path: + description: 'Required: Path is the relative + path name of the file to be created. Must + not be absolute or contain the ''..'' path. + Must be utf-8 encoded. The first item of + the relative path must not start with ''..''' + type: string + resourceFieldRef: + description: 'Selects a resource of the container: + only resources limits and requests (limits.cpu, + limits.memory, requests.cpu and requests.memory) + 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 + required: + - path + type: object + type: array + type: object + emptyDir: + description: 'emptyDir represents a temporary directory + that shares a pod''s lifetime. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' + properties: + medium: + description: 'medium represents what type of storage + medium should back this directory. The default + is "" which means to use the node''s default medium. + Must be an empty string (default) or Memory. More + info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' + type: string + sizeLimit: + anyOf: + - type: integer + - type: string + description: 'sizeLimit is the total amount of local + storage required for this EmptyDir volume. The + size limit is also applicable for memory medium. + The maximum usage on memory medium EmptyDir would + be the minimum value between the SizeLimit specified + here and the sum of memory limits of all containers + in a pod. The default is nil which means that + the limit is undefined. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + ephemeral: + description: "ephemeral represents a volume that is + handled by a cluster storage driver. The volume's + lifecycle is tied to the pod that defines it - it + will be created before the pod starts, and deleted + when the pod is removed. \n Use this if: a) the volume + is only needed while the pod runs, b) features of + normal volumes like restoring from snapshot or capacity + tracking are needed, c) the storage driver is specified + through a storage class, and d) the storage driver + supports dynamic volume provisioning through a PersistentVolumeClaim + (see EphemeralVolumeSource for more information on + the connection between this volume type and PersistentVolumeClaim). + \n Use PersistentVolumeClaim or one of the vendor-specific + APIs for volumes that persist for longer than the + lifecycle of an individual pod. \n Use CSI for light-weight + local ephemeral volumes if the CSI driver is meant + to be used that way - see the documentation of the + driver for more information. \n A pod can use both + types of ephemeral volumes and persistent volumes + at the same time." + properties: + volumeClaimTemplate: + description: "Will be used to create a stand-alone + PVC to provision the volume. The pod in which + this EphemeralVolumeSource is embedded will be + the owner of the PVC, i.e. the PVC will be deleted + together with the pod. The name of the PVC will + be `-` where `` + is the name from the `PodSpec.Volumes` array entry. + Pod validation will reject the pod if the concatenated + name is not valid for a PVC (for example, too + long). \n An existing PVC with that name that + is not owned by the pod will *not* be used for + the pod to avoid using an unrelated volume by + mistake. Starting the pod is then blocked until + the unrelated PVC is removed. If such a pre-created + PVC is meant to be used by the pod, the PVC has + to updated with an owner reference to the pod + once the pod exists. Normally this should not + be necessary, but it may be useful when manually + reconstructing a broken cluster. \n This field + is read-only and no changes will be made by Kubernetes + to the PVC after it has been created. \n Required, + must not be nil." + properties: + metadata: + description: May contain labels and annotations + that will be copied into the PVC when creating + it. No other fields are allowed and will be + rejected during validation. + type: object + spec: + description: The specification for the PersistentVolumeClaim. + The entire content is copied unchanged into + the PVC that gets created from this template. + The same fields as in a PersistentVolumeClaim + are also valid here. + properties: + accessModes: + description: 'accessModes contains the desired + access modes the volume should have. More + info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' + items: + type: string + type: array + dataSource: + description: 'dataSource field can be used + to specify either: * An existing VolumeSnapshot + object (snapshot.storage.k8s.io/VolumeSnapshot) + * An existing PVC (PersistentVolumeClaim) + If the provisioner or an external controller + can support the specified data source, + it will create a new volume based on the + contents of the specified data source. + When the AnyVolumeDataSource feature gate + is enabled, dataSource contents will be + copied to dataSourceRef, and dataSourceRef + contents will be copied to dataSource + when dataSourceRef.namespace is not specified. + If the namespace is specified, then dataSourceRef + will not be copied to dataSource.' + properties: + apiGroup: + description: APIGroup is the group for + the resource being referenced. If + APIGroup is not specified, the specified + Kind must be in the core API group. + For any other third-party types, APIGroup + is required. + type: string + kind: + description: Kind is the type of resource + being referenced + type: string + name: + description: Name is the name of resource + being referenced + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + description: 'dataSourceRef specifies the + object from which to populate the volume + with data, if a non-empty volume is desired. + This may be any object from a non-empty + API group (non core object) or a PersistentVolumeClaim + object. When this field is specified, + volume binding will only succeed if the + type of the specified object matches some + installed volume populator or dynamic + provisioner. This field will replace the + functionality of the dataSource field + and as such if both fields are non-empty, + they must have the same value. For backwards + compatibility, when namespace isn''t specified + in dataSourceRef, both fields (dataSource + and dataSourceRef) will be set to the + same value automatically if one of them + is empty and the other is non-empty. When + namespace is specified in dataSourceRef, + dataSource isn''t set to the same value + and must be empty. There are three important + differences between dataSource and dataSourceRef: + * While dataSource only allows two specific + types of objects, dataSourceRef allows + any non-core object, as well as PersistentVolumeClaim + objects. * While dataSource ignores disallowed + values (dropping them), dataSourceRef + preserves all values, and generates an + error if a disallowed value is specified. + * While dataSource only allows local objects, + dataSourceRef allows objects in any namespaces. + (Beta) Using this field requires the AnyVolumeDataSource + feature gate to be enabled. (Alpha) Using + the namespace field of dataSourceRef requires + the CrossNamespaceVolumeDataSource feature + gate to be enabled.' + properties: + apiGroup: + description: APIGroup is the group for + the resource being referenced. If + APIGroup is not specified, the specified + Kind must be in the core API group. + For any other third-party types, APIGroup + is required. + type: string + kind: + description: Kind is the type of resource + being referenced + type: string + name: + description: Name is the name of resource + being referenced + type: string + namespace: + description: Namespace is the namespace + of resource being referenced Note + that when a namespace is specified, + a gateway.networking.k8s.io/ReferenceGrant + object is required in the referent + namespace to allow that namespace's + owner to accept the reference. See + the ReferenceGrant documentation for + details. (Alpha) This field requires + the CrossNamespaceVolumeDataSource + feature gate to be enabled. + type: string + required: + - kind + - name + type: object + resources: + description: 'resources represents the minimum + resources the volume should have. If RecoverVolumeExpansionFailure + feature is enabled users are allowed to + specify resource requirements that are + lower than previous value but must still + be higher than capacity recorded in the + status field of the claim. More info: + https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' + properties: + 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 + selector: + description: selector is a label query over + volumes to consider for binding. + 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 + required: + - key + - operator + type: object + type: array + 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 + storageClassName: + description: 'storageClassName is the name + of the StorageClass required by the claim. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' + type: string + volumeAttributesClassName: + description: 'volumeAttributesClassName + may be used to set the VolumeAttributesClass + used by this claim. If specified, the + CSI driver will create or update the volume + with the attributes defined in the corresponding + VolumeAttributesClass. This has a different + purpose than storageClassName, it can + be changed after the claim is created. + An empty string value means that no VolumeAttributesClass + will be applied to the claim but it''s + not allowed to reset this field to empty + string once it is set. If unspecified + and the PersistentVolumeClaim is unbound, + the default VolumeAttributesClass will + be set by the persistentvolume controller + if it exists. If the resource referred + to by volumeAttributesClass does not exist, + this PersistentVolumeClaim will be set + to a Pending state, as reflected by the + modifyVolumeStatus field, until such as + a resource exists. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#volumeattributesclass + (Alpha) Using this field requires the + VolumeAttributesClass feature gate to + be enabled.' + type: string + volumeMode: + description: volumeMode defines what type + of volume is required by the claim. Value + of Filesystem is implied when not included + in claim spec. + type: string + volumeName: + description: volumeName is the binding reference + to the PersistentVolume backing this claim. + type: string + type: object + required: + - spec + type: object + type: object + fc: + description: fc represents a Fibre Channel resource + that is attached to a kubelet's host machine and then + exposed to the pod. + properties: + fsType: + description: 'fsType is the filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". Implicitly + inferred to be "ext4" if unspecified. TODO: how + do we prevent errors in the filesystem from compromising + the machine' + type: string + lun: + description: 'lun is Optional: FC target lun number' + format: int32 + type: integer + readOnly: + description: 'readOnly is Optional: Defaults to + false (read/write). ReadOnly here will force the + ReadOnly setting in VolumeMounts.' + type: boolean + targetWWNs: + description: 'targetWWNs is Optional: FC target + worldwide names (WWNs)' + items: + type: string + type: array + wwids: + description: 'wwids Optional: FC volume world wide + identifiers (wwids) Either wwids or combination + of targetWWNs and lun must be set, but not both + simultaneously.' + items: + type: string + type: array + type: object + flexVolume: + description: flexVolume represents a generic volume + resource that is provisioned/attached using an exec + based plugin. + properties: + driver: + description: driver is the name of the driver to + use for this volume. + type: string + fsType: + description: fsType is the filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". The + default filesystem depends on FlexVolume script. + type: string + options: + additionalProperties: + type: string + description: 'options is Optional: this field holds + extra command options if any.' + type: object + readOnly: + description: 'readOnly is Optional: defaults to + false (read/write). ReadOnly here will force the + ReadOnly setting in VolumeMounts.' + type: boolean + secretRef: + description: 'secretRef is Optional: secretRef is + reference to the secret object containing sensitive + information to pass to the plugin scripts. This + may be empty if no secret object is specified. + If the secret object contains more than one secret, + all secrets are passed to the plugin scripts.' + properties: + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + type: object + x-kubernetes-map-type: atomic + required: + - driver + type: object + flocker: + description: flocker represents a Flocker volume attached + to a kubelet's host machine. This depends on the Flocker + control service being running + properties: + datasetName: + description: datasetName is Name of the dataset + stored as metadata -> name on the dataset for + Flocker should be considered as deprecated + type: string + datasetUUID: + description: datasetUUID is the UUID of the dataset. + This is unique identifier of a Flocker dataset + type: string + type: object + gcePersistentDisk: + description: 'gcePersistentDisk represents a GCE Disk + resource that is attached to a kubelet''s host machine + and then exposed to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' + properties: + fsType: + description: 'fsType is filesystem type of the volume + that you want to mount. Tip: Ensure that the filesystem + type is supported by the host operating system. + Examples: "ext4", "xfs", "ntfs". Implicitly inferred + to be "ext4" if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk + TODO: how do we prevent errors in the filesystem + from compromising the machine' + type: string + partition: + description: 'partition is the partition in the + volume that you want to mount. If omitted, the + default is to mount by volume name. Examples: + For volume /dev/sda1, you specify the partition + as "1". Similarly, the volume partition for /dev/sda + is "0" (or you can leave the property empty). + More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' + format: int32 + type: integer + pdName: + description: 'pdName is unique name of the PD resource + in GCE. Used to identify the disk in GCE. More + info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' + type: string + readOnly: + description: 'readOnly here will force the ReadOnly + setting in VolumeMounts. Defaults to false. More + info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' + type: boolean + required: + - pdName + type: object + gitRepo: + description: 'gitRepo represents a git repository at + a particular revision. DEPRECATED: GitRepo is deprecated. + To provision a container with a git repo, mount an + EmptyDir into an InitContainer that clones the repo + using git, then mount the EmptyDir into the Pod''s + container.' + properties: + directory: + description: directory is the target directory name. + Must not contain or start with '..'. If '.' is + supplied, the volume directory will be the git + repository. Otherwise, if specified, the volume + will contain the git repository in the subdirectory + with the given name. + type: string + repository: + description: repository is the URL + type: string + revision: + description: revision is the commit hash for the + specified revision. + type: string + required: + - repository + type: object + glusterfs: + description: 'glusterfs represents a Glusterfs mount + on the host that shares a pod''s lifetime. More info: + https://examples.k8s.io/volumes/glusterfs/README.md' + properties: + endpoints: + description: 'endpoints is the endpoint name that + details Glusterfs topology. More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' + type: string + path: + description: 'path is the Glusterfs volume path. + More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' + type: string + readOnly: + description: 'readOnly here will force the Glusterfs + volume to be mounted with read-only permissions. + Defaults to false. More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' + type: boolean + required: + - endpoints + - path + type: object + hostPath: + description: 'hostPath represents a pre-existing file + or directory on the host machine that is directly + exposed to the container. This is generally used for + system agents or other privileged things that are + allowed to see the host machine. Most containers will + NOT need this. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath + --- TODO(jonesdl) We need to restrict who can use + host directory mounts and who can/can not mount host + directories as read/write.' + properties: + path: + description: 'path of the directory on the host. + If the path is a symlink, it will follow the link + to the real path. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath' + type: string + type: + description: 'type for HostPath Volume Defaults + to "" More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath' + type: string + required: + - path + type: object + iscsi: + description: 'iscsi represents an ISCSI Disk resource + that is attached to a kubelet''s host machine and + then exposed to the pod. More info: https://examples.k8s.io/volumes/iscsi/README.md' + properties: + chapAuthDiscovery: + description: chapAuthDiscovery defines whether support + iSCSI Discovery CHAP authentication + type: boolean + chapAuthSession: + description: chapAuthSession defines whether support + iSCSI Session CHAP authentication + type: boolean + fsType: + description: 'fsType is the filesystem type of the + volume that you want to mount. Tip: Ensure that + the filesystem type is supported by the host operating + system. Examples: "ext4", "xfs", "ntfs". Implicitly + inferred to be "ext4" if unspecified. More info: + https://kubernetes.io/docs/concepts/storage/volumes#iscsi + TODO: how do we prevent errors in the filesystem + from compromising the machine' + type: string + initiatorName: + description: initiatorName is the custom iSCSI Initiator + Name. If initiatorName is specified with iscsiInterface + simultaneously, new iSCSI interface : will be created for the connection. + type: string + iqn: + description: iqn is the target iSCSI Qualified Name. + type: string + iscsiInterface: + description: iscsiInterface is the interface Name + that uses an iSCSI transport. Defaults to 'default' + (tcp). + type: string + lun: + description: lun represents iSCSI Target Lun number. + format: int32 + type: integer + portals: + description: portals is the iSCSI Target Portal + List. The portal is either an IP or ip_addr:port + if the port is other than default (typically TCP + ports 860 and 3260). + items: + type: string + type: array + readOnly: + description: readOnly here will force the ReadOnly + setting in VolumeMounts. Defaults to false. + type: boolean + secretRef: + description: secretRef is the CHAP Secret for iSCSI + target and initiator authentication + properties: + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + type: object + x-kubernetes-map-type: atomic + targetPortal: + description: targetPortal is iSCSI Target Portal. + The Portal is either an IP or ip_addr:port if + the port is other than default (typically TCP + ports 860 and 3260). + type: string + required: + - iqn + - lun + - targetPortal + type: object + name: + description: 'name of the volume. Must be a DNS_LABEL + and unique within the pod. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + nfs: + description: 'nfs represents an NFS mount on the host + that shares a pod''s lifetime More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' + properties: + path: + description: 'path that is exported by the NFS server. + More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' + type: string + readOnly: + description: 'readOnly here will force the NFS export + to be mounted with read-only permissions. Defaults + to false. More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' + type: boolean + server: + description: 'server is the hostname or IP address + of the NFS server. More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' + type: string + required: + - path + - server + type: object + persistentVolumeClaim: + description: 'persistentVolumeClaimVolumeSource represents + a reference to a PersistentVolumeClaim in the same + namespace. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' + properties: + claimName: + description: 'claimName is the name of a PersistentVolumeClaim + in the same namespace as the pod using this volume. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' + type: string + readOnly: + description: readOnly Will force the ReadOnly setting + in VolumeMounts. Default false. + type: boolean + required: + - claimName + type: object + photonPersistentDisk: + description: photonPersistentDisk represents a PhotonController + persistent disk attached and mounted on kubelets host + machine + properties: + fsType: + description: fsType is the filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". Implicitly + inferred to be "ext4" if unspecified. + type: string + pdID: + description: pdID is the ID that identifies Photon + Controller persistent disk + type: string + required: + - pdID + type: object + portworxVolume: + description: portworxVolume represents a portworx volume + attached and mounted on kubelets host machine + properties: + fsType: + description: fSType represents the filesystem type + to mount Must be a filesystem type supported by + the host operating system. Ex. "ext4", "xfs". + Implicitly inferred to be "ext4" if unspecified. + type: string + readOnly: + description: readOnly defaults to false (read/write). + ReadOnly here will force the ReadOnly setting + in VolumeMounts. + type: boolean + volumeID: + description: volumeID uniquely identifies a Portworx + volume + type: string + required: + - volumeID + type: object + projected: + description: projected items for all in one resources + secrets, configmaps, and downward API + properties: + defaultMode: + description: defaultMode are the mode bits used + to set permissions on created files by default. + Must be an octal value between 0000 and 0777 or + a decimal value between 0 and 511. YAML accepts + both octal and decimal values, JSON requires decimal + values for mode bits. Directories within the path + are not affected by this setting. This might be + in conflict with other options that affect the + file mode, like fsGroup, and the result can be + other mode bits set. + format: int32 + type: integer + sources: + description: sources is the list of volume projections + items: + description: Projection that may be projected + along with other supported volume types + properties: + clusterTrustBundle: + description: "ClusterTrustBundle allows a + pod to access the `.spec.trustBundle` field + of ClusterTrustBundle objects in an auto-updating + file. \n Alpha, gated by the ClusterTrustBundleProjection + feature gate. \n ClusterTrustBundle objects + can either be selected by name, or by the + combination of signer name and a label selector. + \n Kubelet performs aggressive normalization + of the PEM contents written into the pod + filesystem. Esoteric PEM features such + as inter-block comments and block headers + are stripped. Certificates are deduplicated. + The ordering of certificates within the + file is arbitrary, and Kubelet may change + the order over time." + properties: + labelSelector: + description: Select all ClusterTrustBundles + that match this label selector. Only + has effect if signerName is set. Mutually-exclusive + with name. If unset, interpreted as + "match nothing". If set but empty, + interpreted as "match everything". + 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 + required: + - key + - operator + type: object + type: array + 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 + name: + description: Select a single ClusterTrustBundle + by object name. Mutually-exclusive + with signerName and labelSelector. + type: string + optional: + description: If true, don't block pod + startup if the referenced ClusterTrustBundle(s) + aren't available. If using name, then + the named ClusterTrustBundle is allowed + not to exist. If using signerName, + then the combination of signerName and + labelSelector is allowed to match zero + ClusterTrustBundles. + type: boolean + path: + description: Relative path from the volume + root to write the bundle. + type: string + signerName: + description: Select all ClusterTrustBundles + that match this signer name. Mutually-exclusive + with name. The contents of all selected + ClusterTrustBundles will be unified + and deduplicated. + type: string + required: + - path + type: object + configMap: + description: configMap information about the + configMap data to project + properties: + items: + description: items if unspecified, each + key-value pair in the Data field of + the referenced ConfigMap will be projected + into the volume as a file whose name + is the key and content is the value. + If specified, the listed keys will be + projected into the specified paths, + and unlisted keys will not be present. + If a key is specified which is not present + in the ConfigMap, the volume setup will + error unless it is marked optional. + Paths must be relative and may not contain + the '..' path or start with '..'. + items: + description: Maps a string key to a + path within a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: + mode bits used to set permissions + on this file. Must be an octal + value between 0000 and 0777 or + a decimal value between 0 and + 511. YAML accepts both octal and + decimal values, JSON requires + decimal values for mode bits. + If not specified, the volume defaultMode + will be used. This might be in + conflict with other options that + affect the file mode, like fsGroup, + and the result can be other mode + bits set.' + format: int32 + type: integer + path: + description: path is the relative + path of the file to map the key + to. May not be an absolute path. + May not contain the path element + '..'. May not start with the string + '..'. + type: string + required: + - key + - path + type: object + type: array + name: + description: 'Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + optional: + description: optional specify whether + the ConfigMap or its keys must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + downwardAPI: + description: downwardAPI information about + the downwardAPI data to project + properties: + items: + description: Items is a list of DownwardAPIVolume + file + items: + description: DownwardAPIVolumeFile represents + information to create the file containing + the pod field + properties: + fieldRef: + description: 'Required: Selects + a field of the pod: only annotations, + labels, name and namespace are + supported.' + 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 + mode: + description: 'Optional: mode bits + used to set permissions on this + file, must be an octal value between + 0000 and 0777 or a decimal value + between 0 and 511. YAML accepts + both octal and decimal values, + JSON requires decimal values for + mode bits. If not specified, the + volume defaultMode will be used. + This might be in conflict with + other options that affect the + file mode, like fsGroup, and the + result can be other mode bits + set.' + format: int32 + type: integer + path: + description: 'Required: Path is the + relative path name of the file + to be created. Must not be absolute + or contain the ''..'' path. Must + be utf-8 encoded. The first item + of the relative path must not + start with ''..''' + type: string + resourceFieldRef: + description: 'Selects a resource + of the container: only resources + limits and requests (limits.cpu, + limits.memory, requests.cpu and + requests.memory) 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 + required: + - path + type: object + type: array + type: object + secret: + description: secret information about the + secret data to project + properties: + items: + description: items if unspecified, each + key-value pair in the Data field of + the referenced Secret will be projected + into the volume as a file whose name + is the key and content is the value. + If specified, the listed keys will be + projected into the specified paths, + and unlisted keys will not be present. + If a key is specified which is not present + in the Secret, the volume setup will + error unless it is marked optional. + Paths must be relative and may not contain + the '..' path or start with '..'. + items: + description: Maps a string key to a + path within a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: + mode bits used to set permissions + on this file. Must be an octal + value between 0000 and 0777 or + a decimal value between 0 and + 511. YAML accepts both octal and + decimal values, JSON requires + decimal values for mode bits. + If not specified, the volume defaultMode + will be used. This might be in + conflict with other options that + affect the file mode, like fsGroup, + and the result can be other mode + bits set.' + format: int32 + type: integer + path: + description: path is the relative + path of the file to map the key + to. May not be an absolute path. + May not contain the path element + '..'. May not start with the string + '..'. + type: string + required: + - key + - path + type: object + type: array + name: + description: 'Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + optional: + description: optional field specify whether + the Secret or its key must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + serviceAccountToken: + description: serviceAccountToken is information + about the serviceAccountToken data to project + properties: + audience: + description: audience is the intended + audience of the token. A recipient of + a token must identify itself with an + identifier specified in the audience + of the token, and otherwise should reject + the token. The audience defaults to + the identifier of the apiserver. + type: string + expirationSeconds: + description: expirationSeconds is the + requested duration of validity of the + service account token. As the token + approaches expiration, the kubelet volume + plugin will proactively rotate the service + account token. The kubelet will start + trying to rotate the token if the token + is older than 80 percent of its time + to live or if the token is older than + 24 hours.Defaults to 1 hour and must + be at least 10 minutes. + format: int64 + type: integer + path: + description: path is the path relative + to the mount point of the file to project + the token into. + type: string + required: + - path + type: object + type: object + type: array + type: object + quobyte: + description: quobyte represents a Quobyte mount on the + host that shares a pod's lifetime + properties: + group: + description: group to map volume access to Default + is no group + type: string + readOnly: + description: readOnly here will force the Quobyte + volume to be mounted with read-only permissions. + Defaults to false. + type: boolean + registry: + description: registry represents a single or multiple + Quobyte Registry services specified as a string + as host:port pair (multiple entries are separated + with commas) which acts as the central registry + for volumes + type: string + tenant: + description: tenant owning the given Quobyte volume + in the Backend Used with dynamically provisioned + Quobyte volumes, value is set by the plugin + type: string + user: + description: user to map volume access to Defaults + to serivceaccount user + type: string + volume: + description: volume is a string that references + an already created Quobyte volume by name. + type: string + required: + - registry + - volume + type: object + rbd: + description: 'rbd represents a Rados Block Device mount + on the host that shares a pod''s lifetime. More info: + https://examples.k8s.io/volumes/rbd/README.md' + properties: + fsType: + description: 'fsType is the filesystem type of the + volume that you want to mount. Tip: Ensure that + the filesystem type is supported by the host operating + system. Examples: "ext4", "xfs", "ntfs". Implicitly + inferred to be "ext4" if unspecified. More info: + https://kubernetes.io/docs/concepts/storage/volumes#rbd + TODO: how do we prevent errors in the filesystem + from compromising the machine' + type: string + image: + description: 'image is the rados image name. More + info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: string + keyring: + description: 'keyring is the path to key ring for + RBDUser. Default is /etc/ceph/keyring. More info: + https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: string + monitors: + description: 'monitors is a collection of Ceph monitors. + More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + items: + type: string + type: array + pool: + description: 'pool is the rados pool name. Default + is rbd. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: string + readOnly: + description: 'readOnly here will force the ReadOnly + setting in VolumeMounts. Defaults to false. More + info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: boolean + secretRef: + description: 'secretRef is name of the authentication + secret for RBDUser. If provided overrides keyring. + Default is nil. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + properties: + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + type: object + x-kubernetes-map-type: atomic + user: + description: 'user is the rados user name. Default + is admin. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: string + required: + - image + - monitors + type: object + scaleIO: + description: scaleIO represents a ScaleIO persistent + volume attached and mounted on Kubernetes nodes. + properties: + fsType: + description: fsType is the filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". Default + is "xfs". + type: string + gateway: + description: gateway is the host address of the + ScaleIO API Gateway. + type: string + protectionDomain: + description: protectionDomain is the name of the + ScaleIO Protection Domain for the configured storage. + type: string + readOnly: + description: readOnly Defaults to false (read/write). + ReadOnly here will force the ReadOnly setting + in VolumeMounts. + type: boolean + secretRef: + description: secretRef references to the secret + for ScaleIO user and other sensitive information. + If this is not provided, Login operation will + fail. + properties: + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + type: object + x-kubernetes-map-type: atomic + sslEnabled: + description: sslEnabled Flag enable/disable SSL + communication with Gateway, default false + type: boolean + storageMode: + description: storageMode indicates whether the storage + for a volume should be ThickProvisioned or ThinProvisioned. + Default is ThinProvisioned. + type: string + storagePool: + description: storagePool is the ScaleIO Storage + Pool associated with the protection domain. + type: string + system: + description: system is the name of the storage system + as configured in ScaleIO. + type: string + volumeName: + description: volumeName is the name of a volume + already created in the ScaleIO system that is + associated with this volume source. + type: string + required: + - gateway + - secretRef + - system + type: object + secret: + description: 'secret represents a secret that should + populate this volume. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' + properties: + defaultMode: + description: 'defaultMode is Optional: mode bits + used to set permissions on created files by default. + Must be an octal value between 0000 and 0777 or + a decimal value between 0 and 511. YAML accepts + both octal and decimal values, JSON requires decimal + values for mode bits. Defaults to 0644. Directories + within the path are not affected by this setting. + This might be in conflict with other options that + affect the file mode, like fsGroup, and the result + can be other mode bits set.' + format: int32 + type: integer + items: + description: items If unspecified, each key-value + pair in the Data field of the referenced Secret + will be projected into the volume as a file whose + name is the key and content is the value. If specified, + the listed keys will be projected into the specified + paths, and unlisted keys will not be present. + If a key is specified which is not present in + the Secret, the volume setup will error unless + it is marked optional. Paths must be relative + and may not contain the '..' path or start with + '..'. + items: + description: Maps a string key to a path within + a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: mode bits + used to set permissions on this file. Must + be an octal value between 0000 and 0777 + or a decimal value between 0 and 511. YAML + accepts both octal and decimal values, JSON + requires decimal values for mode bits. If + not specified, the volume defaultMode will + be used. This might be in conflict with + other options that affect the file mode, + like fsGroup, and the result can be other + mode bits set.' + format: int32 + type: integer + path: + description: path is the relative path of + the file to map the key to. May not be an + absolute path. May not contain the path + element '..'. May not start with the string + '..'. + type: string + required: + - key + - path + type: object + type: array + optional: + description: optional field specify whether the + Secret or its keys must be defined + type: boolean + secretName: + description: 'secretName is the name of the secret + in the pod''s namespace to use. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' + type: string + type: object + storageos: + description: storageOS represents a StorageOS volume + attached and mounted on Kubernetes nodes. + properties: + fsType: + description: fsType is the filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". Implicitly + inferred to be "ext4" if unspecified. + type: string + readOnly: + description: readOnly defaults to false (read/write). + ReadOnly here will force the ReadOnly setting + in VolumeMounts. + type: boolean + secretRef: + description: secretRef specifies the secret to use + for obtaining the StorageOS API credentials. If + not specified, default values will be attempted. + properties: + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + type: object + x-kubernetes-map-type: atomic + volumeName: + description: volumeName is the human-readable name + of the StorageOS volume. Volume names are only + unique within a namespace. + type: string + volumeNamespace: + description: volumeNamespace specifies the scope + of the volume within StorageOS. If no namespace + is specified then the Pod's namespace will be + used. This allows the Kubernetes name scoping + to be mirrored within StorageOS for tighter integration. + Set VolumeName to any name to override the default + behaviour. Set to "default" if you are not using + namespaces within StorageOS. Namespaces that do + not pre-exist within StorageOS will be created. + type: string + type: object + vsphereVolume: + description: vsphereVolume represents a vSphere volume + attached and mounted on kubelets host machine + properties: + fsType: + description: fsType is filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". Implicitly + inferred to be "ext4" if unspecified. + type: string + storagePolicyID: + description: storagePolicyID is the storage Policy + Based Management (SPBM) profile ID associated + with the StoragePolicyName. + type: string + storagePolicyName: + description: storagePolicyName is the storage Policy + Based Management (SPBM) profile name. + type: string + volumePath: + description: volumePath is the path that identifies + vSphere volume vmdk + type: string + required: + - volumePath + type: object + required: + - name + type: object + type: array + affinity: + description: 'If specified, the Tenant Control Plane pod''s + scheduling constraints. More info: https://kubernetes.io/docs/tasks/configure-pod-container/assign-pods-nodes-using-node-affinity/' + properties: + nodeAffinity: + description: Describes node affinity scheduling rules + for the pod. + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule + pods to nodes that satisfy the affinity expressions + specified by this field, but it may choose a node + that violates one or more of the expressions. The + node that is most preferred is the one with the + greatest sum of weights, i.e. for each node that + meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, + etc.), compute a sum by iterating through the elements + of this field and adding "weight" to the sum if + the node matches the corresponding matchExpressions; + the node(s) with the highest sum are the most preferred. + items: + description: An empty preferred scheduling term + matches all objects with implicit weight 0 (i.e. + it's a no-op). A null preferred scheduling term + matches no objects (i.e. is also a no-op). + properties: + preference: + description: A node selector term, associated + with the corresponding weight. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: The label key that the + selector applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: 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. + If the operator is Gt or Lt, the + values array must have a single + element, which will be interpreted + as an integer. This array is replaced + during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: The label key that the + selector applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: 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. + If the operator is Gt or Lt, the + values array must have a single + element, which will be interpreted + as an integer. This array is replaced + during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + x-kubernetes-map-type: atomic + weight: + description: Weight associated with matching + the corresponding nodeSelectorTerm, in the + range 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified + by this field are not met at scheduling time, the + pod will not be scheduled onto the node. If the + affinity requirements specified by this field cease + to be met at some point during pod execution (e.g. + due to an update), the system may or may not try + to eventually evict the pod from its node. + properties: + nodeSelectorTerms: + description: Required. A list of node selector + terms. The terms are ORed. + items: + description: A null or empty node selector term + matches no objects. The requirements of them + are ANDed. The TopologySelectorTerm type implements + a subset of the NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: The label key that the + selector applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: 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. + If the operator is Gt or Lt, the + values array must have a single + element, which will be interpreted + as an integer. This array is replaced + during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: The label key that the + selector applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: 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. + If the operator is Gt or Lt, the + values array must have a single + element, which will be interpreted + as an integer. This array is replaced + during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + x-kubernetes-map-type: atomic + type: array + required: + - nodeSelectorTerms + type: object + x-kubernetes-map-type: atomic + type: object + podAffinity: + description: Describes pod affinity scheduling rules (e.g. + co-locate this pod in the same node, zone, etc. as some + other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule + pods to nodes that satisfy the affinity expressions + specified by this field, but it may choose a node + that violates one or more of the expressions. The + node that is most preferred is the one with the + greatest sum of weights, i.e. for each node that + meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, + etc.), compute a sum by iterating through the elements + of this field and adding "weight" to the sum if + the node has pods which matches the corresponding + podAffinityTerm; the node(s) with the highest sum + are the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, + associated with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of + resources, in this case pods. If it's + null, this PodAffinityTerm matches with + no Pods. + 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 + required: + - key + - operator + type: object + type: array + 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 which pods will + be taken into consideration. The keys + are used to lookup values from the incoming + pod labels, those key-value labels are + merged with `LabelSelector` as `key in + (value)` to select the group of existing + pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. + Keys that don't exist in the incoming + pod labels will be ignored. The default + value is empty. The same key is forbidden + to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when + LabelSelector isn't set. This is an alpha + field and requires enabling MatchLabelKeysInPodAffinity + feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: MismatchLabelKeys is a set + of pod label keys to select which pods + will be taken into consideration. The + keys are used to lookup values from the + incoming pod labels, those key-value labels + are merged with `LabelSelector` as `key + notin (value)` to select the group of + existing pods which pods will be taken + into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist + in the incoming pod labels will be ignored. + The default value is empty. The same key + is forbidden to exist in both MismatchLabelKeys + and LabelSelector. Also, MismatchLabelKeys + cannot be set when LabelSelector isn't + set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature + gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + description: A label query over the set + of namespaces that the term applies to. + The term is applied to the union of the + namespaces selected by this field and + the ones listed in the namespaces field. + null selector and null or empty namespaces + list means "this pod's namespace". An + empty selector ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static + list of namespace names that the term + applies to. The term is applied to the + union of the namespaces listed in this + field and the ones selected by namespaceSelector. + null or empty namespaces list and null + namespaceSelector means "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located + (affinity) or not co-located (anti-affinity) + with the pods matching the labelSelector + in the specified namespaces, where co-located + is defined as running on a node whose + value of the label with key topologyKey + matches that of any node on which any + of the selected pods is running. Empty + topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching + the corresponding podAffinityTerm, in the + range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified + by this field are not met at scheduling time, the + pod will not be scheduled onto the node. If the + affinity requirements specified by this field cease + to be met at some point during pod execution (e.g. + due to a pod label update), the system may or may + not try to eventually evict the pod from its node. + When there are multiple elements, the lists of nodes + corresponding to each podAffinityTerm are intersected, + i.e. all terms must be satisfied. + items: + description: Defines a set of pods (namely those + matching the labelSelector relative to the given + namespace(s)) that this pod should be co-located + (affinity) or not co-located (anti-affinity) with, + where co-located is defined as running on a node + whose value of the label with key + matches that of any node on which a pod of the + set of pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. If it's null, this PodAffinityTerm + matches with no Pods. + 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 + required: + - key + - operator + type: object + type: array + 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 which pods will be taken + into consideration. The keys are used to lookup + values from the incoming pod labels, those + key-value labels are merged with `LabelSelector` + as `key in (value)` to select the group of + existing pods which pods will be taken into + consideration for the incoming pod's pod (anti) + affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value + is empty. The same key is forbidden to exist + in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature + gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: MismatchLabelKeys is a set of pod + label keys to select which pods will be taken + into consideration. The keys are used to lookup + values from the incoming pod labels, those + key-value labels are merged with `LabelSelector` + as `key notin (value)` to select the group + of existing pods which pods will be taken + into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist + in the incoming pod labels will be ignored. + The default value is empty. The same key is + forbidden to exist in both MismatchLabelKeys + and LabelSelector. Also, MismatchLabelKeys + cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling + MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by + this field and the ones listed in the namespaces + field. null selector and null or empty namespaces + list means "this pod's namespace". An empty + selector ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. + The term is applied to the union of the namespaces + listed in this field and the ones selected + by namespaceSelector. null or empty namespaces + list and null namespaceSelector means "this + pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the + pods matching the labelSelector in the specified + namespaces, where co-located is defined as + running on a node whose value of the label + with key topologyKey matches that of any node + on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + podAntiAffinity: + description: Describes pod anti-affinity scheduling rules + (e.g. avoid putting this pod in the same node, zone, + etc. as some other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule + pods to nodes that satisfy the anti-affinity expressions + specified by this field, but it may choose a node + that violates one or more of the expressions. The + node that is most preferred is the one with the + greatest sum of weights, i.e. for each node that + meets all of the scheduling requirements (resource + request, requiredDuringScheduling anti-affinity + expressions, etc.), compute a sum by iterating through + the elements of this field and adding "weight" to + the sum if the node has pods which matches the corresponding + podAffinityTerm; the node(s) with the highest sum + are the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, + associated with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of + resources, in this case pods. If it's + null, this PodAffinityTerm matches with + no Pods. + 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 + required: + - key + - operator + type: object + type: array + 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 which pods will + be taken into consideration. The keys + are used to lookup values from the incoming + pod labels, those key-value labels are + merged with `LabelSelector` as `key in + (value)` to select the group of existing + pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. + Keys that don't exist in the incoming + pod labels will be ignored. The default + value is empty. The same key is forbidden + to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when + LabelSelector isn't set. This is an alpha + field and requires enabling MatchLabelKeysInPodAffinity + feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: MismatchLabelKeys is a set + of pod label keys to select which pods + will be taken into consideration. The + keys are used to lookup values from the + incoming pod labels, those key-value labels + are merged with `LabelSelector` as `key + notin (value)` to select the group of + existing pods which pods will be taken + into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist + in the incoming pod labels will be ignored. + The default value is empty. The same key + is forbidden to exist in both MismatchLabelKeys + and LabelSelector. Also, MismatchLabelKeys + cannot be set when LabelSelector isn't + set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature + gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + description: A label query over the set + of namespaces that the term applies to. + The term is applied to the union of the + namespaces selected by this field and + the ones listed in the namespaces field. + null selector and null or empty namespaces + list means "this pod's namespace". An + empty selector ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static + list of namespace names that the term + applies to. The term is applied to the + union of the namespaces listed in this + field and the ones selected by namespaceSelector. + null or empty namespaces list and null + namespaceSelector means "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located + (affinity) or not co-located (anti-affinity) + with the pods matching the labelSelector + in the specified namespaces, where co-located + is defined as running on a node whose + value of the label with key topologyKey + matches that of any node on which any + of the selected pods is running. Empty + topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching + the corresponding podAffinityTerm, in the + range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the anti-affinity requirements specified + by this field are not met at scheduling time, the + pod will not be scheduled onto the node. If the + anti-affinity requirements specified by this field + cease to be met at some point during pod execution + (e.g. due to a pod label update), the system may + or may not try to eventually evict the pod from + its node. When there are multiple elements, the + lists of nodes corresponding to each podAffinityTerm + are intersected, i.e. all terms must be satisfied. + items: + description: Defines a set of pods (namely those + matching the labelSelector relative to the given + namespace(s)) that this pod should be co-located + (affinity) or not co-located (anti-affinity) with, + where co-located is defined as running on a node + whose value of the label with key + matches that of any node on which a pod of the + set of pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. If it's null, this PodAffinityTerm + matches with no Pods. + 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 + required: + - key + - operator + type: object + type: array + 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 which pods will be taken + into consideration. The keys are used to lookup + values from the incoming pod labels, those + key-value labels are merged with `LabelSelector` + as `key in (value)` to select the group of + existing pods which pods will be taken into + consideration for the incoming pod's pod (anti) + affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value + is empty. The same key is forbidden to exist + in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature + gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: MismatchLabelKeys is a set of pod + label keys to select which pods will be taken + into consideration. The keys are used to lookup + values from the incoming pod labels, those + key-value labels are merged with `LabelSelector` + as `key notin (value)` to select the group + of existing pods which pods will be taken + into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist + in the incoming pod labels will be ignored. + The default value is empty. The same key is + forbidden to exist in both MismatchLabelKeys + and LabelSelector. Also, MismatchLabelKeys + cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling + MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by + this field and the ones listed in the namespaces + field. null selector and null or empty namespaces + list means "this pod's namespace". An empty + selector ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. + The term is applied to the union of the namespaces + listed in this field and the ones selected + by namespaceSelector. null or empty namespaces + list and null namespaceSelector means "this + pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the + pods matching the labelSelector in the specified + namespaces, where co-located is defined as + running on a node whose value of the label + with key topologyKey matches that of any node + on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + type: object + extraArgs: + description: ExtraArgs allows adding additional arguments + to the Control Plane components, such as kube-apiserver, + controller-manager, and scheduler. + properties: + apiServer: + items: + type: string + type: array + controllerManager: + items: + type: string + type: array + kine: + description: Available only if Kamaji is running using + Kine as backing storage. + items: + type: string + type: array + scheduler: + items: + type: string + type: array + type: object + nodeSelector: + additionalProperties: + type: string + description: 'NodeSelector is a selector which must be true + for the pod to fit on a node. Selector which must match + a node''s labels for the pod to be scheduled on that node. + More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/' + type: object + registrySettings: + default: + apiServerImage: kube-apiserver + controllerManagerImage: kube-controller-manager + registry: registry.k8s.io + schedulerImage: kube-scheduler + description: RegistrySettings allows to override the default + images for the given Tenant Control Plane instance. It could + be used to point to a different container registry rather + than the public one. + properties: + apiServerImage: + default: kube-apiserver + type: string + controllerManagerImage: + default: kube-controller-manager + type: string + registry: + default: registry.k8s.io + type: string + schedulerImage: + default: kube-scheduler + type: string + tagSuffix: + description: The tag to append to all the Control Plane + container images. Optional. + type: string + type: object + replicas: + default: 2 + format: int32 + type: integer + resources: + description: Resources defines the amount of memory and CPU + to allocate to each component of the Control Plane (kube-apiserver, + controller-manager, and scheduler). + properties: + apiServer: + description: ResourceRequirements describes the compute + resource requirements. + properties: + claims: + description: "Claims lists the names of resources, + defined in spec.resourceClaims, that are used by + this container. \n This is an alpha field and requires + enabling the DynamicResourceAllocation feature gate. + \n 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 + 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 + controllerManager: + description: ResourceRequirements describes the compute + resource requirements. + properties: + claims: + description: "Claims lists the names of resources, + defined in spec.resourceClaims, that are used by + this container. \n This is an alpha field and requires + enabling the DynamicResourceAllocation feature gate. + \n 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 + 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 + kine: + description: Define the kine container resources. Available + only if Kamaji is running using Kine as backing storage. + properties: + claims: + description: "Claims lists the names of resources, + defined in spec.resourceClaims, that are used by + this container. \n This is an alpha field and requires + enabling the DynamicResourceAllocation feature gate. + \n 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 + 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 + scheduler: + description: ResourceRequirements describes the compute + resource requirements. + properties: + claims: + description: "Claims lists the names of resources, + defined in spec.resourceClaims, that are used by + this container. \n This is an alpha field and requires + enabling the DynamicResourceAllocation feature gate. + \n 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 + 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 + type: object + runtimeClassName: + description: 'RuntimeClassName refers to a RuntimeClass object + in the node.k8s.io group, which should be used to run the + Tenant Control Plane pod. If no RuntimeClass resource matches + the named class, the pod will not be run. If unset or empty, + the "legacy" RuntimeClass will be used, which is an implicit + class with an empty definition that uses the default runtime + handler. More info: https://git.k8s.io/enhancements/keps/sig-node/585-runtime-class' + type: string + strategy: + default: + rollingUpdate: + maxSurge: 100% + maxUnavailable: 0 + type: RollingUpdate + description: Strategy describes how to replace existing pods + with new ones for the given Tenant Control Plane. Default + value is set to Rolling Update, with a blue/green strategy. + properties: + rollingUpdate: + description: 'Rolling update config params. Present only + if DeploymentStrategyType = RollingUpdate. --- TODO: + Update this to follow our convention for oneOf, whatever + we decide it to be.' + properties: + maxSurge: + anyOf: + - type: integer + - type: string + description: 'The maximum number of pods that can + be scheduled above the desired number of pods. Value + can be an absolute number (ex: 5) or a percentage + of desired pods (ex: 10%). This can not be 0 if + MaxUnavailable is 0. Absolute number is calculated + from percentage by rounding up. Defaults to 25%. + Example: when this is set to 30%, the new ReplicaSet + can be scaled up immediately when the rolling update + starts, such that the total number of old and new + pods do not exceed 130% of desired pods. Once old + pods have been killed, new ReplicaSet can be scaled + up further, ensuring that total number of pods running + at any time during the update is at most 130% of + desired pods.' + x-kubernetes-int-or-string: true + maxUnavailable: + anyOf: + - type: integer + - type: string + description: 'The maximum number of pods that can + be unavailable during the update. Value can be an + absolute number (ex: 5) or a percentage of desired + pods (ex: 10%). Absolute number is calculated from + percentage by rounding down. This can not be 0 if + MaxSurge is 0. Defaults to 25%. Example: when this + is set to 30%, the old ReplicaSet can be scaled + down to 70% of desired pods immediately when the + rolling update starts. Once new pods are ready, + old ReplicaSet can be scaled down further, followed + by scaling up the new ReplicaSet, ensuring that + the total number of pods available at all times + during the update is at least 70% of desired pods.' + x-kubernetes-int-or-string: true + type: object + type: + description: Type of deployment. Can be "Recreate" or + "RollingUpdate". Default is RollingUpdate. + type: string + type: object + tolerations: + description: 'If specified, the Tenant Control Plane pod''s + tolerations. More info: 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 + topologySpreadConstraints: + description: TopologySpreadConstraints describes how the Tenant + Control Plane pods ought to spread across topology domains. + Scheduler will schedule pods in a way which abides by the + constraints. In case of nil underlying LabelSelector, the + Kamaji one for the given Tenant Control Plane will be used. + All topologySpreadConstraints are ANDed. + 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 + required: + - key + - operator + type: object + type: array + 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. Keys that don't exist in + the incoming pod labels will be ignored. A null or + empty list means only match against labelSelector. + \n This is a beta field and requires the MatchLabelKeysInPodTopologySpread + feature gate to be enabled (enabled by default)." + 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. + For example, in a 3-zone cluster, MaxSkew is set to + 1, and pods with the same labelSelector spread as + 2/2/1: In this case, the global minimum is 1. | zone1 + | zone2 | zone3 | | P P | P P | P | - if MaxSkew + is 1, incoming pod can only be scheduled to zone3 + to become 2/2/2; scheduling it onto zone1(zone2) would + make the ActualSkew(3-1) on zone1(zone2) violate MaxSkew(1). + - if MaxSkew is 2, incoming pod can be scheduled onto + any zone. When `whenUnsatisfiable=ScheduleAnyway`, + it is used to give higher precedence to topologies + that satisfy it. It''s a required field. Default value + is 1 and 0 is not allowed.' + 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. As a result, when + the number of eligible domains is less than minDomains, + scheduler won't schedule more than maxSkew Pods to + those domains. If value is nil, the constraint behaves + as if MinDomains is equal to 1. Valid values are integers + greater than 0. When value is not nil, WhenUnsatisfiable + must be DoNotSchedule. \n For example, in a 3-zone + cluster, MaxSkew is set to 2, MinDomains is set to + 5 and pods with the same labelSelector spread as 2/2/2: + | zone1 | zone2 | zone3 | | P P | P P | P P | + The number of domains is less than 5(MinDomains), + so \"global minimum\" is treated as 0. In this situation, + new pod with the same labelSelector cannot be scheduled, + because computed skew will be 3(3 - 0) if new Pod + is scheduled to any of the three zones, it will violate + MaxSkew. \n This is a beta field and requires the + MinDomainsInPodTopologySpread feature gate to be enabled + (enabled by default)." + 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. + \n 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. \n 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.io/hostname", + each Node is a domain of that topology. And, if TopologyKey + is "topology.kubernetes.io/zone", each zone is a domain + of that topology. It's a required field. + 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. For example, in a 3-zone cluster, MaxSkew + is set to 1, and pods with the same labelSelector + spread as 3/1/1: | zone1 | zone2 | zone3 | | P P P + | P | P | If WhenUnsatisfiable is set to DoNotSchedule, + incoming pod can only be scheduled to zone2(zone3) + to become 3/2/1(3/1/2) as ActualSkew(2-1) on zone2(zone3) + satisfies MaxSkew(1). In other words, the cluster + can still be imbalanced, but scheduler won''t make + it *more* imbalanced. It''s a required field.' + type: string + required: + - maxSkew + - topologyKey + - whenUnsatisfiable + type: object + type: array + type: object + ingress: + description: Defining the options for an Optional Ingress which + will expose API Server of the Tenant Control Plane + properties: + additionalMetadata: + description: AdditionalMetadata defines which additional metadata, + such as labels and annotations, must be attached to the + created resource. + properties: + annotations: + additionalProperties: + type: string + type: object + labels: + additionalProperties: + type: string + type: object + type: object + hostname: + description: Hostname is an optional field which will be used + as Ingress's Host. If it is not defined, Ingress's host + will be "..", where domain is + specified under NetworkProfileSpec + type: string + ingressClassName: + type: string + type: object + service: + description: Defining the options for the Tenant Control Plane + Service resource. + properties: + additionalMetadata: + description: AdditionalMetadata defines which additional metadata, + such as labels and annotations, must be attached to the + created resource. + properties: + annotations: + additionalProperties: + type: string + type: object + labels: + additionalProperties: + type: string + type: object + type: object + serviceType: + description: ServiceType allows specifying how to expose the + Tenant Control Plane. + enum: + - ClusterIP + - NodePort + - LoadBalancer + type: string + required: + - serviceType + type: object + required: + - service + type: object + dataStore: + description: DataStore allows to specify a DataStore that should be + used to store the Kubernetes data for the given Tenant Control Plane. + This parameter is optional and acts as an override over the default + one which is used by the Kamaji Operator. Migration from a different + DataStore to another one is not yet supported and the reconciliation + will be blocked. + type: string + kubernetes: + description: Kubernetes specification for tenant control plane + properties: + admissionControllers: + default: + - CertificateApproval + - CertificateSigning + - CertificateSubjectRestriction + - DefaultIngressClass + - DefaultStorageClass + - DefaultTolerationSeconds + - LimitRanger + - MutatingAdmissionWebhook + - NamespaceLifecycle + - PersistentVolumeClaimResize + - Priority + - ResourceQuota + - RuntimeClass + - ServiceAccount + - StorageObjectInUseProtection + - TaintNodesByCondition + - ValidatingAdmissionWebhook + description: 'List of enabled Admission Controllers for the Tenant + cluster. Full reference available here: https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers' + items: + enum: + - AlwaysAdmit + - AlwaysDeny + - AlwaysPullImages + - CertificateApproval + - CertificateSigning + - CertificateSubjectRestriction + - DefaultIngressClass + - DefaultStorageClass + - DefaultTolerationSeconds + - DenyEscalatingExec + - DenyExecOnPrivileged + - DenyServiceExternalIPs + - EventRateLimit + - ExtendedResourceToleration + - ImagePolicyWebhook + - LimitPodHardAntiAffinityTopology + - LimitRanger + - MutatingAdmissionWebhook + - NamespaceAutoProvision + - NamespaceExists + - NamespaceLifecycle + - NodeRestriction + - OwnerReferencesPermissionEnforcement + - PersistentVolumeClaimResize + - PersistentVolumeLabel + - PodNodeSelector + - PodSecurity + - PodSecurityPolicy + - PodTolerationRestriction + - Priority + - ResourceQuota + - RuntimeClass + - SecurityContextDeny + - ServiceAccount + - StorageObjectInUseProtection + - TaintNodesByCondition + - ValidatingAdmissionWebhook + type: string + type: array + kubelet: + properties: + cgroupfs: + description: CGroupFS defines the cgroup driver for Kubelet + https://kubernetes.io/docs/tasks/administer-cluster/kubeadm/configure-cgroup-driver/ + enum: + - systemd + - cgroupfs + type: string + preferredAddressTypes: + default: + - Hostname + - InternalIP + - ExternalIP + description: Ordered list of the preferred NodeAddressTypes + to use for kubelet connections. Default to Hostname, InternalIP, + ExternalIP. + items: + enum: + - Hostname + - InternalIP + - ExternalIP + - InternalDNS + - ExternalDNS + type: string + minItems: 1 + type: array + type: object + version: + description: Kubernetes Version for the tenant control plane + type: string + required: + - kubelet + - version + type: object + networkProfile: + description: NetworkProfile specifies how the network is + properties: + address: + description: Address where API server of will be exposed. In case + of LoadBalancer Service, this can be empty in order to use the + exposed IP provided by the cloud controller manager. + type: string + allowAddressAsExternalIP: + description: AllowAddressAsExternalIP will include tenantControlPlane.Spec.NetworkProfile.Address + in the section of ExternalIPs of the Kubernetes Service (only + ClusterIP or NodePort) + type: boolean + certSANs: + description: CertSANs sets extra Subject Alternative Names (SANs) + for the API Server signing certificate. Use this field to add + additional hostnames when exposing the Tenant Control Plane + with third solutions. + items: + type: string + type: array + dnsServiceIPs: + default: + - 10.96.0.10 + items: + type: string + type: array + podCidr: + default: 10.244.0.0/16 + description: CIDR for Kubernetes Pods + type: string + port: + default: 6443 + description: Port where API server of will be exposed + format: int32 + type: integer + serviceCidr: + default: 10.96.0.0/16 + description: Kubernetes Service + type: string + type: object + required: + - controlPlane + - kubernetes + type: object + status: + description: TenantControlPlaneStatus defines the observed state of TenantControlPlane. + properties: + addons: + description: Addons contains the status of the different Addons + properties: + coreDNS: + description: AddonStatus defines the observed state of an Addon. + properties: + enabled: + type: boolean + lastUpdate: + format: date-time + type: string + required: + - enabled + type: object + konnectivity: + description: KonnectivityStatus defines the status of Konnectivity + as Addon. + properties: + agent: + properties: + lastUpdate: + description: Last time when k8s object was updated + format: date-time + type: string + name: + type: string + namespace: + type: string + type: object + certificate: + description: CertificatePrivateKeyPairStatus defines the status. + properties: + checksum: + type: string + lastUpdate: + format: date-time + type: string + secretName: + type: string + type: object + clusterrolebinding: + properties: + lastUpdate: + description: Last time when k8s object was updated + format: date-time + type: string + name: + type: string + namespace: + type: string + type: object + configMap: + properties: + checksum: + type: string + name: + type: string + type: object + enabled: + type: boolean + kubeconfig: + description: KubeconfigStatus contains information about the + generated kubeconfig. + properties: + checksum: + type: string + lastUpdate: + format: date-time + type: string + secretName: + type: string + type: object + sa: + properties: + lastUpdate: + description: Last time when k8s object was updated + format: date-time + type: string + name: + type: string + namespace: + type: string + type: object + service: + description: KubernetesServiceStatus defines the status for + the Tenant Control Plane Service in the management cluster. + properties: + conditions: + description: Current service state + items: + description: "Condition contains details for one aspect + of the current state of this API Resource. --- This + struct is intended for direct use as an array at the + field path .status.conditions. For example, \n type + FooStatus struct{ // Represents the observations of + a foo's current state. // Known .status.conditions.type + are: \"Available\", \"Progressing\", and \"Degraded\" + // +patchMergeKey=type // +patchStrategy=merge // + +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" + patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` + \n // other fields }" + 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 + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + loadBalancer: + description: LoadBalancer contains the current status + of the load-balancer, if one is present. + properties: + ingress: + description: Ingress is a list containing ingress + points for the load-balancer. Traffic intended for + the service should be sent to these ingress points. + items: + description: 'LoadBalancerIngress represents the + status of a load-balancer ingress point: traffic + intended for the service should be sent to an + ingress point.' + properties: + hostname: + description: Hostname is set for load-balancer + ingress points that are DNS based (typically + AWS load-balancers) + type: string + ip: + description: IP is set for load-balancer ingress + points that are IP based (typically GCE or + OpenStack load-balancers) + type: string + ipMode: + description: IPMode specifies how the load-balancer + IP behaves, and may only be specified when + the ip field is specified. Setting this to + "VIP" indicates that traffic is delivered + to the node with the destination set to the + load-balancer's IP and port. Setting this + to "Proxy" indicates that traffic is delivered + to the node or pod with the destination set + to the node's IP and node port or the pod's + IP and port. Service implementations may use + this information to adjust traffic routing. + type: string + ports: + description: Ports is a list of records of service + ports If used, every port defined in the service + should have an entry in it + items: + properties: + error: + description: 'Error is to record the problem + with the service port The format of + the error shall comply with the following + rules: - built-in error values shall + be specified in this file and those + shall use CamelCase names - cloud provider + specific error values must have names + that comply with the format foo.example.com/CamelCase. + --- 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 + port: + description: Port is the port number of + the service port of which status is + recorded here + format: int32 + type: integer + protocol: + default: TCP + description: 'Protocol is the protocol + of the service port of which status + is recorded here The supported values + are: "TCP", "UDP", "SCTP"' + type: string + required: + - port + - protocol + type: object + type: array + x-kubernetes-list-type: atomic + type: object + type: array + type: object + name: + description: The name of the Service for the given cluster. + type: string + namespace: + description: The namespace which the Service for the given + cluster is deployed. + type: string + port: + description: The port where the service is running + format: int32 + type: integer + required: + - name + - namespace + - port + type: object + required: + - enabled + type: object + kubeProxy: + description: AddonStatus defines the observed state of an Addon. + properties: + enabled: + type: boolean + lastUpdate: + format: date-time + type: string + required: + - enabled + type: object + type: object + certificates: + description: Certificates contains information about the different + certificates that are necessary to run a kubernetes control plane + properties: + apiServer: + description: CertificatePrivateKeyPairStatus defines the status. + properties: + checksum: + type: string + lastUpdate: + format: date-time + type: string + secretName: + type: string + type: object + apiServerKubeletClient: + description: CertificatePrivateKeyPairStatus defines the status. + properties: + checksum: + type: string + lastUpdate: + format: date-time + type: string + secretName: + type: string + type: object + ca: + description: CertificatePrivateKeyPairStatus defines the status. + properties: + checksum: + type: string + lastUpdate: + format: date-time + type: string + secretName: + type: string + type: object + etcd: + description: ETCDCertificatesStatus defines the observed state + of ETCD Certificate for API server. + properties: + apiServer: + description: APIServerCertificatesStatus defines the observed + state of ETCD Certificate for API server. + properties: + checksum: + type: string + lastUpdate: + format: date-time + type: string + secretName: + type: string + type: object + ca: + description: ETCDCertificateStatus defines the observed state + of ETCD Certificate for API server. + properties: + checksum: + type: string + lastUpdate: + format: date-time + type: string + secretName: + type: string + type: object + type: object + frontProxyCA: + description: CertificatePrivateKeyPairStatus defines the status. + properties: + checksum: + type: string + lastUpdate: + format: date-time + type: string + secretName: + type: string + type: object + frontProxyClient: + description: CertificatePrivateKeyPairStatus defines the status. + properties: + checksum: + type: string + lastUpdate: + format: date-time + type: string + secretName: + type: string + type: object + sa: + description: PublicKeyPrivateKeyPairStatus defines the status. + properties: + checksum: + type: string + lastUpdate: + format: date-time + type: string + secretName: + type: string + type: object + type: object + controlPlaneEndpoint: + description: ControlPlaneEndpoint contains the status of the kubernetes + control plane + type: string + kubeadmPhase: + description: KubeadmPhase contains the status of the kubeadm phases + action + properties: + bootstrapToken: + description: KubeadmPhaseStatus contains the status of a kubeadm + phase action. + properties: + checksum: + type: string + lastUpdate: + format: date-time + type: string + type: object + required: + - bootstrapToken + type: object + kubeadmconfig: + description: KubeadmConfig contains the status of the configuration + required by kubeadm + properties: + checksum: + description: Checksum of the kubeadm configuration to detect changes + type: string + configmapName: + type: string + lastUpdate: + format: date-time + type: string + type: object + kubeconfig: + description: KubeConfig contains information about the kubenconfigs + that control plane pieces need + properties: + admin: + description: KubeconfigStatus contains information about the generated + kubeconfig. + properties: + checksum: + type: string + lastUpdate: + format: date-time + type: string + secretName: + type: string + type: object + controllerManager: + description: KubeconfigStatus contains information about the generated + kubeconfig. + properties: + checksum: + type: string + lastUpdate: + format: date-time + type: string + secretName: + type: string + type: object + scheduler: + description: KubeconfigStatus contains information about the generated + kubeconfig. + properties: + checksum: + type: string + lastUpdate: + format: date-time + type: string + secretName: + type: string + type: object + type: object + kubernetesResources: + description: Kubernetes contains information about the reconciliation + of the required Kubernetes resources deployed in the admin cluster + properties: + deployment: + description: KubernetesDeploymentStatus defines the status for + the Tenant Control Plane Deployment in the management cluster. + properties: + availableReplicas: + description: Total number of available pods (ready for at + least minReadySeconds) targeted by this deployment. + format: int32 + type: integer + collisionCount: + description: Count of hash collisions for the Deployment. + The Deployment controller uses this field as a collision + avoidance mechanism when it needs to create the name for + the newest ReplicaSet. + format: int32 + type: integer + conditions: + description: Represents the latest available observations + of a deployment's current state. + items: + description: DeploymentCondition describes the state of + a deployment at a certain point. + properties: + lastTransitionTime: + description: Last time the condition transitioned from + one status to another. + format: date-time + type: string + lastUpdateTime: + description: The last time this condition was updated. + format: date-time + type: string + message: + description: A human readable message indicating details + about the transition. + type: string + reason: + description: The reason for the condition's last transition. + type: string + status: + description: Status of the condition, one of True, False, + Unknown. + type: string + type: + description: Type of deployment condition. + type: string + required: + - status + - type + type: object + type: array + lastUpdate: + description: Last time when deployment was updated + format: date-time + type: string + name: + description: The name of the Deployment for the given cluster. + type: string + namespace: + description: The namespace which the Deployment for the given + cluster is deployed. + type: string + observedGeneration: + description: The generation observed by the deployment controller. + format: int64 + type: integer + readyReplicas: + description: readyReplicas is the number of pods targeted + by this Deployment with a Ready Condition. + format: int32 + type: integer + replicas: + description: Total number of non-terminated pods targeted + by this deployment (their labels match the selector). + format: int32 + type: integer + selector: + description: Selector is the label selector used to group + the Tenant Control Plane Pods used by the scale subresource. + type: string + unavailableReplicas: + description: Total number of unavailable pods targeted by + this deployment. This is the total number of pods that are + still required for the deployment to have 100% available + capacity. They may either be pods that are running but not + yet available or pods that still have not been created. + format: int32 + type: integer + updatedReplicas: + description: Total number of non-terminated pods targeted + by this deployment that have the desired template spec. + format: int32 + type: integer + required: + - name + - namespace + - selector + type: object + ingress: + description: KubernetesIngressStatus defines the status for the + Tenant Control Plane Ingress in the management cluster. + properties: + loadBalancer: + description: loadBalancer contains the current status of the + load-balancer. + properties: + ingress: + description: ingress is a list containing ingress points + for the load-balancer. + items: + description: IngressLoadBalancerIngress represents the + status of a load-balancer ingress point. + properties: + hostname: + description: hostname is set for load-balancer ingress + points that are DNS based. + type: string + ip: + description: ip is set for load-balancer ingress + points that are IP based. + type: string + ports: + description: ports provides information about the + ports exposed by this LoadBalancer. + items: + description: IngressPortStatus represents the + error condition of a service port + properties: + error: + description: 'error is to record the problem + with the service port The format of the + error shall comply with the following rules: + - built-in error values shall be specified + in this file and those shall use CamelCase + names - cloud provider specific error values + must have names that comply with the format + foo.example.com/CamelCase. --- 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 + port: + description: port is the port number of the + ingress port. + format: int32 + type: integer + protocol: + default: TCP + description: 'protocol is the protocol of + the ingress port. The supported values are: + "TCP", "UDP", "SCTP"' + type: string + required: + - port + - protocol + type: object + type: array + x-kubernetes-list-type: atomic + type: object + type: array + type: object + name: + description: The name of the Ingress for the given cluster. + type: string + namespace: + description: The namespace which the Ingress for the given + cluster is deployed. + type: string + required: + - name + - namespace + type: object + service: + description: KubernetesServiceStatus defines the status for the + Tenant Control Plane Service in the management cluster. + properties: + conditions: + description: Current service state + items: + description: "Condition contains details for one aspect + of the current state of this API Resource. --- This struct + is intended for direct use as an array at the field path + .status.conditions. For example, \n type FooStatus struct{ + // Represents the observations of a foo's current state. + // Known .status.conditions.type are: \"Available\", \"Progressing\", + and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" + patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` + \n // other fields }" + 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 + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + loadBalancer: + description: LoadBalancer contains the current status of the + load-balancer, if one is present. + properties: + ingress: + description: Ingress is a list containing ingress points + for the load-balancer. Traffic intended for the service + should be sent to these ingress points. + items: + description: 'LoadBalancerIngress represents the status + of a load-balancer ingress point: traffic intended + for the service should be sent to an ingress point.' + properties: + hostname: + description: Hostname is set for load-balancer ingress + points that are DNS based (typically AWS load-balancers) + type: string + ip: + description: IP is set for load-balancer ingress + points that are IP based (typically GCE or OpenStack + load-balancers) + type: string + ipMode: + description: IPMode specifies how the load-balancer + IP behaves, and may only be specified when the + ip field is specified. Setting this to "VIP" indicates + that traffic is delivered to the node with the + destination set to the load-balancer's IP and + port. Setting this to "Proxy" indicates that traffic + is delivered to the node or pod with the destination + set to the node's IP and node port or the pod's + IP and port. Service implementations may use this + information to adjust traffic routing. + type: string + ports: + description: Ports is a list of records of service + ports If used, every port defined in the service + should have an entry in it + items: + properties: + error: + description: 'Error is to record the problem + with the service port The format of the + error shall comply with the following rules: + - built-in error values shall be specified + in this file and those shall use CamelCase + names - cloud provider specific error values + must have names that comply with the format + foo.example.com/CamelCase. --- 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 + port: + description: Port is the port number of the + service port of which status is recorded + here + format: int32 + type: integer + protocol: + default: TCP + description: 'Protocol is the protocol of + the service port of which status is recorded + here The supported values are: "TCP", "UDP", + "SCTP"' + type: string + required: + - port + - protocol + type: object + type: array + x-kubernetes-list-type: atomic + type: object + type: array + type: object + name: + description: The name of the Service for the given cluster. + type: string + namespace: + description: The namespace which the Service for the given + cluster is deployed. + type: string + port: + description: The port where the service is running + format: int32 + type: integer + required: + - name + - namespace + - port + type: object + version: + description: KubernetesVersion contains the information regarding + the running Kubernetes version, and its upgrade status. + properties: + status: + default: Provisioning + description: Status returns the current status of the Kubernetes + version, such as its provisioning state, or completed upgrade. + enum: + - Provisioning + - CertificateAuthorityRotating + - Upgrading + - Migrating + - Ready + - NotReady + type: string + version: + description: Version is the running Kubernetes version of + the Tenant Control Plane. + type: string + type: object + type: object + storage: + description: Storage Status contains information about Kubernetes + storage system + properties: + certificate: + properties: + checksum: + type: string + lastUpdate: + format: date-time + type: string + secretName: + type: string + type: object + config: + properties: + checksum: + type: string + secretName: + type: string + type: object + dataStoreName: + type: string + driver: + type: string + setup: + properties: + checksum: + type: string + lastUpdate: + format: date-time + type: string + schema: + type: string + user: + type: string + type: object + type: object + type: object + type: object + served: true + storage: true + subresources: + scale: + labelSelectorPath: .status.kubernetesResources.deployment.selector + specReplicasPath: .spec.controlPlane.deployment.replicas + statusReplicasPath: .status.kubernetesResources.deployment.replicas + status: {} diff --git a/packages/system/kamaji/charts/kamaji/templates/NOTES.txt b/packages/system/kamaji/charts/kamaji/templates/NOTES.txt new file mode 100644 index 00000000..670014e9 --- /dev/null +++ b/packages/system/kamaji/charts/kamaji/templates/NOTES.txt @@ -0,0 +1,5 @@ +List the available CRDs installed by Kamaji: + kubectl get customresourcedefinitions.apiextensions.k8s.io + +List all the Tenant Control Plane resources deployed in your cluster: + kubectl get tenantcontrolplanes.kamaji.clastix.io --all-namespaces diff --git a/packages/system/kamaji/charts/kamaji/templates/_helpers.tpl b/packages/system/kamaji/charts/kamaji/templates/_helpers.tpl new file mode 100644 index 00000000..f44ca63d --- /dev/null +++ b/packages/system/kamaji/charts/kamaji/templates/_helpers.tpl @@ -0,0 +1,91 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "kamaji.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | 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 "kamaji.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "kamaji.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "kamaji.labels" -}} +helm.sh/chart: {{ include "kamaji.chart" . }} +{{ include "kamaji.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "kamaji.selectorLabels" -}} +app.kubernetes.io/name: {{ default (include "kamaji.name" .) .name }} +app.kubernetes.io/instance: {{ default .Release.Name .instance }} +app.kubernetes.io/component: {{ default "controller-manager" .component }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "kamaji.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "kamaji.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} + +{{/* +Create the name of the Service to user for webhooks +*/}} +{{- define "kamaji.webhookServiceName" -}} +{{- printf "%s-webhook-service" (include "kamaji.fullname" .) }} +{{- end }} + +{{/* +Create the name of the Service to user for metrics +*/}} +{{- define "kamaji.metricsServiceName" -}} +{{- printf "%s-metrics-service" (include "kamaji.fullname" .) }} +{{- end }} + +{{/* +Create the name of the cert-manager secret +*/}} +{{- define "kamaji.webhookSecretName" -}} +{{- printf "%s-webhook-server-cert" (include "kamaji.fullname" .) }} +{{- end }} + +{{/* +Create the name of the cert-manager Certificate +*/}} +{{- define "kamaji.certificateName" -}} +{{- printf "%s-serving-cert" (include "kamaji.fullname" .) }} +{{- end }} diff --git a/packages/system/kamaji/charts/kamaji/templates/_helpers_datastore.tpl b/packages/system/kamaji/charts/kamaji/templates/_helpers_datastore.tpl new file mode 100644 index 00000000..3ed2c16e --- /dev/null +++ b/packages/system/kamaji/charts/kamaji/templates/_helpers_datastore.tpl @@ -0,0 +1,94 @@ +{{/* +Create a default fully qualified datastore name. +*/}} +{{- define "datastore.fullname" -}} +{{- if .Values.datastore.enabled }} +{{- default "default" .Values.datastore.nameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- required "A valid .Values.datastore.nameOverride required!" .Values.datastore.nameOverride }} +{{- end }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "datastore.labels" -}} +kamaji.clastix.io/datastore: {{ .Values.datastore.driver }} +helm.sh/chart: {{ include "kamaji.chart" . }} +{{ include "kamaji.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Datastore endpoints, in case of ETCD, retrieving the one provided by the chart. +*/}} +{{- define "datastore.endpoints" -}} +{{- if eq .Values.datastore.driver "etcd" }} +{{ include "etcd.endpoints" . }} +{{- else }} +{{ .Values.datastore.endpoints }} +{{- end }} +{{- end }} + +{{/* +The Certificate Authority section for the DataSource object. +*/}} +{{- define "datastore.certificateAuthority" -}} +{{- if eq .Values.datastore.driver "etcd" }} +certificate: + secretReference: + name: {{ include "etcd.caSecretName" . }} + namespace: {{ include "etcd.caSecretNamespace" . }} + keyPath: ca.crt +privateKey: + secretReference: + name: {{ include "etcd.caSecretName" . }} + namespace: {{ include "etcd.caSecretNamespace" . }} + keyPath: ca.key +{{- else }} +certificate: + secretReference: + name: {{ .Values.datastore.tlsConfig.certificateAuthority.certificate.name }} + namespace: {{ .Values.datastore.tlsConfig.certificateAuthority.certificate.namespace }} + keyPath: {{ .Values.datastore.tlsConfig.certificateAuthority.certificate.keyPath }} +{{- if .Values.datastore.tlsConfig.certificateAuthority.privateKey.name }} +privateKey: + secretReference: + name: {{ .Values.datastore.tlsConfig.certificateAuthority.privateKey.name }} + namespace: {{ .Values.datastore.tlsConfig.certificateAuthority.privateKey.namespace }} + keyPath: {{ .Values.datastore.tlsConfig.certificateAuthority.privateKey.keyPath }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +The Client Certificate section for the DataSource object. +*/}} +{{- define "datastore.clientCertificate" -}} +{{- if eq .Values.datastore.driver "etcd" }} +certificate: + secretReference: + name: {{ include "etcd.clientSecretName" . }} + namespace: {{ include "etcd.clientSecretNamespace" . }} + keyPath: tls.crt +privateKey: + secretReference: + name: {{ include "etcd.clientSecretName" . }} + namespace: {{ include "etcd.clientSecretNamespace" . }} + keyPath: tls.key +{{- else }} +certificate: + secretReference: + name: {{ .Values.datastore.tlsConfig.clientCertificate.certificate.name }} + namespace: {{ .Values.datastore.tlsConfig.clientCertificate.certificate.namespace }} + keyPath: {{ .Values.datastore.tlsConfig.clientCertificate.certificate.keyPath }} +privateKey: + secretReference: + name: {{ .Values.datastore.tlsConfig.clientCertificate.privateKey.name }} + namespace: {{ .Values.datastore.tlsConfig.clientCertificate.privateKey.namespace }} + keyPath: {{ .Values.datastore.tlsConfig.clientCertificate.privateKey.keyPath }} +{{- end }} +{{- end }} diff --git a/packages/system/kamaji/charts/kamaji/templates/_helpers_etcd.tpl b/packages/system/kamaji/charts/kamaji/templates/_helpers_etcd.tpl new file mode 100644 index 00000000..2a6b5247 --- /dev/null +++ b/packages/system/kamaji/charts/kamaji/templates/_helpers_etcd.tpl @@ -0,0 +1,142 @@ +{{/* +Create a default fully qualified etcd name. +*/}} +{{- define "etcd.fullname" -}} +{{- printf "etcd" }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "etcd.serviceAccountName" -}} +{{- if .Values.etcd.serviceAccount.create }} +{{- default (include "etcd.fullname" .) .Values.etcd.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.etcd.serviceAccount.name }} +{{- end }} +{{- end }} + +{{/* +Create the name of the Service to use +*/}} +{{- define "etcd.serviceName" -}} +{{- printf "%s" (include "etcd.fullname" .) | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "etcd.labels" -}} +app.kubernetes.io/name: {{ include "kamaji.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +app.kubernetes.io/components: etcd +{{- end }} + +{{/* +Selector labels. +*/}} +{{- define "etcd.selectorLabels" -}} +app.kubernetes.io/name: {{ include "kamaji.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +app.kubernetes.io/component: etcd +{{- end }} + +{{/* +Name of the etcd CA secret. +*/}} +{{- define "etcd.caSecretName" }} +{{- if .Values.etcd.deploy }} +{{- printf "%s-%s" (include "etcd.fullname" .) "certs" | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- required "A valid .Values.etcd.overrides.caSecret.name required!" .Values.etcd.overrides.caSecret.name }} +{{- end }} +{{- end }} + +{{/* +Namespace of the etcd CA secret. +*/}} +{{- define "etcd.caSecretNamespace" }} +{{- if .Values.etcd.deploy }} +{{- .Release.Namespace }} +{{- else }} +{{- required "A valid .Values.etcd.overrides.caSecret.namespace required!" .Values.etcd.overrides.caSecret.namespace }} +{{- end }} +{{- end }} + +{{/* +Name of the certificate signing requests for the certificates required by etcd. +*/}} +{{- define "etcd.csrConfigMapName" }} +{{- printf "%s-csr" (include "etcd.fullname" .) }} +{{- end }} + +{{/* +Name of the etcd root-client secret. +*/}} +{{- define "etcd.clientSecretName" }} +{{- if .Values.etcd.deploy }} +{{- printf "root-client-certs" }} +{{- else }} +{{- required "A valid .Values.etcd.overrides.clientSecret.name required!" .Values.etcd.overrides.clientSecret.name }} +{{- end }} +{{- end }} + +{{/* +Namespace of the etcd root-client secret. +*/}} +{{- define "etcd.clientSecretNamespace" }} +{{- if .Values.etcd.deploy }} +{{- .Release.Namespace }} +{{- else }} +{{- required "A valid .Values.etcd.overrides.clientSecret.namespace required!" .Values.etcd.overrides.clientSecret.namespace }} +{{- end }} +{{- end }} + +{{/* +Comma separated list of etcd endpoints, using the overrides in case of unmanaged etcd. +*/}} +{{- define "etcd.endpoints" }} +{{- $list := list -}} +{{- if .Values.etcd.deploy }} + {{- range $count := until 3 -}} + {{- $list = append $list (printf "%s-%d.%s.%s.svc.cluster.local:%d" "etcd" $count ( include "etcd.serviceName" . ) $.Release.Namespace (int $.Values.etcd.port) ) -}} + {{- end }} +{{- else if .Values.etcd.overrides.endpoints }} + {{- range $v := .Values.etcd.overrides.endpoints -}} + {{- $list = append $list (printf "%s:%d" $v (int $.Values.etcd.port) ) -}} + {{- end -}} +{{- else if not .Values.etcd.overrides.endpoints }} + {{- fail "A valid .Values.etcd.overrides.endpoints required!" }} +{{- end }} +{{- $list | toYaml }} +{{- end }} + +{{/* +Key-value of the etcd peers, using the overrides in case of unmanaged etcd. +*/}} +{{- define "etcd.initialCluster" }} +{{- $list := list -}} +{{- if .Values.etcd.deploy }} + {{- range $i, $count := until 3 -}} + {{- $list = append $list ( printf "etcd-%d=https://%s-%d.%s.%s.svc.cluster.local:%d" $i "etcd" $count ( include "etcd.serviceName" . ) $.Release.Namespace (int $.Values.etcd.peerApiPort) ) -}} + {{- end }} +{{- else if .Values.etcd.overrides.endpoints }} + {{- range $k, $v := .Values.etcd.overrides.endpoints -}} + {{- $list = append $list ( printf "%s=%s:%d" $k $v (int $.Values.etcd.peerApiPort) ) -}} + {{- end -}} +{{- else if not .Values.etcd.overrides.endpoints }} + {{- fail "A valid .Values.etcd.overrides.endpoints required!" }} +{{- end }} +{{- join "," $list -}} +{{- end }} + +{{/* +Retrieve the current Kubernetes version to launch a kubectl container with the minimum version skew possible. +*/}} +{{- define "etcd.jobsTagKubeVersion" -}} +{{- if contains "-eks-" .Capabilities.KubeVersion.GitVersion }} +{{- print "v" .Capabilities.KubeVersion.Major "." (.Capabilities.KubeVersion.Minor | replace "+" "") -}} +{{- else }} +{{- print "v" .Capabilities.KubeVersion.Major "." .Capabilities.KubeVersion.Minor -}} +{{- end }} +{{- end }} diff --git a/packages/system/kamaji/charts/kamaji/templates/certmanager_certificate.yaml b/packages/system/kamaji/charts/kamaji/templates/certmanager_certificate.yaml new file mode 100644 index 00000000..2f310b16 --- /dev/null +++ b/packages/system/kamaji/charts/kamaji/templates/certmanager_certificate.yaml @@ -0,0 +1,16 @@ +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + labels: + {{- $data := . | mustMergeOverwrite (dict "component" "certificate") -}} + {{- include "kamaji.labels" $data | nindent 4 }} + name: {{ include "kamaji.certificateName" . }} + namespace: {{ .Release.Namespace }} +spec: + dnsNames: + - {{ include "kamaji.webhookServiceName" . }}.{{ .Release.Namespace }}.svc + - {{ include "kamaji.webhookServiceName" . }}.{{ .Release.Namespace }}.svc.cluster.local + issuerRef: + kind: Issuer + name: kamaji-selfsigned-issuer + secretName: {{ include "kamaji.webhookSecretName" . }} \ No newline at end of file diff --git a/packages/system/kamaji/charts/kamaji/templates/certmanager_issuer.yaml b/packages/system/kamaji/charts/kamaji/templates/certmanager_issuer.yaml new file mode 100644 index 00000000..1bc3cbb6 --- /dev/null +++ b/packages/system/kamaji/charts/kamaji/templates/certmanager_issuer.yaml @@ -0,0 +1,10 @@ +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + labels: + {{- $data := . | mustMergeOverwrite (dict "component" "issuer") -}} + {{- include "kamaji.labels" $data | nindent 4 }} + name: kamaji-selfsigned-issuer + namespace: {{ .Release.Namespace }} +spec: + selfSigned: {} \ No newline at end of file diff --git a/packages/system/kamaji/charts/kamaji/templates/controller.yaml b/packages/system/kamaji/charts/kamaji/templates/controller.yaml new file mode 100644 index 00000000..82ddd5cb --- /dev/null +++ b/packages/system/kamaji/charts/kamaji/templates/controller.yaml @@ -0,0 +1,105 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "kamaji.fullname" . }} + labels: + {{- include "kamaji.labels" . | nindent 4 }} + namespace: {{ .Release.Namespace }} +spec: + replicas: {{ .Values.replicaCount }} + selector: + matchLabels: + {{- include "kamaji.selectorLabels" . | nindent 6 }} + template: + metadata: + {{- with .Values.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "kamaji.selectorLabels" . | nindent 8 }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + serviceAccountName: {{ include "kamaji.serviceAccountName" . }} + containers: + - args: + - manager + - --health-probe-bind-address={{ .Values.healthProbeBindAddress }} + - --leader-elect + - --metrics-bind-address={{ .Values.metricsBindAddress }} + - --tmp-directory={{ .Values.temporaryDirectoryPath }} + - --datastore={{ include "datastore.fullname" . }} + {{- if .Values.loggingDevel.enable }} + - --zap-devel + {{- end }} + {{- with .Values.extraArgs }} + {{- toYaml . | nindent 8 }} + {{- end }} + command: + - /kamaji + env: + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: SERVICE_ACCOUNT + valueFrom: + fieldRef: + fieldPath: spec.serviceAccountName + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + {{- with .Values.livenessProbe }} + livenessProbe: + {{- toYaml . | nindent 10 }} + {{- end }} + name: manager + ports: + - containerPort: 9443 + name: webhook-server + protocol: TCP + - containerPort: 8080 + name: metrics + protocol: TCP + - containerPort: 8081 + name: healthcheck + protocol: TCP + {{- with .Values.readinessProbe }} + readinessProbe: + {{- toYaml . | nindent 10 }} + {{- end }} + resources: + {{- toYaml .Values.resources | nindent 12 }} + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + volumeMounts: + - mountPath: /tmp + name: tmp + - mountPath: /tmp/k8s-webhook-server/serving-certs + name: cert + readOnly: true + terminationGracePeriodSeconds: 10 + volumes: + - name: tmp + emptyDir: + medium: Memory + - name: cert + secret: + defaultMode: 420 + secretName: {{ include "kamaji.webhookSecretName" . }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} diff --git a/packages/system/kamaji/charts/kamaji/templates/datastore.yaml b/packages/system/kamaji/charts/kamaji/templates/datastore.yaml new file mode 100644 index 00000000..b54ef99a --- /dev/null +++ b/packages/system/kamaji/charts/kamaji/templates/datastore.yaml @@ -0,0 +1,28 @@ +{{- if .Values.datastore.enabled}} +apiVersion: kamaji.clastix.io/v1alpha1 +kind: DataStore +metadata: + name: {{ include "datastore.fullname" . }} + annotations: + "helm.sh/hook": pre-install + labels: + {{- include "datastore.labels" . | nindent 4 }} +spec: + driver: {{ .Values.datastore.driver }} + endpoints: + {{- include "datastore.endpoints" . | indent 4 }} +{{- if (and .Values.datastore.basicAuth.usernameSecret.name .Values.datastore.basicAuth.passwordSecret.name) }} + basicAuth: + username: + secretReference: + {{- .Values.datastore.basicAuth.usernameSecret | toYaml | nindent 8 }} + password: + secretReference: + {{- .Values.datastore.basicAuth.passwordSecret | toYaml | nindent 8 }} +{{- end }} + tlsConfig: + certificateAuthority: + {{- include "datastore.certificateAuthority" . | indent 6 }} + clientCertificate: + {{- include "datastore.clientCertificate" . | indent 6 }} +{{- end}} diff --git a/packages/system/kamaji/charts/kamaji/templates/etcd_cm.yaml b/packages/system/kamaji/charts/kamaji/templates/etcd_cm.yaml new file mode 100644 index 00000000..53e48b5a --- /dev/null +++ b/packages/system/kamaji/charts/kamaji/templates/etcd_cm.yaml @@ -0,0 +1,98 @@ +{{- if .Values.etcd.deploy }} +apiVersion: v1 +kind: ConfigMap +metadata: + labels: + {{- include "etcd.labels" . | nindent 4 }} + name: {{ include "etcd.csrConfigMapName" . }} + namespace: {{ .Release.Namespace }} + annotations: + "helm.sh/hook": pre-install + "helm.sh/hook-weight": "-5" + "helm.sh/hook-delete-policy": "hook-succeeded,hook-failed" +data: + ca-csr.json: |- + { + "CN": "Clastix CA", + "key": { + "algo": "rsa", + "size": 2048 + }, + "names": [ + { + "C": "IT", + "ST": "Italy", + "L": "Milan" + } + ] + } + config.json: |- + { + "signing": { + "default": { + "expiry": "8760h" + }, + "profiles": { + "server-authentication": { + "usages": ["signing", "key encipherment", "server auth"], + "expiry": "8760h" + }, + "client-authentication": { + "usages": ["signing", "key encipherment", "client auth"], + "expiry": "8760h" + }, + "peer-authentication": { + "usages": ["signing", "key encipherment", "server auth", "client auth"], + "expiry": "8760h" + } + } + } + } + server-csr.json: |- + { + "CN": "etcd", + "key": { + "algo": "rsa", + "size": 2048 + }, + "hosts": [ +{{- range $count := until 3 -}} + {{ printf "\"etcd-%d.%s.%s.svc.cluster.local\"," $count (include "etcd.serviceName" .) $.Release.Namespace }} +{{- end }} + "etcd-server.{{ .Release.Namespace }}.svc.cluster.local", + "etcd-server.{{ .Release.Namespace }}.svc", + "etcd-server", + "127.0.0.1" + ] + } + peer-csr.json: |- + { + "CN": "etcd", + "key": { + "algo": "rsa", + "size": 2048 + }, + "hosts": [ +{{- range $count := until 3 -}} + {{ printf "\"etcd-%d\"," $count }} + {{ printf "\"etcd-%d.%s\"," $count (include "etcd.serviceName" .) }} + {{ printf "\"etcd-%d.%s.%s.svc\"," $count (include "etcd.serviceName" .) $.Release.Namespace }} + {{ printf "\"etcd-%d.%s.%s.svc.cluster.local\"," $count (include "etcd.serviceName" .) $.Release.Namespace }} +{{- end }} + "127.0.0.1" + ] + } + root-client-csr.json: |- + { + "CN": "root", + "key": { + "algo": "rsa", + "size": 2048 + }, + "names": [ + { + "O": "system:masters" + } + ] + } +{{- end }} diff --git a/packages/system/kamaji/charts/kamaji/templates/etcd_job_postdelete.yaml b/packages/system/kamaji/charts/kamaji/templates/etcd_job_postdelete.yaml new file mode 100644 index 00000000..45a8b4e6 --- /dev/null +++ b/packages/system/kamaji/charts/kamaji/templates/etcd_job_postdelete.yaml @@ -0,0 +1,35 @@ +{{- if .Values.etcd.deploy }} +apiVersion: batch/v1 +kind: Job +metadata: + labels: + {{- include "etcd.labels" . | nindent 4 }} + annotations: + "helm.sh/hook": pre-delete + "helm.sh/hook-weight": "-5" + "helm.sh/hook-delete-policy": "hook-succeeded,hook-failed" + name: "{{ .Release.Name }}-etcd-teardown" + namespace: {{ .Release.Namespace }} +spec: + template: + metadata: + name: "{{ .Release.Name }}" + spec: + serviceAccountName: {{ include "etcd.serviceAccountName" . }} + restartPolicy: Never + containers: + - name: kubectl + image: {{ printf "clastix/kubectl:%s" (include "etcd.jobsTagKubeVersion" .) }} + command: + - kubectl + - --namespace={{ .Release.Namespace }} + - delete + - secret + - --ignore-not-found=true + - {{ include "etcd.caSecretName" . }} + - {{ include "etcd.clientSecretName" . }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} +{{- end }} diff --git a/packages/system/kamaji/charts/kamaji/templates/etcd_job_postinstall.yaml b/packages/system/kamaji/charts/kamaji/templates/etcd_job_postinstall.yaml new file mode 100644 index 00000000..0ecd928f --- /dev/null +++ b/packages/system/kamaji/charts/kamaji/templates/etcd_job_postinstall.yaml @@ -0,0 +1,74 @@ +{{- if .Values.etcd.deploy }} +apiVersion: batch/v1 +kind: Job +metadata: + labels: + {{- include "etcd.labels" . | nindent 4 }} + annotations: + "helm.sh/hook": post-install + "helm.sh/hook-weight": "-5" + "helm.sh/hook-delete-policy": "hook-succeeded,hook-failed" + name: "{{ .Release.Name }}-etcd-setup" + namespace: {{ .Release.Namespace }} +spec: + template: + metadata: + name: "{{ .Release.Name }}" + spec: + serviceAccountName: {{ include "etcd.serviceAccountName" . }} + restartPolicy: Never + initContainers: + - name: kubectl + image: {{ printf "clastix/kubectl:%s" (include "etcd.jobsTagKubeVersion" .) }} + command: + - sh + - -c + - |- + kubectl --namespace={{ .Release.Namespace }} rollout status sts/etcd --timeout=300s + containers: + - command: + - bash + - -c + - |- + etcdctl member list -w table + if etcdctl user get root &>/dev/null; then + echo "User already exists, nothing to do" + else + etcdctl user add --no-password=true root && + etcdctl role add root && + etcdctl user grant-role root root && + etcdctl auth enable + fi + env: + - name: ETCDCTL_ENDPOINTS + value: https://etcd-0.{{ include "etcd.serviceName" . }}.{{ .Release.Namespace }}.svc.cluster.local:2379 + - name: ETCDCTL_CACERT + value: /opt/certs/ca/ca.crt + - name: ETCDCTL_CERT + value: /opt/certs/root-certs/tls.crt + - name: ETCDCTL_KEY + value: /opt/certs/root-certs/tls.key + image: quay.io/coreos/etcd:v3.5.1 + imagePullPolicy: Always + name: etcd-client + volumeMounts: + - name: root-certs + mountPath: /opt/certs/root-certs + - name: certs + mountPath: /opt/certs/ca + securityContext: + runAsUser: 1000 + runAsGroup: 1000 + fsGroup: 1000 + volumes: + - name: root-certs + secret: + secretName: {{ include "etcd.clientSecretName" . }} + - name: certs + secret: + secretName: {{ include "etcd.caSecretName" . }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} +{{- end }} diff --git a/packages/system/kamaji/charts/kamaji/templates/etcd_job_preinstall.yaml b/packages/system/kamaji/charts/kamaji/templates/etcd_job_preinstall.yaml new file mode 100644 index 00000000..834e2973 --- /dev/null +++ b/packages/system/kamaji/charts/kamaji/templates/etcd_job_preinstall.yaml @@ -0,0 +1,72 @@ +{{- if .Values.etcd.deploy }} +apiVersion: batch/v1 +kind: Job +metadata: + labels: + {{- include "etcd.labels" . | nindent 4 }} + annotations: + "helm.sh/hook": pre-install + "helm.sh/hook-weight": "-5" + "helm.sh/hook-delete-policy": "hook-succeeded" + name: "{{ .Release.Name }}-etcd-certs" + namespace: {{ .Release.Namespace }} +spec: + template: + metadata: + name: "{{ .Release.Name }}" + spec: + serviceAccountName: {{ include "etcd.serviceAccountName" . }} + restartPolicy: Never + initContainers: + - name: cfssl + image: cfssl/cfssl:latest + command: + - bash + - -c + - |- + cfssl gencert -initca /csr/ca-csr.json | cfssljson -bare /certs/ca && + mv /certs/ca.pem /certs/ca.crt && mv /certs/ca-key.pem /certs/ca.key && + cfssl gencert -ca=/certs/ca.crt -ca-key=/certs/ca.key -config=/csr/config.json -profile=peer-authentication /csr/peer-csr.json | cfssljson -bare /certs/peer && + cfssl gencert -ca=/certs/ca.crt -ca-key=/certs/ca.key -config=/csr/config.json -profile=peer-authentication /csr/server-csr.json | cfssljson -bare /certs/server && + cfssl gencert -ca=/certs/ca.crt -ca-key=/certs/ca.key -config=/csr/config.json -profile=client-authentication /csr/root-client-csr.json | cfssljson -bare /certs/root-client + volumeMounts: + - mountPath: /certs + name: certs + - mountPath: /csr + name: csr + containers: + - name: kubectl + image: {{ printf "clastix/kubectl:%s" (include "etcd.jobsTagKubeVersion" .) }} + command: ["/bin/sh", "-c"] + args: + - | + if kubectl get secret {{ include "etcd.caSecretName" . }} --namespace={{ .Release.Namespace }} &>/dev/null; then + echo "Secret {{ include "etcd.caSecretName" . }} already exists" + else + echo "Creating secret {{ include "etcd.caSecretName" . }}" + kubectl --namespace={{ .Release.Namespace }} create secret generic {{ include "etcd.caSecretName" . }} --from-file=/certs/ca.crt --from-file=/certs/ca.key --from-file=/certs/peer-key.pem --from-file=/certs/peer.pem --from-file=/certs/server-key.pem --from-file=/certs/server.pem + fi + if kubectl get secret {{ include "etcd.clientSecretName" . }} --namespace={{ .Release.Namespace }} &>/dev/null; then + echo "Secret {{ include "etcd.clientSecretName" . }} already exists" + else + echo "Creating secret {{ include "etcd.clientSecretName" . }}" + kubectl --namespace={{ .Release.Namespace }} create secret tls {{ include "etcd.clientSecretName" . }} --key=/certs/root-client-key.pem --cert=/certs/root-client.pem + fi + volumeMounts: + - mountPath: /certs + name: certs + securityContext: + runAsUser: 1000 + runAsGroup: 1000 + fsGroup: 1000 + volumes: + - name: csr + configMap: + name: {{ include "etcd.csrConfigMapName" . }} + - name: certs + emptyDir: {} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} +{{- end }} diff --git a/packages/system/kamaji/charts/kamaji/templates/etcd_rbac.yaml b/packages/system/kamaji/charts/kamaji/templates/etcd_rbac.yaml new file mode 100644 index 00000000..c34d3bcc --- /dev/null +++ b/packages/system/kamaji/charts/kamaji/templates/etcd_rbac.yaml @@ -0,0 +1,56 @@ +{{- if .Values.etcd.deploy }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + labels: + {{- include "etcd.labels" . | nindent 4 }} + name: etcd-gen-certs-role + annotations: + "helm.sh/hook": pre-install + "helm.sh/hook-weight": "-5" + namespace: {{ .Release.Namespace }} +rules: + - apiGroups: + - "" + resources: + - secrets + verbs: + - get + - delete + resourceNames: + - {{ include "etcd.caSecretName" . }} + - {{ include "etcd.clientSecretName" . }} + - apiGroups: + - "" + resources: + - secrets + verbs: + - create + - apiGroups: + - apps + resources: + - statefulsets + verbs: + - get + - list + - watch +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + labels: + {{- include "etcd.labels" . | nindent 4 }} + name: etcd-gen-certs-rolebiding + namespace: {{ .Release.Namespace }} + annotations: + "helm.sh/hook": pre-install + "helm.sh/hook-weight": "-5" +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: etcd-gen-certs-role +subjects: + - kind: ServiceAccount + name: {{ include "etcd.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} +{{- end }} diff --git a/packages/system/kamaji/charts/kamaji/templates/etcd_sa.yaml b/packages/system/kamaji/charts/kamaji/templates/etcd_sa.yaml new file mode 100644 index 00000000..e511ef2a --- /dev/null +++ b/packages/system/kamaji/charts/kamaji/templates/etcd_sa.yaml @@ -0,0 +1,12 @@ +{{- if .Values.etcd.deploy }} +apiVersion: v1 +kind: ServiceAccount +metadata: + labels: + {{- include "etcd.labels" . | nindent 4 }} + name: {{ include "etcd.serviceAccountName" . }} + annotations: + "helm.sh/hook": pre-install + "helm.sh/hook-weight": "-5" + namespace: {{ .Release.Namespace }} +{{- end }} diff --git a/packages/system/kamaji/charts/kamaji/templates/etcd_service.yaml b/packages/system/kamaji/charts/kamaji/templates/etcd_service.yaml new file mode 100644 index 00000000..96342427 --- /dev/null +++ b/packages/system/kamaji/charts/kamaji/templates/etcd_service.yaml @@ -0,0 +1,18 @@ +{{- if .Values.etcd.deploy }} +apiVersion: v1 +kind: Service +metadata: + labels: + {{- include "etcd.labels" . | nindent 4 }} + name: {{ include "etcd.serviceName" . }} + namespace: {{ .Release.Namespace }} +spec: + clusterIP: None + ports: + - port: {{ .Values.etcd.port }} + name: client + - port: {{ .Values.etcd.peerApiPort }} + name: peer + selector: + {{- include "etcd.selectorLabels" . | nindent 4 }} +{{- end }} diff --git a/packages/system/kamaji/charts/kamaji/templates/etcd_sts.yaml b/packages/system/kamaji/charts/kamaji/templates/etcd_sts.yaml new file mode 100644 index 00000000..516873bf --- /dev/null +++ b/packages/system/kamaji/charts/kamaji/templates/etcd_sts.yaml @@ -0,0 +1,101 @@ +{{- if .Values.etcd.deploy }} +apiVersion: apps/v1 +kind: StatefulSet +metadata: + labels: + {{- include "etcd.labels" . | nindent 4 }} + name: {{ include "etcd.fullname" . }} + namespace: {{ .Release.Namespace }} +spec: + serviceName: {{ include "etcd.serviceName" . }} + selector: + matchLabels: + {{- include "etcd.selectorLabels" . | nindent 6 }} + replicas: 3 + template: + metadata: + name: etcd + labels: + {{- include "etcd.selectorLabels" . | nindent 8 }} + spec: + volumes: + - name: certs + secret: + secretName: {{ include "etcd.caSecretName" . }} + {{- with .Values.etcd.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: etcd + image: {{ .Values.etcd.image.repository }}:{{ .Values.etcd.image.tag | default "v3.5.4" }} + imagePullPolicy: {{ .Values.etcd.image.pullPolicy }} + ports: + - containerPort: 2379 + name: client + - containerPort: 2380 + name: peer + volumeMounts: + - name: data + mountPath: /var/run/etcd + - name: certs + mountPath: /etc/etcd/pki + command: + - etcd + - --data-dir=/var/run/etcd + - --name=$(POD_NAME) + - --initial-cluster-state=new + - --initial-cluster={{ include "etcd.initialCluster" . }} + - --initial-advertise-peer-urls=https://$(POD_NAME).etcd.$(POD_NAMESPACE).svc.cluster.local:2380 + - --advertise-client-urls=https://$(POD_NAME).etcd.$(POD_NAMESPACE).svc.cluster.local:2379 + - --initial-cluster-token=kamaji + - --listen-client-urls=https://0.0.0.0:2379 + - --listen-metrics-urls=http://0.0.0.0:2381 + - --listen-peer-urls=https://0.0.0.0:2380 + - --client-cert-auth=true + - --peer-client-cert-auth=true + - --trusted-ca-file=/etc/etcd/pki/ca.crt + - --cert-file=/etc/etcd/pki/server.pem + - --key-file=/etc/etcd/pki/server-key.pem + - --peer-trusted-ca-file=/etc/etcd/pki/ca.crt + - --peer-cert-file=/etc/etcd/pki/peer.pem + - --peer-key-file=/etc/etcd/pki/peer-key.pem + - --auto-compaction-mode=periodic + - --auto-compaction-retention=5m + - --snapshot-count=10000 + - --quota-backend-bytes=8589934592 + - --v=8 + env: + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + {{- with .Values.etcd.livenessProbe }} + livenessProbe: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.etcd.startupProbe }} + startupProbe: + {{- toYaml . | nindent 12 }} + {{- end }} + volumeClaimTemplates: + - metadata: + name: data + {{- with .Values.etcd.persistence.customAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + storageClassName: {{ .Values.etcd.persistence.storageClassName }} + accessModes: + {{- range .Values.etcd.persistence.accessModes }} + - {{ . | quote }} + {{- end }} + resources: + requests: + storage: {{ .Values.etcd.persistence.size }} +{{- end }} diff --git a/packages/system/kamaji/charts/kamaji/templates/mutatingwebhookconfiguration.yaml b/packages/system/kamaji/charts/kamaji/templates/mutatingwebhookconfiguration.yaml new file mode 100644 index 00000000..f68843eb --- /dev/null +++ b/packages/system/kamaji/charts/kamaji/templates/mutatingwebhookconfiguration.yaml @@ -0,0 +1,30 @@ +apiVersion: admissionregistration.k8s.io/v1 +kind: MutatingWebhookConfiguration +metadata: + annotations: + cert-manager.io/inject-ca-from: {{ .Release.Namespace }}/{{ include "kamaji.certificateName" . }} + labels: + {{- $data := . | mustMergeOverwrite (dict "instance" "mutating-webhook-configuration") -}} + {{- include "kamaji.labels" $data | nindent 4 }} + name: kamaji-mutating-webhook-configuration +webhooks: + - admissionReviewVersions: + - v1 + clientConfig: + service: + name: {{ include "kamaji.webhookServiceName" . }} + namespace: {{ .Release.Namespace }} + path: /mutate-kamaji-clastix-io-v1alpha1-tenantcontrolplane + failurePolicy: Fail + name: mtenantcontrolplane.kb.io + rules: + - apiGroups: + - kamaji.clastix.io + apiVersions: + - v1alpha1 + operations: + - CREATE + - UPDATE + resources: + - tenantcontrolplanes + sideEffects: None \ No newline at end of file diff --git a/packages/system/kamaji/charts/kamaji/templates/rbac.yaml b/packages/system/kamaji/charts/kamaji/templates/rbac.yaml new file mode 100644 index 00000000..8fb939c3 --- /dev/null +++ b/packages/system/kamaji/charts/kamaji/templates/rbac.yaml @@ -0,0 +1,240 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "kamaji.serviceAccountName" . }} + labels: + {{- include "kamaji.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} + namespace: {{ .Release.Namespace }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: kamaji-leader-election-role + namespace: {{ .Release.Namespace }} +rules: +- apiGroups: + - "" + resources: + - configmaps + verbs: + - get + - list + - watch + - create + - update + - patch + - delete +- apiGroups: + - coordination.k8s.io + resources: + - leases + verbs: + - get + - list + - watch + - create + - update + - patch + - delete +- apiGroups: + - "" + resources: + - events + verbs: + - create + - patch +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + creationTimestamp: null + name: kamaji-manager-role +rules: +- apiGroups: + - apps + resources: + - deployments + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - batch + resources: + - jobs + verbs: + - create + - delete + - get + - list + - watch +- apiGroups: + - "" + resources: + - configmaps + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - "" + resources: + - secrets + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - "" + resources: + - services + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - kamaji.clastix.io + resources: + - datastores + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - kamaji.clastix.io + resources: + - datastores/status + verbs: + - get + - patch + - update +- apiGroups: + - kamaji.clastix.io + resources: + - tenantcontrolplanes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - kamaji.clastix.io + resources: + - tenantcontrolplanes/finalizers + verbs: + - update +- apiGroups: + - kamaji.clastix.io + resources: + - tenantcontrolplanes/status + verbs: + - get + - patch + - update +- apiGroups: + - networking.k8s.io + resources: + - ingresses + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: kamaji-metrics-reader +rules: +- nonResourceURLs: + - /metrics + verbs: + - get +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: kamaji-proxy-role +rules: +- apiGroups: + - authentication.k8s.io + resources: + - tokenreviews + verbs: + - create +- apiGroups: + - authorization.k8s.io + resources: + - subjectaccessreviews + verbs: + - create +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: kamaji-leader-election-rolebinding + namespace: {{ .Release.Namespace }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: kamaji-leader-election-role +subjects: +- kind: ServiceAccount + name: {{ include "kamaji.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: kamaji-manager-rolebinding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: kamaji-manager-role +subjects: +- kind: ServiceAccount + name: {{ include "kamaji.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: kamaji-proxy-rolebinding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: kamaji-proxy-role +subjects: +- kind: ServiceAccount + name: {{ include "kamaji.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} diff --git a/packages/system/kamaji/charts/kamaji/templates/service_metrics.yaml b/packages/system/kamaji/charts/kamaji/templates/service_metrics.yaml new file mode 100644 index 00000000..68ef848b --- /dev/null +++ b/packages/system/kamaji/charts/kamaji/templates/service_metrics.yaml @@ -0,0 +1,16 @@ +apiVersion: v1 +kind: Service +metadata: + labels: + {{- $data := . | mustMergeOverwrite (dict "component" "metrics") -}} + {{- include "kamaji.labels" $data | nindent 4 }} + name: {{ include "kamaji.metricsServiceName" . }} + namespace: {{ .Release.Namespace }} +spec: + ports: + - port: 8080 + name: metrics + protocol: TCP + targetPort: metrics + selector: + {{- include "kamaji.selectorLabels" . | nindent 4 }} diff --git a/packages/system/kamaji/charts/kamaji/templates/service_webhook.yaml b/packages/system/kamaji/charts/kamaji/templates/service_webhook.yaml new file mode 100644 index 00000000..cdb26cd3 --- /dev/null +++ b/packages/system/kamaji/charts/kamaji/templates/service_webhook.yaml @@ -0,0 +1,16 @@ +apiVersion: v1 +kind: Service +metadata: + labels: + {{- $data := . | mustMergeOverwrite (dict "component" "webhook" "instance" "webhook-service") -}} + {{- include "kamaji.labels" $data | nindent 4 }} + name: {{ include "kamaji.webhookServiceName" . }} + namespace: {{ .Release.Namespace }} +spec: + ports: + - port: 443 + protocol: TCP + name: webhook-server + targetPort: webhook-server + selector: + {{- include "kamaji.selectorLabels" . | nindent 4 }} diff --git a/packages/system/kamaji/charts/kamaji/templates/servicemonitor.yaml b/packages/system/kamaji/charts/kamaji/templates/servicemonitor.yaml new file mode 100644 index 00000000..ce8d2194 --- /dev/null +++ b/packages/system/kamaji/charts/kamaji/templates/servicemonitor.yaml @@ -0,0 +1,21 @@ +{{- if and (.Capabilities.APIVersions.Has "monitoring.coreos.com/v1") .Values.serviceMonitor.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + labels: + {{- $data := . | mustMergeOverwrite (dict "component" "servicemonitor") -}} + {{- include "kamaji.labels" $data | nindent 4 }} + name: {{ include "kamaji.fullname" . }} + namespace: {{ .Release.Namespace }} +spec: + endpoints: + - path: /metrics + port: metrics + scheme: http + namespaceSelector: + matchNames: + - {{ .Release.Namespace }} + selector: + matchLabels: + app.kubernetes.io/name: {{ include "kamaji.name" . }} +{{- end }} diff --git a/packages/system/kamaji/charts/kamaji/templates/validatingwebhookconfiguration.yaml b/packages/system/kamaji/charts/kamaji/templates/validatingwebhookconfiguration.yaml new file mode 100644 index 00000000..d981e974 --- /dev/null +++ b/packages/system/kamaji/charts/kamaji/templates/validatingwebhookconfiguration.yaml @@ -0,0 +1,70 @@ +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingWebhookConfiguration +metadata: + annotations: + cert-manager.io/inject-ca-from: {{ .Release.Namespace }}/{{ include "kamaji.certificateName" . }} + labels: + {{- $data := . | mustMergeOverwrite (dict "instance" "validating-webhook-configuration") -}} + {{- include "kamaji.labels" $data | nindent 4 }} + name: kamaji-validating-webhook-configuration +webhooks: + - admissionReviewVersions: + - v1 + clientConfig: + service: + name: {{ include "kamaji.webhookServiceName" . }} + namespace: {{ .Release.Namespace }} + path: /validate--v1-secret + failurePolicy: Ignore + name: vdatastoresecrets.kb.io + rules: + - apiGroups: + - "" + apiVersions: + - v1 + operations: + - DELETE + resources: + - secrets + sideEffects: None + - admissionReviewVersions: + - v1 + clientConfig: + service: + name: {{ include "kamaji.webhookServiceName" . }} + namespace: {{ .Release.Namespace }} + path: /validate-kamaji-clastix-io-v1alpha1-datastore + failurePolicy: Fail + name: vdatastore.kb.io + rules: + - apiGroups: + - kamaji.clastix.io + apiVersions: + - v1alpha1 + operations: + - CREATE + - UPDATE + - DELETE + resources: + - datastores + sideEffects: None + - admissionReviewVersions: + - v1 + clientConfig: + service: + name: {{ include "kamaji.webhookServiceName" . }} + namespace: {{ .Release.Namespace }} + path: /validate-kamaji-clastix-io-v1alpha1-tenantcontrolplane + failurePolicy: Fail + name: vtenantcontrolplane.kb.io + rules: + - apiGroups: + - kamaji.clastix.io + apiVersions: + - v1alpha1 + operations: + - CREATE + - UPDATE + resources: + - tenantcontrolplanes + sideEffects: None \ No newline at end of file diff --git a/packages/system/kamaji/charts/kamaji/values.sample.yaml b/packages/system/kamaji/charts/kamaji/values.sample.yaml new file mode 100644 index 00000000..a37f1400 --- /dev/null +++ b/packages/system/kamaji/charts/kamaji/values.sample.yaml @@ -0,0 +1,2 @@ +etcd: + endpoints: "https://etcd-0.etcd.kamaji-system.svc.cluster.local:2379,https://etcd-1.etcd.kamaji-system.svc.cluster.local:2379,https://etcd-2.etcd.kamaji-system.svc.cluster.local:2379" diff --git a/packages/system/kamaji/charts/kamaji/values.yaml b/packages/system/kamaji/charts/kamaji/values.yaml new file mode 100644 index 00000000..6dc584db --- /dev/null +++ b/packages/system/kamaji/charts/kamaji/values.yaml @@ -0,0 +1,216 @@ +# Default values for kamaji. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +# -- The number of the pod replicas for the Kamaji controller. +replicaCount: 1 + +image: + # -- The container image of the Kamaji controller. + repository: clastix/kamaji + pullPolicy: Always + # -- Overrides the image tag whose default is the chart appVersion. + tag: + +# -- A list of extra arguments to add to the kamaji controller default ones +extraArgs: [] + + +serviceMonitor: + # -- Toggle the ServiceMonitor true if you have Prometheus Operator installed and configured + enabled: false + +etcd: + # -- Install an etcd with enabled multi-tenancy along with Kamaji + deploy: true + + # -- The peer API port which servers are listening to. + peerApiPort: 2380 + + # -- The client request port. + port: 2379 + + # -- Install specific etcd image + image: + repository: quay.io/coreos/etcd + tag: "v3.5.6" + pullPolicy: IfNotPresent + + # -- The livenessProbe for the etcd container + livenessProbe: + failureThreshold: 8 + httpGet: + path: /health?serializable=true + port: 2381 + scheme: HTTP + initialDelaySeconds: 10 + periodSeconds: 10 + timeoutSeconds: 15 + + serviceAccount: + # -- Create a ServiceAccount, required to install and provision the etcd backing storage (default: true) + create: true + # -- Define the ServiceAccount name to use during the setup and provision of the etcd backing storage (default: "") + name: "" + persistence: + size: 10Gi + storageClassName: "" + accessModes: + - ReadWriteOnce + # -- The custom annotations to add to the PVC + customAnnotations: {} + # volumeType: local + + # -- (array) Kubernetes affinity rules to apply to Kamaji etcd pods + tolerations: [] + + overrides: + caSecret: + # -- Name of the secret which contains CA's certificate and private key. (default: "etcd-certs") + name: etcd-certs + # -- Namespace of the secret which contains CA's certificate and private key. (default: "kamaji-system") + namespace: kamaji-system + clientSecret: + # -- Name of the secret which contains ETCD client certificates. (default: "root-client-certs") + name: root-client-certs + # -- Name of the namespace where the secret which contains ETCD client certificates is. (default: "kamaji-system") + namespace: kamaji-system + # -- (map) Dictionary of the endpoints for the etcd cluster's members, key is the name of the etcd server. Don't define the protocol (TLS is automatically inflected), or any port, inflected from .etcd.peerApiPort value. + endpoints: + etcd-0: etcd-0.etcd.kamaji-system.svc.cluster.local + etcd-1: etcd-1.etcd.kamaji-system.svc.cluster.local + etcd-2: etcd-2.etcd.kamaji-system.svc.cluster.local + # -- ETCD Compaction interval (e.g. "5m0s"). (default: "0" (disabled)) + compactionInterval: 0 + +# -- The address the probe endpoint binds to. (default ":8081") +healthProbeBindAddress: ":8081" + +# -- The livenessProbe for the controller container +livenessProbe: + httpGet: + path: /healthz + port: healthcheck + initialDelaySeconds: 15 + periodSeconds: 20 + +# -- The readinessProbe for the controller container +readinessProbe: + httpGet: + path: /readyz + port: healthcheck + initialDelaySeconds: 5 + periodSeconds: 10 + +# -- (string) The address the metric endpoint binds to. (default ":8080") +metricsBindAddress: ":8080" + +imagePullSecrets: [] +nameOverride: "" +fullnameOverride: "" + +serviceAccount: + # Specifies whether a service account should be created + create: true + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: kamaji-controller-manager + +# -- The annotations to apply to the Kamaji controller pods. +podAnnotations: {} + +# -- The securityContext to apply to the Kamaji controller pods. +podSecurityContext: + runAsNonRoot: true + +# -- The securityContext to apply to the Kamaji controller container only. It does not apply to the Kamaji RBAC proxy container. +securityContext: + allowPrivilegeEscalation: false + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 + +resources: + limits: + cpu: 200m + memory: 100Mi + requests: + cpu: 100m + memory: 20Mi + +# -- Kubernetes node selector rules to schedule Kamaji controller +nodeSelector: {} + +# -- Kubernetes node taints that the Kamaji controller pods would tolerate +tolerations: [] + +# -- Kubernetes affinity rules to apply to Kamaji controller pods +affinity: {} + +# -- Directory which will be used to work with temporary files. (default "/tmp/kamaji") +temporaryDirectoryPath: "/tmp/kamaji" + +loggingDevel: + # -- (string) Development Mode defaults(encoder=consoleEncoder,logLevel=Debug,stackTraceLevel=Warn). Production Mode defaults(encoder=jsonEncoder,logLevel=Info,stackTraceLevel=Error) (default false) + enable: false + +datastore: + # -- (bool) Enable the Kamaji Datastore creation (default=true) + enabled: true + # -- (string) The Datastore name override, if empty and enabled=true defaults to `default`, if enabled=false, this is the name of the Datastore to connect to. + nameOverride: + # -- (string) The Kamaji Datastore driver, supported: etcd, MySQL, PostgreSQL (defaults=etcd). + driver: etcd + # -- (array) List of endpoints of the selected Datastore. When letting the Chart install the etcd datastore, this field is populated automatically. + endpoints: [] + basicAuth: + usernameSecret: + # -- The name of the Secret containing the username used to connect to the relational database. + name: + # -- The namespace of the Secret containing the username used to connect to the relational database. + namespace: + # -- The Secret key where the data is stored. + keyPath: + passwordSecret: + # -- The name of the Secret containing the password used to connect to the relational database. + name: + # -- The namespace of the Secret containing the password used to connect to the relational database. + namespace: + # -- The Secret key where the data is stored. + keyPath: + tlsConfig: + certificateAuthority: + certificate: + # -- Name of the Secret containing the CA required to establish the mandatory SSL/TLS connection to the datastore. + name: + # -- Namespace of the Secret containing the CA required to establish the mandatory SSL/TLS connection to the datastore. + namespace: + # -- Key of the Secret which contains the content of the certificate. + keyPath: + privateKey: + # -- Name of the Secret containing the CA private key required to establish the mandatory SSL/TLS connection to the datastore. + name: + # -- Namespace of the Secret containing the CA private key required to establish the mandatory SSL/TLS connection to the datastore. + namespace: + # -- Key of the Secret which contains the content of the private key. + keyPath: + clientCertificate: + certificate: + # -- Name of the Secret containing the client certificate required to establish the mandatory SSL/TLS connection to the datastore. + name: + # -- Namespace of the Secret containing the client certificate required to establish the mandatory SSL/TLS connection to the datastore. + namespace: + # -- Key of the Secret which contains the content of the certificate. + keyPath: + privateKey: + # -- Name of the Secret containing the client certificate private key required to establish the mandatory SSL/TLS connection to the datastore. + name: + # -- Namespace of the Secret containing the client certificate private key required to establish the mandatory SSL/TLS connection to the datastore. + namespace: + # -- Key of the Secret which contains the content of the private key. + keyPath: diff --git a/packages/system/kamaji/values.yaml b/packages/system/kamaji/values.yaml new file mode 100644 index 00000000..f6997f49 --- /dev/null +++ b/packages/system/kamaji/values.yaml @@ -0,0 +1,8 @@ +kamaji: + etcd: + deploy: false + + # Fix https://github.com/clastix/kamaji/pull/408 + image: + repository: ghcr.io/kvaps/test + tag: kamaji-v0.4.1-fix diff --git a/packages/system/kubeovn/Chart.yaml b/packages/system/kubeovn/Chart.yaml new file mode 100644 index 00000000..cc97b8db --- /dev/null +++ b/packages/system/kubeovn/Chart.yaml @@ -0,0 +1,2 @@ +name: cozy-kubeovn +version: 1.0.0 diff --git a/packages/system/kubeovn/Makefile b/packages/system/kubeovn/Makefile new file mode 100644 index 00000000..fdef3f6c --- /dev/null +++ b/packages/system/kubeovn/Makefile @@ -0,0 +1,17 @@ +NAMESPACE=cozy-kubeovn +NAME=kubeovn + +show: + helm template --dry-run=server -n $(NAMESPACE) $(NAME) . + +apply: + helm upgrade -i -n $(NAMESPACE) $(NAME) . + +diff: + helm diff upgrade --allow-unreleased --normalize-manifests -n $(NAMESPACE) $(NAME) . + +update: + rm -rf charts && mkdir -p charts/kube-ovn + curl -sSL https://github.com/kubeovn/kube-ovn/archive/refs/heads/master.tar.gz | \ + tar -C charts/kube-ovn -xzvf - --strip 2 kube-ovn-master/charts + patch -p4 < patches/cozyconfig.diff diff --git a/packages/system/kubeovn/charts/kube-ovn/Chart.yaml b/packages/system/kubeovn/charts/kube-ovn/Chart.yaml new file mode 100644 index 00000000..1cb8212f --- /dev/null +++ b/packages/system/kubeovn/charts/kube-ovn/Chart.yaml @@ -0,0 +1,24 @@ +apiVersion: v2 +name: kube-ovn +description: Helm chart for Kube-OVN + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +# Versions are expected to follow Semantic Versioning (https://semver.org/) +version: 0.1.0 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. Versions are not expected to +# follow Semantic Versioning. They should reflect the version the application is using. +# It is recommended to use it with quotes. +appVersion: "1.13.0" diff --git a/packages/system/kubeovn/charts/kube-ovn/README.md b/packages/system/kubeovn/charts/kube-ovn/README.md new file mode 100644 index 00000000..f9295ca9 --- /dev/null +++ b/packages/system/kubeovn/charts/kube-ovn/README.md @@ -0,0 +1,42 @@ +# Kube-OVN-helm + +Currently supported version: 1.9 + +Installation : + +```bash +$ kubectl label node -lbeta.kubernetes.io/os=linux kubernetes.io/os=linux --overwrite +$ kubectl label node -lnode-role.kubernetes.io/control-plane kube-ovn/role=master --overwrite +$ kubectl label node -lovn.kubernetes.io/ovs_dp_type!=userspace ovn.kubernetes.io/ovs_dp_type=kernel --overwrite + +# standard install +$ helm install --debug kubeovn ./charts --set MASTER_NODES=${Node0} + +# high availability install +$ helm install --debug kubeovn ./charts --set MASTER_NODES=${Node0},${Node1},${Node2} + +# upgrade to this version +$ helm upgrade --debug kubeovn ./charts --set MASTER_NODES=${Node0},${Node1},${Node2} +``` + +If `MASTER_NODES` unspecified Helm will take internal IPs of nodes with `kube-ovn/role=master` label + +### Talos Linux + +To install Kube-OVN on Talos Linux, declare openvswitch module in machine config: + +``` +machine: + kernel: + modules: + - name: openvswitch +``` + +and use the following options for install this Helm-chart: + +``` +--set cni_conf.MOUNT_LOCAL_BIN_DIR=false +--set OPENVSWITCH_DIR=/var/lib/openvswitch +--set OVN_DIR=/var/lib/ovn +--set DISABLE_MODULES_MANAGEMENT=true +``` diff --git a/packages/system/kubeovn/charts/kube-ovn/crds/crd.yaml b/packages/system/kubeovn/charts/kube-ovn/crds/crd.yaml new file mode 100644 index 00000000..2d545cc2 --- /dev/null +++ b/packages/system/kubeovn/charts/kube-ovn/crds/crd.yaml @@ -0,0 +1,2278 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: vpc-dnses.kubeovn.io +spec: + group: kubeovn.io + names: + plural: vpc-dnses + singular: vpc-dns + shortNames: + - vpc-dns + kind: VpcDns + listKind: VpcDnsList + scope: Cluster + versions: + - additionalPrinterColumns: + - jsonPath: .status.active + name: Active + type: boolean + - jsonPath: .spec.vpc + name: Vpc + type: string + - jsonPath: .spec.subnet + name: Subnet + type: string + name: v1 + served: true + storage: true + subresources: + status: {} + schema: + openAPIV3Schema: + type: object + properties: + spec: + type: object + properties: + vpc: + type: string + subnet: + type: string + replicas: + type: integer + minimum: 1 + maximum: 3 + status: + type: object + properties: + active: + type: boolean + conditions: + type: array + items: + type: object + properties: + type: + type: string + status: + type: string + reason: + type: string + message: + type: string + lastUpdateTime: + type: string + lastTransitionTime: + type: string +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: switch-lb-rules.kubeovn.io +spec: + group: kubeovn.io + names: + plural: switch-lb-rules + singular: switch-lb-rule + shortNames: + - slr + kind: SwitchLBRule + listKind: SwitchLBRuleList + scope: Cluster + versions: + - additionalPrinterColumns: + - jsonPath: .spec.vip + name: vip + type: string + - jsonPath: .status.ports + name: port(s) + type: string + - jsonPath: .status.service + name: service + type: string + - jsonPath: .metadata.creationTimestamp + name: age + type: date + name: v1 + served: true + storage: true + subresources: + status: {} + schema: + openAPIV3Schema: + type: object + properties: + spec: + type: object + properties: + namespace: + type: string + vip: + type: string + sessionAffinity: + type: string + ports: + items: + properties: + name: + type: string + port: + type: integer + minimum: 1 + maximum: 65535 + protocol: + type: string + targetPort: + type: integer + minimum: 1 + maximum: 65535 + type: object + type: array + selector: + items: + type: string + type: array + status: + type: object + properties: + ports: + type: string + service: + type: string +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: vpc-nat-gateways.kubeovn.io +spec: + group: kubeovn.io + names: + plural: vpc-nat-gateways + singular: vpc-nat-gateway + shortNames: + - vpc-nat-gw + kind: VpcNatGateway + listKind: VpcNatGatewayList + scope: Cluster + versions: + - additionalPrinterColumns: + - jsonPath: .spec.vpc + name: Vpc + type: string + - jsonPath: .spec.subnet + name: Subnet + type: string + - jsonPath: .spec.lanIp + name: LanIP + type: string + name: v1 + served: true + storage: true + schema: + openAPIV3Schema: + type: object + properties: + spec: + type: object + properties: + lanIp: + type: string + subnet: + type: string + externalSubnets: + items: + type: string + type: array + vpc: + type: string + selector: + type: array + items: + type: string + tolerations: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + enum: + - Equal + - Exists + value: + type: string + effect: + type: string + enum: + - NoExecute + - NoSchedule + - PreferNoSchedule + tolerationSeconds: + type: integer + affinity: + properties: + nodeAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + preference: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + weight: + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + properties: + nodeSelectorTerms: + items: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + type: array + required: + - nodeSelectorTerms + type: object + type: object + podAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + podAffinityTerm: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + x-kubernetes-patch-strategy: merge + x-kubernetes-patch-merge-key: key + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + namespaces: + items: + type: string + type: array + topologyKey: + type: string + required: + - topologyKey + type: object + weight: + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + x-kubernetes-patch-strategy: merge + x-kubernetes-patch-merge-key: key + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + namespaces: + items: + type: string + type: array + topologyKey: + type: string + required: + - topologyKey + type: object + type: array + type: object + podAntiAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + podAffinityTerm: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + x-kubernetes-patch-strategy: merge + x-kubernetes-patch-merge-key: key + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + namespaces: + items: + type: string + type: array + topologyKey: + type: string + required: + - topologyKey + type: object + weight: + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + x-kubernetes-patch-strategy: merge + x-kubernetes-patch-merge-key: key + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + namespaces: + items: + type: string + type: array + topologyKey: + type: string + required: + - topologyKey + type: object + type: array + type: object + type: object +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: iptables-eips.kubeovn.io +spec: + group: kubeovn.io + names: + plural: iptables-eips + singular: iptables-eip + shortNames: + - eip + kind: IptablesEIP + listKind: IptablesEIPList + scope: Cluster + versions: + - name: v1 + served: true + storage: true + subresources: + status: {} + additionalPrinterColumns: + - jsonPath: .status.ip + name: IP + type: string + - jsonPath: .spec.macAddress + name: Mac + type: string + - jsonPath: .status.nat + name: Nat + type: string + - jsonPath: .spec.natGwDp + name: NatGwDp + type: string + - jsonPath: .status.ready + name: Ready + type: boolean + schema: + openAPIV3Schema: + type: object + properties: + status: + type: object + properties: + ready: + type: boolean + ip: + type: string + nat: + type: string + redo: + type: string + qosPolicy: + type: string + conditions: + type: array + items: + type: object + properties: + type: + type: string + status: + type: string + reason: + type: string + message: + type: string + lastUpdateTime: + type: string + lastTransitionTime: + type: string + spec: + type: object + properties: + v4ip: + type: string + v6ip: + type: string + macAddress: + type: string + natGwDp: + type: string + qosPolicy: + type: string + externalSubnet: + type: string +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: iptables-fip-rules.kubeovn.io +spec: + group: kubeovn.io + names: + plural: iptables-fip-rules + singular: iptables-fip-rule + shortNames: + - fip + kind: IptablesFIPRule + listKind: IptablesFIPRuleList + scope: Cluster + versions: + - name: v1 + served: true + storage: true + subresources: + status: {} + additionalPrinterColumns: + - jsonPath: .spec.eip + name: Eip + type: string + - jsonPath: .status.v4ip + name: V4ip + type: string + - jsonPath: .spec.internalIp + name: InternalIp + type: string + - jsonPath: .status.v6ip + name: V6ip + type: string + - jsonPath: .status.ready + name: Ready + type: boolean + - jsonPath: .status.natGwDp + name: NatGwDp + type: string + schema: + openAPIV3Schema: + type: object + properties: + status: + type: object + properties: + ready: + type: boolean + v4ip: + type: string + v6ip: + type: string + natGwDp: + type: string + redo: + type: string + internalIp: + type: string + conditions: + type: array + items: + type: object + properties: + type: + type: string + status: + type: string + reason: + type: string + message: + type: string + lastUpdateTime: + type: string + lastTransitionTime: + type: string + spec: + type: object + properties: + eip: + type: string + internalIp: + type: string +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: iptables-dnat-rules.kubeovn.io +spec: + group: kubeovn.io + names: + plural: iptables-dnat-rules + singular: iptables-dnat-rule + shortNames: + - dnat + kind: IptablesDnatRule + listKind: IptablesDnatRuleList + scope: Cluster + versions: + - name: v1 + served: true + storage: true + subresources: + status: {} + additionalPrinterColumns: + - jsonPath: .spec.eip + name: Eip + type: string + - jsonPath: .spec.protocol + name: Protocol + type: string + - jsonPath: .status.v4ip + name: V4ip + type: string + - jsonPath: .status.v6ip + name: V6ip + type: string + - jsonPath: .spec.internalIp + name: InternalIp + type: string + - jsonPath: .spec.externalPort + name: ExternalPort + type: string + - jsonPath: .spec.internalPort + name: InternalPort + type: string + - jsonPath: .status.natGwDp + name: NatGwDp + type: string + - jsonPath: .status.ready + name: Ready + type: boolean + schema: + openAPIV3Schema: + type: object + properties: + status: + type: object + properties: + ready: + type: boolean + v4ip: + type: string + v6ip: + type: string + natGwDp: + type: string + redo: + type: string + protocol: + type: string + internalIp: + type: string + internalPort: + type: string + externalPort: + type: string + conditions: + type: array + items: + type: object + properties: + type: + type: string + status: + type: string + reason: + type: string + message: + type: string + lastUpdateTime: + type: string + lastTransitionTime: + type: string + spec: + type: object + properties: + eip: + type: string + externalPort: + type: string + protocol: + type: string + internalIp: + type: string + internalPort: + type: string +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: iptables-snat-rules.kubeovn.io +spec: + group: kubeovn.io + names: + plural: iptables-snat-rules + singular: iptables-snat-rule + shortNames: + - snat + kind: IptablesSnatRule + listKind: IptablesSnatRuleList + scope: Cluster + versions: + - name: v1 + served: true + storage: true + subresources: + status: {} + additionalPrinterColumns: + - jsonPath: .spec.eip + name: EIP + type: string + - jsonPath: .status.v4ip + name: V4ip + type: string + - jsonPath: .status.v6ip + name: V6ip + type: string + - jsonPath: .spec.internalCIDR + name: InternalCIDR + type: string + - jsonPath: .status.natGwDp + name: NatGwDp + type: string + - jsonPath: .status.ready + name: Ready + type: boolean + schema: + openAPIV3Schema: + type: object + properties: + status: + type: object + properties: + ready: + type: boolean + v4ip: + type: string + v6ip: + type: string + natGwDp: + type: string + redo: + type: string + internalCIDR: + type: string + conditions: + type: array + items: + type: object + properties: + type: + type: string + status: + type: string + reason: + type: string + message: + type: string + lastUpdateTime: + type: string + lastTransitionTime: + type: string + spec: + type: object + properties: + eip: + type: string + internalCIDR: + type: string +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: ovn-eips.kubeovn.io +spec: + group: kubeovn.io + names: + plural: ovn-eips + singular: ovn-eip + shortNames: + - oeip + kind: OvnEip + listKind: OvnEipList + scope: Cluster + versions: + - name: v1 + served: true + storage: true + subresources: + status: {} + additionalPrinterColumns: + - jsonPath: .status.v4Ip + name: V4IP + type: string + - jsonPath: .status.v6Ip + name: V6IP + type: string + - jsonPath: .status.macAddress + name: Mac + type: string + - jsonPath: .status.type + name: Type + type: string + - jsonPath: .status.nat + name: Nat + type: string + - jsonPath: .status.ready + name: Ready + type: boolean + schema: + openAPIV3Schema: + type: object + properties: + status: + type: object + properties: + type: + type: string + nat: + type: string + ready: + type: boolean + v4Ip: + type: string + v6Ip: + type: string + macAddress: + type: string + conditions: + type: array + items: + type: object + properties: + type: + type: string + status: + type: string + reason: + type: string + message: + type: string + lastUpdateTime: + type: string + lastTransitionTime: + type: string + spec: + type: object + properties: + externalSubnet: + type: string + type: + type: string + v4Ip: + type: string + v6Ip: + type: string + macAddress: + type: string +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: ovn-fips.kubeovn.io +spec: + group: kubeovn.io + names: + plural: ovn-fips + singular: ovn-fip + shortNames: + - ofip + kind: OvnFip + listKind: OvnFipList + scope: Cluster + versions: + - name: v1 + served: true + storage: true + subresources: + status: {} + additionalPrinterColumns: + - jsonPath: .status.vpc + name: Vpc + type: string + - jsonPath: .status.v4Eip + name: V4Eip + type: string + - jsonPath: .status.v4Ip + name: V4Ip + type: string + - jsonPath: .status.ready + name: Ready + type: boolean + - jsonPath: .spec.ipType + name: IpType + type: string + - jsonPath: .spec.ipName + name: IpName + type: string + schema: + openAPIV3Schema: + type: object + properties: + status: + type: object + properties: + ready: + type: boolean + v4Eip: + type: string + v4Ip: + type: string + vpc: + type: string + conditions: + type: array + items: + type: object + properties: + type: + type: string + status: + type: string + reason: + type: string + message: + type: string + lastUpdateTime: + type: string + lastTransitionTime: + type: string + spec: + type: object + properties: + ovnEip: + type: string + ipType: + type: string + ipName: + type: string + vpc: + type: string + v4Ip: + type: string +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: ovn-snat-rules.kubeovn.io +spec: + group: kubeovn.io + names: + plural: ovn-snat-rules + singular: ovn-snat-rule + shortNames: + - osnat + kind: OvnSnatRule + listKind: OvnSnatRuleList + scope: Cluster + versions: + - name: v1 + served: true + storage: true + subresources: + status: {} + additionalPrinterColumns: + - jsonPath: .status.vpc + name: Vpc + type: string + - jsonPath: .status.v4Eip + name: V4Eip + type: string + - jsonPath: .status.v4IpCidr + name: V4IpCidr + type: string + - jsonPath: .status.ready + name: Ready + type: boolean + schema: + openAPIV3Schema: + type: object + properties: + status: + type: object + properties: + ready: + type: boolean + v4Eip: + type: string + v4IpCidr: + type: string + vpc: + type: string + conditions: + type: array + items: + type: object + properties: + type: + type: string + status: + type: string + reason: + type: string + message: + type: string + lastUpdateTime: + type: string + lastTransitionTime: + type: string + spec: + type: object + properties: + ovnEip: + type: string + vpcSubnet: + type: string + ipName: + type: string + vpc: + type: string + v4IpCidr: + type: string +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: ovn-dnat-rules.kubeovn.io +spec: + group: kubeovn.io + names: + plural: ovn-dnat-rules + singular: ovn-dnat-rule + shortNames: + - odnat + kind: OvnDnatRule + listKind: OvnDnatRuleList + scope: Cluster + versions: + - name: v1 + served: true + storage: true + subresources: + status: {} + additionalPrinterColumns: + - jsonPath: .status.vpc + name: Vpc + type: string + - jsonPath: .spec.ovnEip + name: Eip + type: string + - jsonPath: .status.protocol + name: Protocol + type: string + - jsonPath: .status.v4Eip + name: V4Eip + type: string + - jsonPath: .status.v4Ip + name: V4Ip + type: string + - jsonPath: .status.internalPort + name: InternalPort + type: string + - jsonPath: .status.externalPort + name: ExternalPort + type: string + - jsonPath: .spec.ipName + name: IpName + type: string + - jsonPath: .status.ready + name: Ready + type: boolean + schema: + openAPIV3Schema: + type: object + properties: + status: + type: object + properties: + ready: + type: boolean + v4Eip: + type: string + v4Ip: + type: string + vpc: + type: string + externalPort: + type: string + internalPort: + type: string + protocol: + type: string + ipName: + type: string + conditions: + type: array + items: + type: object + properties: + type: + type: string + status: + type: string + reason: + type: string + message: + type: string + lastUpdateTime: + type: string + lastTransitionTime: + type: string + spec: + type: object + properties: + ovnEip: + type: string + ipType: + type: string + ipName: + type: string + externalPort: + type: string + internalPort: + type: string + protocol: + type: string + vpc: + type: string + v4Ip: + type: string +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: vpcs.kubeovn.io +spec: + group: kubeovn.io + versions: + - additionalPrinterColumns: + - jsonPath: .status.enableExternal + name: EnableExternal + type: boolean + - jsonPath: .status.enableBfd + name: EnableBfd + type: boolean + - jsonPath: .status.standby + name: Standby + type: boolean + - jsonPath: .status.subnets + name: Subnets + type: string + - jsonPath: .status.extraExternalSubnets + name: ExtraExternalSubnets + type: string + - jsonPath: .spec.namespaces + name: Namespaces + type: string + name: v1 + schema: + openAPIV3Schema: + properties: + spec: + properties: + enableExternal: + type: boolean + enableBfd: + type: boolean + namespaces: + items: + type: string + type: array + extraExternalSubnets: + items: + type: string + type: array + staticRoutes: + items: + properties: + policy: + type: string + cidr: + type: string + nextHopIP: + type: string + ecmpMode: + type: string + bfdId: + type: string + routeTable: + type: string + type: object + type: array + policyRoutes: + items: + properties: + priority: + type: integer + action: + type: string + match: + type: string + nextHopIP: + type: string + type: object + type: array + vpcPeerings: + items: + properties: + remoteVpc: + type: string + localConnectIP: + type: string + type: object + type: array + type: object + status: + properties: + conditions: + items: + properties: + lastTransitionTime: + type: string + lastUpdateTime: + type: string + message: + type: string + reason: + type: string + status: + type: string + type: + type: string + type: object + type: array + default: + type: boolean + defaultLogicalSwitch: + type: string + router: + type: string + standby: + type: boolean + enableExternal: + type: boolean + enableBfd: + type: boolean + subnets: + items: + type: string + type: array + extraExternalSubnets: + items: + type: string + type: array + vpcPeerings: + items: + type: string + type: array + tcpLoadBalancer: + type: string + tcpSessionLoadBalancer: + type: string + udpLoadBalancer: + type: string + udpSessionLoadBalancer: + type: string + sctpLoadBalancer: + type: string + sctpSessionLoadBalancer: + type: string + type: object + type: object + served: true + storage: true + subresources: + status: {} + names: + kind: Vpc + listKind: VpcList + plural: vpcs + shortNames: + - vpc + singular: vpc + scope: Cluster +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: ips.kubeovn.io +spec: + group: kubeovn.io + versions: + - name: v1 + served: true + storage: true + additionalPrinterColumns: + - name: V4IP + type: string + jsonPath: .spec.v4IpAddress + - name: V6IP + type: string + jsonPath: .spec.v6IpAddress + - name: Mac + type: string + jsonPath: .spec.macAddress + - name: Node + type: string + jsonPath: .spec.nodeName + - name: Subnet + type: string + jsonPath: .spec.subnet + schema: + openAPIV3Schema: + type: object + properties: + spec: + type: object + properties: + podName: + type: string + namespace: + type: string + subnet: + type: string + attachSubnets: + type: array + items: + type: string + nodeName: + type: string + ipAddress: + type: string + v4IpAddress: + type: string + v6IpAddress: + type: string + attachIps: + type: array + items: + type: string + macAddress: + type: string + attachMacs: + type: array + items: + type: string + containerID: + type: string + podType: + type: string + scope: Cluster + names: + plural: ips + singular: ip + kind: IP + shortNames: + - ip +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: vips.kubeovn.io +spec: + group: kubeovn.io + names: + plural: vips + singular: vip + shortNames: + - vip + kind: Vip + listKind: VipList + scope: Cluster + versions: + - name: v1 + served: true + storage: true + additionalPrinterColumns: + - name: V4IP + type: string + jsonPath: .status.v4ip + - name: V6IP + type: string + jsonPath: .status.v6ip + - name: Mac + type: string + jsonPath: .status.mac + - name: PMac + type: string + jsonPath: .spec.parentMac + - name: Subnet + type: string + jsonPath: .spec.subnet + - jsonPath: .status.ready + name: Ready + type: boolean + - jsonPath: .status.type + name: Type + type: string + schema: + openAPIV3Schema: + type: object + properties: + status: + type: object + properties: + type: + type: string + ready: + type: boolean + v4ip: + type: string + v6ip: + type: string + mac: + type: string + pv4ip: + type: string + pv6ip: + type: string + pmac: + type: string + selector: + type: array + items: + type: string + conditions: + type: array + items: + type: object + properties: + type: + type: string + status: + type: string + reason: + type: string + message: + type: string + lastUpdateTime: + type: string + lastTransitionTime: + type: string + spec: + type: object + properties: + namespace: + type: string + subnet: + type: string + type: + type: string + attachSubnets: + type: array + items: + type: string + v4ip: + type: string + macAddress: + type: string + v6ip: + type: string + parentV4ip: + type: string + parentMac: + type: string + parentV6ip: + type: string + selector: + type: array + items: + type: string +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: subnets.kubeovn.io +spec: + group: kubeovn.io + versions: + - name: v1 + served: true + storage: true + subresources: + status: {} + additionalPrinterColumns: + - name: Provider + type: string + jsonPath: .spec.provider + - name: Vpc + type: string + jsonPath: .spec.vpc + - name: Protocol + type: string + jsonPath: .spec.protocol + - name: CIDR + type: string + jsonPath: .spec.cidrBlock + - name: Private + type: boolean + jsonPath: .spec.private + - name: NAT + type: boolean + jsonPath: .spec.natOutgoing + - name: Default + type: boolean + jsonPath: .spec.default + - name: GatewayType + type: string + jsonPath: .spec.gatewayType + - name: V4Used + type: number + jsonPath: .status.v4usingIPs + - name: V4Available + type: number + jsonPath: .status.v4availableIPs + - name: V6Used + type: number + jsonPath: .status.v6usingIPs + - name: V6Available + type: number + jsonPath: .status.v6availableIPs + - name: ExcludeIPs + type: string + jsonPath: .spec.excludeIps + - name: U2OInterconnectionIP + type: string + jsonPath: .status.u2oInterconnectionIP + schema: + openAPIV3Schema: + type: object + properties: + status: + type: object + properties: + v4availableIPs: + type: number + v4usingIPs: + type: number + v6availableIPs: + type: number + v6usingIPs: + type: number + activateGateway: + type: string + dhcpV4OptionsUUID: + type: string + dhcpV6OptionsUUID: + type: string + u2oInterconnectionIP: + type: string + u2oInterconnectionVPC: + type: string + v4usingIPrange: + type: string + v4availableIPrange: + type: string + v6usingIPrange: + type: string + v6availableIPrange: + type: string + natOutgoingPolicyRules: + type: array + items: + type: object + properties: + ruleID: + type: string + action: + type: string + enum: + - nat + - forward + match: + type: object + properties: + srcIPs: + type: string + dstIPs: + type: string + conditions: + type: array + items: + type: object + properties: + type: + type: string + status: + type: string + reason: + type: string + message: + type: string + lastUpdateTime: + type: string + lastTransitionTime: + type: string + spec: + type: object + properties: + vpc: + type: string + default: + type: boolean + protocol: + type: string + enum: + - IPv4 + - IPv6 + - Dual + cidrBlock: + type: string + namespaces: + type: array + items: + type: string + gateway: + type: string + provider: + type: string + excludeIps: + type: array + items: + type: string + vips: + type: array + items: + type: string + gatewayType: + type: string + allowSubnets: + type: array + items: + type: string + gatewayNode: + type: string + natOutgoing: + type: boolean + externalEgressGateway: + type: string + policyRoutingPriority: + type: integer + minimum: 1 + maximum: 32765 + policyRoutingTableID: + type: integer + minimum: 1 + maximum: 2147483647 + not: + enum: + - 252 # compat + - 253 # default + - 254 # main + - 255 # local + mtu: + type: integer + minimum: 68 + maximum: 65535 + private: + type: boolean + vlan: + type: string + logicalGateway: + type: boolean + disableGatewayCheck: + type: boolean + disableInterConnection: + type: boolean + enableDHCP: + type: boolean + dhcpV4Options: + type: string + dhcpV6Options: + type: string + enableIPv6RA: + type: boolean + ipv6RAConfigs: + type: string + allowEWTraffic: + type: boolean + acls: + type: array + items: + type: object + properties: + direction: + type: string + enum: + - from-lport + - to-lport + priority: + type: integer + minimum: 0 + maximum: 32767 + match: + type: string + action: + type: string + enum: + - allow-related + - allow-stateless + - allow + - drop + - reject + natOutgoingPolicyRules: + type: array + items: + type: object + properties: + action: + type: string + enum: + - nat + - forward + match: + type: object + properties: + srcIPs: + type: string + dstIPs: + type: string + u2oInterconnection: + type: boolean + u2oInterconnectionIP: + type: string + enableLb: + type: boolean + enableEcmp: + type: boolean + enableMulticastSnoop: + type: boolean + routeTable: + type: string + scope: Cluster + names: + plural: subnets + singular: subnet + kind: Subnet + shortNames: + - subnet +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: ippools.kubeovn.io +spec: + group: kubeovn.io + versions: + - name: v1 + served: true + storage: true + subresources: + status: {} + additionalPrinterColumns: + - name: Subnet + type: string + jsonPath: .spec.subnet + - name: IPs + type: string + jsonPath: .spec.ips + - name: V4Used + type: number + jsonPath: .status.v4UsingIPs + - name: V4Available + type: number + jsonPath: .status.v4AvailableIPs + - name: V6Used + type: number + jsonPath: .status.v6UsingIPs + - name: V6Available + type: number + jsonPath: .status.v6AvailableIPs + schema: + openAPIV3Schema: + type: object + properties: + spec: + type: object + properties: + subnet: + type: string + x-kubernetes-validations: + - rule: "self == oldSelf" + message: "This field is immutable." + namespaces: + type: array + x-kubernetes-list-type: set + items: + type: string + ips: + type: array + minItems: 1 + x-kubernetes-list-type: set + items: + type: string + anyOf: + - format: ipv4 + - format: ipv6 + - format: cidr + - pattern: ^(?:(?:[01]?\d{1,2}|2[0-4]\d|25[0-5])\.){3}(?:[01]?\d{1,2}|2[0-4]\d|25[0-5])\.\.(?:(?:[01]?\d{1,2}|2[0-4]\d|25[0-5])\.){3}(?:[01]?\d{1,2}|2[0-4]\d|25[0-5])$ + - pattern: ^((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|:)))\.\.((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|:)))$ + required: + - subnet + - ips + status: + type: object + properties: + v4AvailableIPs: + type: number + v4UsingIPs: + type: number + v6AvailableIPs: + type: number + v6UsingIPs: + type: number + v4AvailableIPRange: + type: string + v4UsingIPRange: + type: string + v6AvailableIPRange: + type: string + v6UsingIPRange: + type: string + conditions: + type: array + items: + type: object + properties: + type: + type: string + status: + type: string + reason: + type: string + message: + type: string + lastUpdateTime: + type: string + lastTransitionTime: + type: string + scope: Cluster + names: + plural: ippools + singular: ippool + kind: IPPool + shortNames: + - ippool +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: vlans.kubeovn.io +spec: + group: kubeovn.io + versions: + - name: v1 + served: true + storage: true + subresources: + status: {} + schema: + openAPIV3Schema: + type: object + properties: + spec: + type: object + properties: + id: + type: integer + minimum: 0 + maximum: 4095 + provider: + type: string + vlanId: + type: integer + description: Deprecated in favor of id + providerInterfaceName: + type: string + description: Deprecated in favor of provider + required: + - provider + status: + type: object + properties: + subnets: + type: array + items: + type: string + additionalPrinterColumns: + - name: ID + type: string + jsonPath: .spec.id + - name: Provider + type: string + jsonPath: .spec.provider + scope: Cluster + names: + plural: vlans + singular: vlan + kind: Vlan + shortNames: + - vlan +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: provider-networks.kubeovn.io +spec: + group: kubeovn.io + versions: + - name: v1 + served: true + storage: true + subresources: + status: {} + schema: + openAPIV3Schema: + type: object + properties: + metadata: + type: object + properties: + name: + type: string + maxLength: 12 + not: + enum: + - int + spec: + type: object + properties: + defaultInterface: + type: string + maxLength: 15 + pattern: '^[^/\s]+$' + customInterfaces: + type: array + items: + type: object + properties: + interface: + type: string + maxLength: 15 + pattern: '^[^/\s]+$' + nodes: + type: array + items: + type: string + exchangeLinkName: + type: boolean + excludeNodes: + type: array + items: + type: string + required: + - defaultInterface + status: + type: object + properties: + ready: + type: boolean + readyNodes: + type: array + items: + type: string + notReadyNodes: + type: array + items: + type: string + vlans: + type: array + items: + type: string + conditions: + type: array + items: + type: object + properties: + node: + type: string + type: + type: string + status: + type: string + reason: + type: string + message: + type: string + lastUpdateTime: + type: string + lastTransitionTime: + type: string + additionalPrinterColumns: + - name: DefaultInterface + type: string + jsonPath: .spec.defaultInterface + - name: Ready + type: boolean + jsonPath: .status.ready + scope: Cluster + names: + plural: provider-networks + singular: provider-network + kind: ProviderNetwork + listKind: ProviderNetworkList +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: security-groups.kubeovn.io +spec: + group: kubeovn.io + names: + plural: security-groups + singular: security-group + shortNames: + - sg + kind: SecurityGroup + listKind: SecurityGroupList + scope: Cluster + versions: + - name: v1 + served: true + storage: true + schema: + openAPIV3Schema: + type: object + properties: + spec: + type: object + properties: + ingressRules: + type: array + items: + type: object + properties: + ipVersion: + type: string + protocol: + type: string + priority: + type: integer + remoteType: + type: string + remoteAddress: + type: string + remoteSecurityGroup: + type: string + portRangeMin: + type: integer + portRangeMax: + type: integer + policy: + type: string + egressRules: + type: array + items: + type: object + properties: + ipVersion: + type: string + protocol: + type: string + priority: + type: integer + remoteType: + type: string + remoteAddress: + type: string + remoteSecurityGroup: + type: string + portRangeMin: + type: integer + portRangeMax: + type: integer + policy: + type: string + allowSameGroupTraffic: + type: boolean + status: + type: object + properties: + portGroup: + type: string + allowSameGroupTraffic: + type: boolean + ingressMd5: + type: string + egressMd5: + type: string + ingressLastSyncSuccess: + type: boolean + egressLastSyncSuccess: + type: boolean + subresources: + status: {} + conversion: + strategy: None +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: qos-policies.kubeovn.io +spec: + group: kubeovn.io + names: + plural: qos-policies + singular: qos-policy + shortNames: + - qos + kind: QoSPolicy + listKind: QoSPolicyList + scope: Cluster + versions: + - name: v1 + served: true + storage: true + subresources: + status: {} + additionalPrinterColumns: + - jsonPath: .spec.shared + name: Shared + type: string + - jsonPath: .spec.bindingType + name: BindingType + type: string + schema: + openAPIV3Schema: + type: object + properties: + status: + type: object + properties: + shared: + type: boolean + bindingType: + type: string + bandwidthLimitRules: + type: array + items: + type: object + properties: + name: + type: string + interface: + type: string + rateMax: + type: string + burstMax: + type: string + priority: + type: integer + direction: + type: string + matchType: + type: string + matchValue: + type: string + conditions: + type: array + items: + type: object + properties: + type: + type: string + status: + type: string + reason: + type: string + message: + type: string + lastUpdateTime: + type: string + lastTransitionTime: + type: string + spec: + type: object + properties: + shared: + type: boolean + bindingType: + type: string + bandwidthLimitRules: + type: array + items: + type: object + properties: + name: + type: string + interface: + type: string + rateMax: + type: string + burstMax: + type: string + priority: + type: integer + direction: + type: string + matchType: + type: string + matchValue: + type: string + required: + - name + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map diff --git a/packages/system/kubeovn/charts/kube-ovn/templates/_helpers.tpl b/packages/system/kubeovn/charts/kube-ovn/templates/_helpers.tpl new file mode 100644 index 00000000..8be2462d --- /dev/null +++ b/packages/system/kubeovn/charts/kube-ovn/templates/_helpers.tpl @@ -0,0 +1,31 @@ +{{/* +Get IP-addresses of master nodes +*/}} +{{- define "kubeovn.nodeIPs" -}} +{{- $nodes := lookup "v1" "Node" "" "" -}} +{{- $ips := list -}} +{{- range $node := $nodes.items -}} + {{- $label := splitList "=" $.Values.MASTER_NODES_LABEL }} + {{- $key := index $label 0 }} + {{- $val := "" }} + {{- if eq (len $label) 2 }} + {{- $val = index $label 1 }} + {{- end }} + {{- if eq (index $node.metadata.labels $key) $val -}} + {{- range $address := $node.status.addresses -}} + {{- if eq $address.type "InternalIP" -}} + {{- $ips = append $ips $address.address -}} + {{- break -}} + {{- end -}} + {{- end -}} + {{- end -}} +{{- end -}} +{{ join "," $ips }} +{{- end -}} + +{{/* +Number of master nodes +*/}} +{{- define "kubeovn.nodeCount" -}} + {{- len (split "," (.Values.MASTER_NODES | default (include "kubeovn.nodeIPs" .))) }} +{{- end -}} diff --git a/packages/system/kubeovn/charts/kube-ovn/templates/central-deploy.yaml b/packages/system/kubeovn/charts/kube-ovn/templates/central-deploy.yaml new file mode 100644 index 00000000..bf234e11 --- /dev/null +++ b/packages/system/kubeovn/charts/kube-ovn/templates/central-deploy.yaml @@ -0,0 +1,161 @@ +kind: Deployment +apiVersion: apps/v1 +metadata: + name: ovn-central + namespace: {{ .Values.namespace }} + annotations: + kubernetes.io/description: | + OVN components: northd, nb and sb. +spec: + replicas: {{ include "kubeovn.nodeCount" . }} + strategy: + rollingUpdate: + maxSurge: 0 + maxUnavailable: 1 + type: RollingUpdate + selector: + matchLabels: + app: ovn-central + template: + metadata: + labels: + app: ovn-central + component: network + type: infra + spec: + tolerations: + - effect: NoSchedule + operator: Exists + - effect: NoExecute + operator: Exists + - key: CriticalAddonsOnly + operator: Exists + affinity: + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchLabels: + app: ovn-central + topologyKey: kubernetes.io/hostname + priorityClassName: system-cluster-critical + serviceAccountName: ovn-ovs + hostNetwork: true + containers: + - name: ovn-central + image: {{ .Values.global.registry.address }}/{{ .Values.global.images.kubeovn.repository }}:{{ .Values.global.images.kubeovn.tag }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + command: + - /kube-ovn/start-db.sh + securityContext: + capabilities: + add: ["SYS_NICE"] + env: + - name: ENABLE_SSL + value: "{{ .Values.networking.ENABLE_SSL }}" + - name: NODE_IPS + value: "{{ .Values.MASTER_NODES | default (include "kubeovn.nodeIPs" .) }}" + - name: POD_IP + valueFrom: + fieldRef: + fieldPath: status.podIP + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: POD_IPS + valueFrom: + fieldRef: + fieldPath: status.podIPs + - name: ENABLE_BIND_LOCAL_IP + value: "{{- .Values.func.ENABLE_BIND_LOCAL_IP }}" + - name: PROBE_INTERVAL + value: "{{ .Values.networking.PROBE_INTERVAL }}" + - name: OVN_LEADER_PROBE_INTERVAL + value: "{{ .Values.networking.OVN_LEADER_PROBE_INTERVAL }}" + - name: OVN_NORTHD_N_THREADS + value: "{{ .Values.networking.OVN_NORTHD_N_THREADS }}" + - name: ENABLE_COMPACT + value: "{{ .Values.networking.ENABLE_COMPACT }}" + resources: + requests: + cpu: {{ index .Values "ovn-central" "requests" "cpu" }} + memory: {{ index .Values "ovn-central" "requests" "memory" }} + limits: + cpu: {{ index .Values "ovn-central" "limits" "cpu" }} + memory: {{ index .Values "ovn-central" "limits" "memory" }} + volumeMounts: + - mountPath: /var/run/openvswitch + name: host-run-ovs + - mountPath: /var/run/ovn + name: host-run-ovn + - mountPath: /sys + name: host-sys + readOnly: true + - mountPath: /etc/openvswitch + name: host-config-openvswitch + - mountPath: /etc/ovn + name: host-config-ovn + - mountPath: /var/log/openvswitch + name: host-log-ovs + - mountPath: /var/log/ovn + name: host-log-ovn + - mountPath: /etc/localtime + name: localtime + readOnly: true + - mountPath: /var/run/tls + name: kube-ovn-tls + readinessProbe: + exec: + command: + - bash + - /kube-ovn/ovn-healthcheck.sh + periodSeconds: 15 + timeoutSeconds: 45 + livenessProbe: + exec: + command: + - bash + - /kube-ovn/ovn-healthcheck.sh + initialDelaySeconds: 30 + periodSeconds: 15 + failureThreshold: 5 + timeoutSeconds: 45 + nodeSelector: + kubernetes.io/os: "linux" + {{- with splitList "=" .Values.MASTER_NODES_LABEL }} + {{ index . 0 }}: "{{ if eq (len .) 2 }}{{ index . 1 }}{{ end }}" + {{- end }} + volumes: + - name: host-run-ovs + hostPath: + path: /run/openvswitch + - name: host-run-ovn + hostPath: + path: /run/ovn + - name: host-sys + hostPath: + path: /sys + - name: host-config-openvswitch + hostPath: + path: {{ .Values.OPENVSWITCH_DIR }} + - name: host-config-ovn + hostPath: + path: {{ .Values.OVN_DIR }} + - name: host-log-ovs + hostPath: + path: {{ .Values.log_conf.LOG_DIR }}/openvswitch + - name: host-log-ovn + hostPath: + path: {{ .Values.log_conf.LOG_DIR }}/ovn + - name: localtime + hostPath: + path: /etc/localtime + - name: kube-ovn-tls + secret: + optional: true + secretName: kube-ovn-tls + diff --git a/packages/system/kubeovn/charts/kube-ovn/templates/controller-deploy.yaml b/packages/system/kubeovn/charts/kube-ovn/templates/controller-deploy.yaml new file mode 100644 index 00000000..756eb7cc --- /dev/null +++ b/packages/system/kubeovn/charts/kube-ovn/templates/controller-deploy.yaml @@ -0,0 +1,163 @@ +kind: Deployment +apiVersion: apps/v1 +metadata: + name: kube-ovn-controller + namespace: {{ .Values.namespace }} + annotations: + kubernetes.io/description: | + kube-ovn controller +spec: + replicas: {{ include "kubeovn.nodeCount" . }} + selector: + matchLabels: + app: kube-ovn-controller + strategy: + rollingUpdate: + maxSurge: 0% + maxUnavailable: 100% + type: RollingUpdate + template: + metadata: + labels: + app: kube-ovn-controller + component: network + type: infra + spec: + tolerations: + - effect: NoSchedule + operator: Exists + - key: CriticalAddonsOnly + operator: Exists + affinity: + nodeAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - preference: + matchExpressions: + - key: "ovn.kubernetes.io/ic-gw" + operator: NotIn + values: + - "true" + weight: 100 + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchLabels: + app: kube-ovn-controller + topologyKey: kubernetes.io/hostname + priorityClassName: system-cluster-critical + serviceAccountName: ovn + hostNetwork: true + containers: + - name: kube-ovn-controller + image: {{ .Values.global.registry.address }}/{{ .Values.global.images.kubeovn.repository }}:{{ .Values.global.images.kubeovn.tag }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + args: + {{- $cozyConfig := lookup "v1" "ConfigMap" "cozy-system" "cozystack" }} + - /kube-ovn/start-controller.sh + - --default-ls={{ .Values.networking.DEFAULT_SUBNET }} + - --default-cidr={{ index $cozyConfig.data "ipv4-pod-cidr" }} + - --default-gateway={{ index $cozyConfig.data "ipv4-pod-gateway" }} + - --default-gateway-check={{- .Values.func.CHECK_GATEWAY }} + - --default-logical-gateway={{- .Values.func.LOGICAL_GATEWAY }} + - --default-u2o-interconnection={{- .Values.func.U2O_INTERCONNECTION }} + - --default-exclude-ips={{- .Values.networking.EXCLUDE_IPS }} + - --cluster-router={{ .Values.networking.DEFAULT_VPC }} + - --node-switch={{ .Values.networking.NODE_SUBNET }} + - --node-switch-cidr={{ index $cozyConfig.data "ipv4-join-cidr" }} + - --service-cluster-ip-range={{ index $cozyConfig.data "ipv4-svc-cidr" }} + - --network-type={{- .Values.networking.NETWORK_TYPE }} + - --default-provider-name={{ .Values.networking.vlan.PROVIDER_NAME }} + - --default-interface-name={{- .Values.networking.vlan.VLAN_INTERFACE_NAME }} + - --default-exchange-link-name={{- .Values.networking.EXCHANGE_LINK_NAME }} + - --default-vlan-name={{- .Values.networking.vlan.VLAN_NAME }} + - --default-vlan-id={{- .Values.networking.vlan.VLAN_ID }} + - --ls-dnat-mod-dl-dst={{- .Values.func.LS_DNAT_MOD_DL_DST }} + - --pod-nic-type={{- .Values.networking.POD_NIC_TYPE }} + - --enable-lb={{- .Values.func.ENABLE_LB }} + - --enable-np={{- .Values.func.ENABLE_NP }} + - --enable-eip-snat={{- .Values.networking.ENABLE_EIP_SNAT }} + - --enable-external-vpc={{- .Values.func.ENABLE_EXTERNAL_VPC }} + - --enable-ecmp={{- .Values.networking.ENABLE_ECMP }} + - --logtostderr=false + - --alsologtostderr=true + - --gc-interval={{- .Values.performance.GC_INTERVAL }} + - --inspect-interval={{- .Values.performance.INSPECT_INTERVAL }} + - --log_file=/var/log/kube-ovn/kube-ovn-controller.log + - --log_file_max_size=0 + - --enable-lb-svc={{- .Values.func.ENABLE_LB_SVC }} + - --keep-vm-ip={{- .Values.func.ENABLE_KEEP_VM_IP }} + - --pod-default-fip-type={{- .Values.networking.POD_DEFAULT_FIP_TYPE }} + - --enable-metrics={{- .Values.networking.ENABLE_METRICS }} + - --node-local-dns-ip={{- .Values.networking.NODE_LOCAL_DNS_IP }} + env: + - name: ENABLE_SSL + value: "{{ .Values.networking.ENABLE_SSL }}" + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: KUBE_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: KUBE_NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + - name: OVN_DB_IPS + value: "{{ .Values.MASTER_NODES | default (include "kubeovn.nodeIPs" .) }}" + - name: POD_IPS + valueFrom: + fieldRef: + fieldPath: status.podIPs + - name: ENABLE_BIND_LOCAL_IP + value: "{{- .Values.func.ENABLE_BIND_LOCAL_IP }}" + volumeMounts: + - mountPath: /etc/localtime + name: localtime + readOnly: true + - mountPath: /var/log/kube-ovn + name: kube-ovn-log + # ovn-ic log directory + - mountPath: /var/log/ovn + name: ovn-log + - mountPath: /var/run/tls + name: kube-ovn-tls + readinessProbe: + exec: + command: + - /kube-ovn/kube-ovn-controller-healthcheck + periodSeconds: 3 + timeoutSeconds: 45 + livenessProbe: + exec: + command: + - /kube-ovn/kube-ovn-controller-healthcheck + initialDelaySeconds: 300 + periodSeconds: 7 + failureThreshold: 5 + timeoutSeconds: 45 + resources: + requests: + cpu: {{ index .Values "kube-ovn-controller" "requests" "cpu" }} + memory: {{ index .Values "kube-ovn-controller" "requests" "memory" }} + limits: + cpu: {{ index .Values "kube-ovn-controller" "limits" "cpu" }} + memory: {{ index .Values "kube-ovn-controller" "limits" "memory" }} + nodeSelector: + kubernetes.io/os: "linux" + volumes: + - name: localtime + hostPath: + path: /etc/localtime + - name: kube-ovn-log + hostPath: + path: {{ .Values.log_conf.LOG_DIR }}/kube-ovn + - name: ovn-log + hostPath: + path: {{ .Values.log_conf.LOG_DIR }}/ovn + - name: kube-ovn-tls + secret: + optional: true + secretName: kube-ovn-tls + diff --git a/packages/system/kubeovn/charts/kube-ovn/templates/controller-svc.yaml b/packages/system/kubeovn/charts/kube-ovn/templates/controller-svc.yaml new file mode 100644 index 00000000..b4d39619 --- /dev/null +++ b/packages/system/kubeovn/charts/kube-ovn/templates/controller-svc.yaml @@ -0,0 +1,16 @@ +kind: Service +apiVersion: v1 +metadata: + name: kube-ovn-controller + namespace: {{ .Values.namespace }} + labels: + app: kube-ovn-controller +spec: + selector: + app: kube-ovn-controller + ports: + - port: 10660 + name: metrics + {{- if eq .Values.networking.NET_STACK "dual_stack" }} + ipFamilyPolicy: PreferDualStack + {{- end }} diff --git a/packages/system/kubeovn/charts/kube-ovn/templates/monitor-deploy.yaml b/packages/system/kubeovn/charts/kube-ovn/templates/monitor-deploy.yaml new file mode 100644 index 00000000..b938ebfe --- /dev/null +++ b/packages/system/kubeovn/charts/kube-ovn/templates/monitor-deploy.yaml @@ -0,0 +1,139 @@ +kind: Deployment +apiVersion: apps/v1 +metadata: + name: kube-ovn-monitor + namespace: {{ .Values.namespace }} + annotations: + kubernetes.io/description: | + Metrics for OVN components: northd, nb and sb. +spec: + replicas: 1 + strategy: + rollingUpdate: + maxSurge: 1 + maxUnavailable: 1 + type: RollingUpdate + selector: + matchLabels: + app: kube-ovn-monitor + template: + metadata: + labels: + app: kube-ovn-monitor + component: network + type: infra + spec: + tolerations: + - effect: NoSchedule + operator: Exists + - key: CriticalAddonsOnly + operator: Exists + affinity: + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchLabels: + app: kube-ovn-monitor + topologyKey: kubernetes.io/hostname + priorityClassName: system-cluster-critical + serviceAccountName: kube-ovn-app + hostNetwork: true + containers: + - name: kube-ovn-monitor + image: {{ .Values.global.registry.address }}/{{ .Values.global.images.kubeovn.repository }}:{{ .Values.global.images.kubeovn.tag }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + command: ["/kube-ovn/start-ovn-monitor.sh"] + args: + - --log_file=/var/log/kube-ovn/kube-ovn-monitor.log + - --logtostderr=false + - --alsologtostderr=true + - --log_file_max_size=0 + securityContext: + runAsUser: 0 + privileged: false + env: + - name: ENABLE_SSL + value: "{{ .Values.networking.ENABLE_SSL }}" + - name: KUBE_NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + - name: POD_IPS + valueFrom: + fieldRef: + fieldPath: status.podIPs + - name: ENABLE_BIND_LOCAL_IP + value: "{{- .Values.func.ENABLE_BIND_LOCAL_IP }}" + resources: + requests: + cpu: {{ index .Values "kube-ovn-monitor" "requests" "cpu" }} + memory: {{ index .Values "kube-ovn-monitor" "requests" "memory" }} + limits: + cpu: {{ index .Values "kube-ovn-monitor" "limits" "cpu" }} + memory: {{ index .Values "kube-ovn-monitor" "limits" "memory" }} + volumeMounts: + - mountPath: /var/run/openvswitch + name: host-run-ovs + - mountPath: /var/run/ovn + name: host-run-ovn + - mountPath: /etc/openvswitch + name: host-config-openvswitch + - mountPath: /etc/ovn + name: host-config-ovn + - mountPath: /var/log/ovn + name: host-log-ovn + readOnly: true + - mountPath: /etc/localtime + name: localtime + readOnly: true + - mountPath: /var/run/tls + name: kube-ovn-tls + - mountPath: /var/log/kube-ovn + name: kube-ovn-log + livenessProbe: + failureThreshold: 3 + initialDelaySeconds: 30 + periodSeconds: 7 + successThreshold: 1 + tcpSocket: + port: 10661 + timeoutSeconds: 3 + readinessProbe: + failureThreshold: 3 + initialDelaySeconds: 30 + periodSeconds: 7 + successThreshold: 1 + tcpSocket: + port: 10661 + timeoutSeconds: 3 + nodeSelector: + kubernetes.io/os: "linux" + {{- with splitList "=" .Values.MASTER_NODES_LABEL }} + {{ index . 0 }}: "{{ if eq (len .) 2 }}{{ index . 1 }}{{ end }}" + {{- end }} + volumes: + - name: host-run-ovs + hostPath: + path: /run/openvswitch + - name: host-run-ovn + hostPath: + path: /run/ovn + - name: host-config-openvswitch + hostPath: + path: {{ .Values.OPENVSWITCH_DIR }} + - name: host-config-ovn + hostPath: + path: {{ .Values.OVN_DIR }} + - name: host-log-ovn + hostPath: + path: {{ .Values.log_conf.LOG_DIR }}/ovn + - name: localtime + hostPath: + path: /etc/localtime + - name: kube-ovn-tls + secret: + optional: true + secretName: kube-ovn-tls + - name: kube-ovn-log + hostPath: + path: {{ .Values.log_conf.LOG_DIR }}/kube-ovn diff --git a/packages/system/kubeovn/charts/kube-ovn/templates/monitor-svc.yaml b/packages/system/kubeovn/charts/kube-ovn/templates/monitor-svc.yaml new file mode 100644 index 00000000..1ad1800d --- /dev/null +++ b/packages/system/kubeovn/charts/kube-ovn/templates/monitor-svc.yaml @@ -0,0 +1,18 @@ +kind: Service +apiVersion: v1 +metadata: + name: kube-ovn-monitor + namespace: {{ .Values.namespace }} + labels: + app: kube-ovn-monitor +spec: + ports: + - name: metrics + port: 10661 + type: ClusterIP + selector: + app: kube-ovn-monitor + sessionAffinity: None + {{- if eq .Values.networking.NET_STACK "dual_stack" }} + ipFamilyPolicy: PreferDualStack + {{- end }} diff --git a/packages/system/kubeovn/charts/kube-ovn/templates/nb-svc.yaml b/packages/system/kubeovn/charts/kube-ovn/templates/nb-svc.yaml new file mode 100644 index 00000000..43992e91 --- /dev/null +++ b/packages/system/kubeovn/charts/kube-ovn/templates/nb-svc.yaml @@ -0,0 +1,19 @@ +kind: Service +apiVersion: v1 +metadata: + name: ovn-nb + namespace: {{ .Values.namespace }} +spec: + ports: + - name: ovn-nb + protocol: TCP + port: 6641 + targetPort: 6641 + type: ClusterIP + {{- if eq .Values.networking.NET_STACK "dual_stack" }} + ipFamilyPolicy: PreferDualStack + {{- end }} + selector: + app: ovn-central + ovn-nb-leader: "true" + sessionAffinity: None diff --git a/packages/system/kubeovn/charts/kube-ovn/templates/northd-svc.yaml b/packages/system/kubeovn/charts/kube-ovn/templates/northd-svc.yaml new file mode 100644 index 00000000..cec07233 --- /dev/null +++ b/packages/system/kubeovn/charts/kube-ovn/templates/northd-svc.yaml @@ -0,0 +1,19 @@ +kind: Service +apiVersion: v1 +metadata: + name: ovn-northd + namespace: {{ .Values.namespace }} +spec: + ports: + - name: ovn-northd + protocol: TCP + port: 6643 + targetPort: 6643 + type: ClusterIP + {{- if eq .Values.networking.NET_STACK "dual_stack" }} + ipFamilyPolicy: PreferDualStack + {{- end }} + selector: + app: ovn-central + ovn-northd-leader: "true" + sessionAffinity: None diff --git a/packages/system/kubeovn/charts/kube-ovn/templates/ovn-CR.yaml b/packages/system/kubeovn/charts/kube-ovn/templates/ovn-CR.yaml new file mode 100644 index 00000000..2aa39184 --- /dev/null +++ b/packages/system/kubeovn/charts/kube-ovn/templates/ovn-CR.yaml @@ -0,0 +1,231 @@ +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + annotations: + rbac.authorization.k8s.io/system-only: "true" + name: system:ovn +rules: + - apiGroups: + - "kubeovn.io" + resources: + - vpcs + - vpcs/status + - vpc-nat-gateways + - vpc-nat-gateways/status + - subnets + - subnets/status + - ippools + - ippools/status + - ips + - vips + - vips/status + - vlans + - vlans/status + - provider-networks + - provider-networks/status + - security-groups + - security-groups/status + - iptables-eips + - iptables-fip-rules + - iptables-dnat-rules + - iptables-snat-rules + - iptables-eips/status + - iptables-fip-rules/status + - iptables-dnat-rules/status + - iptables-snat-rules/status + - ovn-eips + - ovn-fips + - ovn-snat-rules + - ovn-eips/status + - ovn-fips/status + - ovn-snat-rules/status + - ovn-dnat-rules + - ovn-dnat-rules/status + - switch-lb-rules + - switch-lb-rules/status + - vpc-dnses + - vpc-dnses/status + - qos-policies + - qos-policies/status + verbs: + - "*" + - apiGroups: + - "" + resources: + - pods + - pods/exec + - namespaces + - nodes + - configmaps + verbs: + - create + - get + - list + - watch + - patch + - update + - apiGroups: + - "k8s.cni.cncf.io" + resources: + - network-attachment-definitions + verbs: + - get + - apiGroups: + - "" + - networking.k8s.io + - apps + resources: + - networkpolicies + - daemonsets + verbs: + - get + - list + - watch + - apiGroups: + - "" + - apps + resources: + - services/status + verbs: + - update + - apiGroups: + - "" + - networking.k8s.io + - apps + - extensions + resources: + - services + - endpoints + - statefulsets + - deployments + - deployments/scale + verbs: + - create + - delete + - update + - patch + - get + - list + - watch + - apiGroups: + - "" + resources: + - events + verbs: + - create + - patch + - update + - apiGroups: + - coordination.k8s.io + resources: + - leases + verbs: + - "*" + - apiGroups: + - "kubevirt.io" + resources: + - virtualmachines + - virtualmachineinstances + verbs: + - get + - list + +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + annotations: + rbac.authorization.k8s.io/system-only: "true" + name: system:ovn-ovs +rules: + - apiGroups: + - "" + resources: + - pods + verbs: + - get + - patch + - apiGroups: + - "" + - networking.k8s.io + - apps + resources: + - services + - endpoints + verbs: + - get + - apiGroups: + - apps + resources: + - controllerrevisions + verbs: + - get + - list + +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + annotations: + rbac.authorization.k8s.io/system-only: "true" + name: system:kube-ovn-cni +rules: + - apiGroups: + - "kubeovn.io" + resources: + - subnets + - provider-networks + - ovn-eips + - ovn-eips/status + - ips + verbs: + - get + - list + - patch + - update + - watch + - apiGroups: + - "" + resources: + - pods + - nodes + - configmaps + verbs: + - get + - list + - patch + - watch + - apiGroups: + - "" + resources: + - events + verbs: + - create + - patch + - update + +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + annotations: + rbac.authorization.k8s.io/system-only: "true" + name: system:kube-ovn-app +rules: + - apiGroups: + - "" + resources: + - pods + - nodes + verbs: + - get + - list + - apiGroups: + - "" + - networking.k8s.io + - apps + resources: + - daemonsets + verbs: + - get diff --git a/packages/system/kubeovn/charts/kube-ovn/templates/ovn-CRB.yaml b/packages/system/kubeovn/charts/kube-ovn/templates/ovn-CRB.yaml new file mode 100644 index 00000000..9230d900 --- /dev/null +++ b/packages/system/kubeovn/charts/kube-ovn/templates/ovn-CRB.yaml @@ -0,0 +1,54 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: ovn +roleRef: + name: system:ovn + kind: ClusterRole + apiGroup: rbac.authorization.k8s.io +subjects: + - kind: ServiceAccount + name: ovn + namespace: {{ .Values.namespace }} + +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: ovn-ovs +roleRef: + name: system:ovn-ovs + kind: ClusterRole + apiGroup: rbac.authorization.k8s.io +subjects: + - kind: ServiceAccount + name: ovn-ovs + namespace: {{ .Values.namespace }} + +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: kube-ovn-cni +roleRef: + name: system:kube-ovn-cni + kind: ClusterRole + apiGroup: rbac.authorization.k8s.io +subjects: + - kind: ServiceAccount + name: kube-ovn-cni + namespace: {{ .Values.namespace }} + +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: kube-ovn-app +roleRef: + name: system:kube-ovn-app + kind: ClusterRole + apiGroup: rbac.authorization.k8s.io +subjects: + - kind: ServiceAccount + name: kube-ovn-app + namespace: {{ .Values.namespace }} diff --git a/packages/system/kubeovn/charts/kube-ovn/templates/ovn-dpdk-ds.yaml b/packages/system/kubeovn/charts/kube-ovn/templates/ovn-dpdk-ds.yaml new file mode 100644 index 00000000..1d799899 --- /dev/null +++ b/packages/system/kubeovn/charts/kube-ovn/templates/ovn-dpdk-ds.yaml @@ -0,0 +1,164 @@ +{{- if .Values.HYBRID_DPDK }} +kind: DaemonSet +apiVersion: apps/v1 +metadata: + name: ovs-ovn-dpdk + namespace: {{ .Values.namespace }} + annotations: + kubernetes.io/description: | + This daemon set launches the openvswitch daemon. +spec: + selector: + matchLabels: + app: ovs-dpdk + updateStrategy: + type: RollingUpdate + rollingUpdate: + maxSurge: 1 + maxUnavailable: 0 + template: + metadata: + labels: + app: ovs-dpdk + component: network + type: infra + spec: + tolerations: + - operator: Exists + priorityClassName: system-node-critical + serviceAccountName: ovn-ovs + hostNetwork: true + hostPID: true + containers: + - name: openvswitch + image: {{ .Values.global.registry.address }}/{{ .Values.global.images.kubeovn.repository }}:{{ .Values.global.images.kubeovn.tag }}-dpdk + imagePullPolicy: {{ .Values.image.pullPolicy }} + command: ["/kube-ovn/start-ovs-dpdk-v2.sh"] + securityContext: + runAsUser: 0 + privileged: true + env: + - name: ENABLE_SSL + value: "{{ .Values.networking.ENABLE_SSL }}" + - name: POD_IP + valueFrom: + fieldRef: + fieldPath: status.podIP + - name: HW_OFFLOAD + value: "{{- .Values.func.HW_OFFLOAD }}" + - name: TUNNEL_TYPE + value: "{{- .Values.networking.TUNNEL_TYPE }}" + - name: DPDK_TUNNEL_IFACE + value: "{{- .Values.networking.DPDK_TUNNEL_IFACE }}" + - name: KUBE_NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + - name: OVN_DB_IPS + value: "{{ .Values.MASTER_NODES | default (include "kubeovn.nodeIPs" .) }}" + - name: OVN_REMOTE_PROBE_INTERVAL + value: "{{ .Values.networking.OVN_REMOTE_PROBE_INTERVAL }}" + - name: OVN_REMOTE_OPENFLOW_INTERVAL + value: "{{ .Values.networking.OVN_REMOTE_OPENFLOW_INTERVAL }}" + volumeMounts: + - mountPath: /opt/ovs-config + name: host-config-ovs + - name: shareddir + mountPath: {{ .Values.kubelet_conf.KUBELET_DIR }}/pods + - name: hugepage + mountPath: /dev/hugepages + - mountPath: /lib/modules + name: host-modules + readOnly: true + - mountPath: /var/run/openvswitch + name: host-run-ovs + mountPropagation: HostToContainer + - mountPath: /var/run/ovn + name: host-run-ovn + - mountPath: /sys + name: host-sys + - mountPath: /etc/openvswitch + name: host-config-openvswitch + - mountPath: /etc/ovn + name: host-config-ovn + - mountPath: /var/log/openvswitch + name: host-log-ovs + - mountPath: /var/log/ovn + name: host-log-ovn + - mountPath: /etc/localtime + name: localtime + readOnly: true + - mountPath: /var/run/tls + name: kube-ovn-tls + readinessProbe: + exec: + command: + - bash + - -c + - LOG_ROTATE=true /kube-ovn/ovs-healthcheck.sh + periodSeconds: 5 + timeoutSeconds: 45 + livenessProbe: + exec: + command: + - bash + - /kube-ovn/ovs-healthcheck.sh + initialDelaySeconds: 60 + periodSeconds: 5 + failureThreshold: 5 + timeoutSeconds: 45 + resources: + requests: + cpu: {{ index .Values "ovs-ovn" "requests" "cpu" }} + memory: {{ index .Values "ovs-ovn" "requests" "memory" }} + limits: + cpu: {{ index .Values "ovs-ovn" "limits" "cpu" }} + {{.Values.HUGEPAGE_SIZE_TYPE}}: {{.Values.HUGEPAGES}} + memory: {{ index .Values "ovs-ovn" "limits" "memory" }} + nodeSelector: + kubernetes.io/os: "linux" + ovn.kubernetes.io/ovs_dp_type: "userspace" + volumes: + - name: host-config-ovs + hostPath: + path: /opt/ovs-config + type: DirectoryOrCreate + - name: shareddir + hostPath: + path: {{ .Values.kubelet_conf.KUBELET_DIR }}/pods + type: '' + - name: hugepage + emptyDir: + medium: HugePages + - name: host-modules + hostPath: + path: /lib/modules + - name: host-run-ovs + hostPath: + path: /run/openvswitch + - name: host-run-ovn + hostPath: + path: /run/ovn + - name: host-sys + hostPath: + path: /sys + - name: host-config-openvswitch + hostPath: + path: {{ .Values.OPENVSWITCH_DIR }} + - name: host-config-ovn + hostPath: + path: {{ .Values.OVN_DIR }} + - name: host-log-ovs + hostPath: + path: {{ .Values.log_conf.LOG_DIR }}/openvswitch + - name: host-log-ovn + hostPath: + path: {{ .Values.log_conf.LOG_DIR }}/ovn + - name: localtime + hostPath: + path: /etc/localtime + - name: kube-ovn-tls + secret: + optional: true + secretName: kube-ovn-tls +{{- end }} diff --git a/packages/system/kubeovn/charts/kube-ovn/templates/ovn-sa.yaml b/packages/system/kubeovn/charts/kube-ovn/templates/ovn-sa.yaml new file mode 100644 index 00000000..17b4a92f --- /dev/null +++ b/packages/system/kubeovn/charts/kube-ovn/templates/ovn-sa.yaml @@ -0,0 +1,34 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: ovn + namespace: {{ .Values.namespace }} +{{- if .Values.global.registry.imagePullSecrets }} +imagePullSecrets: +{{- range $index, $secret := .Values.global.registry.imagePullSecrets }} +{{- if $secret }} +- name: {{ $secret | quote}} +{{- end }} +{{- end }} +{{- end }} + +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: ovn-ovs + namespace: {{ .Values.namespace }} + +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: kube-ovn-cni + namespace: {{ .Values.namespace }} + +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: kube-ovn-app + namespace: {{ .Values.namespace }} diff --git a/packages/system/kubeovn/charts/kube-ovn/templates/ovn-tls-secret.yaml b/packages/system/kubeovn/charts/kube-ovn/templates/ovn-tls-secret.yaml new file mode 100644 index 00000000..dde40203 --- /dev/null +++ b/packages/system/kubeovn/charts/kube-ovn/templates/ovn-tls-secret.yaml @@ -0,0 +1,23 @@ +{{- if .Values.networking.ENABLE_SSL }} +{{- $cn := "ovn" -}} +{{- $ca := genCA "ovn-ca" 3650 -}} +--- +apiVersion: v1 +kind: Secret +metadata: + name: kube-ovn-tls + namespace: {{ .Values.namespace }} +data: +{{- $existingSecret := lookup "v1" "Secret" .Values.namespace "kube-ovn-tls" }} + {{- if $existingSecret }} + cacert: {{ index $existingSecret.data "cacert" }} + cert: {{ index $existingSecret.data "cert" }} + key: {{ index $existingSecret.data "key" }} + {{- else }} + {{- with genSignedCert $cn nil nil 3650 $ca }} + cacert: {{ b64enc $ca.Cert }} + cert: {{ b64enc .Cert }} + key: {{ b64enc .Key }} + {{- end }} + {{- end }} +{{- end }} diff --git a/packages/system/kubeovn/charts/kube-ovn/templates/ovncni-ds.yaml b/packages/system/kubeovn/charts/kube-ovn/templates/ovncni-ds.yaml new file mode 100644 index 00000000..b2e12dd1 --- /dev/null +++ b/packages/system/kubeovn/charts/kube-ovn/templates/ovncni-ds.yaml @@ -0,0 +1,209 @@ +kind: DaemonSet +apiVersion: apps/v1 +metadata: + name: kube-ovn-cni + namespace: {{ .Values.namespace }} + annotations: + kubernetes.io/description: | + This daemon set launches the kube-ovn cni daemon. +spec: + selector: + matchLabels: + app: kube-ovn-cni + template: + metadata: + labels: + app: kube-ovn-cni + component: network + type: infra + spec: + tolerations: + - effect: NoSchedule + operator: Exists + - effect: NoExecute + operator: Exists + - key: CriticalAddonsOnly + operator: Exists + priorityClassName: system-node-critical + serviceAccountName: kube-ovn-cni + hostNetwork: true + hostPID: true + initContainers: + - name: install-cni + image: {{ .Values.global.registry.address }}/{{ .Values.global.images.kubeovn.repository }}:{{ .Values.global.images.kubeovn.tag }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + command: ["/kube-ovn/install-cni.sh"] + securityContext: + runAsUser: 0 + privileged: true + volumeMounts: + - mountPath: /opt/cni/bin + name: cni-bin + {{- if .Values.cni_conf.MOUNT_LOCAL_BIN_DIR }} + - mountPath: /usr/local/bin + name: local-bin + {{- end }} + containers: + - name: cni-server + image: {{ .Values.global.registry.address }}/{{ .Values.global.images.kubeovn.repository }}:{{ .Values.global.images.kubeovn.tag }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + command: + - bash + - /kube-ovn/start-cniserver.sh + args: + {{- $cozyConfig := lookup "v1" "ConfigMap" "cozy-system" "cozystack" }} + - --enable-mirror={{- .Values.debug.ENABLE_MIRROR }} + - --mirror-iface={{- .Values.debug.MIRROR_IFACE }} + - --node-switch={{ .Values.networking.NODE_SUBNET }} + - --encap-checksum=true + - --service-cluster-ip-range={{ index $cozyConfig.data "ipv4-svc-cidr" }} + {{- if eq .Values.networking.NETWORK_TYPE "vlan" }} + - --iface= + {{- else}} + - --iface={{- .Values.networking.IFACE }} + {{- end }} + - --dpdk-tunnel-iface={{- .Values.networking.DPDK_TUNNEL_IFACE }} + - --network-type={{- .Values.networking.TUNNEL_TYPE }} + - --default-interface-name={{- .Values.networking.vlan.VLAN_INTERFACE_NAME }} + - --cni-conf-dir={{ .Values.cni_conf.CNI_CONF_DIR }} + - --cni-conf-file={{ .Values.cni_conf.CNI_CONF_FILE }} + - --cni-conf-name={{- .Values.cni_conf.CNI_CONFIG_PRIORITY -}}-kube-ovn.conflist + - --logtostderr=false + - --alsologtostderr=true + - --log_file=/var/log/kube-ovn/kube-ovn-cni.log + - --log_file_max_size=0 + - --enable-metrics={{- .Values.networking.ENABLE_METRICS }} + - --kubelet-dir={{ .Values.kubelet_conf.KUBELET_DIR }} + - --enable-tproxy={{ .Values.func.ENABLE_TPROXY }} + - --ovs-vsctl-concurrency={{ .Values.performance.OVS_VSCTL_CONCURRENCY }} + securityContext: + runAsUser: 0 + privileged: true + env: + - name: ENABLE_SSL + value: "{{ .Values.networking.ENABLE_SSL }}" + - name: POD_IP + valueFrom: + fieldRef: + fieldPath: status.podIP + - name: KUBE_NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + - name: MODULES + value: "{{- .Values.performance.MODULES }}" + - name: RPMS + value: "{{- .Values.performance.RPMS }}" + - name: POD_IPS + valueFrom: + fieldRef: + fieldPath: status.podIPs + - name: ENABLE_BIND_LOCAL_IP + value: "{{- .Values.func.ENABLE_BIND_LOCAL_IP }}" + - name: DBUS_SYSTEM_BUS_ADDRESS + value: "unix:path=/host/var/run/dbus/system_bus_socket" + volumeMounts: + - name: host-modules + mountPath: /lib/modules + readOnly: true + - name: shared-dir + mountPath: {{ .Values.kubelet_conf.KUBELET_DIR }}/pods + - mountPath: /etc/openvswitch + name: systemid + readOnly: true + - mountPath: /etc/cni/net.d + name: cni-conf + - mountPath: /run/openvswitch + name: host-run-ovs + mountPropagation: Bidirectional + - mountPath: /run/ovn + name: host-run-ovn + - mountPath: /host/var/run/dbus + name: host-dbus + mountPropagation: HostToContainer + - mountPath: /var/run/netns + name: host-ns + mountPropagation: HostToContainer + - mountPath: /var/log/kube-ovn + name: kube-ovn-log + - mountPath: /var/log/openvswitch + name: host-log-ovs + - mountPath: /var/log/ovn + name: host-log-ovn + - mountPath: /etc/localtime + name: localtime + readOnly: true + - mountPath: /tmp + name: tmp + readinessProbe: + failureThreshold: 3 + periodSeconds: 7 + successThreshold: 1 + tcpSocket: + port: 10665 + timeoutSeconds: 3 + livenessProbe: + failureThreshold: 3 + initialDelaySeconds: 30 + periodSeconds: 7 + successThreshold: 1 + tcpSocket: + port: 10665 + timeoutSeconds: 3 + resources: + requests: + cpu: {{ index .Values "kube-ovn-cni" "requests" "cpu" }} + memory: {{ index .Values "kube-ovn-cni" "requests" "memory" }} + limits: + cpu: {{ index .Values "kube-ovn-cni" "limits" "cpu" }} + memory: {{ index .Values "kube-ovn-cni" "limits" "memory" }} + nodeSelector: + kubernetes.io/os: "linux" + volumes: + - name: host-modules + hostPath: + path: /lib/modules + - name: shared-dir + hostPath: + path: {{ .Values.kubelet_conf.KUBELET_DIR }}/pods + - name: systemid + hostPath: + path: {{ .Values.OPENVSWITCH_DIR }} + - name: host-run-ovs + hostPath: + path: /run/openvswitch + - name: host-run-ovn + hostPath: + path: /run/ovn + - name: cni-conf + hostPath: + path: {{ .Values.cni_conf.CNI_CONF_DIR }} + - name: cni-bin + hostPath: + path: {{ .Values.cni_conf.CNI_BIN_DIR }} + - name: host-ns + hostPath: + path: /var/run/netns + - name: host-dbus + hostPath: + path: /var/run/dbus + - name: kube-ovn-log + hostPath: + path: {{ .Values.log_conf.LOG_DIR }}/kube-ovn + - name: localtime + hostPath: + path: /etc/localtime + - name: host-log-ovs + hostPath: + path: {{ .Values.log_conf.LOG_DIR }}/openvswitch + - name: host-log-ovn + hostPath: + path: {{ .Values.log_conf.LOG_DIR }}/ovn + - name: tmp + hostPath: + path: /tmp + {{- if .Values.cni_conf.MOUNT_LOCAL_BIN_DIR }} + - name: local-bin + hostPath: + path: {{ .Values.cni_conf.MOUNT_LOCAL_BIN_DIR }} + {{- end }} diff --git a/packages/system/kubeovn/charts/kube-ovn/templates/ovncni-svc.yaml b/packages/system/kubeovn/charts/kube-ovn/templates/ovncni-svc.yaml new file mode 100644 index 00000000..e1c47c80 --- /dev/null +++ b/packages/system/kubeovn/charts/kube-ovn/templates/ovncni-svc.yaml @@ -0,0 +1,16 @@ +kind: Service +apiVersion: v1 +metadata: + name: kube-ovn-cni + namespace: {{ .Values.namespace }} + labels: + app: kube-ovn-cni +spec: + selector: + app: kube-ovn-cni + ports: + - port: 10665 + name: metrics + {{- if eq .Values.networking.NET_STACK "dual_stack" }} + ipFamilyPolicy: PreferDualStack + {{- end }} diff --git a/packages/system/kubeovn/charts/kube-ovn/templates/ovsovn-ds.yaml b/packages/system/kubeovn/charts/kube-ovn/templates/ovsovn-ds.yaml new file mode 100644 index 00000000..319d74a9 --- /dev/null +++ b/packages/system/kubeovn/charts/kube-ovn/templates/ovsovn-ds.yaml @@ -0,0 +1,224 @@ +kind: DaemonSet +apiVersion: apps/v1 +metadata: + name: ovs-ovn + namespace: {{ .Values.namespace }} + annotations: + kubernetes.io/description: | + This daemon set launches the openvswitch daemon. +spec: + selector: + matchLabels: + app: ovs + updateStrategy: + type: RollingUpdate + rollingUpdate: + maxSurge: 1 + maxUnavailable: 0 + template: + metadata: + labels: + app: ovs + component: network + type: infra + spec: + tolerations: + - effect: NoSchedule + operator: Exists + - effect: NoExecute + operator: Exists + - key: CriticalAddonsOnly + operator: Exists + priorityClassName: system-node-critical + serviceAccountName: ovn-ovs + hostNetwork: true + hostPID: true + containers: + - name: openvswitch + {{- if .Values.DPDK }} + image: {{ .Values.global.registry.address }}/{{ .Values.global.images.kubeovn.dpdkRepository }}:{{ .Values.DPDK_VERSION }}-{{ .Values.global.images.kubeovn.tag }} + {{- else }} + image: {{ .Values.global.registry.address }}/{{ .Values.global.images.kubeovn.repository }}:{{ .Values.global.images.kubeovn.tag }} + {{- end }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + {{- if .Values.DPDK }} + command: ["/kube-ovn/start-ovs-dpdk.sh"] + {{- else }} + command: + {{- if .Values.DISABLE_MODULES_MANAGEMENT }} + - /bin/sh + - -ec + - | + ln -sf /bin/true /usr/sbin/modprobe + ln -sf /bin/true /usr/sbin/modinfo + ln -sf /bin/true /usr/sbin/rmmod + exec /kube-ovn/start-ovs.sh + {{- else }} + - /kube-ovn/start-ovs.sh + {{- end }} + {{- end }} + securityContext: + runAsUser: 0 + privileged: true + env: + - name: ENABLE_SSL + value: "{{ .Values.networking.ENABLE_SSL }}" + - name: POD_IP + valueFrom: + fieldRef: + fieldPath: status.podIP + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: HW_OFFLOAD + value: "{{- .Values.func.HW_OFFLOAD }}" + - name: TUNNEL_TYPE + value: "{{- .Values.networking.TUNNEL_TYPE }}" + - name: KUBE_NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + - name: OVN_DB_IPS + value: "{{ .Values.MASTER_NODES | default (include "kubeovn.nodeIPs" .) }}" + - name: OVN_REMOTE_PROBE_INTERVAL + value: "{{ .Values.networking.OVN_REMOTE_PROBE_INTERVAL }}" + - name: OVN_REMOTE_OPENFLOW_INTERVAL + value: "{{ .Values.networking.OVN_REMOTE_OPENFLOW_INTERVAL }}" + volumeMounts: + - mountPath: /var/run/netns + name: host-ns + mountPropagation: HostToContainer + - mountPath: /lib/modules + name: host-modules + readOnly: true + - mountPath: /var/run/openvswitch + name: host-run-ovs + - mountPath: /var/run/ovn + name: host-run-ovn + - mountPath: /sys + name: host-sys + readOnly: true + - mountPath: /etc/openvswitch + name: host-config-openvswitch + - mountPath: /etc/ovn + name: host-config-ovn + - mountPath: /var/log/openvswitch + name: host-log-ovs + - mountPath: /var/log/ovn + name: host-log-ovn + - mountPath: /etc/localtime + name: localtime + readOnly: true + - mountPath: /var/run/tls + name: kube-ovn-tls + - mountPath: /var/run/containerd + name: cruntime + readOnly: true + {{- if .Values.DPDK }} + - mountPath: /opt/ovs-config + name: host-config-ovs + - mountPath: /dev/hugepages + name: hugepage + {{- end }} + readinessProbe: + exec: + {{- if .Values.DPDK }} + command: + - bash + - /kube-ovn/ovs-dpdk-healthcheck.sh + {{- else }} + command: + - bash + - -c + - LOG_ROTATE=true /kube-ovn/ovs-healthcheck.sh + {{- end }} + initialDelaySeconds: 10 + periodSeconds: 5 + timeoutSeconds: 45 + livenessProbe: + exec: + {{- if .Values.DPDK }} + command: + - bash + - /kube-ovn/ovs-dpdk-healthcheck.sh + {{- else }} + command: + - bash + - /kube-ovn/ovs-healthcheck.sh + {{- end }} + initialDelaySeconds: 60 + periodSeconds: 5 + failureThreshold: 5 + timeoutSeconds: 45 + resources: + requests: + {{- if .Values.DPDK }} + cpu: {{ .Values.DPDK_CPU }} + memory: {{ .Values.DPDK_MEMORY }} + {{- else }} + cpu: {{ index .Values "ovs-ovn" "requests" "cpu" }} + memory: {{ index .Values "ovs-ovn" "requests" "memory" }} + {{- end }} + limits: + {{- if .Values.DPDK }} + cpu: {{ .Values.DPDK_CPU }} + memory: {{ .Values.DPDK_MEMORY }} + hugepages-1Gi: 1Gi + {{- else }} + cpu: {{ index .Values "ovs-ovn" "limits" "cpu" }} + memory: {{ index .Values "ovs-ovn" "limits" "memory" }} + {{- end }} + nodeSelector: + kubernetes.io/os: "linux" + volumes: + - name: host-modules + hostPath: + path: /lib/modules + - name: host-run-ovs + hostPath: + path: /run/openvswitch + - name: host-run-ovn + hostPath: + path: /run/ovn + - name: host-sys + hostPath: + path: /sys + - name: host-config-openvswitch + hostPath: + path: {{ .Values.OPENVSWITCH_DIR }} + - name: host-config-ovn + hostPath: + path: {{ .Values.OVN_DIR }} + - name: host-log-ovs + hostPath: + path: {{ .Values.log_conf.LOG_DIR }}/openvswitch + - name: host-log-ovn + hostPath: + path: {{ .Values.log_conf.LOG_DIR }}/ovn + - name: localtime + hostPath: + path: /etc/localtime + - name: kube-ovn-tls + secret: + optional: true + secretName: kube-ovn-tls + - name: host-ns + hostPath: + path: /var/run/netns + - hostPath: + path: /var/run/containerd + name: cruntime + {{- if .Values.DPDK }} + - name: host-config-ovs + hostPath: + path: /opt/ovs-config + type: DirectoryOrCreate + - name: hugepage + emptyDir: + medium: HugePages + {{- end }} diff --git a/packages/system/kubeovn/charts/kube-ovn/templates/pinger-ds.yaml b/packages/system/kubeovn/charts/kube-ovn/templates/pinger-ds.yaml new file mode 100644 index 00000000..f54b276a --- /dev/null +++ b/packages/system/kubeovn/charts/kube-ovn/templates/pinger-ds.yaml @@ -0,0 +1,137 @@ +kind: DaemonSet +apiVersion: apps/v1 +metadata: + name: kube-ovn-pinger + namespace: {{ .Values.namespace }} + annotations: + kubernetes.io/description: | + This daemon set launches the openvswitch daemon. +spec: + selector: + matchLabels: + app: kube-ovn-pinger + updateStrategy: + type: RollingUpdate + template: + metadata: + labels: + app: kube-ovn-pinger + component: network + type: infra + spec: + priorityClassName: system-node-critical + tolerations: + - effect: NoSchedule + operator: Exists + - effect: NoExecute + operator: Exists + - key: CriticalAddonsOnly + operator: Exists + serviceAccountName: kube-ovn-app + hostPID: true + containers: + - name: pinger + image: {{ .Values.global.registry.address }}/{{ .Values.global.images.kubeovn.repository }}:{{ .Values.global.images.kubeovn.tag }} + command: + - /kube-ovn/kube-ovn-pinger + args: + - --external-address= + {{- if eq .Values.networking.NET_STACK "dual_stack" -}} + {{ .Values.dual_stack.PINGER_EXTERNAL_ADDRESS }} + {{- else if eq .Values.networking.NET_STACK "ipv4" -}} + {{ .Values.ipv4.PINGER_EXTERNAL_ADDRESS }} + {{- else if eq .Values.networking.NET_STACK "ipv6" -}} + {{ .Values.ipv6.PINGER_EXTERNAL_ADDRESS }} + {{- end }} + - --external-dns= + {{- if eq .Values.networking.NET_STACK "dual_stack" -}} + {{ .Values.dual_stack.PINGER_EXTERNAL_DOMAIN }} + {{- else if eq .Values.networking.NET_STACK "ipv4" -}} + {{ .Values.ipv4.PINGER_EXTERNAL_DOMAIN }} + {{- else if eq .Values.networking.NET_STACK "ipv6" -}} + {{ .Values.ipv6.PINGER_EXTERNAL_DOMAIN }} + {{- end }} + - --ds-namespace={{ .Values.namespace }} + - --logtostderr=false + - --alsologtostderr=true + - --log_file=/var/log/kube-ovn/kube-ovn-pinger.log + - --log_file_max_size=0 + - --enable-metrics={{- .Values.networking.ENABLE_METRICS }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + securityContext: + runAsUser: 0 + privileged: false + env: + - name: ENABLE_SSL + value: "{{ .Values.networking.ENABLE_SSL }}" + - name: POD_IP + valueFrom: + fieldRef: + fieldPath: status.podIP + - name: HOST_IP + valueFrom: + fieldRef: + fieldPath: status.hostIP + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + volumeMounts: + - mountPath: /var/run/openvswitch + name: host-run-ovs + - mountPath: /var/run/ovn + name: host-run-ovn + - mountPath: /etc/openvswitch + name: host-config-openvswitch + - mountPath: /var/log/openvswitch + name: host-log-ovs + readOnly: true + - mountPath: /var/log/ovn + name: host-log-ovn + readOnly: true + - mountPath: /var/log/kube-ovn + name: kube-ovn-log + - mountPath: /etc/localtime + name: localtime + readOnly: true + - mountPath: /var/run/tls + name: kube-ovn-tls + resources: + requests: + cpu: {{ index .Values "kube-ovn-pinger" "requests" "cpu" }} + memory: {{ index .Values "kube-ovn-pinger" "requests" "memory" }} + limits: + cpu: {{ index .Values "kube-ovn-pinger" "limits" "cpu" }} + memory: {{ index .Values "kube-ovn-pinger" "limits" "memory" }} + nodeSelector: + kubernetes.io/os: "linux" + volumes: + - name: host-run-ovs + hostPath: + path: /run/openvswitch + - name: host-run-ovn + hostPath: + path: /run/ovn + - name: host-config-openvswitch + hostPath: + path: {{ .Values.OPENVSWITCH_DIR }} + - name: host-log-ovs + hostPath: + path: {{ .Values.log_conf.LOG_DIR }}/openvswitch + - name: kube-ovn-log + hostPath: + path: {{ .Values.log_conf.LOG_DIR }}/kube-ovn + - name: host-log-ovn + hostPath: + path: {{ .Values.log_conf.LOG_DIR }}/ovn + - name: localtime + hostPath: + path: /etc/localtime + - name: kube-ovn-tls + secret: + optional: true + secretName: kube-ovn-tls diff --git a/packages/system/kubeovn/charts/kube-ovn/templates/pinger-svc.yaml b/packages/system/kubeovn/charts/kube-ovn/templates/pinger-svc.yaml new file mode 100644 index 00000000..ef169e8e --- /dev/null +++ b/packages/system/kubeovn/charts/kube-ovn/templates/pinger-svc.yaml @@ -0,0 +1,16 @@ +kind: Service +apiVersion: v1 +metadata: + name: kube-ovn-pinger + namespace: {{ .Values.namespace }} + labels: + app: kube-ovn-pinger +spec: + selector: + app: kube-ovn-pinger + ports: + - port: 8080 + name: metrics + {{- if eq .Values.networking.NET_STACK "dual_stack" }} + ipFamilyPolicy: PreferDualStack + {{- end }} diff --git a/packages/system/kubeovn/charts/kube-ovn/templates/pre-delete-hook.yaml b/packages/system/kubeovn/charts/kube-ovn/templates/pre-delete-hook.yaml new file mode 100644 index 00000000..d81c5ca2 --- /dev/null +++ b/packages/system/kubeovn/charts/kube-ovn/templates/pre-delete-hook.yaml @@ -0,0 +1,123 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: kube-ovn-pre-delete-hook + namespace: {{ .Values.namespace }} + 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-weight": "1" + "helm.sh/hook-delete-policy": hook-succeeded +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + annotations: + rbac.authorization.k8s.io/system-only: "true" + # 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-weight": "2" + "helm.sh/hook-delete-policy": hook-succeeded + name: system:kube-ovn-pre-delete-hook +rules: + - apiGroups: + - kubeovn.io + resources: + - subnets + verbs: + - get + - list + - patch +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: kube-ovn-pre-delete-hook + 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-weight": "3" + "helm.sh/hook-delete-policy": hook-succeeded +roleRef: + name: system:kube-ovn-pre-delete-hook + kind: ClusterRole + apiGroup: rbac.authorization.k8s.io +subjects: + - kind: ServiceAccount + name: kube-ovn-pre-delete-hook + namespace: {{ .Values.namespace }} +--- +apiVersion: batch/v1 +kind: Job +metadata: + name: "{{ .Chart.Name }}-pre-delete-hook" + namespace: {{ .Values.namespace }} + labels: + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + app.kubernetes.io/version: {{ .Chart.AppVersion }} + helm.sh/chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" + 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-weight": "4" + "helm.sh/hook-delete-policy": hook-succeeded +spec: + completions: 1 + template: + metadata: + name: "{{ .Release.Name }}" + labels: + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + helm.sh/chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" + app: kube-ovn-pre-delete-hook + component: job + spec: + tolerations: + - key: "" + operator: "Exists" + effect: "NoSchedule" + affinity: + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - topologyKey: kubernetes.io/hostname + labelSelector: + matchExpressions: + - key: app + operator: In + values: + - kube-ovn-pre-delete-hook + - key: component + operator: In + values: + - job + restartPolicy: Never + hostNetwork: true + nodeSelector: + kubernetes.io/os: "linux" + serviceAccount: kube-ovn-pre-delete-hook + serviceAccountName: kube-ovn-pre-delete-hook + containers: + - name: remove-subnet-finalizer + image: "{{ .Values.global.registry.address}}/{{ .Values.global.images.kubeovn.repository }}:{{ .Values.global.images.kubeovn.tag }}" + env: + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + command: + - sh + - -c + - /kube-ovn/remove-subnet-finalizer.sh 2>&1 | tee -a /var/log/kube-ovn/remove-subnet-finalizer.log + volumeMounts: + - mountPath: /var/log/kube-ovn + name: kube-ovn-log + volumes: + - name: kube-ovn-log + hostPath: + path: {{ .Values.log_conf.LOG_DIR }}/kube-ovn diff --git a/packages/system/kubeovn/charts/kube-ovn/templates/sb-svc.yaml b/packages/system/kubeovn/charts/kube-ovn/templates/sb-svc.yaml new file mode 100644 index 00000000..36a4a27a --- /dev/null +++ b/packages/system/kubeovn/charts/kube-ovn/templates/sb-svc.yaml @@ -0,0 +1,19 @@ +kind: Service +apiVersion: v1 +metadata: + name: ovn-sb + namespace: {{ .Values.namespace }} +spec: + ports: + - name: ovn-sb + protocol: TCP + port: 6642 + targetPort: 6642 + type: ClusterIP + {{- if eq .Values.networking.NET_STACK "dual_stack" }} + ipFamilyPolicy: PreferDualStack + {{- end }} + selector: + app: ovn-central + ovn-sb-leader: "true" + sessionAffinity: None diff --git a/packages/system/kubeovn/charts/kube-ovn/templates/upgrade-ovs-ovn.yaml b/packages/system/kubeovn/charts/kube-ovn/templates/upgrade-ovs-ovn.yaml new file mode 100644 index 00000000..980354e6 --- /dev/null +++ b/packages/system/kubeovn/charts/kube-ovn/templates/upgrade-ovs-ovn.yaml @@ -0,0 +1,142 @@ +{{ if (lookup "apps/v1" "DaemonSet" .Values.namespace "ovs-ovn") }} +{{ if eq (lookup "apps/v1" "DaemonSet" .Values.namespace "ovs-ovn").spec.updateStrategy.type "OnDelete" }} +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: ovs-ovn-upgrade + namespace: {{ .Values.namespace }} + annotations: + # This is what defines this resource as a hook. Without this line, the + # job is considered part of the release. + "helm.sh/hook": post-upgrade + "helm.sh/hook-weight": "1" + "helm.sh/hook-delete-policy": hook-succeeded +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + annotations: + rbac.authorization.k8s.io/system-only: "true" + # This is what defines this resource as a hook. Without this line, the + # job is considered part of the release. + "helm.sh/hook": post-upgrade + "helm.sh/hook-weight": "2" + "helm.sh/hook-delete-policy": hook-succeeded + name: system:ovs-ovn-upgrade +rules: + - apiGroups: + - apps + resources: + - daemonsets + resourceNames: + - ovs-ovn + verbs: + - get + - apiGroups: + - "" + resources: + - nodes + verbs: + - list + - apiGroups: + - "" + resources: + - pods + verbs: + - list + - get + - delete +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: ovs-ovn-upgrade + annotations: + # This is what defines this resource as a hook. Without this line, the + # job is considered part of the release. + "helm.sh/hook": post-upgrade + "helm.sh/hook-weight": "3" + "helm.sh/hook-delete-policy": hook-succeeded +roleRef: + name: system:ovs-ovn-upgrade + kind: ClusterRole + apiGroup: rbac.authorization.k8s.io +subjects: + - kind: ServiceAccount + name: ovs-ovn-upgrade + namespace: {{ .Values.namespace }} +--- +apiVersion: batch/v1 +kind: Job +metadata: + name: "{{ .Chart.Name }}-post-upgrade-hook" + namespace: {{ .Values.namespace }} + labels: + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + app.kubernetes.io/version: {{ .Chart.AppVersion }} + helm.sh/chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" + annotations: + # This is what defines this resource as a hook. Without this line, the + # job is considered part of the release. + "helm.sh/hook": post-upgrade + "helm.sh/hook-weight": "4" + "helm.sh/hook-delete-policy": hook-succeeded +spec: + completions: 1 + template: + metadata: + name: "{{ .Release.Name }}" + labels: + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + helm.sh/chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" + app: post-upgrade + component: job + spec: + tolerations: + - key: "" + operator: "Exists" + effect: "NoSchedule" + affinity: + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - topologyKey: kubernetes.io/hostname + labelSelector: + matchExpressions: + - key: app + operator: In + values: + - post-upgrade + - key: component + operator: In + values: + - job + restartPolicy: Never + hostNetwork: true + nodeSelector: + kubernetes.io/os: "linux" + serviceAccount: ovs-ovn-upgrade + serviceAccountName: ovs-ovn-upgrade + containers: + - name: ovs-ovn-upgrade + image: "{{ .Values.global.registry.address}}/{{ .Values.global.images.kubeovn.repository }}:{{ .Values.global.images.kubeovn.tag }}" + env: + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + command: + - sh + - -c + - /kube-ovn/upgrade-ovs.sh 2>&1 | tee -a /var/log/kube-ovn/upgrade-ovs.log + volumeMounts: + - mountPath: /var/log/kube-ovn + name: kube-ovn-log + volumes: + - name: kube-ovn-log + hostPath: + path: {{ .Values.log_conf.LOG_DIR }}/kube-ovn +{{ end }} +{{ end }} diff --git a/packages/system/kubeovn/charts/kube-ovn/templates/vpc-nat-config.yaml b/packages/system/kubeovn/charts/kube-ovn/templates/vpc-nat-config.yaml new file mode 100755 index 00000000..0f9bd0f5 --- /dev/null +++ b/packages/system/kubeovn/charts/kube-ovn/templates/vpc-nat-config.yaml @@ -0,0 +1,10 @@ +kind: ConfigMap +apiVersion: v1 +metadata: + name: ovn-vpc-nat-config + namespace: {{ .Values.namespace }} + annotations: + kubernetes.io/description: | + kube-ovn vpc-nat common config +data: + image: {{ .Values.global.registry.address }}/{{ .Values.global.images.kubeovn.vpcRepository }}:{{ .Values.global.images.kubeovn.tag }} \ No newline at end of file diff --git a/packages/system/kubeovn/charts/kube-ovn/values.yaml b/packages/system/kubeovn/charts/kube-ovn/values.yaml new file mode 100644 index 00000000..b8807499 --- /dev/null +++ b/packages/system/kubeovn/charts/kube-ovn/values.yaml @@ -0,0 +1,177 @@ +# Default values for kubeovn. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. +global: + registry: + address: docker.io/kubeovn + imagePullSecrets: [] + images: + kubeovn: + repository: kube-ovn + dpdkRepository: kube-ovn-dpdk + vpcRepository: vpc-nat-gateway + tag: v1.13.0 + support_arm: true + thirdparty: true + +image: + pullPolicy: IfNotPresent + +namespace: kube-system +MASTER_NODES: "" +MASTER_NODES_LABEL: "kube-ovn/role=master" + +networking: + # NET_STACK could be dual_stack, ipv4, ipv6 + NET_STACK: ipv4 + ENABLE_SSL: false + # network type could be geneve or vlan + NETWORK_TYPE: geneve + # tunnel type could be geneve, vxlan or stt + TUNNEL_TYPE: geneve + IFACE: "" + DPDK_TUNNEL_IFACE: "br-phy" + EXCLUDE_IPS: "" + POD_NIC_TYPE: "veth-pair" + vlan: + PROVIDER_NAME: "provider" + VLAN_INTERFACE_NAME: "" + VLAN_NAME: "ovn-vlan" + VLAN_ID: "100" + EXCHANGE_LINK_NAME: false + ENABLE_EIP_SNAT: true + POD_DEFAULT_FIP_TYPE: "" + DEFAULT_SUBNET: "ovn-default" + DEFAULT_VPC: "ovn-cluster" + NODE_SUBNET: "join" + ENABLE_ECMP: false + ENABLE_METRICS: true + NODE_LOCAL_DNS_IP: "" + PROBE_INTERVAL: 180000 + OVN_LEADER_PROBE_INTERVAL: 5 + OVN_REMOTE_PROBE_INTERVAL: 10000 + OVN_REMOTE_OPENFLOW_INTERVAL: 180 + OVN_NORTHD_N_THREADS: 1 + ENABLE_COMPACT: false + +func: + ENABLE_LB: true + ENABLE_NP: true + ENABLE_EIP_SNAT: true + ENABLE_EXTERNAL_VPC: true + HW_OFFLOAD: false + ENABLE_LB_SVC: false + ENABLE_KEEP_VM_IP: true + LS_DNAT_MOD_DL_DST: true + CHECK_GATEWAY: true + LOGICAL_GATEWAY: false + ENABLE_BIND_LOCAL_IP: true + U2O_INTERCONNECTION: false + ENABLE_TPROXY: false + +ipv4: + PINGER_EXTERNAL_ADDRESS: "1.1.1.1" + PINGER_EXTERNAL_DOMAIN: "alauda.cn." + +ipv6: + POD_CIDR: "fd00:10:16::/112" + POD_GATEWAY: "fd00:10:16::1" + SVC_CIDR: "fd00:10:96::/112" + JOIN_CIDR: "fd00:100:64::/112" + PINGER_EXTERNAL_ADDRESS: "2606:4700:4700::1111" + PINGER_EXTERNAL_DOMAIN: "google.com." + +dual_stack: + POD_CIDR: "10.16.0.0/16,fd00:10:16::/112" + POD_GATEWAY: "10.16.0.1,fd00:10:16::1" + SVC_CIDR: "10.96.0.0/12,fd00:10:96::/112" + JOIN_CIDR: "100.64.0.0/16,fd00:100:64::/112" + PINGER_EXTERNAL_ADDRESS: "1.1.1.1,2606:4700:4700::1111" + PINGER_EXTERNAL_DOMAIN: "google.com." + +performance: + MODULES: "kube_ovn_fastpath.ko" + RPMS: "openvswitch-kmod" + GC_INTERVAL: 360 + INSPECT_INTERVAL: 20 + OVS_VSCTL_CONCURRENCY: 100 + +debug: + ENABLE_MIRROR: false + MIRROR_IFACE: "mirror0" + +cni_conf: + CNI_CONFIG_PRIORITY: "01" + CNI_CONF_DIR: "/etc/cni/net.d" + CNI_BIN_DIR: "/opt/cni/bin" + CNI_CONF_FILE: "/kube-ovn/01-kube-ovn.conflist" + LOCAL_BIN_DIR: "/usr/local/bin" + MOUNT_LOCAL_BIN_DIR: false + +kubelet_conf: + KUBELET_DIR: "/var/lib/kubelet" + +log_conf: + LOG_DIR: "/var/log" + +OPENVSWITCH_DIR: "/etc/origin/openvswitch" +OVN_DIR: "/etc/origin/ovn" +DISABLE_MODULES_MANAGEMENT: false + +imagePullSecrets: [] +nameOverride: "" +fullnameOverride: "" + +# hybrid dpdk +HYBRID_DPDK: false +HUGEPAGE_SIZE_TYPE: hugepages-2Mi # Default +HUGEPAGES: 1Gi + +# DPDK +DPDK: false +DPDK_VERSION: "19.11" +DPDK_CPU: "1000m" # Default CPU configuration +DPDK_MEMORY: "2Gi" # Default Memory configuration + +ovn-central: + requests: + cpu: "300m" + memory: "200Mi" + limits: + cpu: "3" + memory: "4Gi" +ovs-ovn: + requests: + cpu: "200m" + memory: "200Mi" + limits: + cpu: "1000m" + memory: "1000Mi" +kube-ovn-controller: + requests: + cpu: "200m" + memory: "200Mi" + limits: + cpu: "1000m" + memory: "1Gi" +kube-ovn-cni: + requests: + cpu: "100m" + memory: "100Mi" + limits: + cpu: "1000m" + memory: "1Gi" +kube-ovn-pinger: + requests: + cpu: "100m" + memory: "100Mi" + limits: + cpu: "200m" + memory: "400Mi" +kube-ovn-monitor: + requests: + cpu: "200m" + memory: "200Mi" + limits: + cpu: "200m" + memory: "200Mi" diff --git a/packages/system/kubeovn/patches/cozyconfig.diff b/packages/system/kubeovn/patches/cozyconfig.diff new file mode 100644 index 00000000..c5a14190 --- /dev/null +++ b/packages/system/kubeovn/patches/cozyconfig.diff @@ -0,0 +1,97 @@ + +diff --git a/packages/system/kubeovn/charts/kube-ovn/templates/ovncni-ds.yaml b/packages/system/kubeovn/charts/kube-ovn/templates/ovncni-ds.yaml +index d9a9a67..b2e12dd 100644 +--- a/packages/system/kubeovn/charts/kube-ovn/templates/ovncni-ds.yaml ++++ b/packages/system/kubeovn/charts/kube-ovn/templates/ovncni-ds.yaml +@@ -51,18 +51,12 @@ spec: + - bash + - /kube-ovn/start-cniserver.sh + args: ++ {{- $cozyConfig := lookup "v1" "ConfigMap" "cozy-system" "cozystack" }} + - --enable-mirror={{- .Values.debug.ENABLE_MIRROR }} + - --mirror-iface={{- .Values.debug.MIRROR_IFACE }} + - --node-switch={{ .Values.networking.NODE_SUBNET }} + - --encap-checksum=true +- - --service-cluster-ip-range= +- {{- if eq .Values.networking.NET_STACK "dual_stack" -}} +- {{ .Values.dual_stack.SVC_CIDR }} +- {{- else if eq .Values.networking.NET_STACK "ipv4" -}} +- {{ .Values.ipv4.SVC_CIDR }} +- {{- else if eq .Values.networking.NET_STACK "ipv6" -}} +- {{ .Values.ipv6.SVC_CIDR }} +- {{- end }} ++ - --service-cluster-ip-range={{ index $cozyConfig.data "ipv4-svc-cidr" }} + {{- if eq .Values.networking.NETWORK_TYPE "vlan" }} + - --iface= + {{- else}} +diff --git a/packages/system/kubeovn/charts/kube-ovn/templates/controller-deploy.yaml b/packages/system/kubeovn/charts/kube-ovn/templates/controller-deploy.yaml +index 0e69494..756eb7c 100644 +--- a/packages/system/kubeovn/charts/kube-ovn/templates/controller-deploy.yaml ++++ b/packages/system/kubeovn/charts/kube-ovn/templates/controller-deploy.yaml +@@ -52,46 +52,19 @@ spec: + image: {{ .Values.global.registry.address }}/{{ .Values.global.images.kubeovn.repository }}:{{ .Values.global.images.kubeovn.tag }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + args: ++ {{- $cozyConfig := lookup "v1" "ConfigMap" "cozy-system" "cozystack" }} + - /kube-ovn/start-controller.sh + - --default-ls={{ .Values.networking.DEFAULT_SUBNET }} +- - --default-cidr= +- {{- if eq .Values.networking.NET_STACK "dual_stack" -}} +- {{ .Values.dual_stack.POD_CIDR }} +- {{- else if eq .Values.networking.NET_STACK "ipv4" -}} +- {{ .Values.ipv4.POD_CIDR }} +- {{- else if eq .Values.networking.NET_STACK "ipv6" -}} +- {{ .Values.ipv6.POD_CIDR }} +- {{- end }} +- - --default-gateway= +- {{- if eq .Values.networking.NET_STACK "dual_stack" -}} +- {{ .Values.dual_stack.POD_GATEWAY }} +- {{- else if eq .Values.networking.NET_STACK "ipv4" -}} +- {{ .Values.ipv4.POD_GATEWAY }} +- {{- else if eq .Values.networking.NET_STACK "ipv6" -}} +- {{ .Values.ipv6.POD_GATEWAY }} +- {{- end }} ++ - --default-cidr={{ index $cozyConfig.data "ipv4-pod-cidr" }} ++ - --default-gateway={{ index $cozyConfig.data "ipv4-pod-gateway" }} + - --default-gateway-check={{- .Values.func.CHECK_GATEWAY }} + - --default-logical-gateway={{- .Values.func.LOGICAL_GATEWAY }} + - --default-u2o-interconnection={{- .Values.func.U2O_INTERCONNECTION }} + - --default-exclude-ips={{- .Values.networking.EXCLUDE_IPS }} + - --cluster-router={{ .Values.networking.DEFAULT_VPC }} + - --node-switch={{ .Values.networking.NODE_SUBNET }} +- - --node-switch-cidr= +- {{- if eq .Values.networking.NET_STACK "dual_stack" -}} +- {{ .Values.dual_stack.JOIN_CIDR }} +- {{- else if eq .Values.networking.NET_STACK "ipv4" -}} +- {{ .Values.ipv4.JOIN_CIDR }} +- {{- else if eq .Values.networking.NET_STACK "ipv6" -}} +- {{ .Values.ipv6.JOIN_CIDR }} +- {{- end }} +- - --service-cluster-ip-range= +- {{- if eq .Values.networking.NET_STACK "dual_stack" -}} +- {{ .Values.dual_stack.SVC_CIDR }} +- {{- else if eq .Values.networking.NET_STACK "ipv4" -}} +- {{ .Values.ipv4.SVC_CIDR }} +- {{- else if eq .Values.networking.NET_STACK "ipv6" -}} +- {{ .Values.ipv6.SVC_CIDR }} +- {{- end }} ++ - --node-switch-cidr={{ index $cozyConfig.data "ipv4-join-cidr" }} ++ - --service-cluster-ip-range={{ index $cozyConfig.data "ipv4-svc-cidr" }} + - --network-type={{- .Values.networking.NETWORK_TYPE }} + - --default-provider-name={{ .Values.networking.vlan.PROVIDER_NAME }} + - --default-interface-name={{- .Values.networking.vlan.VLAN_INTERFACE_NAME }} +diff --git a/packages/system/kubeovn/charts/kube-ovn/values.yaml b/packages/system/kubeovn/charts/kube-ovn/values.yaml +index bfffc4d..b880749 100644 +--- a/packages/system/kubeovn/charts/kube-ovn/values.yaml ++++ b/packages/system/kubeovn/charts/kube-ovn/values.yaml +@@ -70,10 +70,6 @@ func: + ENABLE_TPROXY: false + + ipv4: +- POD_CIDR: "10.16.0.0/16" +- POD_GATEWAY: "10.16.0.1" +- SVC_CIDR: "10.96.0.0/12" +- JOIN_CIDR: "100.64.0.0/16" + PINGER_EXTERNAL_ADDRESS: "1.1.1.1" + PINGER_EXTERNAL_DOMAIN: "alauda.cn." + diff --git a/packages/system/kubeovn/values.yaml b/packages/system/kubeovn/values.yaml new file mode 100644 index 00000000..421b14de --- /dev/null +++ b/packages/system/kubeovn/values.yaml @@ -0,0 +1,25 @@ +kube-ovn: + global: + registry: + address: ghcr.io/kvaps + images: + kubeovn: + repository: test + tag: kube-ovn-static-v1.13.0-cozystack2 + + namespace: cozy-kubeovn + + func: + ENABLE_NP: false + + MASTER_NODES_LABEL: "node-role.kubernetes.io/control-plane" + networking: + ENABLE_SSL: true + + cni_conf: + CNI_CONFIG_PRIORITY: "10" + MOUNT_LOCAL_BIN_DIR: false + + OPENVSWITCH_DIR: "/var/lib/openvswitch" + OVN_DIR: "/var/lib/ovn" + DISABLE_MODULES_MANAGEMENT: true diff --git a/packages/system/kubevirt-cdi-operator/Chart.yaml b/packages/system/kubevirt-cdi-operator/Chart.yaml new file mode 100644 index 00000000..943a489a --- /dev/null +++ b/packages/system/kubevirt-cdi-operator/Chart.yaml @@ -0,0 +1,2 @@ +name: cozy-kubevirt-cdi-operator +version: 1.0.0 diff --git a/packages/system/kubevirt-cdi-operator/Makefile b/packages/system/kubevirt-cdi-operator/Makefile new file mode 100644 index 00000000..756906ea --- /dev/null +++ b/packages/system/kubevirt-cdi-operator/Makefile @@ -0,0 +1,19 @@ +NAME=kubevirt-cdi-operator +NAMESPACE=cozy-kubevirt-cdi + +show: + helm template --dry-run=server -n $(NAMESPACE) $(NAME) . + +apply: + helm upgrade -i -n $(NAMESPACE) $(NAME) . + +diff: + helm diff upgrade --allow-unreleased --normalize-manifests -n $(NAMESPACE) $(NAME) . + +update: + rm -rf templates + mkdir templates + export VERSION=$$(basename $$(curl -s -w %{redirect_url} https://github.com/kubevirt/containerized-data-importer/releases/latest)) && \ + wget https://github.com/kubevirt/containerized-data-importer/releases/download/$$VERSION/cdi-operator.yaml -O templates/cdi-operator.yaml + sed -i 's/namespace: cdi/namespace: cozy-kubevirt-cdi/g' templates/cdi-operator.yaml + awk -i inplace -v RS="---" '!/kind: Namespace/{printf "%s", $$0 RS}' templates/cdi-operator.yaml diff --git a/packages/system/kubevirt-cdi-operator/templates/cdi-operator.yaml b/packages/system/kubevirt-cdi-operator/templates/cdi-operator.yaml new file mode 100644 index 00000000..e6a07e06 --- /dev/null +++ b/packages/system/kubevirt-cdi-operator/templates/cdi-operator.yaml @@ -0,0 +1,5091 @@ + +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.13.0 + name: cdis.cdi.kubevirt.io +spec: + group: cdi.kubevirt.io + names: + kind: CDI + listKind: CDIList + plural: cdis + shortNames: + - cdi + - cdis + singular: cdi + scope: Cluster + versions: + - additionalPrinterColumns: + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + - jsonPath: .status.phase + name: Phase + type: string + name: v1alpha1 + schema: + openAPIV3Schema: + description: CDI is the CDI Operator CRD + 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: CDISpec defines our specification for the CDI installation + properties: + certConfig: + description: certificate configuration + properties: + ca: + description: CA configuration CA certs are kept in the CA bundle + as long as they are valid + properties: + duration: + description: The requested 'duration' (i.e. lifetime) of the + Certificate. + type: string + renewBefore: + description: The amount of time before the currently issued + certificate's `notAfter` time that we will begin to attempt + to renew the certificate. + type: string + type: object + server: + description: Server configuration Certs are rotated and discarded + properties: + duration: + description: The requested 'duration' (i.e. lifetime) of the + Certificate. + type: string + renewBefore: + description: The amount of time before the currently issued + certificate's `notAfter` time that we will begin to attempt + to renew the certificate. + type: string + type: object + type: object + cloneStrategyOverride: + description: 'Clone strategy override: should we use a host-assisted + copy even if snapshots are available?' + enum: + - copy + - snapshot + - csi-clone + type: string + config: + description: CDIConfig at CDI level + properties: + dataVolumeTTLSeconds: + description: DataVolumeTTLSeconds is the time in seconds after + DataVolume completion it can be garbage collected. Disabled + by default. + format: int32 + type: integer + featureGates: + description: FeatureGates are a list of specific enabled feature + gates + items: + type: string + type: array + filesystemOverhead: + description: FilesystemOverhead describes the space reserved for + overhead when using Filesystem volumes. A value is between 0 + and 1, if not defined it is 0.055 (5.5% overhead) + properties: + global: + description: Global is how much space of a Filesystem volume + should be reserved for overhead. This value is used unless + overridden by a more specific value (per storageClass) + pattern: ^(0(?:\.\d{1,3})?|1)$ + type: string + storageClass: + additionalProperties: + description: 'Percent is a string that can only be a value + between [0,1) (Note: we actually rely on reconcile to + reject invalid values)' + pattern: ^(0(?:\.\d{1,3})?|1)$ + type: string + description: StorageClass specifies how much space of a Filesystem + volume should be reserved for safety. The keys are the storageClass + and the values are the overhead. This value overrides the + global value + type: object + type: object + imagePullSecrets: + description: The imagePullSecrets used to pull the container images + items: + description: LocalObjectReference contains enough information + to let you locate the referenced object inside the same namespace. + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + x-kubernetes-map-type: atomic + type: array + importProxy: + description: ImportProxy contains importer pod proxy configuration. + properties: + HTTPProxy: + description: HTTPProxy is the URL http://:@: + of the import proxy for HTTP requests. Empty means unset + and will not result in the import pod env var. + type: string + HTTPSProxy: + description: HTTPSProxy is the URL https://:@: + of the import proxy for HTTPS requests. Empty means unset + and will not result in the import pod env var. + type: string + noProxy: + description: NoProxy is a comma-separated list of hostnames + and/or CIDRs for which the proxy should not be used. Empty + means unset and will not result in the import pod env var. + type: string + trustedCAProxy: + description: "TrustedCAProxy is the name of a ConfigMap in + the cdi namespace that contains a user-provided trusted + certificate authority (CA) bundle. The TrustedCAProxy ConfigMap + is consumed by the DataImportCron controller for creating + cronjobs, and by the import controller referring a copy + of the ConfigMap in the import namespace. Here is an example + of the ConfigMap (in yaml): \n apiVersion: v1 kind: ConfigMap + metadata: name: my-ca-proxy-cm namespace: cozy-kubevirt-cdi data: ca.pem: + | -----BEGIN CERTIFICATE----- ... + ... -----END CERTIFICATE-----" + type: string + type: object + insecureRegistries: + description: InsecureRegistries is a list of TLS disabled registries + items: + type: string + type: array + logVerbosity: + description: LogVerbosity overrides the default verbosity level + used to initialize loggers + format: int32 + type: integer + podResourceRequirements: + description: ResourceRequirements describes the compute resource + requirements. + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable." + 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 + 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. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + preallocation: + description: Preallocation controls whether storage for DataVolumes + should be allocated in advance. + type: boolean + scratchSpaceStorageClass: + description: 'Override the storage class to used for scratch space + during transfer operations. The scratch space storage class + is determined in the following order: 1. value of scratchSpaceStorageClass, + if that doesn''t exist, use the default storage class, if there + is no default storage class, use the storage class of the DataVolume, + if no storage class specified, use no storage class for scratch + space' + type: string + tlsSecurityProfile: + description: TLSSecurityProfile is used by operators to apply + cluster-wide TLS security settings to operands. + properties: + custom: + description: "custom is a user-defined TLS security profile. + Be extremely careful using a custom profile as invalid configurations + can be catastrophic. An example custom profile looks like + this: \n ciphers: - ECDHE-ECDSA-CHACHA20-POLY1305 - ECDHE-RSA-CHACHA20-POLY1305 + - ECDHE-RSA-AES128-GCM-SHA256 - ECDHE-ECDSA-AES128-GCM-SHA256 + minTLSVersion: TLSv1.1" + nullable: true + properties: + ciphers: + description: "ciphers is used to specify the cipher algorithms + that are negotiated during the TLS handshake. Operators + may remove entries their operands do not support. For + example, to use DES-CBC3-SHA (yaml): \n ciphers: - + DES-CBC3-SHA" + items: + type: string + type: array + minTLSVersion: + description: "minTLSVersion is used to specify the minimal + version of the TLS protocol that is negotiated during + the TLS handshake. For example, to use TLS versions + 1.1, 1.2 and 1.3 (yaml): \n minTLSVersion: TLSv1.1 \n + NOTE: currently the highest minTLSVersion allowed is + VersionTLS12" + enum: + - VersionTLS10 + - VersionTLS11 + - VersionTLS12 + - VersionTLS13 + type: string + type: object + intermediate: + description: "intermediate is a TLS security profile based + on: \n https://wiki.mozilla.org/Security/Server_Side_TLS#Intermediate_compatibility_.28recommended.29 + \n and looks like this (yaml): \n ciphers: - TLS_AES_128_GCM_SHA256 + - TLS_AES_256_GCM_SHA384 - TLS_CHACHA20_POLY1305_SHA256 + - ECDHE-ECDSA-AES128-GCM-SHA256 - ECDHE-RSA-AES128-GCM-SHA256 + - ECDHE-ECDSA-AES256-GCM-SHA384 - ECDHE-RSA-AES256-GCM-SHA384 + - ECDHE-ECDSA-CHACHA20-POLY1305 - ECDHE-RSA-CHACHA20-POLY1305 + - DHE-RSA-AES128-GCM-SHA256 - DHE-RSA-AES256-GCM-SHA384 + minTLSVersion: TLSv1.2" + nullable: true + type: object + modern: + description: "modern is a TLS security profile based on: \n + https://wiki.mozilla.org/Security/Server_Side_TLS#Modern_compatibility + \n and looks like this (yaml): \n ciphers: - TLS_AES_128_GCM_SHA256 + - TLS_AES_256_GCM_SHA384 - TLS_CHACHA20_POLY1305_SHA256 + minTLSVersion: TLSv1.3 \n NOTE: Currently unsupported." + nullable: true + type: object + old: + description: "old is a TLS security profile based on: \n https://wiki.mozilla.org/Security/Server_Side_TLS#Old_backward_compatibility + \n and looks like this (yaml): \n ciphers: - TLS_AES_128_GCM_SHA256 + - TLS_AES_256_GCM_SHA384 - TLS_CHACHA20_POLY1305_SHA256 + - ECDHE-ECDSA-AES128-GCM-SHA256 - ECDHE-RSA-AES128-GCM-SHA256 + - ECDHE-ECDSA-AES256-GCM-SHA384 - ECDHE-RSA-AES256-GCM-SHA384 + - ECDHE-ECDSA-CHACHA20-POLY1305 - ECDHE-RSA-CHACHA20-POLY1305 + - DHE-RSA-AES128-GCM-SHA256 - DHE-RSA-AES256-GCM-SHA384 + - DHE-RSA-CHACHA20-POLY1305 - ECDHE-ECDSA-AES128-SHA256 + - ECDHE-RSA-AES128-SHA256 - ECDHE-ECDSA-AES128-SHA - ECDHE-RSA-AES128-SHA + - ECDHE-ECDSA-AES256-SHA384 - ECDHE-RSA-AES256-SHA384 - + ECDHE-ECDSA-AES256-SHA - ECDHE-RSA-AES256-SHA - DHE-RSA-AES128-SHA256 + - DHE-RSA-AES256-SHA256 - AES128-GCM-SHA256 - AES256-GCM-SHA384 + - AES128-SHA256 - AES256-SHA256 - AES128-SHA - AES256-SHA + - DES-CBC3-SHA minTLSVersion: TLSv1.0" + nullable: true + type: object + type: + description: "type is one of Old, Intermediate, Modern or + Custom. Custom provides the ability to specify individual + TLS security profile parameters. Old, Intermediate and Modern + are TLS security profiles based on: \n https://wiki.mozilla.org/Security/Server_Side_TLS#Recommended_configurations + \n The profiles are intent based, so they may change over + time as new ciphers are developed and existing ciphers are + found to be insecure. Depending on precisely which ciphers + are available to a process, the list may be reduced. \n + Note that the Modern profile is currently not supported + because it is not yet well adopted by common software libraries." + enum: + - Old + - Intermediate + - Modern + - Custom + type: string + type: object + uploadProxyURLOverride: + description: Override the URL used when uploading to a DataVolume + type: string + type: object + imagePullPolicy: + description: PullPolicy describes a policy for if/when to pull a container + image + enum: + - Always + - IfNotPresent + - Never + type: string + infra: + description: Rules on which nodes CDI infrastructure pods will be + scheduled + properties: + affinity: + description: affinity enables pod affinity/anti-affinity placement + expanding the types of constraints that can be expressed with + nodeSelector. affinity is going to be applied to the relevant + kind of pods in parallel with nodeSelector See https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#affinity-and-anti-affinity + properties: + nodeAffinity: + description: Describes node affinity scheduling rules for + the pod. + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods + to nodes that satisfy the affinity expressions specified + by this field, but it may choose a node that violates + one or more of the expressions. The node that is most + preferred is the one with the greatest sum of weights, + i.e. for each node that meets all of the scheduling + requirements (resource request, requiredDuringScheduling + affinity expressions, etc.), compute a sum by iterating + through the elements of this field and adding "weight" + to the sum if the node matches the corresponding matchExpressions; + the node(s) with the highest sum are the most preferred. + items: + description: An empty preferred scheduling term matches + all objects with implicit weight 0 (i.e. it's a no-op). + A null preferred scheduling term matches no objects + (i.e. is also a no-op). + properties: + preference: + description: A node selector term, associated with + the corresponding weight. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: 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. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: 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. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + x-kubernetes-map-type: atomic + weight: + description: Weight associated with matching the + corresponding nodeSelectorTerm, in the range 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by + this field are not met at scheduling time, the pod will + not be scheduled onto the node. If the affinity requirements + specified by this field cease to be met at some point + during pod execution (e.g. due to an update), the system + may or may not try to eventually evict the pod from + its node. + properties: + nodeSelectorTerms: + description: Required. A list of node selector terms. + The terms are ORed. + items: + description: A null or empty node selector term + matches no objects. The requirements of them are + ANDed. The TopologySelectorTerm type implements + a subset of the NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: 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. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: 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. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + x-kubernetes-map-type: atomic + type: array + required: + - nodeSelectorTerms + type: object + x-kubernetes-map-type: atomic + type: object + podAffinity: + description: Describes pod affinity scheduling rules (e.g. + co-locate this pod in the same node, zone, etc. as some + other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods + to nodes that satisfy the affinity expressions specified + by this field, but it may choose a node that violates + one or more of the expressions. The node that is most + preferred is the one with the greatest sum of weights, + i.e. for each node that meets all of the scheduling + requirements (resource request, requiredDuringScheduling + affinity expressions, etc.), compute a sum by iterating + through the elements of this field and adding "weight" + to the sum if the node has pods which matches the corresponding + podAffinityTerm; the node(s) with the highest sum are + the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by + this field and the ones listed in the namespaces + field. null selector and null or empty namespaces + list means "this pod's namespace". An empty + selector ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. + The term is applied to the union of the namespaces + listed in this field and the ones selected + by namespaceSelector. null or empty namespaces + list and null namespaceSelector means "this + pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the + pods matching the labelSelector in the specified + namespaces, where co-located is defined as + running on a node whose value of the label + with key topologyKey matches that of any node + on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching the + corresponding podAffinityTerm, in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by + this field are not met at scheduling time, the pod will + not be scheduled onto the node. If the affinity requirements + specified by this field cease to be met at some point + during pod execution (e.g. due to a pod label update), + the system may or may not try to eventually evict the + pod from its node. When there are multiple elements, + the lists of nodes corresponding to each podAffinityTerm + are intersected, i.e. all terms must be satisfied. + items: + description: Defines a set of pods (namely those matching + the labelSelector relative to the given namespace(s)) + that this pod should be co-located (affinity) or not + co-located (anti-affinity) with, where co-located + is defined as running on a node whose value of the + label with key matches that of any node + on which a pod of the set of pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by this + field and the ones listed in the namespaces field. + null selector and null or empty namespaces list + means "this pod's namespace". An empty selector + ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. The + term is applied to the union of the namespaces + listed in this field and the ones selected by + namespaceSelector. null or empty namespaces list + and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods + matching the labelSelector in the specified namespaces, + where co-located is defined as running on a node + whose value of the label with key topologyKey + matches that of any node on which any of the selected + pods is running. Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + podAntiAffinity: + description: Describes pod anti-affinity scheduling rules + (e.g. avoid putting this pod in the same node, zone, etc. + as some other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods + to nodes that satisfy the anti-affinity expressions + specified by this field, but it may choose a node that + violates one or more of the expressions. The node that + is most preferred is the one with the greatest sum of + weights, i.e. for each node that meets all of the scheduling + requirements (resource request, requiredDuringScheduling + anti-affinity expressions, etc.), compute a sum by iterating + through the elements of this field and adding "weight" + to the sum if the node has pods which matches the corresponding + podAffinityTerm; the node(s) with the highest sum are + the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by + this field and the ones listed in the namespaces + field. null selector and null or empty namespaces + list means "this pod's namespace". An empty + selector ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. + The term is applied to the union of the namespaces + listed in this field and the ones selected + by namespaceSelector. null or empty namespaces + list and null namespaceSelector means "this + pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the + pods matching the labelSelector in the specified + namespaces, where co-located is defined as + running on a node whose value of the label + with key topologyKey matches that of any node + on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching the + corresponding podAffinityTerm, in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the anti-affinity requirements specified + by this field are not met at scheduling time, the pod + will not be scheduled onto the node. If the anti-affinity + requirements specified by this field cease to be met + at some point during pod execution (e.g. due to a pod + label update), the system may or may not try to eventually + evict the pod from its node. When there are multiple + elements, the lists of nodes corresponding to each podAffinityTerm + are intersected, i.e. all terms must be satisfied. + items: + description: Defines a set of pods (namely those matching + the labelSelector relative to the given namespace(s)) + that this pod should be co-located (affinity) or not + co-located (anti-affinity) with, where co-located + is defined as running on a node whose value of the + label with key matches that of any node + on which a pod of the set of pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by this + field and the ones listed in the namespaces field. + null selector and null or empty namespaces list + means "this pod's namespace". An empty selector + ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. The + term is applied to the union of the namespaces + listed in this field and the ones selected by + namespaceSelector. null or empty namespaces list + and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods + matching the labelSelector in the specified namespaces, + where co-located is defined as running on a node + whose value of the label with key topologyKey + matches that of any node on which any of the selected + pods is running. Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + type: object + nodeSelector: + additionalProperties: + type: string + description: 'nodeSelector is the node selector applied to the + relevant kind of pods It specifies a map of key-value pairs: + for the pod to be eligible to run on a node, the node must have + each of the indicated key-value pairs as labels (it can have + additional labels as well). See https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#nodeselector' + type: object + tolerations: + description: tolerations is a list of tolerations applied to the + relevant kind of pods See https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ + for more info. These are additional tolerations other than default + ones. + 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 + type: object + priorityClass: + description: PriorityClass of the CDI control plane + type: string + uninstallStrategy: + description: CDIUninstallStrategy defines the state to leave CDI on + uninstall + enum: + - RemoveWorkloads + - BlockUninstallIfWorkloadsExist + type: string + workload: + description: Restrict on which nodes CDI workload pods will be scheduled + properties: + affinity: + description: affinity enables pod affinity/anti-affinity placement + expanding the types of constraints that can be expressed with + nodeSelector. affinity is going to be applied to the relevant + kind of pods in parallel with nodeSelector See https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#affinity-and-anti-affinity + properties: + nodeAffinity: + description: Describes node affinity scheduling rules for + the pod. + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods + to nodes that satisfy the affinity expressions specified + by this field, but it may choose a node that violates + one or more of the expressions. The node that is most + preferred is the one with the greatest sum of weights, + i.e. for each node that meets all of the scheduling + requirements (resource request, requiredDuringScheduling + affinity expressions, etc.), compute a sum by iterating + through the elements of this field and adding "weight" + to the sum if the node matches the corresponding matchExpressions; + the node(s) with the highest sum are the most preferred. + items: + description: An empty preferred scheduling term matches + all objects with implicit weight 0 (i.e. it's a no-op). + A null preferred scheduling term matches no objects + (i.e. is also a no-op). + properties: + preference: + description: A node selector term, associated with + the corresponding weight. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: 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. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: 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. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + x-kubernetes-map-type: atomic + weight: + description: Weight associated with matching the + corresponding nodeSelectorTerm, in the range 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by + this field are not met at scheduling time, the pod will + not be scheduled onto the node. If the affinity requirements + specified by this field cease to be met at some point + during pod execution (e.g. due to an update), the system + may or may not try to eventually evict the pod from + its node. + properties: + nodeSelectorTerms: + description: Required. A list of node selector terms. + The terms are ORed. + items: + description: A null or empty node selector term + matches no objects. The requirements of them are + ANDed. The TopologySelectorTerm type implements + a subset of the NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: 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. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: 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. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + x-kubernetes-map-type: atomic + type: array + required: + - nodeSelectorTerms + type: object + x-kubernetes-map-type: atomic + type: object + podAffinity: + description: Describes pod affinity scheduling rules (e.g. + co-locate this pod in the same node, zone, etc. as some + other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods + to nodes that satisfy the affinity expressions specified + by this field, but it may choose a node that violates + one or more of the expressions. The node that is most + preferred is the one with the greatest sum of weights, + i.e. for each node that meets all of the scheduling + requirements (resource request, requiredDuringScheduling + affinity expressions, etc.), compute a sum by iterating + through the elements of this field and adding "weight" + to the sum if the node has pods which matches the corresponding + podAffinityTerm; the node(s) with the highest sum are + the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by + this field and the ones listed in the namespaces + field. null selector and null or empty namespaces + list means "this pod's namespace". An empty + selector ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. + The term is applied to the union of the namespaces + listed in this field and the ones selected + by namespaceSelector. null or empty namespaces + list and null namespaceSelector means "this + pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the + pods matching the labelSelector in the specified + namespaces, where co-located is defined as + running on a node whose value of the label + with key topologyKey matches that of any node + on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching the + corresponding podAffinityTerm, in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by + this field are not met at scheduling time, the pod will + not be scheduled onto the node. If the affinity requirements + specified by this field cease to be met at some point + during pod execution (e.g. due to a pod label update), + the system may or may not try to eventually evict the + pod from its node. When there are multiple elements, + the lists of nodes corresponding to each podAffinityTerm + are intersected, i.e. all terms must be satisfied. + items: + description: Defines a set of pods (namely those matching + the labelSelector relative to the given namespace(s)) + that this pod should be co-located (affinity) or not + co-located (anti-affinity) with, where co-located + is defined as running on a node whose value of the + label with key matches that of any node + on which a pod of the set of pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by this + field and the ones listed in the namespaces field. + null selector and null or empty namespaces list + means "this pod's namespace". An empty selector + ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. The + term is applied to the union of the namespaces + listed in this field and the ones selected by + namespaceSelector. null or empty namespaces list + and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods + matching the labelSelector in the specified namespaces, + where co-located is defined as running on a node + whose value of the label with key topologyKey + matches that of any node on which any of the selected + pods is running. Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + podAntiAffinity: + description: Describes pod anti-affinity scheduling rules + (e.g. avoid putting this pod in the same node, zone, etc. + as some other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods + to nodes that satisfy the anti-affinity expressions + specified by this field, but it may choose a node that + violates one or more of the expressions. The node that + is most preferred is the one with the greatest sum of + weights, i.e. for each node that meets all of the scheduling + requirements (resource request, requiredDuringScheduling + anti-affinity expressions, etc.), compute a sum by iterating + through the elements of this field and adding "weight" + to the sum if the node has pods which matches the corresponding + podAffinityTerm; the node(s) with the highest sum are + the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by + this field and the ones listed in the namespaces + field. null selector and null or empty namespaces + list means "this pod's namespace". An empty + selector ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. + The term is applied to the union of the namespaces + listed in this field and the ones selected + by namespaceSelector. null or empty namespaces + list and null namespaceSelector means "this + pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the + pods matching the labelSelector in the specified + namespaces, where co-located is defined as + running on a node whose value of the label + with key topologyKey matches that of any node + on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching the + corresponding podAffinityTerm, in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the anti-affinity requirements specified + by this field are not met at scheduling time, the pod + will not be scheduled onto the node. If the anti-affinity + requirements specified by this field cease to be met + at some point during pod execution (e.g. due to a pod + label update), the system may or may not try to eventually + evict the pod from its node. When there are multiple + elements, the lists of nodes corresponding to each podAffinityTerm + are intersected, i.e. all terms must be satisfied. + items: + description: Defines a set of pods (namely those matching + the labelSelector relative to the given namespace(s)) + that this pod should be co-located (affinity) or not + co-located (anti-affinity) with, where co-located + is defined as running on a node whose value of the + label with key matches that of any node + on which a pod of the set of pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by this + field and the ones listed in the namespaces field. + null selector and null or empty namespaces list + means "this pod's namespace". An empty selector + ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. The + term is applied to the union of the namespaces + listed in this field and the ones selected by + namespaceSelector. null or empty namespaces list + and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods + matching the labelSelector in the specified namespaces, + where co-located is defined as running on a node + whose value of the label with key topologyKey + matches that of any node on which any of the selected + pods is running. Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + type: object + nodeSelector: + additionalProperties: + type: string + description: 'nodeSelector is the node selector applied to the + relevant kind of pods It specifies a map of key-value pairs: + for the pod to be eligible to run on a node, the node must have + each of the indicated key-value pairs as labels (it can have + additional labels as well). See https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#nodeselector' + type: object + tolerations: + description: tolerations is a list of tolerations applied to the + relevant kind of pods See https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ + for more info. These are additional tolerations other than default + ones. + 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 + type: object + type: object + status: + description: CDIStatus defines the status of the installation + properties: + conditions: + description: A list of current conditions of the resource + items: + description: Condition represents the state of the operator's reconciliation + functionality. + properties: + lastHeartbeatTime: + format: date-time + type: string + lastTransitionTime: + format: date-time + type: string + message: + type: string + reason: + type: string + status: + type: string + type: + description: ConditionType is the state of the operator's reconciliation + functionality. + type: string + required: + - status + - type + type: object + type: array + observedVersion: + description: The observed version of the resource + type: string + operatorVersion: + description: The version of the resource as defined by the operator + type: string + phase: + description: Phase is the current phase of the deployment + type: string + targetVersion: + description: The desired version of the resource + type: string + type: object + required: + - spec + type: object + served: true + storage: false + subresources: {} + - additionalPrinterColumns: + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + - jsonPath: .status.phase + name: Phase + type: string + name: v1beta1 + schema: + openAPIV3Schema: + description: CDI is the CDI Operator CRD + 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: CDISpec defines our specification for the CDI installation + properties: + certConfig: + description: certificate configuration + properties: + ca: + description: CA configuration CA certs are kept in the CA bundle + as long as they are valid + properties: + duration: + description: The requested 'duration' (i.e. lifetime) of the + Certificate. + type: string + renewBefore: + description: The amount of time before the currently issued + certificate's `notAfter` time that we will begin to attempt + to renew the certificate. + type: string + type: object + server: + description: Server configuration Certs are rotated and discarded + properties: + duration: + description: The requested 'duration' (i.e. lifetime) of the + Certificate. + type: string + renewBefore: + description: The amount of time before the currently issued + certificate's `notAfter` time that we will begin to attempt + to renew the certificate. + type: string + type: object + type: object + cloneStrategyOverride: + description: 'Clone strategy override: should we use a host-assisted + copy even if snapshots are available?' + enum: + - copy + - snapshot + - csi-clone + type: string + config: + description: CDIConfig at CDI level + properties: + dataVolumeTTLSeconds: + description: DataVolumeTTLSeconds is the time in seconds after + DataVolume completion it can be garbage collected. Disabled + by default. + format: int32 + type: integer + featureGates: + description: FeatureGates are a list of specific enabled feature + gates + items: + type: string + type: array + filesystemOverhead: + description: FilesystemOverhead describes the space reserved for + overhead when using Filesystem volumes. A value is between 0 + and 1, if not defined it is 0.055 (5.5% overhead) + properties: + global: + description: Global is how much space of a Filesystem volume + should be reserved for overhead. This value is used unless + overridden by a more specific value (per storageClass) + pattern: ^(0(?:\.\d{1,3})?|1)$ + type: string + storageClass: + additionalProperties: + description: 'Percent is a string that can only be a value + between [0,1) (Note: we actually rely on reconcile to + reject invalid values)' + pattern: ^(0(?:\.\d{1,3})?|1)$ + type: string + description: StorageClass specifies how much space of a Filesystem + volume should be reserved for safety. The keys are the storageClass + and the values are the overhead. This value overrides the + global value + type: object + type: object + imagePullSecrets: + description: The imagePullSecrets used to pull the container images + items: + description: LocalObjectReference contains enough information + to let you locate the referenced object inside the same namespace. + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + x-kubernetes-map-type: atomic + type: array + importProxy: + description: ImportProxy contains importer pod proxy configuration. + properties: + HTTPProxy: + description: HTTPProxy is the URL http://:@: + of the import proxy for HTTP requests. Empty means unset + and will not result in the import pod env var. + type: string + HTTPSProxy: + description: HTTPSProxy is the URL https://:@: + of the import proxy for HTTPS requests. Empty means unset + and will not result in the import pod env var. + type: string + noProxy: + description: NoProxy is a comma-separated list of hostnames + and/or CIDRs for which the proxy should not be used. Empty + means unset and will not result in the import pod env var. + type: string + trustedCAProxy: + description: "TrustedCAProxy is the name of a ConfigMap in + the cdi namespace that contains a user-provided trusted + certificate authority (CA) bundle. The TrustedCAProxy ConfigMap + is consumed by the DataImportCron controller for creating + cronjobs, and by the import controller referring a copy + of the ConfigMap in the import namespace. Here is an example + of the ConfigMap (in yaml): \n apiVersion: v1 kind: ConfigMap + metadata: name: my-ca-proxy-cm namespace: cozy-kubevirt-cdi data: ca.pem: + | -----BEGIN CERTIFICATE----- ... + ... -----END CERTIFICATE-----" + type: string + type: object + insecureRegistries: + description: InsecureRegistries is a list of TLS disabled registries + items: + type: string + type: array + logVerbosity: + description: LogVerbosity overrides the default verbosity level + used to initialize loggers + format: int32 + type: integer + podResourceRequirements: + description: ResourceRequirements describes the compute resource + requirements. + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable." + 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 + 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. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + preallocation: + description: Preallocation controls whether storage for DataVolumes + should be allocated in advance. + type: boolean + scratchSpaceStorageClass: + description: 'Override the storage class to used for scratch space + during transfer operations. The scratch space storage class + is determined in the following order: 1. value of scratchSpaceStorageClass, + if that doesn''t exist, use the default storage class, if there + is no default storage class, use the storage class of the DataVolume, + if no storage class specified, use no storage class for scratch + space' + type: string + tlsSecurityProfile: + description: TLSSecurityProfile is used by operators to apply + cluster-wide TLS security settings to operands. + properties: + custom: + description: "custom is a user-defined TLS security profile. + Be extremely careful using a custom profile as invalid configurations + can be catastrophic. An example custom profile looks like + this: \n ciphers: - ECDHE-ECDSA-CHACHA20-POLY1305 - ECDHE-RSA-CHACHA20-POLY1305 + - ECDHE-RSA-AES128-GCM-SHA256 - ECDHE-ECDSA-AES128-GCM-SHA256 + minTLSVersion: TLSv1.1" + nullable: true + properties: + ciphers: + description: "ciphers is used to specify the cipher algorithms + that are negotiated during the TLS handshake. Operators + may remove entries their operands do not support. For + example, to use DES-CBC3-SHA (yaml): \n ciphers: - + DES-CBC3-SHA" + items: + type: string + type: array + minTLSVersion: + description: "minTLSVersion is used to specify the minimal + version of the TLS protocol that is negotiated during + the TLS handshake. For example, to use TLS versions + 1.1, 1.2 and 1.3 (yaml): \n minTLSVersion: TLSv1.1 \n + NOTE: currently the highest minTLSVersion allowed is + VersionTLS12" + enum: + - VersionTLS10 + - VersionTLS11 + - VersionTLS12 + - VersionTLS13 + type: string + type: object + intermediate: + description: "intermediate is a TLS security profile based + on: \n https://wiki.mozilla.org/Security/Server_Side_TLS#Intermediate_compatibility_.28recommended.29 + \n and looks like this (yaml): \n ciphers: - TLS_AES_128_GCM_SHA256 + - TLS_AES_256_GCM_SHA384 - TLS_CHACHA20_POLY1305_SHA256 + - ECDHE-ECDSA-AES128-GCM-SHA256 - ECDHE-RSA-AES128-GCM-SHA256 + - ECDHE-ECDSA-AES256-GCM-SHA384 - ECDHE-RSA-AES256-GCM-SHA384 + - ECDHE-ECDSA-CHACHA20-POLY1305 - ECDHE-RSA-CHACHA20-POLY1305 + - DHE-RSA-AES128-GCM-SHA256 - DHE-RSA-AES256-GCM-SHA384 + minTLSVersion: TLSv1.2" + nullable: true + type: object + modern: + description: "modern is a TLS security profile based on: \n + https://wiki.mozilla.org/Security/Server_Side_TLS#Modern_compatibility + \n and looks like this (yaml): \n ciphers: - TLS_AES_128_GCM_SHA256 + - TLS_AES_256_GCM_SHA384 - TLS_CHACHA20_POLY1305_SHA256 + minTLSVersion: TLSv1.3 \n NOTE: Currently unsupported." + nullable: true + type: object + old: + description: "old is a TLS security profile based on: \n https://wiki.mozilla.org/Security/Server_Side_TLS#Old_backward_compatibility + \n and looks like this (yaml): \n ciphers: - TLS_AES_128_GCM_SHA256 + - TLS_AES_256_GCM_SHA384 - TLS_CHACHA20_POLY1305_SHA256 + - ECDHE-ECDSA-AES128-GCM-SHA256 - ECDHE-RSA-AES128-GCM-SHA256 + - ECDHE-ECDSA-AES256-GCM-SHA384 - ECDHE-RSA-AES256-GCM-SHA384 + - ECDHE-ECDSA-CHACHA20-POLY1305 - ECDHE-RSA-CHACHA20-POLY1305 + - DHE-RSA-AES128-GCM-SHA256 - DHE-RSA-AES256-GCM-SHA384 + - DHE-RSA-CHACHA20-POLY1305 - ECDHE-ECDSA-AES128-SHA256 + - ECDHE-RSA-AES128-SHA256 - ECDHE-ECDSA-AES128-SHA - ECDHE-RSA-AES128-SHA + - ECDHE-ECDSA-AES256-SHA384 - ECDHE-RSA-AES256-SHA384 - + ECDHE-ECDSA-AES256-SHA - ECDHE-RSA-AES256-SHA - DHE-RSA-AES128-SHA256 + - DHE-RSA-AES256-SHA256 - AES128-GCM-SHA256 - AES256-GCM-SHA384 + - AES128-SHA256 - AES256-SHA256 - AES128-SHA - AES256-SHA + - DES-CBC3-SHA minTLSVersion: TLSv1.0" + nullable: true + type: object + type: + description: "type is one of Old, Intermediate, Modern or + Custom. Custom provides the ability to specify individual + TLS security profile parameters. Old, Intermediate and Modern + are TLS security profiles based on: \n https://wiki.mozilla.org/Security/Server_Side_TLS#Recommended_configurations + \n The profiles are intent based, so they may change over + time as new ciphers are developed and existing ciphers are + found to be insecure. Depending on precisely which ciphers + are available to a process, the list may be reduced. \n + Note that the Modern profile is currently not supported + because it is not yet well adopted by common software libraries." + enum: + - Old + - Intermediate + - Modern + - Custom + type: string + type: object + uploadProxyURLOverride: + description: Override the URL used when uploading to a DataVolume + type: string + type: object + imagePullPolicy: + description: PullPolicy describes a policy for if/when to pull a container + image + enum: + - Always + - IfNotPresent + - Never + type: string + infra: + description: Rules on which nodes CDI infrastructure pods will be + scheduled + properties: + affinity: + description: affinity enables pod affinity/anti-affinity placement + expanding the types of constraints that can be expressed with + nodeSelector. affinity is going to be applied to the relevant + kind of pods in parallel with nodeSelector See https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#affinity-and-anti-affinity + properties: + nodeAffinity: + description: Describes node affinity scheduling rules for + the pod. + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods + to nodes that satisfy the affinity expressions specified + by this field, but it may choose a node that violates + one or more of the expressions. The node that is most + preferred is the one with the greatest sum of weights, + i.e. for each node that meets all of the scheduling + requirements (resource request, requiredDuringScheduling + affinity expressions, etc.), compute a sum by iterating + through the elements of this field and adding "weight" + to the sum if the node matches the corresponding matchExpressions; + the node(s) with the highest sum are the most preferred. + items: + description: An empty preferred scheduling term matches + all objects with implicit weight 0 (i.e. it's a no-op). + A null preferred scheduling term matches no objects + (i.e. is also a no-op). + properties: + preference: + description: A node selector term, associated with + the corresponding weight. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: 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. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: 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. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + x-kubernetes-map-type: atomic + weight: + description: Weight associated with matching the + corresponding nodeSelectorTerm, in the range 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by + this field are not met at scheduling time, the pod will + not be scheduled onto the node. If the affinity requirements + specified by this field cease to be met at some point + during pod execution (e.g. due to an update), the system + may or may not try to eventually evict the pod from + its node. + properties: + nodeSelectorTerms: + description: Required. A list of node selector terms. + The terms are ORed. + items: + description: A null or empty node selector term + matches no objects. The requirements of them are + ANDed. The TopologySelectorTerm type implements + a subset of the NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: 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. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: 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. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + x-kubernetes-map-type: atomic + type: array + required: + - nodeSelectorTerms + type: object + x-kubernetes-map-type: atomic + type: object + podAffinity: + description: Describes pod affinity scheduling rules (e.g. + co-locate this pod in the same node, zone, etc. as some + other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods + to nodes that satisfy the affinity expressions specified + by this field, but it may choose a node that violates + one or more of the expressions. The node that is most + preferred is the one with the greatest sum of weights, + i.e. for each node that meets all of the scheduling + requirements (resource request, requiredDuringScheduling + affinity expressions, etc.), compute a sum by iterating + through the elements of this field and adding "weight" + to the sum if the node has pods which matches the corresponding + podAffinityTerm; the node(s) with the highest sum are + the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by + this field and the ones listed in the namespaces + field. null selector and null or empty namespaces + list means "this pod's namespace". An empty + selector ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. + The term is applied to the union of the namespaces + listed in this field and the ones selected + by namespaceSelector. null or empty namespaces + list and null namespaceSelector means "this + pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the + pods matching the labelSelector in the specified + namespaces, where co-located is defined as + running on a node whose value of the label + with key topologyKey matches that of any node + on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching the + corresponding podAffinityTerm, in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by + this field are not met at scheduling time, the pod will + not be scheduled onto the node. If the affinity requirements + specified by this field cease to be met at some point + during pod execution (e.g. due to a pod label update), + the system may or may not try to eventually evict the + pod from its node. When there are multiple elements, + the lists of nodes corresponding to each podAffinityTerm + are intersected, i.e. all terms must be satisfied. + items: + description: Defines a set of pods (namely those matching + the labelSelector relative to the given namespace(s)) + that this pod should be co-located (affinity) or not + co-located (anti-affinity) with, where co-located + is defined as running on a node whose value of the + label with key matches that of any node + on which a pod of the set of pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by this + field and the ones listed in the namespaces field. + null selector and null or empty namespaces list + means "this pod's namespace". An empty selector + ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. The + term is applied to the union of the namespaces + listed in this field and the ones selected by + namespaceSelector. null or empty namespaces list + and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods + matching the labelSelector in the specified namespaces, + where co-located is defined as running on a node + whose value of the label with key topologyKey + matches that of any node on which any of the selected + pods is running. Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + podAntiAffinity: + description: Describes pod anti-affinity scheduling rules + (e.g. avoid putting this pod in the same node, zone, etc. + as some other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods + to nodes that satisfy the anti-affinity expressions + specified by this field, but it may choose a node that + violates one or more of the expressions. The node that + is most preferred is the one with the greatest sum of + weights, i.e. for each node that meets all of the scheduling + requirements (resource request, requiredDuringScheduling + anti-affinity expressions, etc.), compute a sum by iterating + through the elements of this field and adding "weight" + to the sum if the node has pods which matches the corresponding + podAffinityTerm; the node(s) with the highest sum are + the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by + this field and the ones listed in the namespaces + field. null selector and null or empty namespaces + list means "this pod's namespace". An empty + selector ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. + The term is applied to the union of the namespaces + listed in this field and the ones selected + by namespaceSelector. null or empty namespaces + list and null namespaceSelector means "this + pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the + pods matching the labelSelector in the specified + namespaces, where co-located is defined as + running on a node whose value of the label + with key topologyKey matches that of any node + on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching the + corresponding podAffinityTerm, in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the anti-affinity requirements specified + by this field are not met at scheduling time, the pod + will not be scheduled onto the node. If the anti-affinity + requirements specified by this field cease to be met + at some point during pod execution (e.g. due to a pod + label update), the system may or may not try to eventually + evict the pod from its node. When there are multiple + elements, the lists of nodes corresponding to each podAffinityTerm + are intersected, i.e. all terms must be satisfied. + items: + description: Defines a set of pods (namely those matching + the labelSelector relative to the given namespace(s)) + that this pod should be co-located (affinity) or not + co-located (anti-affinity) with, where co-located + is defined as running on a node whose value of the + label with key matches that of any node + on which a pod of the set of pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by this + field and the ones listed in the namespaces field. + null selector and null or empty namespaces list + means "this pod's namespace". An empty selector + ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. The + term is applied to the union of the namespaces + listed in this field and the ones selected by + namespaceSelector. null or empty namespaces list + and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods + matching the labelSelector in the specified namespaces, + where co-located is defined as running on a node + whose value of the label with key topologyKey + matches that of any node on which any of the selected + pods is running. Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + type: object + nodeSelector: + additionalProperties: + type: string + description: 'nodeSelector is the node selector applied to the + relevant kind of pods It specifies a map of key-value pairs: + for the pod to be eligible to run on a node, the node must have + each of the indicated key-value pairs as labels (it can have + additional labels as well). See https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#nodeselector' + type: object + tolerations: + description: tolerations is a list of tolerations applied to the + relevant kind of pods See https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ + for more info. These are additional tolerations other than default + ones. + 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 + type: object + priorityClass: + description: PriorityClass of the CDI control plane + type: string + uninstallStrategy: + description: CDIUninstallStrategy defines the state to leave CDI on + uninstall + enum: + - RemoveWorkloads + - BlockUninstallIfWorkloadsExist + type: string + workload: + description: Restrict on which nodes CDI workload pods will be scheduled + properties: + affinity: + description: affinity enables pod affinity/anti-affinity placement + expanding the types of constraints that can be expressed with + nodeSelector. affinity is going to be applied to the relevant + kind of pods in parallel with nodeSelector See https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#affinity-and-anti-affinity + properties: + nodeAffinity: + description: Describes node affinity scheduling rules for + the pod. + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods + to nodes that satisfy the affinity expressions specified + by this field, but it may choose a node that violates + one or more of the expressions. The node that is most + preferred is the one with the greatest sum of weights, + i.e. for each node that meets all of the scheduling + requirements (resource request, requiredDuringScheduling + affinity expressions, etc.), compute a sum by iterating + through the elements of this field and adding "weight" + to the sum if the node matches the corresponding matchExpressions; + the node(s) with the highest sum are the most preferred. + items: + description: An empty preferred scheduling term matches + all objects with implicit weight 0 (i.e. it's a no-op). + A null preferred scheduling term matches no objects + (i.e. is also a no-op). + properties: + preference: + description: A node selector term, associated with + the corresponding weight. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: 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. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: 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. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + x-kubernetes-map-type: atomic + weight: + description: Weight associated with matching the + corresponding nodeSelectorTerm, in the range 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by + this field are not met at scheduling time, the pod will + not be scheduled onto the node. If the affinity requirements + specified by this field cease to be met at some point + during pod execution (e.g. due to an update), the system + may or may not try to eventually evict the pod from + its node. + properties: + nodeSelectorTerms: + description: Required. A list of node selector terms. + The terms are ORed. + items: + description: A null or empty node selector term + matches no objects. The requirements of them are + ANDed. The TopologySelectorTerm type implements + a subset of the NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: 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. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: 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. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + x-kubernetes-map-type: atomic + type: array + required: + - nodeSelectorTerms + type: object + x-kubernetes-map-type: atomic + type: object + podAffinity: + description: Describes pod affinity scheduling rules (e.g. + co-locate this pod in the same node, zone, etc. as some + other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods + to nodes that satisfy the affinity expressions specified + by this field, but it may choose a node that violates + one or more of the expressions. The node that is most + preferred is the one with the greatest sum of weights, + i.e. for each node that meets all of the scheduling + requirements (resource request, requiredDuringScheduling + affinity expressions, etc.), compute a sum by iterating + through the elements of this field and adding "weight" + to the sum if the node has pods which matches the corresponding + podAffinityTerm; the node(s) with the highest sum are + the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by + this field and the ones listed in the namespaces + field. null selector and null or empty namespaces + list means "this pod's namespace". An empty + selector ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. + The term is applied to the union of the namespaces + listed in this field and the ones selected + by namespaceSelector. null or empty namespaces + list and null namespaceSelector means "this + pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the + pods matching the labelSelector in the specified + namespaces, where co-located is defined as + running on a node whose value of the label + with key topologyKey matches that of any node + on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching the + corresponding podAffinityTerm, in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by + this field are not met at scheduling time, the pod will + not be scheduled onto the node. If the affinity requirements + specified by this field cease to be met at some point + during pod execution (e.g. due to a pod label update), + the system may or may not try to eventually evict the + pod from its node. When there are multiple elements, + the lists of nodes corresponding to each podAffinityTerm + are intersected, i.e. all terms must be satisfied. + items: + description: Defines a set of pods (namely those matching + the labelSelector relative to the given namespace(s)) + that this pod should be co-located (affinity) or not + co-located (anti-affinity) with, where co-located + is defined as running on a node whose value of the + label with key matches that of any node + on which a pod of the set of pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by this + field and the ones listed in the namespaces field. + null selector and null or empty namespaces list + means "this pod's namespace". An empty selector + ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. The + term is applied to the union of the namespaces + listed in this field and the ones selected by + namespaceSelector. null or empty namespaces list + and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods + matching the labelSelector in the specified namespaces, + where co-located is defined as running on a node + whose value of the label with key topologyKey + matches that of any node on which any of the selected + pods is running. Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + podAntiAffinity: + description: Describes pod anti-affinity scheduling rules + (e.g. avoid putting this pod in the same node, zone, etc. + as some other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods + to nodes that satisfy the anti-affinity expressions + specified by this field, but it may choose a node that + violates one or more of the expressions. The node that + is most preferred is the one with the greatest sum of + weights, i.e. for each node that meets all of the scheduling + requirements (resource request, requiredDuringScheduling + anti-affinity expressions, etc.), compute a sum by iterating + through the elements of this field and adding "weight" + to the sum if the node has pods which matches the corresponding + podAffinityTerm; the node(s) with the highest sum are + the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by + this field and the ones listed in the namespaces + field. null selector and null or empty namespaces + list means "this pod's namespace". An empty + selector ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. + The term is applied to the union of the namespaces + listed in this field and the ones selected + by namespaceSelector. null or empty namespaces + list and null namespaceSelector means "this + pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the + pods matching the labelSelector in the specified + namespaces, where co-located is defined as + running on a node whose value of the label + with key topologyKey matches that of any node + on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching the + corresponding podAffinityTerm, in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the anti-affinity requirements specified + by this field are not met at scheduling time, the pod + will not be scheduled onto the node. If the anti-affinity + requirements specified by this field cease to be met + at some point during pod execution (e.g. due to a pod + label update), the system may or may not try to eventually + evict the pod from its node. When there are multiple + elements, the lists of nodes corresponding to each podAffinityTerm + are intersected, i.e. all terms must be satisfied. + items: + description: Defines a set of pods (namely those matching + the labelSelector relative to the given namespace(s)) + that this pod should be co-located (affinity) or not + co-located (anti-affinity) with, where co-located + is defined as running on a node whose value of the + label with key matches that of any node + on which a pod of the set of pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by this + field and the ones listed in the namespaces field. + null selector and null or empty namespaces list + means "this pod's namespace". An empty selector + ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. The + term is applied to the union of the namespaces + listed in this field and the ones selected by + namespaceSelector. null or empty namespaces list + and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods + matching the labelSelector in the specified namespaces, + where co-located is defined as running on a node + whose value of the label with key topologyKey + matches that of any node on which any of the selected + pods is running. Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + type: object + nodeSelector: + additionalProperties: + type: string + description: 'nodeSelector is the node selector applied to the + relevant kind of pods It specifies a map of key-value pairs: + for the pod to be eligible to run on a node, the node must have + each of the indicated key-value pairs as labels (it can have + additional labels as well). See https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#nodeselector' + type: object + tolerations: + description: tolerations is a list of tolerations applied to the + relevant kind of pods See https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ + for more info. These are additional tolerations other than default + ones. + 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 + type: object + type: object + status: + description: CDIStatus defines the status of the installation + properties: + conditions: + description: A list of current conditions of the resource + items: + description: Condition represents the state of the operator's reconciliation + functionality. + properties: + lastHeartbeatTime: + format: date-time + type: string + lastTransitionTime: + format: date-time + type: string + message: + type: string + reason: + type: string + status: + type: string + type: + description: ConditionType is the state of the operator's reconciliation + functionality. + type: string + required: + - status + - type + type: object + type: array + observedVersion: + description: The observed version of the resource + type: string + operatorVersion: + description: The version of the resource as defined by the operator + type: string + phase: + description: Phase is the current phase of the deployment + type: string + targetVersion: + description: The desired version of the resource + type: string + type: object + required: + - spec + type: object + served: true + storage: true + subresources: {} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + operator.cdi.kubevirt.io: "" + name: cdi-operator-cluster +rules: +- apiGroups: + - rbac.authorization.k8s.io + resources: + - clusterrolebindings + - clusterroles + verbs: + - get + - list + - watch + - create + - update + - delete +- apiGroups: + - security.openshift.io + resources: + - securitycontextconstraints + verbs: + - get + - list + - watch + - update + - create +- apiGroups: + - apiextensions.k8s.io + resources: + - customresourcedefinitions + - customresourcedefinitions/status + verbs: + - get + - list + - watch + - create + - update + - delete +- apiGroups: + - cdi.kubevirt.io + - upload.cdi.kubevirt.io + resources: + - '*' + verbs: + - '*' +- apiGroups: + - admissionregistration.k8s.io + resources: + - validatingwebhookconfigurations + - mutatingwebhookconfigurations + verbs: + - create + - list + - watch +- apiGroups: + - admissionregistration.k8s.io + resourceNames: + - cdi-api-dataimportcron-validate + - cdi-api-populator-validate + - cdi-api-datavolume-validate + - cdi-api-validate + - objecttransfer-api-validate + resources: + - validatingwebhookconfigurations + verbs: + - get + - update + - delete +- apiGroups: + - admissionregistration.k8s.io + resourceNames: + - cdi-api-datavolume-mutate + resources: + - mutatingwebhookconfigurations + verbs: + - get + - update + - delete +- apiGroups: + - apiregistration.k8s.io + resources: + - apiservices + verbs: + - get + - list + - watch + - create + - update + - delete +- apiGroups: + - authorization.k8s.io + resources: + - subjectaccessreviews + verbs: + - create +- apiGroups: + - "" + resources: + - configmaps + verbs: + - get + - list + - watch +- apiGroups: + - "" + resources: + - persistentvolumeclaims + verbs: + - get +- apiGroups: + - "" + resources: + - namespaces + verbs: + - get +- apiGroups: + - snapshot.storage.k8s.io + resources: + - volumesnapshots + verbs: + - get +- apiGroups: + - cdi.kubevirt.io + resources: + - datavolumes + verbs: + - list + - get +- apiGroups: + - cdi.kubevirt.io + resources: + - datasources + verbs: + - get +- apiGroups: + - cdi.kubevirt.io + resources: + - cdis + verbs: + - get +- apiGroups: + - cdi.kubevirt.io + resources: + - cdis/finalizers + verbs: + - update +- apiGroups: + - "" + resources: + - events + verbs: + - create + - patch +- apiGroups: + - "" + resources: + - persistentvolumeclaims + verbs: + - get + - list + - watch + - create + - update + - delete + - deletecollection + - patch +- apiGroups: + - "" + resources: + - persistentvolumes + verbs: + - get + - list + - watch + - update +- apiGroups: + - "" + resources: + - persistentvolumeclaims/finalizers + - pods/finalizers + verbs: + - update +- apiGroups: + - "" + resources: + - pods + - services + verbs: + - get + - list + - watch + - create + - delete +- apiGroups: + - "" + resources: + - configmaps + verbs: + - get + - create +- apiGroups: + - storage.k8s.io + resources: + - storageclasses + - csidrivers + verbs: + - get + - list + - watch +- apiGroups: + - config.openshift.io + resources: + - proxies + verbs: + - get + - list + - watch +- apiGroups: + - cdi.kubevirt.io + resources: + - '*' + verbs: + - '*' +- apiGroups: + - snapshot.storage.k8s.io + resources: + - volumesnapshots + - volumesnapshotclasses + - volumesnapshotcontents + verbs: + - get + - list + - watch + - create + - delete +- apiGroups: + - snapshot.storage.k8s.io + resources: + - volumesnapshots + verbs: + - update + - deletecollection +- apiGroups: + - apiextensions.k8s.io + resources: + - customresourcedefinitions + verbs: + - get + - list + - watch +- apiGroups: + - scheduling.k8s.io + resources: + - priorityclasses + verbs: + - get + - list + - watch +- apiGroups: + - image.openshift.io + resources: + - imagestreams + verbs: + - get + - list + - watch +- apiGroups: + - "" + resources: + - secrets + verbs: + - create +- apiGroups: + - kubevirt.io + resources: + - virtualmachines/finalizers + verbs: + - update +- apiGroups: + - "" + resources: + - persistentvolumeclaims + verbs: + - get +- apiGroups: + - cdi.kubevirt.io + resources: + - dataimportcrons + verbs: + - get + - list + - update +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + labels: + operator.cdi.kubevirt.io: "" + name: cdi-operator +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: cdi-operator-cluster +subjects: +- kind: ServiceAccount + name: cdi-operator + namespace: cozy-kubevirt-cdi +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + labels: + operator.cdi.kubevirt.io: "" + name: cdi-operator + namespace: cozy-kubevirt-cdi +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + labels: + app.kubernetes.io/component: storage + app.kubernetes.io/managed-by: cdi-operator + cdi.kubevirt.io: "" + name: cdi-operator + namespace: cozy-kubevirt-cdi +rules: +- apiGroups: + - rbac.authorization.k8s.io + resources: + - rolebindings + - roles + verbs: + - get + - list + - watch + - create + - update + - delete +- apiGroups: + - "" + resources: + - serviceaccounts + - configmaps + - events + - secrets + - services + verbs: + - get + - list + - watch + - create + - update + - patch + - delete +- apiGroups: + - apps + resources: + - deployments + - deployments/finalizers + verbs: + - get + - list + - watch + - create + - update + - delete +- apiGroups: + - route.openshift.io + resources: + - routes + - routes/custom-host + verbs: + - get + - list + - watch + - create + - update +- apiGroups: + - config.openshift.io + resources: + - proxies + verbs: + - get + - list + - watch +- apiGroups: + - monitoring.coreos.com + resources: + - servicemonitors + - prometheusrules + verbs: + - get + - list + - watch + - create + - delete + - update + - patch +- apiGroups: + - coordination.k8s.io + resources: + - leases + verbs: + - get + - create + - update +- apiGroups: + - "" + resources: + - secrets + - configmaps + verbs: + - get + - list + - watch + - create +- apiGroups: + - "" + resources: + - configmaps + verbs: + - get + - list + - watch + - create + - update + - delete +- apiGroups: + - "" + resources: + - secrets + verbs: + - get + - list + - watch +- apiGroups: + - batch + resources: + - cronjobs + verbs: + - get + - list + - watch + - create + - update + - delete +- apiGroups: + - batch + resources: + - jobs + verbs: + - create + - delete + - list + - watch +- apiGroups: + - coordination.k8s.io + resources: + - leases + verbs: + - get + - create + - update +- apiGroups: + - networking.k8s.io + resources: + - ingresses + verbs: + - get + - list + - watch +- apiGroups: + - route.openshift.io + resources: + - routes + verbs: + - get + - list + - watch +- apiGroups: + - "" + resources: + - configmaps + verbs: + - get +- apiGroups: + - "" + resources: + - services + - endpoints + - pods + verbs: + - get + - list + - watch +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + labels: + app.kubernetes.io/component: storage + app.kubernetes.io/managed-by: cdi-operator + cdi.kubevirt.io: "" + name: cdi-operator + namespace: cozy-kubevirt-cdi +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: cdi-operator +subjects: +- kind: ServiceAccount + name: cdi-operator + namespace: cozy-kubevirt-cdi +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + name: cdi-operator + operator.cdi.kubevirt.io: "" + prometheus.cdi.kubevirt.io: "true" + name: cdi-operator + namespace: cozy-kubevirt-cdi +spec: + replicas: 1 + selector: + matchLabels: + name: cdi-operator + operator.cdi.kubevirt.io: "" + strategy: {} + template: + metadata: + labels: + name: cdi-operator + operator.cdi.kubevirt.io: "" + prometheus.cdi.kubevirt.io: "true" + spec: + containers: + - env: + - name: DEPLOY_CLUSTER_RESOURCES + value: "true" + - name: OPERATOR_VERSION + value: v1.58.0 + - name: CONTROLLER_IMAGE + value: quay.io/kubevirt/cdi-controller:v1.58.0 + - name: IMPORTER_IMAGE + value: quay.io/kubevirt/cdi-importer:v1.58.0 + - name: CLONER_IMAGE + value: quay.io/kubevirt/cdi-cloner:v1.58.0 + - name: APISERVER_IMAGE + value: quay.io/kubevirt/cdi-apiserver:v1.58.0 + - name: UPLOAD_SERVER_IMAGE + value: quay.io/kubevirt/cdi-uploadserver:v1.58.0 + - name: UPLOAD_PROXY_IMAGE + value: quay.io/kubevirt/cdi-uploadproxy:v1.58.0 + - name: VERBOSITY + value: "1" + - name: PULL_POLICY + value: IfNotPresent + - name: MONITORING_NAMESPACE + image: quay.io/kubevirt/cdi-operator:v1.58.0 + imagePullPolicy: IfNotPresent + name: cdi-operator + ports: + - containerPort: 8080 + name: metrics + protocol: TCP + resources: + requests: + cpu: 100m + memory: 150Mi + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + runAsNonRoot: true + seccompProfile: + type: RuntimeDefault + nodeSelector: + kubernetes.io/os: linux + securityContext: + runAsNonRoot: true + serviceAccountName: cdi-operator + tolerations: + - key: CriticalAddonsOnly + operator: Exists +--- \ No newline at end of file diff --git a/packages/system/kubevirt-cdi/Chart.yaml b/packages/system/kubevirt-cdi/Chart.yaml new file mode 100644 index 00000000..d525d5e8 --- /dev/null +++ b/packages/system/kubevirt-cdi/Chart.yaml @@ -0,0 +1,2 @@ +name: cozy-kubevirt-cdi +version: 1.0.0 diff --git a/packages/system/kubevirt-cdi/Makefile b/packages/system/kubevirt-cdi/Makefile new file mode 100644 index 00000000..53551e66 --- /dev/null +++ b/packages/system/kubevirt-cdi/Makefile @@ -0,0 +1,17 @@ +NAME=kubevirt-cdi +NAMESPACE=cozy-kubevirt-cdi + +show: + helm template --dry-run=server -n $(NAMESPACE) $(NAME) . + +apply: + helm upgrade -i -n $(NAMESPACE) $(NAME) . + +diff: + helm diff upgrade --allow-unreleased --normalize-manifests -n $(NAMESPACE) $(NAME) . + +update: + rm -rf templates + mkdir templates + export VERSION=$$(basename $$(curl -s -w %{redirect_url} https://github.com/kubevirt/containerized-data-importer/releases/latest)) && \ + wget https://github.com/kubevirt/containerized-data-importer/releases/download/$$VERSION/cdi-cr.yaml -O templates/cdi-cr.yaml diff --git a/packages/system/kubevirt-cdi/templates/cdi-cr.yaml b/packages/system/kubevirt-cdi/templates/cdi-cr.yaml new file mode 100644 index 00000000..76cd20da --- /dev/null +++ b/packages/system/kubevirt-cdi/templates/cdi-cr.yaml @@ -0,0 +1,18 @@ +apiVersion: cdi.kubevirt.io/v1beta1 +kind: CDI +metadata: + name: cdi +spec: + config: + featureGates: + - HonorWaitForFirstConsumer + imagePullPolicy: IfNotPresent + infra: + nodeSelector: + kubernetes.io/os: linux + tolerations: + - key: CriticalAddonsOnly + operator: Exists + workload: + nodeSelector: + kubernetes.io/os: linux diff --git a/packages/system/kubevirt-csi-node/Chart.yaml b/packages/system/kubevirt-csi-node/Chart.yaml new file mode 100644 index 00000000..bb596fa9 --- /dev/null +++ b/packages/system/kubevirt-csi-node/Chart.yaml @@ -0,0 +1,2 @@ +name: cozy-kubevirt-csi-node +version: 1.0.0 diff --git a/packages/system/kubevirt-csi-node/templates/deploy.yaml b/packages/system/kubevirt-csi-node/templates/deploy.yaml new file mode 100644 index 00000000..49b84ff5 --- /dev/null +++ b/packages/system/kubevirt-csi-node/templates/deploy.yaml @@ -0,0 +1,278 @@ +apiVersion: storage.k8s.io/v1 +kind: CSIDriver +metadata: + name: csi.kubevirt.io +spec: + attachRequired: true + podInfoOnMount: true + fsGroupPolicy: ReadWriteOnceWithFSType +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: kubevirt-csi-controller-sa + namespace: {{ .Release.Namespace }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: kubevirt-csi-controller-cr +rules: + - apiGroups: [''] + resources: ['persistentvolumes'] + verbs: ['create', 'delete', 'get', 'list', 'watch', 'update', 'patch'] + - apiGroups: [''] + resources: ['secrets'] + verbs: ['get', 'list'] + - apiGroups: [''] + resources: ['persistentvolumeclaims'] + verbs: ['get', 'list', 'watch', 'update'] + - apiGroups: [""] + resources: ["persistentvolumeclaims/status"] + verbs: ["update", "patch"] + - apiGroups: [''] + resources: ['nodes'] + verbs: ['get', 'list', 'watch'] + - apiGroups: ['storage.k8s.io'] + resources: ['volumeattachments'] + verbs: ['get', 'list', 'watch', 'update', 'patch'] + - apiGroups: ['storage.k8s.io'] + resources: ['storageclasses'] + verbs: ['get', 'list', 'watch'] + - apiGroups: ['csi.storage.k8s.io'] + resources: ['csidrivers'] + verbs: ['get', 'list', 'watch', 'update', 'create'] + - apiGroups: [''] + resources: ['events'] + verbs: ['list', 'watch', 'create', 'update', 'patch'] + - apiGroups: ["snapshot.storage.k8s.io"] + resources: ["volumesnapshotclasses"] + verbs: ["get", "list", "watch"] + - apiGroups: ["snapshot.storage.k8s.io"] + resources: ["volumesnapshotcontents"] + verbs: ["create", "get", "list", "watch", "update", "delete"] + - apiGroups: ["snapshot.storage.k8s.io"] + resources: ["volumesnapshots"] + verbs: ["get", "list", "watch", "update"] + - apiGroups: ["snapshot.storage.k8s.io"] + resources: ["volumesnapshots/status"] + verbs: ["update"] + - apiGroups: [ "storage.k8s.io" ] + resources: [ "volumeattachments/status" ] + verbs: [ "get", "list", "watch", "update", "patch" ] + - apiGroups: ["storage.k8s.io"] + resources: ["csinodes"] + verbs: ["get", "list", "watch"] + - apiGroups: ["security.openshift.io"] + resources: ["securitycontextconstraints"] + verbs: ["use"] + resourceNames: ["privileged"] +--- +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: kubevirt-csi-controller-binding +subjects: + - kind: ServiceAccount + name: kubevirt-csi-controller-sa + namespace: {{ .Release.Namespace }} +roleRef: + kind: ClusterRole + name: kubevirt-csi-controller-cr + apiGroup: rbac.authorization.k8s.io +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: kubevirt-csi-node-sa + namespace: {{ .Release.Namespace }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: kubevirt-csi-node-cr +rules: + - apiGroups: [""] + resources: ["persistentvolumes"] + verbs: ["get", "list", "watch", "update", "create", "delete"] + - apiGroups: [""] + resources: ["persistentvolumeclaims"] + verbs: ["get", "list", "watch", "update"] + - apiGroups: ["storage.k8s.io"] + resources: ["storageclasses"] + verbs: ["get", "list", "watch"] + - apiGroups: [""] + resources: ["nodes"] + verbs: ["get", "list", "watch", "update", "patch"] + - apiGroups: ["csi.storage.k8s.io"] + resources: ["csinodeinfos"] + verbs: ["get", "list", "watch"] + - apiGroups: ["storage.k8s.io"] + resources: ["csinodes"] + verbs: ["get", "list", "watch"] + - apiGroups: ["storage.k8s.io"] + resources: ["volumeattachments"] + verbs: ["get", "list", "watch", "update"] + - apiGroups: ["storage.k8s.io"] + resources: ["volumeattachments/status"] + verbs: ["get", "list", "watch", "update", "patch"] + - apiGroups: [""] + resources: ["events"] + verbs: ["list", "watch", "create", "update", "patch"] + - apiGroups: ["security.openshift.io"] + resources: ["securitycontextconstraints"] + verbs: ["use"] + resourceNames: ["privileged"] +--- +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: kubevirt-csi-node-binding +subjects: + - kind: ServiceAccount + name: kubevirt-csi-node-sa + namespace: {{ .Release.Namespace }} +roleRef: + kind: ClusterRole + name: kubevirt-csi-node-cr + apiGroup: rbac.authorization.k8s.io +--- +kind: DaemonSet +apiVersion: apps/v1 +metadata: + name: kubevirt-csi-node + namespace: {{ .Release.Namespace }} +spec: + selector: + matchLabels: + app: {{ .Release.Namespace }} + updateStrategy: + type: RollingUpdate + template: + metadata: + labels: + app: {{ .Release.Namespace }} + spec: + serviceAccount: kubevirt-csi-node-sa + priorityClassName: system-node-critical + tolerations: + - operator: Exists + containers: + - name: csi-driver + securityContext: + privileged: true + allowPrivilegeEscalation: true + imagePullPolicy: Always + image: ghcr.io/kvaps/test:kubevirt-csi-driver + args: + - "--endpoint=unix:/csi/csi.sock" + - "--node-name=$(KUBE_NODE_NAME)" + - "--v=5" + env: + - name: KUBE_NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + volumeMounts: + - name: kubelet-dir + mountPath: /var/lib/kubelet + mountPropagation: "Bidirectional" + - name: plugin-dir + mountPath: /csi + - name: device-dir + mountPath: /dev + - name: udev + mountPath: /run/udev + ports: + - name: healthz + containerPort: 10300 + protocol: TCP + livenessProbe: + httpGet: + path: /healthz + port: healthz + initialDelaySeconds: 10 + timeoutSeconds: 3 + periodSeconds: 10 + failureThreshold: 5 + resources: + requests: + memory: 50Mi + cpu: 10m + - name: csi-node-driver-registrar + image: quay.io/openshift/origin-csi-node-driver-registrar:latest + args: + - "--csi-address=$(ADDRESS)" + - "--kubelet-registration-path=$(DRIVER_REG_SOCK_PATH)" + - "--v=5" + lifecycle: + preStop: + exec: + command: ["/bin/sh", "-c", "rm -rf /registration/csi.kubevirt.io-reg.sock /csi/csi.sock"] + env: + - name: ADDRESS + value: /csi/csi.sock + - name: DRIVER_REG_SOCK_PATH + value: /var/lib/kubelet/plugins/csi.kubevirt.io/csi.sock + volumeMounts: + - name: plugin-dir + mountPath: /csi + - name: registration-dir + mountPath: /registration + resources: + requests: + memory: 20Mi + cpu: 5m + - name: csi-liveness-probe + image: quay.io/openshift/origin-csi-livenessprobe:latest + args: + - "--csi-address=/csi/csi.sock" + - "--probe-timeout=3s" + - "--health-port=10300" + volumeMounts: + - name: plugin-dir + mountPath: /csi + resources: + requests: + memory: 20Mi + cpu: 5m + volumes: + - name: kubelet-dir + hostPath: + path: /var/lib/kubelet + type: Directory + - name: plugin-dir + hostPath: + path: /var/lib/kubelet/plugins/csi.kubevirt.io/ + type: DirectoryOrCreate + - name: registration-dir + hostPath: + path: /var/lib/kubelet/plugins_registry/ + type: Directory + - name: device-dir + hostPath: + path: /dev + type: Directory + - name: udev + hostPath: + path: /run/udev +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: driver-config + namespace: {{ .Release.Namespace }} +data: + infraClusterNamespace: + infraClusterLabels: csi-driver/cluster=tenant +--- +apiVersion: storage.k8s.io/v1 +kind: StorageClass +metadata: + name: kubevirt + annotations: + storageclass.kubernetes.io/is-default-class: "true" +provisioner: csi.kubevirt.io +parameters: + infraStorageClassName: replicated + bus: scsi diff --git a/packages/system/kubevirt-operator/Chart.yaml b/packages/system/kubevirt-operator/Chart.yaml new file mode 100644 index 00000000..2bfbb7e6 --- /dev/null +++ b/packages/system/kubevirt-operator/Chart.yaml @@ -0,0 +1,2 @@ +name: cozy-kubevirt-operator +version: 1.0.0 diff --git a/packages/system/kubevirt-operator/Makefile b/packages/system/kubevirt-operator/Makefile new file mode 100644 index 00000000..b4545502 --- /dev/null +++ b/packages/system/kubevirt-operator/Makefile @@ -0,0 +1,19 @@ +NAME=kubevirt-operator +NAMESPACE=cozy-kubevirt + +show: + helm template --dry-run=server -n $(NAMESPACE) $(NAME) . + +apply: + helm upgrade -i -n $(NAMESPACE) $(NAME) . + +diff: + helm diff upgrade --allow-unreleased --normalize-manifests -n $(NAMESPACE) $(NAME) . + +update: + rm -rf templates + mkdir templates + export RELEASE=$$(curl https://storage.googleapis.com/kubevirt-prow/release/kubevirt/kubevirt/stable.txt) && \ + wget https://github.com/kubevirt/kubevirt/releases/download/$${RELEASE}/kubevirt-operator.yaml -O templates/kubevirt-operator.yaml && \ + sed -i 's/namespace: kubevirt/namespace: cozy-kubevirt/g' templates/kubevirt-operator.yaml + awk -i inplace -v RS="---" '!/kind: Namespace/{printf "%s", $$0 RS}' templates/kubevirt-operator.yaml diff --git a/packages/system/kubevirt-operator/templates/kubevirt-operator.yaml b/packages/system/kubevirt-operator/templates/kubevirt-operator.yaml new file mode 100644 index 00000000..236cd3de --- /dev/null +++ b/packages/system/kubevirt-operator/templates/kubevirt-operator.yaml @@ -0,0 +1,7501 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + labels: + operator.kubevirt.io: "" + name: kubevirts.kubevirt.io +spec: + group: kubevirt.io + names: + categories: + - all + kind: KubeVirt + plural: kubevirts + shortNames: + - kv + - kvs + singular: kubevirt + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + - jsonPath: .status.phase + name: Phase + type: string + name: v1 + schema: + openAPIV3Schema: + description: KubeVirt represents the object deploying all KubeVirt resources + 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: + properties: + certificateRotateStrategy: + properties: + selfSigned: + properties: + ca: + description: CA configuration CA certs are kept in the CA + bundle as long as they are valid + properties: + duration: + description: The requested 'duration' (i.e. lifetime) + of the Certificate. + type: string + renewBefore: + description: The amount of time before the currently issued + certificate's "notAfter" time that we will begin to + attempt to renew the certificate. + type: string + type: object + caOverlapInterval: + description: Deprecated. Use CA.Duration and CA.RenewBefore + instead + type: string + caRotateInterval: + description: Deprecated. Use CA.Duration instead + type: string + certRotateInterval: + description: Deprecated. Use Server.Duration instead + type: string + server: + description: Server configuration Certs are rotated and discarded + properties: + duration: + description: The requested 'duration' (i.e. lifetime) + of the Certificate. + type: string + renewBefore: + description: The amount of time before the currently issued + certificate's "notAfter" time that we will begin to + attempt to renew the certificate. + type: string + type: object + type: object + type: object + configuration: + description: holds kubevirt configurations. same as the virt-configMap + properties: + additionalGuestMemoryOverheadRatio: + description: AdditionalGuestMemoryOverheadRatio can be used to + increase the virtualization infrastructure overhead. This is + useful, since the calculation of this overhead is not accurate + and cannot be entirely known in advance. The ratio that is being + set determines by which factor to increase the overhead calculated + by Kubevirt. A higher ratio means that the VMs would be less + compromised by node pressures, but would mean that fewer VMs + could be scheduled to a node. If not set, the default is 1. + type: string + apiConfiguration: + description: ReloadableComponentConfiguration holds all generic + k8s configuration options which can be reloaded by components + without requiring a restart. + properties: + restClient: + description: RestClient can be used to tune certain aspects + of the k8s client in use. + properties: + rateLimiter: + description: RateLimiter allows selecting and configuring + different rate limiters for the k8s client. + properties: + tokenBucketRateLimiter: + properties: + burst: + description: Maximum burst for throttle. If it's + zero, the component default will be used + type: integer + qps: + description: QPS indicates the maximum QPS to + the apiserver from this client. If it's zero, + the component default will be used + type: number + required: + - burst + - qps + type: object + type: object + type: object + type: object + architectureConfiguration: + properties: + amd64: + properties: + emulatedMachines: + items: + type: string + type: array + x-kubernetes-list-type: atomic + machineType: + type: string + ovmfPath: + type: string + type: object + arm64: + properties: + emulatedMachines: + items: + type: string + type: array + x-kubernetes-list-type: atomic + machineType: + type: string + ovmfPath: + type: string + type: object + defaultArchitecture: + type: string + ppc64le: + properties: + emulatedMachines: + items: + type: string + type: array + x-kubernetes-list-type: atomic + machineType: + type: string + ovmfPath: + type: string + type: object + type: object + autoCPULimitNamespaceLabelSelector: + description: When set, AutoCPULimitNamespaceLabelSelector will + set a CPU limit on virt-launcher for VMIs running inside namespaces + that match the label selector. The CPU limit will equal the + number of requested vCPUs. This setting does not apply to VMIs + with dedicated CPUs. + 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 + required: + - key + - operator + type: object + type: array + 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 + controllerConfiguration: + description: ReloadableComponentConfiguration holds all generic + k8s configuration options which can be reloaded by components + without requiring a restart. + properties: + restClient: + description: RestClient can be used to tune certain aspects + of the k8s client in use. + properties: + rateLimiter: + description: RateLimiter allows selecting and configuring + different rate limiters for the k8s client. + properties: + tokenBucketRateLimiter: + properties: + burst: + description: Maximum burst for throttle. If it's + zero, the component default will be used + type: integer + qps: + description: QPS indicates the maximum QPS to + the apiserver from this client. If it's zero, + the component default will be used + type: number + required: + - burst + - qps + type: object + type: object + type: object + type: object + cpuModel: + type: string + cpuRequest: + 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 + defaultRuntimeClass: + type: string + developerConfiguration: + description: DeveloperConfiguration holds developer options + properties: + cpuAllocationRatio: + description: 'For each requested virtual CPU, CPUAllocationRatio + defines how much physical CPU to request per VMI from the + hosting node. The value is in fraction of a CPU thread (or + core on non-hyperthreaded nodes). For example, a value of + 1 means 1 physical CPU thread per VMI CPU thread. A value + of 100 would be 1% of a physical thread allocated for each + requested VMI thread. This option has no effect on VMIs + that request dedicated CPUs. More information at: https://kubevirt.io/user-guide/operations/node_overcommit/#node-cpu-allocation-ratio + Defaults to 10' + type: integer + diskVerification: + description: DiskVerification holds container disks verification + limits + properties: + memoryLimit: + 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 + required: + - memoryLimit + type: object + featureGates: + description: FeatureGates is the list of experimental features + to enable. Defaults to none + items: + type: string + type: array + logVerbosity: + description: LogVerbosity sets log verbosity level of various + components + properties: + nodeVerbosity: + additionalProperties: + type: integer + description: NodeVerbosity represents a map of nodes with + a specific verbosity level + type: object + virtAPI: + type: integer + virtController: + type: integer + virtHandler: + type: integer + virtLauncher: + type: integer + virtOperator: + type: integer + type: object + memoryOvercommit: + description: MemoryOvercommit is the percentage of memory + we want to give VMIs compared to the amount given to its + parent pod (virt-launcher). For example, a value of 102 + means the VMI will "see" 2% more memory than its parent + pod. Values under 100 are effectively "undercommits". Overcommits + can lead to memory exhaustion, which in turn can lead to + crashes. Use carefully. Defaults to 100 + type: integer + minimumClusterTSCFrequency: + description: Allow overriding the automatically determined + minimum TSC frequency of the cluster and fixate the minimum + to this frequency. + format: int64 + type: integer + minimumReservePVCBytes: + description: MinimumReservePVCBytes is the amount of space, + in bytes, to leave unused on disks. Defaults to 131072 (128KiB) + format: int64 + type: integer + nodeSelectors: + additionalProperties: + type: string + description: NodeSelectors allows restricting VMI creation + to nodes that match a set of labels. Defaults to none + type: object + pvcTolerateLessSpaceUpToPercent: + description: LessPVCSpaceToleration determines how much smaller, + in percentage, disk PVCs are allowed to be compared to the + requested size (to account for various overheads). Defaults + to 10 + type: integer + useEmulation: + description: UseEmulation can be set to true to allow fallback + to software emulation in case hardware-assisted emulation + is not available. Defaults to false + type: boolean + type: object + emulatedMachines: + items: + type: string + type: array + evictionStrategy: + description: EvictionStrategy defines at the cluster level if + the VirtualMachineInstance should be migrated instead of shut-off + in case of a node drain. If the VirtualMachineInstance specific + field is set it overrides the cluster level one. + type: string + handlerConfiguration: + description: ReloadableComponentConfiguration holds all generic + k8s configuration options which can be reloaded by components + without requiring a restart. + properties: + restClient: + description: RestClient can be used to tune certain aspects + of the k8s client in use. + properties: + rateLimiter: + description: RateLimiter allows selecting and configuring + different rate limiters for the k8s client. + properties: + tokenBucketRateLimiter: + properties: + burst: + description: Maximum burst for throttle. If it's + zero, the component default will be used + type: integer + qps: + description: QPS indicates the maximum QPS to + the apiserver from this client. If it's zero, + the component default will be used + type: number + required: + - burst + - qps + type: object + type: object + type: object + type: object + imagePullPolicy: + description: PullPolicy describes a policy for if/when to pull + a container image + type: string + ksmConfiguration: + description: KSMConfiguration holds the information regarding + the enabling the KSM in the nodes (if available). + properties: + nodeLabelSelector: + description: NodeLabelSelector is a selector that filters + in which nodes the KSM will be enabled. Empty NodeLabelSelector + will enable ksm for every node. + 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 + required: + - key + - operator + type: object + type: array + 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 + type: object + liveUpdateConfiguration: + description: LiveUpdateConfiguration holds defaults for live update + features + properties: + maxCpuSockets: + description: MaxCpuSockets holds the maximum amount of sockets + that can be hotplugged + format: int32 + type: integer + maxGuest: + anyOf: + - type: integer + - type: string + description: MaxGuest defines the maximum amount memory that + can be allocated to the guest using hotplug. + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + maxHotplugRatio: + description: 'MaxHotplugRatio is the ratio used to define + the max amount of a hotplug resource that can be made available + to a VM when the specific Max* setting is not defined (MaxCpuSockets, + MaxGuest) Example: VM is configured with 512Mi of guest + memory, if MaxGuest is not defined and MaxHotplugRatio is + 2 then MaxGuest = 1Gi defaults to 4' + format: int32 + type: integer + type: object + machineType: + description: Deprecated. Use architectureConfiguration instead. + type: string + mediatedDevicesConfiguration: + description: MediatedDevicesConfiguration holds information about + MDEV types to be defined, if available + properties: + mediatedDeviceTypes: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mediatedDevicesTypes: + description: Deprecated. Use mediatedDeviceTypes instead. + items: + type: string + type: array + x-kubernetes-list-type: atomic + nodeMediatedDeviceTypes: + items: + description: NodeMediatedDeviceTypesConfig holds information + about MDEV types to be defined in a specific node that + matches the NodeSelector field. + properties: + mediatedDeviceTypes: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mediatedDevicesTypes: + description: Deprecated. Use mediatedDeviceTypes instead. + items: + type: string + type: array + x-kubernetes-list-type: atomic + nodeSelector: + additionalProperties: + type: string + description: 'NodeSelector is a selector which must + be true for the vmi to fit on a node. Selector which + must match a node''s labels for the vmi to be scheduled + on that node. More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/' + type: object + required: + - nodeSelector + type: object + type: array + x-kubernetes-list-type: atomic + type: object + memBalloonStatsPeriod: + format: int32 + type: integer + migrations: + description: MigrationConfiguration holds migration options. Can + be overridden for specific groups of VMs though migration policies. + Visit https://kubevirt.io/user-guide/operations/migration_policies/ + for more information. + properties: + allowAutoConverge: + description: AllowAutoConverge allows the platform to compromise + performance/availability of VMIs to guarantee successful + VMI live migrations. Defaults to false + type: boolean + allowPostCopy: + description: AllowPostCopy enables post-copy live migrations. + Such migrations allow even the busiest VMIs to successfully + live-migrate. However, events like a network failure can + cause a VMI crash. If set to true, migrations will still + start in pre-copy, but switch to post-copy when CompletionTimeoutPerGiB + triggers. Defaults to false + type: boolean + bandwidthPerMigration: + anyOf: + - type: integer + - type: string + description: BandwidthPerMigration limits the amount of network + bandwidth live migrations are allowed to use. The value + is in quantity per second. Defaults to 0 (no limit) + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + completionTimeoutPerGiB: + description: CompletionTimeoutPerGiB is the maximum number + of seconds per GiB a migration is allowed to take. If a + live-migration takes longer to migrate than this value multiplied + by the size of the VMI, the migration will be cancelled, + unless AllowPostCopy is true. Defaults to 800 + format: int64 + type: integer + disableTLS: + description: When set to true, DisableTLS will disable the + additional layer of live migration encryption provided by + KubeVirt. This is usually a bad idea. Defaults to false + type: boolean + matchSELinuxLevelOnMigration: + description: By default, the SELinux level of target virt-launcher + pods is forced to the level of the source virt-launcher. + When set to true, MatchSELinuxLevelOnMigration lets the + CRI auto-assign a random level to the target. That will + ensure the target virt-launcher doesn't share categories + with another pod on the node. However, migrations will fail + when using RWX volumes that don't automatically deal with + SELinux levels. + type: boolean + network: + description: Network is the name of the CNI network to use + for live migrations. By default, migrations go through the + pod network. + type: string + nodeDrainTaintKey: + description: 'NodeDrainTaintKey defines the taint key that + indicates a node should be drained. Note: this option relies + on the deprecated node taint feature. Default: kubevirt.io/drain' + type: string + parallelMigrationsPerCluster: + description: ParallelMigrationsPerCluster is the total number + of concurrent live migrations allowed cluster-wide. Defaults + to 5 + format: int32 + type: integer + parallelOutboundMigrationsPerNode: + description: ParallelOutboundMigrationsPerNode is the maximum + number of concurrent outgoing live migrations allowed per + node. Defaults to 2 + format: int32 + type: integer + progressTimeout: + description: ProgressTimeout is the maximum number of seconds + a live migration is allowed to make no progress. Hitting + this timeout means a migration transferred 0 data for that + many seconds. The migration is then considered stuck and + therefore cancelled. Defaults to 150 + format: int64 + type: integer + unsafeMigrationOverride: + description: UnsafeMigrationOverride allows live migrations + to occur even if the compatibility check indicates the migration + will be unsafe to the guest. Defaults to false + type: boolean + type: object + minCPUModel: + type: string + network: + description: NetworkConfiguration holds network options + properties: + binding: + additionalProperties: + properties: + networkAttachmentDefinition: + description: 'NetworkAttachmentDefinition references + to a NetworkAttachmentDefinition CR object. Format: + , /. If namespace is not specified, + VMI namespace is assumed. version: 1alphav1' + type: string + sidecarImage: + description: 'SidecarImage references a container image + that runs in the virt-launcher pod. The sidecar handles + (libvirt) domain configuration and optional services. + version: 1alphav1' + type: string + type: object + type: object + defaultNetworkInterface: + type: string + permitBridgeInterfaceOnPodNetwork: + type: boolean + permitSlirpInterface: + type: boolean + type: object + obsoleteCPUModels: + additionalProperties: + type: boolean + type: object + ovmfPath: + type: string + permittedHostDevices: + description: PermittedHostDevices holds information about devices + allowed for passthrough + properties: + mediatedDevices: + items: + description: MediatedHostDevice represents a host mediated + device allowed for passthrough + properties: + externalResourceProvider: + type: boolean + mdevNameSelector: + type: string + resourceName: + type: string + required: + - mdevNameSelector + - resourceName + type: object + type: array + x-kubernetes-list-type: atomic + pciHostDevices: + items: + description: PciHostDevice represents a host PCI device + allowed for passthrough + properties: + externalResourceProvider: + description: If true, KubeVirt will leave the allocation + and monitoring to an external device plugin + type: boolean + pciVendorSelector: + description: The vendor_id:product_id tuple of the PCI + device + type: string + resourceName: + description: The name of the resource that is representing + the device. Exposed by a device plugin and requested + by VMs. Typically of the form vendor.com/product_name + type: string + required: + - pciVendorSelector + - resourceName + type: object + type: array + x-kubernetes-list-type: atomic + usb: + items: + properties: + externalResourceProvider: + description: If true, KubeVirt will leave the allocation + and monitoring to an external device plugin + type: boolean + resourceName: + description: 'Identifies the list of USB host devices. + e.g: kubevirt.io/storage, kubevirt.io/bootable-usb, + etc' + type: string + selectors: + items: + properties: + product: + type: string + vendor: + type: string + required: + - product + - vendor + type: object + type: array + x-kubernetes-list-type: atomic + required: + - resourceName + type: object + type: array + x-kubernetes-list-type: atomic + type: object + seccompConfiguration: + description: SeccompConfiguration holds Seccomp configuration + for Kubevirt components + properties: + virtualMachineInstanceProfile: + description: VirtualMachineInstanceProfile defines what profile + should be used with virt-launcher. Defaults to none + properties: + customProfile: + description: CustomProfile allows to request arbitrary + profile for virt-launcher + properties: + localhostProfile: + type: string + runtimeDefaultProfile: + type: boolean + type: object + type: object + type: object + selinuxLauncherType: + type: string + smbios: + properties: + family: + type: string + manufacturer: + type: string + product: + type: string + sku: + type: string + version: + type: string + type: object + supportContainerResources: + description: SupportContainerResources specifies the resource + requirements for various types of supporting containers such + as container disks/virtiofs/sidecars and hotplug attachment + pods. If omitted a sensible default will be supplied. + items: + description: SupportContainerResources are used to specify the + cpu/memory request and limits for the containers that support + various features of Virtual Machines. These containers are + usually idle and don't require a lot of memory or cpu. + properties: + resources: + description: ResourceRequirements describes the compute + resource requirements. + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. \n 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 + 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. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + type: + type: string + required: + - resources + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + supportedGuestAgentVersions: + description: deprecated + items: + type: string + type: array + tlsConfiguration: + description: TLSConfiguration holds TLS options + properties: + ciphers: + items: + type: string + type: array + x-kubernetes-list-type: set + minTLSVersion: + description: "MinTLSVersion is a way to specify the minimum + protocol version that is acceptable for TLS connections. + Protocol versions are based on the following most common + TLS configurations: \n https://ssl-config.mozilla.org/ + \n Note that SSLv3.0 is not a supported protocol version + due to well known vulnerabilities such as POODLE: https://en.wikipedia.org/wiki/POODLE" + enum: + - VersionTLS10 + - VersionTLS11 + - VersionTLS12 + - VersionTLS13 + type: string + type: object + virtualMachineInstancesPerNode: + type: integer + virtualMachineOptions: + description: VirtualMachineOptions holds the cluster level information + regarding the virtual machine. + properties: + disableFreePageReporting: + description: DisableFreePageReporting disable the free page + reporting of memory balloon device https://libvirt.org/formatdomain.html#memory-balloon-device. + This will have effect only if AutoattachMemBalloon is not + false and the vmi is not requesting any high performance + feature (dedicatedCPU/realtime/hugePages), in which free + page reporting is always disabled. + type: object + disableSerialConsoleLog: + description: DisableSerialConsoleLog disables logging the + auto-attached default serial console. If not set, serial + console logs will be written to a file and then streamed + from a container named 'guest-console-log'. The value can + be individually overridden for each VM, not relevant if + AutoattachSerialConsole is disabled. + type: object + type: object + vmStateStorageClass: + description: VMStateStorageClass is the name of the storage class + to use for the PVCs created to preserve VM state, like TPM. + The storage class must support RWX in filesystem mode. + type: string + webhookConfiguration: + description: ReloadableComponentConfiguration holds all generic + k8s configuration options which can be reloaded by components + without requiring a restart. + properties: + restClient: + description: RestClient can be used to tune certain aspects + of the k8s client in use. + properties: + rateLimiter: + description: RateLimiter allows selecting and configuring + different rate limiters for the k8s client. + properties: + tokenBucketRateLimiter: + properties: + burst: + description: Maximum burst for throttle. If it's + zero, the component default will be used + type: integer + qps: + description: QPS indicates the maximum QPS to + the apiserver from this client. If it's zero, + the component default will be used + type: number + required: + - burst + - qps + type: object + type: object + type: object + type: object + type: object + customizeComponents: + properties: + flags: + description: Configure the value used for deployment and daemonset + resources + properties: + api: + additionalProperties: + type: string + type: object + controller: + additionalProperties: + type: string + type: object + handler: + additionalProperties: + type: string + type: object + type: object + patches: + items: + properties: + patch: + type: string + resourceName: + minLength: 1 + type: string + resourceType: + minLength: 1 + type: string + type: + type: string + required: + - patch + - resourceName + - resourceType + - type + type: object + type: array + x-kubernetes-list-type: atomic + type: object + imagePullPolicy: + description: The ImagePullPolicy to use. + type: string + imagePullSecrets: + description: The imagePullSecrets to pull the container images from + Defaults to none + items: + description: LocalObjectReference contains enough information to + let you locate the referenced object inside the same namespace. + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + type: array + x-kubernetes-list-type: atomic + imageRegistry: + description: The image registry to pull the container images from + Defaults to the same registry the operator's container image is + pulled from. + type: string + imageTag: + description: The image tag to use for the continer images installed. + Defaults to the same tag as the operator's container image. + type: string + infra: + description: selectors and tolerations that should apply to KubeVirt + infrastructure components + properties: + nodePlacement: + description: nodePlacement describes scheduling configuration + for specific KubeVirt components + properties: + affinity: + description: affinity enables pod affinity/anti-affinity placement + expanding the types of constraints that can be expressed + with nodeSelector. affinity is going to be applied to the + relevant kind of pods in parallel with nodeSelector See + https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#affinity-and-anti-affinity + properties: + nodeAffinity: + description: Describes node affinity scheduling rules + for the pod. + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule + pods to nodes that satisfy the affinity expressions + specified by this field, but it may choose a node + that violates one or more of the expressions. The + node that is most preferred is the one with the + greatest sum of weights, i.e. for each node that + meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, + etc.), compute a sum by iterating through the elements + of this field and adding "weight" to the sum if + the node matches the corresponding matchExpressions; + the node(s) with the highest sum are the most preferred. + items: + description: An empty preferred scheduling term + matches all objects with implicit weight 0 (i.e. + it's a no-op). A null preferred scheduling term + matches no objects (i.e. is also a no-op). + properties: + preference: + description: A node selector term, associated + with the corresponding weight. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: The label key that the + selector applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: 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. + If the operator is Gt or Lt, the + values array must have a single + element, which will be interpreted + as an integer. This array is replaced + during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: The label key that the + selector applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: 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. + If the operator is Gt or Lt, the + values array must have a single + element, which will be interpreted + as an integer. This array is replaced + during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + weight: + description: Weight associated with matching + the corresponding nodeSelectorTerm, in the + range 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified + by this field are not met at scheduling time, the + pod will not be scheduled onto the node. If the + affinity requirements specified by this field cease + to be met at some point during pod execution (e.g. + due to an update), the system may or may not try + to eventually evict the pod from its node. + properties: + nodeSelectorTerms: + description: Required. A list of node selector + terms. The terms are ORed. + items: + description: A null or empty node selector term + matches no objects. The requirements of them + are ANDed. The TopologySelectorTerm type implements + a subset of the NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: The label key that the + selector applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: 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. + If the operator is Gt or Lt, the + values array must have a single + element, which will be interpreted + as an integer. This array is replaced + during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: The label key that the + selector applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: 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. + If the operator is Gt or Lt, the + values array must have a single + element, which will be interpreted + as an integer. This array is replaced + during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + type: array + required: + - nodeSelectorTerms + type: object + type: object + podAffinity: + description: Describes pod affinity scheduling rules (e.g. + co-locate this pod in the same node, zone, etc. as some + other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule + pods to nodes that satisfy the affinity expressions + specified by this field, but it may choose a node + that violates one or more of the expressions. The + node that is most preferred is the one with the + greatest sum of weights, i.e. for each node that + meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, + etc.), compute a sum by iterating through the elements + of this field and adding "weight" to the sum if + the node has pods which matches the corresponding + podAffinityTerm; the node(s) with the highest sum + are the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, + associated with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of + resources, in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set + of namespaces that the term applies to. + The term is applied to the union of the + namespaces selected by this field and + the ones listed in the namespaces field. + null selector and null or empty namespaces + list means "this pod's namespace". An + empty selector ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static + list of namespace names that the term + applies to. The term is applied to the + union of the namespaces listed in this + field and the ones selected by namespaceSelector. + null or empty namespaces list and null + namespaceSelector means "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located + (affinity) or not co-located (anti-affinity) + with the pods matching the labelSelector + in the specified namespaces, where co-located + is defined as running on a node whose + value of the label with key topologyKey + matches that of any node on which any + of the selected pods is running. Empty + topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching + the corresponding podAffinityTerm, in the + range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified + by this field are not met at scheduling time, the + pod will not be scheduled onto the node. If the + affinity requirements specified by this field cease + to be met at some point during pod execution (e.g. + due to a pod label update), the system may or may + not try to eventually evict the pod from its node. + When there are multiple elements, the lists of nodes + corresponding to each podAffinityTerm are intersected, + i.e. all terms must be satisfied. + items: + description: Defines a set of pods (namely those + matching the labelSelector relative to the given + namespace(s)) that this pod should be co-located + (affinity) or not co-located (anti-affinity) with, + where co-located is defined as running on a node + whose value of the label with key + matches that of any node on which a pod of the + set of pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by + this field and the ones listed in the namespaces + field. null selector and null or empty namespaces + list means "this pod's namespace". An empty + selector ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. + The term is applied to the union of the namespaces + listed in this field and the ones selected + by namespaceSelector. null or empty namespaces + list and null namespaceSelector means "this + pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the + pods matching the labelSelector in the specified + namespaces, where co-located is defined as + running on a node whose value of the label + with key topologyKey matches that of any node + on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + podAntiAffinity: + description: Describes pod anti-affinity scheduling rules + (e.g. avoid putting this pod in the same node, zone, + etc. as some other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule + pods to nodes that satisfy the anti-affinity expressions + specified by this field, but it may choose a node + that violates one or more of the expressions. The + node that is most preferred is the one with the + greatest sum of weights, i.e. for each node that + meets all of the scheduling requirements (resource + request, requiredDuringScheduling anti-affinity + expressions, etc.), compute a sum by iterating through + the elements of this field and adding "weight" to + the sum if the node has pods which matches the corresponding + podAffinityTerm; the node(s) with the highest sum + are the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, + associated with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of + resources, in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set + of namespaces that the term applies to. + The term is applied to the union of the + namespaces selected by this field and + the ones listed in the namespaces field. + null selector and null or empty namespaces + list means "this pod's namespace". An + empty selector ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static + list of namespace names that the term + applies to. The term is applied to the + union of the namespaces listed in this + field and the ones selected by namespaceSelector. + null or empty namespaces list and null + namespaceSelector means "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located + (affinity) or not co-located (anti-affinity) + with the pods matching the labelSelector + in the specified namespaces, where co-located + is defined as running on a node whose + value of the label with key topologyKey + matches that of any node on which any + of the selected pods is running. Empty + topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching + the corresponding podAffinityTerm, in the + range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the anti-affinity requirements specified + by this field are not met at scheduling time, the + pod will not be scheduled onto the node. If the + anti-affinity requirements specified by this field + cease to be met at some point during pod execution + (e.g. due to a pod label update), the system may + or may not try to eventually evict the pod from + its node. When there are multiple elements, the + lists of nodes corresponding to each podAffinityTerm + are intersected, i.e. all terms must be satisfied. + items: + description: Defines a set of pods (namely those + matching the labelSelector relative to the given + namespace(s)) that this pod should be co-located + (affinity) or not co-located (anti-affinity) with, + where co-located is defined as running on a node + whose value of the label with key + matches that of any node on which a pod of the + set of pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by + this field and the ones listed in the namespaces + field. null selector and null or empty namespaces + list means "this pod's namespace". An empty + selector ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. + The term is applied to the union of the namespaces + listed in this field and the ones selected + by namespaceSelector. null or empty namespaces + list and null namespaceSelector means "this + pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the + pods matching the labelSelector in the specified + namespaces, where co-located is defined as + running on a node whose value of the label + with key topologyKey matches that of any node + on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + type: object + nodeSelector: + additionalProperties: + type: string + description: 'nodeSelector is the node selector applied to + the relevant kind of pods It specifies a map of key-value + pairs: for the pod to be eligible to run on a node, the + node must have each of the indicated key-value pairs as + labels (it can have additional labels as well). See https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#nodeselector' + type: object + tolerations: + description: tolerations is a list of tolerations applied + to the relevant kind of pods See https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ + for more info. These are additional tolerations other than + default ones. + 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 + type: object + replicas: + description: 'replicas indicates how many replicas should be created + for each KubeVirt infrastructure component (like virt-api or + virt-controller). Defaults to 2. WARNING: this is an advanced + feature that prevents auto-scaling for core kubevirt components. + Please use with caution!' + type: integer + type: object + monitorAccount: + description: The name of the Prometheus service account that needs + read-access to KubeVirt endpoints Defaults to prometheus-k8s + type: string + monitorNamespace: + description: The namespace Prometheus is deployed in Defaults to openshift-monitor + type: string + productComponent: + description: Designate the apps.kubevirt.io/component label for KubeVirt + components. Useful if KubeVirt is included as part of a product. + If ProductComponent is not specified, the component label default + value is kubevirt. + type: string + productName: + description: Designate the apps.kubevirt.io/part-of label for KubeVirt + components. Useful if KubeVirt is included as part of a product. + If ProductName is not specified, the part-of label will be omitted. + type: string + productVersion: + description: Designate the apps.kubevirt.io/version label for KubeVirt + components. Useful if KubeVirt is included as part of a product. + If ProductVersion is not specified, KubeVirt's version will be used. + type: string + serviceMonitorNamespace: + description: The namespace the service monitor will be deployed When + ServiceMonitorNamespace is set, then we'll install the service monitor + object in that namespace otherwise we will use the monitoring namespace. + type: string + uninstallStrategy: + description: Specifies if kubevirt can be deleted if workloads are + still present. This is mainly a precaution to avoid accidental data + loss + type: string + workloadUpdateStrategy: + description: WorkloadUpdateStrategy defines at the cluster level how + to handle automated workload updates + properties: + batchEvictionInterval: + description: "BatchEvictionInterval Represents the interval to + wait before issuing the next batch of shutdowns \n Defaults + to 1 minute" + type: string + batchEvictionSize: + description: "BatchEvictionSize Represents the number of VMIs + that can be forced updated per the BatchShutdownInteral interval + \n Defaults to 10" + type: integer + workloadUpdateMethods: + description: "WorkloadUpdateMethods defines the methods that can + be used to disrupt workloads during automated workload updates. + When multiple methods are present, the least disruptive method + takes precedence over more disruptive methods. For example if + both LiveMigrate and Shutdown methods are listed, only VMs which + are not live migratable will be restarted/shutdown \n An empty + list defaults to no automated workload updating" + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + workloads: + description: selectors and tolerations that should apply to KubeVirt + workloads + properties: + nodePlacement: + description: nodePlacement describes scheduling configuration + for specific KubeVirt components + properties: + affinity: + description: affinity enables pod affinity/anti-affinity placement + expanding the types of constraints that can be expressed + with nodeSelector. affinity is going to be applied to the + relevant kind of pods in parallel with nodeSelector See + https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#affinity-and-anti-affinity + properties: + nodeAffinity: + description: Describes node affinity scheduling rules + for the pod. + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule + pods to nodes that satisfy the affinity expressions + specified by this field, but it may choose a node + that violates one or more of the expressions. The + node that is most preferred is the one with the + greatest sum of weights, i.e. for each node that + meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, + etc.), compute a sum by iterating through the elements + of this field and adding "weight" to the sum if + the node matches the corresponding matchExpressions; + the node(s) with the highest sum are the most preferred. + items: + description: An empty preferred scheduling term + matches all objects with implicit weight 0 (i.e. + it's a no-op). A null preferred scheduling term + matches no objects (i.e. is also a no-op). + properties: + preference: + description: A node selector term, associated + with the corresponding weight. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: The label key that the + selector applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: 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. + If the operator is Gt or Lt, the + values array must have a single + element, which will be interpreted + as an integer. This array is replaced + during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: The label key that the + selector applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: 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. + If the operator is Gt or Lt, the + values array must have a single + element, which will be interpreted + as an integer. This array is replaced + during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + weight: + description: Weight associated with matching + the corresponding nodeSelectorTerm, in the + range 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified + by this field are not met at scheduling time, the + pod will not be scheduled onto the node. If the + affinity requirements specified by this field cease + to be met at some point during pod execution (e.g. + due to an update), the system may or may not try + to eventually evict the pod from its node. + properties: + nodeSelectorTerms: + description: Required. A list of node selector + terms. The terms are ORed. + items: + description: A null or empty node selector term + matches no objects. The requirements of them + are ANDed. The TopologySelectorTerm type implements + a subset of the NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: The label key that the + selector applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: 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. + If the operator is Gt or Lt, the + values array must have a single + element, which will be interpreted + as an integer. This array is replaced + during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: The label key that the + selector applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: 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. + If the operator is Gt or Lt, the + values array must have a single + element, which will be interpreted + as an integer. This array is replaced + during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + type: array + required: + - nodeSelectorTerms + type: object + type: object + podAffinity: + description: Describes pod affinity scheduling rules (e.g. + co-locate this pod in the same node, zone, etc. as some + other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule + pods to nodes that satisfy the affinity expressions + specified by this field, but it may choose a node + that violates one or more of the expressions. The + node that is most preferred is the one with the + greatest sum of weights, i.e. for each node that + meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, + etc.), compute a sum by iterating through the elements + of this field and adding "weight" to the sum if + the node has pods which matches the corresponding + podAffinityTerm; the node(s) with the highest sum + are the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, + associated with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of + resources, in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set + of namespaces that the term applies to. + The term is applied to the union of the + namespaces selected by this field and + the ones listed in the namespaces field. + null selector and null or empty namespaces + list means "this pod's namespace". An + empty selector ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static + list of namespace names that the term + applies to. The term is applied to the + union of the namespaces listed in this + field and the ones selected by namespaceSelector. + null or empty namespaces list and null + namespaceSelector means "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located + (affinity) or not co-located (anti-affinity) + with the pods matching the labelSelector + in the specified namespaces, where co-located + is defined as running on a node whose + value of the label with key topologyKey + matches that of any node on which any + of the selected pods is running. Empty + topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching + the corresponding podAffinityTerm, in the + range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified + by this field are not met at scheduling time, the + pod will not be scheduled onto the node. If the + affinity requirements specified by this field cease + to be met at some point during pod execution (e.g. + due to a pod label update), the system may or may + not try to eventually evict the pod from its node. + When there are multiple elements, the lists of nodes + corresponding to each podAffinityTerm are intersected, + i.e. all terms must be satisfied. + items: + description: Defines a set of pods (namely those + matching the labelSelector relative to the given + namespace(s)) that this pod should be co-located + (affinity) or not co-located (anti-affinity) with, + where co-located is defined as running on a node + whose value of the label with key + matches that of any node on which a pod of the + set of pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by + this field and the ones listed in the namespaces + field. null selector and null or empty namespaces + list means "this pod's namespace". An empty + selector ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. + The term is applied to the union of the namespaces + listed in this field and the ones selected + by namespaceSelector. null or empty namespaces + list and null namespaceSelector means "this + pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the + pods matching the labelSelector in the specified + namespaces, where co-located is defined as + running on a node whose value of the label + with key topologyKey matches that of any node + on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + podAntiAffinity: + description: Describes pod anti-affinity scheduling rules + (e.g. avoid putting this pod in the same node, zone, + etc. as some other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule + pods to nodes that satisfy the anti-affinity expressions + specified by this field, but it may choose a node + that violates one or more of the expressions. The + node that is most preferred is the one with the + greatest sum of weights, i.e. for each node that + meets all of the scheduling requirements (resource + request, requiredDuringScheduling anti-affinity + expressions, etc.), compute a sum by iterating through + the elements of this field and adding "weight" to + the sum if the node has pods which matches the corresponding + podAffinityTerm; the node(s) with the highest sum + are the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, + associated with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of + resources, in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set + of namespaces that the term applies to. + The term is applied to the union of the + namespaces selected by this field and + the ones listed in the namespaces field. + null selector and null or empty namespaces + list means "this pod's namespace". An + empty selector ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static + list of namespace names that the term + applies to. The term is applied to the + union of the namespaces listed in this + field and the ones selected by namespaceSelector. + null or empty namespaces list and null + namespaceSelector means "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located + (affinity) or not co-located (anti-affinity) + with the pods matching the labelSelector + in the specified namespaces, where co-located + is defined as running on a node whose + value of the label with key topologyKey + matches that of any node on which any + of the selected pods is running. Empty + topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching + the corresponding podAffinityTerm, in the + range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the anti-affinity requirements specified + by this field are not met at scheduling time, the + pod will not be scheduled onto the node. If the + anti-affinity requirements specified by this field + cease to be met at some point during pod execution + (e.g. due to a pod label update), the system may + or may not try to eventually evict the pod from + its node. When there are multiple elements, the + lists of nodes corresponding to each podAffinityTerm + are intersected, i.e. all terms must be satisfied. + items: + description: Defines a set of pods (namely those + matching the labelSelector relative to the given + namespace(s)) that this pod should be co-located + (affinity) or not co-located (anti-affinity) with, + where co-located is defined as running on a node + whose value of the label with key + matches that of any node on which a pod of the + set of pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by + this field and the ones listed in the namespaces + field. null selector and null or empty namespaces + list means "this pod's namespace". An empty + selector ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. + The term is applied to the union of the namespaces + listed in this field and the ones selected + by namespaceSelector. null or empty namespaces + list and null namespaceSelector means "this + pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the + pods matching the labelSelector in the specified + namespaces, where co-located is defined as + running on a node whose value of the label + with key topologyKey matches that of any node + on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + type: object + nodeSelector: + additionalProperties: + type: string + description: 'nodeSelector is the node selector applied to + the relevant kind of pods It specifies a map of key-value + pairs: for the pod to be eligible to run on a node, the + node must have each of the indicated key-value pairs as + labels (it can have additional labels as well). See https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#nodeselector' + type: object + tolerations: + description: tolerations is a list of tolerations applied + to the relevant kind of pods See https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ + for more info. These are additional tolerations other than + default ones. + 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 + type: object + replicas: + description: 'replicas indicates how many replicas should be created + for each KubeVirt infrastructure component (like virt-api or + virt-controller). Defaults to 2. WARNING: this is an advanced + feature that prevents auto-scaling for core kubevirt components. + Please use with caution!' + type: integer + type: object + type: object + status: + description: KubeVirtStatus represents information pertaining to a KubeVirt + deployment. + properties: + conditions: + items: + description: KubeVirtCondition represents a condition of a KubeVirt + deployment + properties: + lastProbeTime: + format: date-time + nullable: true + type: string + lastTransitionTime: + format: date-time + nullable: true + type: string + message: + type: string + reason: + type: string + status: + type: string + type: + type: string + required: + - status + - type + type: object + type: array + defaultArchitecture: + type: string + generations: + items: + description: GenerationStatus keeps track of the generation for + a given resource so that decisions about forced updates can be + made. + properties: + group: + description: group is the group of the thing you're tracking + type: string + hash: + description: hash is an optional field set for resources without + generation that are content sensitive like secrets and configmaps + type: string + lastGeneration: + description: lastGeneration is the last generation of the workload + controller involved + format: int64 + type: integer + name: + description: name is the name of the thing you're tracking + type: string + namespace: + description: namespace is where the thing you're tracking is + type: string + resource: + description: resource is the resource type of the thing you're + tracking + type: string + required: + - group + - lastGeneration + - name + - resource + type: object + type: array + x-kubernetes-list-type: atomic + observedDeploymentConfig: + type: string + observedDeploymentID: + type: string + observedGeneration: + format: int64 + type: integer + observedKubeVirtRegistry: + type: string + observedKubeVirtVersion: + type: string + operatorVersion: + type: string + outdatedVirtualMachineInstanceWorkloads: + type: integer + phase: + description: KubeVirtPhase is a label for the phase of a KubeVirt + deployment at the current time. + type: string + targetDeploymentConfig: + type: string + targetDeploymentID: + type: string + targetKubeVirtRegistry: + type: string + targetKubeVirtVersion: + type: string + type: object + required: + - spec + type: object + served: true + storage: true + subresources: + status: {} + - additionalPrinterColumns: + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + - jsonPath: .status.phase + name: Phase + type: string + deprecated: true + deprecationWarning: kubevirt.io/v1alpha3 is now deprecated and will be removed + in a future release. + name: v1alpha3 + schema: + openAPIV3Schema: + description: KubeVirt represents the object deploying all KubeVirt resources + 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: + properties: + certificateRotateStrategy: + properties: + selfSigned: + properties: + ca: + description: CA configuration CA certs are kept in the CA + bundle as long as they are valid + properties: + duration: + description: The requested 'duration' (i.e. lifetime) + of the Certificate. + type: string + renewBefore: + description: The amount of time before the currently issued + certificate's "notAfter" time that we will begin to + attempt to renew the certificate. + type: string + type: object + caOverlapInterval: + description: Deprecated. Use CA.Duration and CA.RenewBefore + instead + type: string + caRotateInterval: + description: Deprecated. Use CA.Duration instead + type: string + certRotateInterval: + description: Deprecated. Use Server.Duration instead + type: string + server: + description: Server configuration Certs are rotated and discarded + properties: + duration: + description: The requested 'duration' (i.e. lifetime) + of the Certificate. + type: string + renewBefore: + description: The amount of time before the currently issued + certificate's "notAfter" time that we will begin to + attempt to renew the certificate. + type: string + type: object + type: object + type: object + configuration: + description: holds kubevirt configurations. same as the virt-configMap + properties: + additionalGuestMemoryOverheadRatio: + description: AdditionalGuestMemoryOverheadRatio can be used to + increase the virtualization infrastructure overhead. This is + useful, since the calculation of this overhead is not accurate + and cannot be entirely known in advance. The ratio that is being + set determines by which factor to increase the overhead calculated + by Kubevirt. A higher ratio means that the VMs would be less + compromised by node pressures, but would mean that fewer VMs + could be scheduled to a node. If not set, the default is 1. + type: string + apiConfiguration: + description: ReloadableComponentConfiguration holds all generic + k8s configuration options which can be reloaded by components + without requiring a restart. + properties: + restClient: + description: RestClient can be used to tune certain aspects + of the k8s client in use. + properties: + rateLimiter: + description: RateLimiter allows selecting and configuring + different rate limiters for the k8s client. + properties: + tokenBucketRateLimiter: + properties: + burst: + description: Maximum burst for throttle. If it's + zero, the component default will be used + type: integer + qps: + description: QPS indicates the maximum QPS to + the apiserver from this client. If it's zero, + the component default will be used + type: number + required: + - burst + - qps + type: object + type: object + type: object + type: object + architectureConfiguration: + properties: + amd64: + properties: + emulatedMachines: + items: + type: string + type: array + x-kubernetes-list-type: atomic + machineType: + type: string + ovmfPath: + type: string + type: object + arm64: + properties: + emulatedMachines: + items: + type: string + type: array + x-kubernetes-list-type: atomic + machineType: + type: string + ovmfPath: + type: string + type: object + defaultArchitecture: + type: string + ppc64le: + properties: + emulatedMachines: + items: + type: string + type: array + x-kubernetes-list-type: atomic + machineType: + type: string + ovmfPath: + type: string + type: object + type: object + autoCPULimitNamespaceLabelSelector: + description: When set, AutoCPULimitNamespaceLabelSelector will + set a CPU limit on virt-launcher for VMIs running inside namespaces + that match the label selector. The CPU limit will equal the + number of requested vCPUs. This setting does not apply to VMIs + with dedicated CPUs. + 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 + required: + - key + - operator + type: object + type: array + 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 + controllerConfiguration: + description: ReloadableComponentConfiguration holds all generic + k8s configuration options which can be reloaded by components + without requiring a restart. + properties: + restClient: + description: RestClient can be used to tune certain aspects + of the k8s client in use. + properties: + rateLimiter: + description: RateLimiter allows selecting and configuring + different rate limiters for the k8s client. + properties: + tokenBucketRateLimiter: + properties: + burst: + description: Maximum burst for throttle. If it's + zero, the component default will be used + type: integer + qps: + description: QPS indicates the maximum QPS to + the apiserver from this client. If it's zero, + the component default will be used + type: number + required: + - burst + - qps + type: object + type: object + type: object + type: object + cpuModel: + type: string + cpuRequest: + 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 + defaultRuntimeClass: + type: string + developerConfiguration: + description: DeveloperConfiguration holds developer options + properties: + cpuAllocationRatio: + description: 'For each requested virtual CPU, CPUAllocationRatio + defines how much physical CPU to request per VMI from the + hosting node. The value is in fraction of a CPU thread (or + core on non-hyperthreaded nodes). For example, a value of + 1 means 1 physical CPU thread per VMI CPU thread. A value + of 100 would be 1% of a physical thread allocated for each + requested VMI thread. This option has no effect on VMIs + that request dedicated CPUs. More information at: https://kubevirt.io/user-guide/operations/node_overcommit/#node-cpu-allocation-ratio + Defaults to 10' + type: integer + diskVerification: + description: DiskVerification holds container disks verification + limits + properties: + memoryLimit: + 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 + required: + - memoryLimit + type: object + featureGates: + description: FeatureGates is the list of experimental features + to enable. Defaults to none + items: + type: string + type: array + logVerbosity: + description: LogVerbosity sets log verbosity level of various + components + properties: + nodeVerbosity: + additionalProperties: + type: integer + description: NodeVerbosity represents a map of nodes with + a specific verbosity level + type: object + virtAPI: + type: integer + virtController: + type: integer + virtHandler: + type: integer + virtLauncher: + type: integer + virtOperator: + type: integer + type: object + memoryOvercommit: + description: MemoryOvercommit is the percentage of memory + we want to give VMIs compared to the amount given to its + parent pod (virt-launcher). For example, a value of 102 + means the VMI will "see" 2% more memory than its parent + pod. Values under 100 are effectively "undercommits". Overcommits + can lead to memory exhaustion, which in turn can lead to + crashes. Use carefully. Defaults to 100 + type: integer + minimumClusterTSCFrequency: + description: Allow overriding the automatically determined + minimum TSC frequency of the cluster and fixate the minimum + to this frequency. + format: int64 + type: integer + minimumReservePVCBytes: + description: MinimumReservePVCBytes is the amount of space, + in bytes, to leave unused on disks. Defaults to 131072 (128KiB) + format: int64 + type: integer + nodeSelectors: + additionalProperties: + type: string + description: NodeSelectors allows restricting VMI creation + to nodes that match a set of labels. Defaults to none + type: object + pvcTolerateLessSpaceUpToPercent: + description: LessPVCSpaceToleration determines how much smaller, + in percentage, disk PVCs are allowed to be compared to the + requested size (to account for various overheads). Defaults + to 10 + type: integer + useEmulation: + description: UseEmulation can be set to true to allow fallback + to software emulation in case hardware-assisted emulation + is not available. Defaults to false + type: boolean + type: object + emulatedMachines: + items: + type: string + type: array + evictionStrategy: + description: EvictionStrategy defines at the cluster level if + the VirtualMachineInstance should be migrated instead of shut-off + in case of a node drain. If the VirtualMachineInstance specific + field is set it overrides the cluster level one. + type: string + handlerConfiguration: + description: ReloadableComponentConfiguration holds all generic + k8s configuration options which can be reloaded by components + without requiring a restart. + properties: + restClient: + description: RestClient can be used to tune certain aspects + of the k8s client in use. + properties: + rateLimiter: + description: RateLimiter allows selecting and configuring + different rate limiters for the k8s client. + properties: + tokenBucketRateLimiter: + properties: + burst: + description: Maximum burst for throttle. If it's + zero, the component default will be used + type: integer + qps: + description: QPS indicates the maximum QPS to + the apiserver from this client. If it's zero, + the component default will be used + type: number + required: + - burst + - qps + type: object + type: object + type: object + type: object + imagePullPolicy: + description: PullPolicy describes a policy for if/when to pull + a container image + type: string + ksmConfiguration: + description: KSMConfiguration holds the information regarding + the enabling the KSM in the nodes (if available). + properties: + nodeLabelSelector: + description: NodeLabelSelector is a selector that filters + in which nodes the KSM will be enabled. Empty NodeLabelSelector + will enable ksm for every node. + 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 + required: + - key + - operator + type: object + type: array + 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 + type: object + liveUpdateConfiguration: + description: LiveUpdateConfiguration holds defaults for live update + features + properties: + maxCpuSockets: + description: MaxCpuSockets holds the maximum amount of sockets + that can be hotplugged + format: int32 + type: integer + maxGuest: + anyOf: + - type: integer + - type: string + description: MaxGuest defines the maximum amount memory that + can be allocated to the guest using hotplug. + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + maxHotplugRatio: + description: 'MaxHotplugRatio is the ratio used to define + the max amount of a hotplug resource that can be made available + to a VM when the specific Max* setting is not defined (MaxCpuSockets, + MaxGuest) Example: VM is configured with 512Mi of guest + memory, if MaxGuest is not defined and MaxHotplugRatio is + 2 then MaxGuest = 1Gi defaults to 4' + format: int32 + type: integer + type: object + machineType: + description: Deprecated. Use architectureConfiguration instead. + type: string + mediatedDevicesConfiguration: + description: MediatedDevicesConfiguration holds information about + MDEV types to be defined, if available + properties: + mediatedDeviceTypes: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mediatedDevicesTypes: + description: Deprecated. Use mediatedDeviceTypes instead. + items: + type: string + type: array + x-kubernetes-list-type: atomic + nodeMediatedDeviceTypes: + items: + description: NodeMediatedDeviceTypesConfig holds information + about MDEV types to be defined in a specific node that + matches the NodeSelector field. + properties: + mediatedDeviceTypes: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mediatedDevicesTypes: + description: Deprecated. Use mediatedDeviceTypes instead. + items: + type: string + type: array + x-kubernetes-list-type: atomic + nodeSelector: + additionalProperties: + type: string + description: 'NodeSelector is a selector which must + be true for the vmi to fit on a node. Selector which + must match a node''s labels for the vmi to be scheduled + on that node. More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/' + type: object + required: + - nodeSelector + type: object + type: array + x-kubernetes-list-type: atomic + type: object + memBalloonStatsPeriod: + format: int32 + type: integer + migrations: + description: MigrationConfiguration holds migration options. Can + be overridden for specific groups of VMs though migration policies. + Visit https://kubevirt.io/user-guide/operations/migration_policies/ + for more information. + properties: + allowAutoConverge: + description: AllowAutoConverge allows the platform to compromise + performance/availability of VMIs to guarantee successful + VMI live migrations. Defaults to false + type: boolean + allowPostCopy: + description: AllowPostCopy enables post-copy live migrations. + Such migrations allow even the busiest VMIs to successfully + live-migrate. However, events like a network failure can + cause a VMI crash. If set to true, migrations will still + start in pre-copy, but switch to post-copy when CompletionTimeoutPerGiB + triggers. Defaults to false + type: boolean + bandwidthPerMigration: + anyOf: + - type: integer + - type: string + description: BandwidthPerMigration limits the amount of network + bandwidth live migrations are allowed to use. The value + is in quantity per second. Defaults to 0 (no limit) + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + completionTimeoutPerGiB: + description: CompletionTimeoutPerGiB is the maximum number + of seconds per GiB a migration is allowed to take. If a + live-migration takes longer to migrate than this value multiplied + by the size of the VMI, the migration will be cancelled, + unless AllowPostCopy is true. Defaults to 800 + format: int64 + type: integer + disableTLS: + description: When set to true, DisableTLS will disable the + additional layer of live migration encryption provided by + KubeVirt. This is usually a bad idea. Defaults to false + type: boolean + matchSELinuxLevelOnMigration: + description: By default, the SELinux level of target virt-launcher + pods is forced to the level of the source virt-launcher. + When set to true, MatchSELinuxLevelOnMigration lets the + CRI auto-assign a random level to the target. That will + ensure the target virt-launcher doesn't share categories + with another pod on the node. However, migrations will fail + when using RWX volumes that don't automatically deal with + SELinux levels. + type: boolean + network: + description: Network is the name of the CNI network to use + for live migrations. By default, migrations go through the + pod network. + type: string + nodeDrainTaintKey: + description: 'NodeDrainTaintKey defines the taint key that + indicates a node should be drained. Note: this option relies + on the deprecated node taint feature. Default: kubevirt.io/drain' + type: string + parallelMigrationsPerCluster: + description: ParallelMigrationsPerCluster is the total number + of concurrent live migrations allowed cluster-wide. Defaults + to 5 + format: int32 + type: integer + parallelOutboundMigrationsPerNode: + description: ParallelOutboundMigrationsPerNode is the maximum + number of concurrent outgoing live migrations allowed per + node. Defaults to 2 + format: int32 + type: integer + progressTimeout: + description: ProgressTimeout is the maximum number of seconds + a live migration is allowed to make no progress. Hitting + this timeout means a migration transferred 0 data for that + many seconds. The migration is then considered stuck and + therefore cancelled. Defaults to 150 + format: int64 + type: integer + unsafeMigrationOverride: + description: UnsafeMigrationOverride allows live migrations + to occur even if the compatibility check indicates the migration + will be unsafe to the guest. Defaults to false + type: boolean + type: object + minCPUModel: + type: string + network: + description: NetworkConfiguration holds network options + properties: + binding: + additionalProperties: + properties: + networkAttachmentDefinition: + description: 'NetworkAttachmentDefinition references + to a NetworkAttachmentDefinition CR object. Format: + , /. If namespace is not specified, + VMI namespace is assumed. version: 1alphav1' + type: string + sidecarImage: + description: 'SidecarImage references a container image + that runs in the virt-launcher pod. The sidecar handles + (libvirt) domain configuration and optional services. + version: 1alphav1' + type: string + type: object + type: object + defaultNetworkInterface: + type: string + permitBridgeInterfaceOnPodNetwork: + type: boolean + permitSlirpInterface: + type: boolean + type: object + obsoleteCPUModels: + additionalProperties: + type: boolean + type: object + ovmfPath: + type: string + permittedHostDevices: + description: PermittedHostDevices holds information about devices + allowed for passthrough + properties: + mediatedDevices: + items: + description: MediatedHostDevice represents a host mediated + device allowed for passthrough + properties: + externalResourceProvider: + type: boolean + mdevNameSelector: + type: string + resourceName: + type: string + required: + - mdevNameSelector + - resourceName + type: object + type: array + x-kubernetes-list-type: atomic + pciHostDevices: + items: + description: PciHostDevice represents a host PCI device + allowed for passthrough + properties: + externalResourceProvider: + description: If true, KubeVirt will leave the allocation + and monitoring to an external device plugin + type: boolean + pciVendorSelector: + description: The vendor_id:product_id tuple of the PCI + device + type: string + resourceName: + description: The name of the resource that is representing + the device. Exposed by a device plugin and requested + by VMs. Typically of the form vendor.com/product_name + type: string + required: + - pciVendorSelector + - resourceName + type: object + type: array + x-kubernetes-list-type: atomic + usb: + items: + properties: + externalResourceProvider: + description: If true, KubeVirt will leave the allocation + and monitoring to an external device plugin + type: boolean + resourceName: + description: 'Identifies the list of USB host devices. + e.g: kubevirt.io/storage, kubevirt.io/bootable-usb, + etc' + type: string + selectors: + items: + properties: + product: + type: string + vendor: + type: string + required: + - product + - vendor + type: object + type: array + x-kubernetes-list-type: atomic + required: + - resourceName + type: object + type: array + x-kubernetes-list-type: atomic + type: object + seccompConfiguration: + description: SeccompConfiguration holds Seccomp configuration + for Kubevirt components + properties: + virtualMachineInstanceProfile: + description: VirtualMachineInstanceProfile defines what profile + should be used with virt-launcher. Defaults to none + properties: + customProfile: + description: CustomProfile allows to request arbitrary + profile for virt-launcher + properties: + localhostProfile: + type: string + runtimeDefaultProfile: + type: boolean + type: object + type: object + type: object + selinuxLauncherType: + type: string + smbios: + properties: + family: + type: string + manufacturer: + type: string + product: + type: string + sku: + type: string + version: + type: string + type: object + supportContainerResources: + description: SupportContainerResources specifies the resource + requirements for various types of supporting containers such + as container disks/virtiofs/sidecars and hotplug attachment + pods. If omitted a sensible default will be supplied. + items: + description: SupportContainerResources are used to specify the + cpu/memory request and limits for the containers that support + various features of Virtual Machines. These containers are + usually idle and don't require a lot of memory or cpu. + properties: + resources: + description: ResourceRequirements describes the compute + resource requirements. + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. \n 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 + 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. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + type: + type: string + required: + - resources + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + supportedGuestAgentVersions: + description: deprecated + items: + type: string + type: array + tlsConfiguration: + description: TLSConfiguration holds TLS options + properties: + ciphers: + items: + type: string + type: array + x-kubernetes-list-type: set + minTLSVersion: + description: "MinTLSVersion is a way to specify the minimum + protocol version that is acceptable for TLS connections. + Protocol versions are based on the following most common + TLS configurations: \n https://ssl-config.mozilla.org/ + \n Note that SSLv3.0 is not a supported protocol version + due to well known vulnerabilities such as POODLE: https://en.wikipedia.org/wiki/POODLE" + enum: + - VersionTLS10 + - VersionTLS11 + - VersionTLS12 + - VersionTLS13 + type: string + type: object + virtualMachineInstancesPerNode: + type: integer + virtualMachineOptions: + description: VirtualMachineOptions holds the cluster level information + regarding the virtual machine. + properties: + disableFreePageReporting: + description: DisableFreePageReporting disable the free page + reporting of memory balloon device https://libvirt.org/formatdomain.html#memory-balloon-device. + This will have effect only if AutoattachMemBalloon is not + false and the vmi is not requesting any high performance + feature (dedicatedCPU/realtime/hugePages), in which free + page reporting is always disabled. + type: object + disableSerialConsoleLog: + description: DisableSerialConsoleLog disables logging the + auto-attached default serial console. If not set, serial + console logs will be written to a file and then streamed + from a container named 'guest-console-log'. The value can + be individually overridden for each VM, not relevant if + AutoattachSerialConsole is disabled. + type: object + type: object + vmStateStorageClass: + description: VMStateStorageClass is the name of the storage class + to use for the PVCs created to preserve VM state, like TPM. + The storage class must support RWX in filesystem mode. + type: string + webhookConfiguration: + description: ReloadableComponentConfiguration holds all generic + k8s configuration options which can be reloaded by components + without requiring a restart. + properties: + restClient: + description: RestClient can be used to tune certain aspects + of the k8s client in use. + properties: + rateLimiter: + description: RateLimiter allows selecting and configuring + different rate limiters for the k8s client. + properties: + tokenBucketRateLimiter: + properties: + burst: + description: Maximum burst for throttle. If it's + zero, the component default will be used + type: integer + qps: + description: QPS indicates the maximum QPS to + the apiserver from this client. If it's zero, + the component default will be used + type: number + required: + - burst + - qps + type: object + type: object + type: object + type: object + type: object + customizeComponents: + properties: + flags: + description: Configure the value used for deployment and daemonset + resources + properties: + api: + additionalProperties: + type: string + type: object + controller: + additionalProperties: + type: string + type: object + handler: + additionalProperties: + type: string + type: object + type: object + patches: + items: + properties: + patch: + type: string + resourceName: + minLength: 1 + type: string + resourceType: + minLength: 1 + type: string + type: + type: string + required: + - patch + - resourceName + - resourceType + - type + type: object + type: array + x-kubernetes-list-type: atomic + type: object + imagePullPolicy: + description: The ImagePullPolicy to use. + type: string + imagePullSecrets: + description: The imagePullSecrets to pull the container images from + Defaults to none + items: + description: LocalObjectReference contains enough information to + let you locate the referenced object inside the same namespace. + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + type: array + x-kubernetes-list-type: atomic + imageRegistry: + description: The image registry to pull the container images from + Defaults to the same registry the operator's container image is + pulled from. + type: string + imageTag: + description: The image tag to use for the continer images installed. + Defaults to the same tag as the operator's container image. + type: string + infra: + description: selectors and tolerations that should apply to KubeVirt + infrastructure components + properties: + nodePlacement: + description: nodePlacement describes scheduling configuration + for specific KubeVirt components + properties: + affinity: + description: affinity enables pod affinity/anti-affinity placement + expanding the types of constraints that can be expressed + with nodeSelector. affinity is going to be applied to the + relevant kind of pods in parallel with nodeSelector See + https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#affinity-and-anti-affinity + properties: + nodeAffinity: + description: Describes node affinity scheduling rules + for the pod. + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule + pods to nodes that satisfy the affinity expressions + specified by this field, but it may choose a node + that violates one or more of the expressions. The + node that is most preferred is the one with the + greatest sum of weights, i.e. for each node that + meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, + etc.), compute a sum by iterating through the elements + of this field and adding "weight" to the sum if + the node matches the corresponding matchExpressions; + the node(s) with the highest sum are the most preferred. + items: + description: An empty preferred scheduling term + matches all objects with implicit weight 0 (i.e. + it's a no-op). A null preferred scheduling term + matches no objects (i.e. is also a no-op). + properties: + preference: + description: A node selector term, associated + with the corresponding weight. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: The label key that the + selector applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: 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. + If the operator is Gt or Lt, the + values array must have a single + element, which will be interpreted + as an integer. This array is replaced + during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: The label key that the + selector applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: 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. + If the operator is Gt or Lt, the + values array must have a single + element, which will be interpreted + as an integer. This array is replaced + during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + weight: + description: Weight associated with matching + the corresponding nodeSelectorTerm, in the + range 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified + by this field are not met at scheduling time, the + pod will not be scheduled onto the node. If the + affinity requirements specified by this field cease + to be met at some point during pod execution (e.g. + due to an update), the system may or may not try + to eventually evict the pod from its node. + properties: + nodeSelectorTerms: + description: Required. A list of node selector + terms. The terms are ORed. + items: + description: A null or empty node selector term + matches no objects. The requirements of them + are ANDed. The TopologySelectorTerm type implements + a subset of the NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: The label key that the + selector applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: 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. + If the operator is Gt or Lt, the + values array must have a single + element, which will be interpreted + as an integer. This array is replaced + during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: The label key that the + selector applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: 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. + If the operator is Gt or Lt, the + values array must have a single + element, which will be interpreted + as an integer. This array is replaced + during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + type: array + required: + - nodeSelectorTerms + type: object + type: object + podAffinity: + description: Describes pod affinity scheduling rules (e.g. + co-locate this pod in the same node, zone, etc. as some + other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule + pods to nodes that satisfy the affinity expressions + specified by this field, but it may choose a node + that violates one or more of the expressions. The + node that is most preferred is the one with the + greatest sum of weights, i.e. for each node that + meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, + etc.), compute a sum by iterating through the elements + of this field and adding "weight" to the sum if + the node has pods which matches the corresponding + podAffinityTerm; the node(s) with the highest sum + are the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, + associated with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of + resources, in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set + of namespaces that the term applies to. + The term is applied to the union of the + namespaces selected by this field and + the ones listed in the namespaces field. + null selector and null or empty namespaces + list means "this pod's namespace". An + empty selector ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static + list of namespace names that the term + applies to. The term is applied to the + union of the namespaces listed in this + field and the ones selected by namespaceSelector. + null or empty namespaces list and null + namespaceSelector means "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located + (affinity) or not co-located (anti-affinity) + with the pods matching the labelSelector + in the specified namespaces, where co-located + is defined as running on a node whose + value of the label with key topologyKey + matches that of any node on which any + of the selected pods is running. Empty + topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching + the corresponding podAffinityTerm, in the + range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified + by this field are not met at scheduling time, the + pod will not be scheduled onto the node. If the + affinity requirements specified by this field cease + to be met at some point during pod execution (e.g. + due to a pod label update), the system may or may + not try to eventually evict the pod from its node. + When there are multiple elements, the lists of nodes + corresponding to each podAffinityTerm are intersected, + i.e. all terms must be satisfied. + items: + description: Defines a set of pods (namely those + matching the labelSelector relative to the given + namespace(s)) that this pod should be co-located + (affinity) or not co-located (anti-affinity) with, + where co-located is defined as running on a node + whose value of the label with key + matches that of any node on which a pod of the + set of pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by + this field and the ones listed in the namespaces + field. null selector and null or empty namespaces + list means "this pod's namespace". An empty + selector ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. + The term is applied to the union of the namespaces + listed in this field and the ones selected + by namespaceSelector. null or empty namespaces + list and null namespaceSelector means "this + pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the + pods matching the labelSelector in the specified + namespaces, where co-located is defined as + running on a node whose value of the label + with key topologyKey matches that of any node + on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + podAntiAffinity: + description: Describes pod anti-affinity scheduling rules + (e.g. avoid putting this pod in the same node, zone, + etc. as some other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule + pods to nodes that satisfy the anti-affinity expressions + specified by this field, but it may choose a node + that violates one or more of the expressions. The + node that is most preferred is the one with the + greatest sum of weights, i.e. for each node that + meets all of the scheduling requirements (resource + request, requiredDuringScheduling anti-affinity + expressions, etc.), compute a sum by iterating through + the elements of this field and adding "weight" to + the sum if the node has pods which matches the corresponding + podAffinityTerm; the node(s) with the highest sum + are the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, + associated with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of + resources, in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set + of namespaces that the term applies to. + The term is applied to the union of the + namespaces selected by this field and + the ones listed in the namespaces field. + null selector and null or empty namespaces + list means "this pod's namespace". An + empty selector ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static + list of namespace names that the term + applies to. The term is applied to the + union of the namespaces listed in this + field and the ones selected by namespaceSelector. + null or empty namespaces list and null + namespaceSelector means "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located + (affinity) or not co-located (anti-affinity) + with the pods matching the labelSelector + in the specified namespaces, where co-located + is defined as running on a node whose + value of the label with key topologyKey + matches that of any node on which any + of the selected pods is running. Empty + topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching + the corresponding podAffinityTerm, in the + range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the anti-affinity requirements specified + by this field are not met at scheduling time, the + pod will not be scheduled onto the node. If the + anti-affinity requirements specified by this field + cease to be met at some point during pod execution + (e.g. due to a pod label update), the system may + or may not try to eventually evict the pod from + its node. When there are multiple elements, the + lists of nodes corresponding to each podAffinityTerm + are intersected, i.e. all terms must be satisfied. + items: + description: Defines a set of pods (namely those + matching the labelSelector relative to the given + namespace(s)) that this pod should be co-located + (affinity) or not co-located (anti-affinity) with, + where co-located is defined as running on a node + whose value of the label with key + matches that of any node on which a pod of the + set of pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by + this field and the ones listed in the namespaces + field. null selector and null or empty namespaces + list means "this pod's namespace". An empty + selector ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. + The term is applied to the union of the namespaces + listed in this field and the ones selected + by namespaceSelector. null or empty namespaces + list and null namespaceSelector means "this + pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the + pods matching the labelSelector in the specified + namespaces, where co-located is defined as + running on a node whose value of the label + with key topologyKey matches that of any node + on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + type: object + nodeSelector: + additionalProperties: + type: string + description: 'nodeSelector is the node selector applied to + the relevant kind of pods It specifies a map of key-value + pairs: for the pod to be eligible to run on a node, the + node must have each of the indicated key-value pairs as + labels (it can have additional labels as well). See https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#nodeselector' + type: object + tolerations: + description: tolerations is a list of tolerations applied + to the relevant kind of pods See https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ + for more info. These are additional tolerations other than + default ones. + 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 + type: object + replicas: + description: 'replicas indicates how many replicas should be created + for each KubeVirt infrastructure component (like virt-api or + virt-controller). Defaults to 2. WARNING: this is an advanced + feature that prevents auto-scaling for core kubevirt components. + Please use with caution!' + type: integer + type: object + monitorAccount: + description: The name of the Prometheus service account that needs + read-access to KubeVirt endpoints Defaults to prometheus-k8s + type: string + monitorNamespace: + description: The namespace Prometheus is deployed in Defaults to openshift-monitor + type: string + productComponent: + description: Designate the apps.kubevirt.io/component label for KubeVirt + components. Useful if KubeVirt is included as part of a product. + If ProductComponent is not specified, the component label default + value is kubevirt. + type: string + productName: + description: Designate the apps.kubevirt.io/part-of label for KubeVirt + components. Useful if KubeVirt is included as part of a product. + If ProductName is not specified, the part-of label will be omitted. + type: string + productVersion: + description: Designate the apps.kubevirt.io/version label for KubeVirt + components. Useful if KubeVirt is included as part of a product. + If ProductVersion is not specified, KubeVirt's version will be used. + type: string + serviceMonitorNamespace: + description: The namespace the service monitor will be deployed When + ServiceMonitorNamespace is set, then we'll install the service monitor + object in that namespace otherwise we will use the monitoring namespace. + type: string + uninstallStrategy: + description: Specifies if kubevirt can be deleted if workloads are + still present. This is mainly a precaution to avoid accidental data + loss + type: string + workloadUpdateStrategy: + description: WorkloadUpdateStrategy defines at the cluster level how + to handle automated workload updates + properties: + batchEvictionInterval: + description: "BatchEvictionInterval Represents the interval to + wait before issuing the next batch of shutdowns \n Defaults + to 1 minute" + type: string + batchEvictionSize: + description: "BatchEvictionSize Represents the number of VMIs + that can be forced updated per the BatchShutdownInteral interval + \n Defaults to 10" + type: integer + workloadUpdateMethods: + description: "WorkloadUpdateMethods defines the methods that can + be used to disrupt workloads during automated workload updates. + When multiple methods are present, the least disruptive method + takes precedence over more disruptive methods. For example if + both LiveMigrate and Shutdown methods are listed, only VMs which + are not live migratable will be restarted/shutdown \n An empty + list defaults to no automated workload updating" + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + workloads: + description: selectors and tolerations that should apply to KubeVirt + workloads + properties: + nodePlacement: + description: nodePlacement describes scheduling configuration + for specific KubeVirt components + properties: + affinity: + description: affinity enables pod affinity/anti-affinity placement + expanding the types of constraints that can be expressed + with nodeSelector. affinity is going to be applied to the + relevant kind of pods in parallel with nodeSelector See + https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#affinity-and-anti-affinity + properties: + nodeAffinity: + description: Describes node affinity scheduling rules + for the pod. + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule + pods to nodes that satisfy the affinity expressions + specified by this field, but it may choose a node + that violates one or more of the expressions. The + node that is most preferred is the one with the + greatest sum of weights, i.e. for each node that + meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, + etc.), compute a sum by iterating through the elements + of this field and adding "weight" to the sum if + the node matches the corresponding matchExpressions; + the node(s) with the highest sum are the most preferred. + items: + description: An empty preferred scheduling term + matches all objects with implicit weight 0 (i.e. + it's a no-op). A null preferred scheduling term + matches no objects (i.e. is also a no-op). + properties: + preference: + description: A node selector term, associated + with the corresponding weight. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: The label key that the + selector applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: 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. + If the operator is Gt or Lt, the + values array must have a single + element, which will be interpreted + as an integer. This array is replaced + during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: The label key that the + selector applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: 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. + If the operator is Gt or Lt, the + values array must have a single + element, which will be interpreted + as an integer. This array is replaced + during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + weight: + description: Weight associated with matching + the corresponding nodeSelectorTerm, in the + range 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified + by this field are not met at scheduling time, the + pod will not be scheduled onto the node. If the + affinity requirements specified by this field cease + to be met at some point during pod execution (e.g. + due to an update), the system may or may not try + to eventually evict the pod from its node. + properties: + nodeSelectorTerms: + description: Required. A list of node selector + terms. The terms are ORed. + items: + description: A null or empty node selector term + matches no objects. The requirements of them + are ANDed. The TopologySelectorTerm type implements + a subset of the NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: The label key that the + selector applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: 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. + If the operator is Gt or Lt, the + values array must have a single + element, which will be interpreted + as an integer. This array is replaced + during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: The label key that the + selector applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: 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. + If the operator is Gt or Lt, the + values array must have a single + element, which will be interpreted + as an integer. This array is replaced + during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + type: array + required: + - nodeSelectorTerms + type: object + type: object + podAffinity: + description: Describes pod affinity scheduling rules (e.g. + co-locate this pod in the same node, zone, etc. as some + other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule + pods to nodes that satisfy the affinity expressions + specified by this field, but it may choose a node + that violates one or more of the expressions. The + node that is most preferred is the one with the + greatest sum of weights, i.e. for each node that + meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, + etc.), compute a sum by iterating through the elements + of this field and adding "weight" to the sum if + the node has pods which matches the corresponding + podAffinityTerm; the node(s) with the highest sum + are the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, + associated with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of + resources, in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set + of namespaces that the term applies to. + The term is applied to the union of the + namespaces selected by this field and + the ones listed in the namespaces field. + null selector and null or empty namespaces + list means "this pod's namespace". An + empty selector ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static + list of namespace names that the term + applies to. The term is applied to the + union of the namespaces listed in this + field and the ones selected by namespaceSelector. + null or empty namespaces list and null + namespaceSelector means "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located + (affinity) or not co-located (anti-affinity) + with the pods matching the labelSelector + in the specified namespaces, where co-located + is defined as running on a node whose + value of the label with key topologyKey + matches that of any node on which any + of the selected pods is running. Empty + topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching + the corresponding podAffinityTerm, in the + range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified + by this field are not met at scheduling time, the + pod will not be scheduled onto the node. If the + affinity requirements specified by this field cease + to be met at some point during pod execution (e.g. + due to a pod label update), the system may or may + not try to eventually evict the pod from its node. + When there are multiple elements, the lists of nodes + corresponding to each podAffinityTerm are intersected, + i.e. all terms must be satisfied. + items: + description: Defines a set of pods (namely those + matching the labelSelector relative to the given + namespace(s)) that this pod should be co-located + (affinity) or not co-located (anti-affinity) with, + where co-located is defined as running on a node + whose value of the label with key + matches that of any node on which a pod of the + set of pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by + this field and the ones listed in the namespaces + field. null selector and null or empty namespaces + list means "this pod's namespace". An empty + selector ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. + The term is applied to the union of the namespaces + listed in this field and the ones selected + by namespaceSelector. null or empty namespaces + list and null namespaceSelector means "this + pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the + pods matching the labelSelector in the specified + namespaces, where co-located is defined as + running on a node whose value of the label + with key topologyKey matches that of any node + on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + podAntiAffinity: + description: Describes pod anti-affinity scheduling rules + (e.g. avoid putting this pod in the same node, zone, + etc. as some other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule + pods to nodes that satisfy the anti-affinity expressions + specified by this field, but it may choose a node + that violates one or more of the expressions. The + node that is most preferred is the one with the + greatest sum of weights, i.e. for each node that + meets all of the scheduling requirements (resource + request, requiredDuringScheduling anti-affinity + expressions, etc.), compute a sum by iterating through + the elements of this field and adding "weight" to + the sum if the node has pods which matches the corresponding + podAffinityTerm; the node(s) with the highest sum + are the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, + associated with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of + resources, in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set + of namespaces that the term applies to. + The term is applied to the union of the + namespaces selected by this field and + the ones listed in the namespaces field. + null selector and null or empty namespaces + list means "this pod's namespace". An + empty selector ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static + list of namespace names that the term + applies to. The term is applied to the + union of the namespaces listed in this + field and the ones selected by namespaceSelector. + null or empty namespaces list and null + namespaceSelector means "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located + (affinity) or not co-located (anti-affinity) + with the pods matching the labelSelector + in the specified namespaces, where co-located + is defined as running on a node whose + value of the label with key topologyKey + matches that of any node on which any + of the selected pods is running. Empty + topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching + the corresponding podAffinityTerm, in the + range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the anti-affinity requirements specified + by this field are not met at scheduling time, the + pod will not be scheduled onto the node. If the + anti-affinity requirements specified by this field + cease to be met at some point during pod execution + (e.g. due to a pod label update), the system may + or may not try to eventually evict the pod from + its node. When there are multiple elements, the + lists of nodes corresponding to each podAffinityTerm + are intersected, i.e. all terms must be satisfied. + items: + description: Defines a set of pods (namely those + matching the labelSelector relative to the given + namespace(s)) that this pod should be co-located + (affinity) or not co-located (anti-affinity) with, + where co-located is defined as running on a node + whose value of the label with key + matches that of any node on which a pod of the + set of pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by + this field and the ones listed in the namespaces + field. null selector and null or empty namespaces + list means "this pod's namespace". An empty + selector ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. + The term is applied to the union of the namespaces + listed in this field and the ones selected + by namespaceSelector. null or empty namespaces + list and null namespaceSelector means "this + pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the + pods matching the labelSelector in the specified + namespaces, where co-located is defined as + running on a node whose value of the label + with key topologyKey matches that of any node + on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + type: object + nodeSelector: + additionalProperties: + type: string + description: 'nodeSelector is the node selector applied to + the relevant kind of pods It specifies a map of key-value + pairs: for the pod to be eligible to run on a node, the + node must have each of the indicated key-value pairs as + labels (it can have additional labels as well). See https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#nodeselector' + type: object + tolerations: + description: tolerations is a list of tolerations applied + to the relevant kind of pods See https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ + for more info. These are additional tolerations other than + default ones. + 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 + type: object + replicas: + description: 'replicas indicates how many replicas should be created + for each KubeVirt infrastructure component (like virt-api or + virt-controller). Defaults to 2. WARNING: this is an advanced + feature that prevents auto-scaling for core kubevirt components. + Please use with caution!' + type: integer + type: object + type: object + status: + description: KubeVirtStatus represents information pertaining to a KubeVirt + deployment. + properties: + conditions: + items: + description: KubeVirtCondition represents a condition of a KubeVirt + deployment + properties: + lastProbeTime: + format: date-time + nullable: true + type: string + lastTransitionTime: + format: date-time + nullable: true + type: string + message: + type: string + reason: + type: string + status: + type: string + type: + type: string + required: + - status + - type + type: object + type: array + defaultArchitecture: + type: string + generations: + items: + description: GenerationStatus keeps track of the generation for + a given resource so that decisions about forced updates can be + made. + properties: + group: + description: group is the group of the thing you're tracking + type: string + hash: + description: hash is an optional field set for resources without + generation that are content sensitive like secrets and configmaps + type: string + lastGeneration: + description: lastGeneration is the last generation of the workload + controller involved + format: int64 + type: integer + name: + description: name is the name of the thing you're tracking + type: string + namespace: + description: namespace is where the thing you're tracking is + type: string + resource: + description: resource is the resource type of the thing you're + tracking + type: string + required: + - group + - lastGeneration + - name + - resource + type: object + type: array + x-kubernetes-list-type: atomic + observedDeploymentConfig: + type: string + observedDeploymentID: + type: string + observedGeneration: + format: int64 + type: integer + observedKubeVirtRegistry: + type: string + observedKubeVirtVersion: + type: string + operatorVersion: + type: string + outdatedVirtualMachineInstanceWorkloads: + type: integer + phase: + description: KubeVirtPhase is a label for the phase of a KubeVirt + deployment at the current time. + type: string + targetDeploymentConfig: + type: string + targetDeploymentID: + type: string + targetKubeVirtRegistry: + type: string + targetKubeVirtVersion: + type: string + type: object + required: + - spec + type: object + served: true + storage: false + subresources: + status: {} + +--- +apiVersion: scheduling.k8s.io/v1 +kind: PriorityClass +metadata: + name: kubevirt-cluster-critical +value: 1000000000 +globalDefault: false +description: "This priority class should be used for core kubevirt components only." +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: kubevirt.io:operator + labels: + operator.kubevirt.io: "" + rbac.authorization.k8s.io/aggregate-to-admin: "true" +rules: + - apiGroups: + - kubevirt.io + resources: + - kubevirts + verbs: + - get + - delete + - create + - update + - patch + - list + - watch + - deletecollection +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + labels: + kubevirt.io: "" + name: kubevirt-operator + namespace: cozy-kubevirt +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + labels: + kubevirt.io: "" + name: kubevirt-operator + namespace: cozy-kubevirt +rules: +- apiGroups: + - "" + resourceNames: + - kubevirt-ca + - kubevirt-export-ca + - kubevirt-virt-handler-certs + - kubevirt-virt-handler-server-certs + - kubevirt-operator-certs + - kubevirt-virt-api-certs + - kubevirt-controller-certs + - kubevirt-exportproxy-certs + resources: + - secrets + verbs: + - create + - get + - list + - watch + - patch + - delete +- apiGroups: + - "" + resources: + - configmaps + verbs: + - create + - get + - list + - watch + - patch + - delete +- apiGroups: + - route.openshift.io + resources: + - routes + verbs: + - create + - get + - list + - watch + - patch + - delete +- apiGroups: + - route.openshift.io + resources: + - routes/custom-host + verbs: + - create +- apiGroups: + - coordination.k8s.io + resources: + - leases + verbs: + - get + - list + - watch + - delete + - update + - create + - patch +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + labels: + kubevirt.io: "" + name: kubevirt-operator-rolebinding + namespace: cozy-kubevirt +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: kubevirt-operator +subjects: +- kind: ServiceAccount + name: kubevirt-operator + namespace: cozy-kubevirt +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + kubevirt.io: "" + name: kubevirt-operator +rules: +- apiGroups: + - kubevirt.io + resources: + - kubevirts + verbs: + - get + - list + - watch + - patch + - update + - patch +- apiGroups: + - "" + resources: + - serviceaccounts + - services + - endpoints + - pods/exec + verbs: + - get + - list + - watch + - create + - update + - delete + - patch +- apiGroups: + - "" + resources: + - configmaps + verbs: + - patch + - delete +- apiGroups: + - batch + resources: + - jobs + verbs: + - get + - list + - watch + - create + - delete + - patch +- apiGroups: + - apps + resources: + - controllerrevisions + verbs: + - watch + - list + - create + - delete + - patch +- apiGroups: + - apps + resources: + - deployments + - daemonsets + verbs: + - get + - list + - watch + - create + - delete + - patch +- apiGroups: + - rbac.authorization.k8s.io + resources: + - clusterroles + - clusterrolebindings + - roles + - rolebindings + verbs: + - get + - list + - watch + - create + - delete + - patch + - update +- apiGroups: + - apiextensions.k8s.io + resources: + - customresourcedefinitions + verbs: + - get + - list + - watch + - create + - delete + - patch +- apiGroups: + - security.openshift.io + resources: + - securitycontextconstraints + verbs: + - create + - get + - list + - watch +- apiGroups: + - security.openshift.io + resourceNames: + - privileged + resources: + - securitycontextconstraints + verbs: + - get + - patch + - update +- apiGroups: + - security.openshift.io + resourceNames: + - kubevirt-handler + - kubevirt-controller + resources: + - securitycontextconstraints + verbs: + - get + - list + - watch + - update + - delete +- apiGroups: + - admissionregistration.k8s.io + resources: + - validatingwebhookconfigurations + - mutatingwebhookconfigurations + verbs: + - get + - list + - watch + - create + - delete + - update + - patch +- apiGroups: + - apiregistration.k8s.io + resources: + - apiservices + verbs: + - get + - list + - watch + - create + - delete + - update + - patch +- apiGroups: + - monitoring.coreos.com + resources: + - servicemonitors + - prometheusrules + verbs: + - get + - list + - watch + - create + - delete + - update + - patch +- apiGroups: + - "" + resources: + - namespaces + verbs: + - get + - list + - watch + - patch +- apiGroups: + - "" + resources: + - pods + verbs: + - get + - list + - delete + - patch +- apiGroups: + - kubevirt.io + resources: + - virtualmachines + - virtualmachineinstances + verbs: + - get + - list + - watch + - patch + - update +- apiGroups: + - "" + resources: + - persistentvolumeclaims + verbs: + - get +- apiGroups: + - kubevirt.io + resources: + - virtualmachines/status + verbs: + - patch +- apiGroups: + - kubevirt.io + resources: + - virtualmachineinstancemigrations + verbs: + - create + - get + - list + - watch + - patch +- apiGroups: + - kubevirt.io + resources: + - virtualmachineinstancepresets + verbs: + - watch + - list +- apiGroups: + - "" + resources: + - configmaps + verbs: + - get + - list + - watch +- apiGroups: + - "" + resources: + - limitranges + verbs: + - watch + - list +- apiGroups: + - apiextensions.k8s.io + resources: + - customresourcedefinitions + verbs: + - get + - list + - watch +- apiGroups: + - kubevirt.io + resources: + - kubevirts + verbs: + - get + - list + - watch +- apiGroups: + - snapshot.kubevirt.io + resources: + - virtualmachinesnapshots + - virtualmachinerestores + - virtualmachinesnapshotcontents + verbs: + - get + - list + - watch +- apiGroups: + - cdi.kubevirt.io + resources: + - datasources + - datavolumes + verbs: + - get + - list + - watch +- apiGroups: + - "" + resources: + - namespaces + verbs: + - get + - list + - watch +- apiGroups: + - instancetype.kubevirt.io + resources: + - virtualmachineinstancetypes + - virtualmachineclusterinstancetypes + - virtualmachinepreferences + - virtualmachineclusterpreferences + verbs: + - get + - list + - watch +- apiGroups: + - migrations.kubevirt.io + resources: + - migrationpolicies + verbs: + - get + - list + - watch +- apiGroups: + - apps + resources: + - controllerrevisions + verbs: + - create + - list + - get +- apiGroups: + - "" + resources: + - configmaps + verbs: + - get + - list + - watch +- apiGroups: + - "" + resources: + - namespaces + verbs: + - get + - list + - watch + - patch +- apiGroups: + - policy + resources: + - poddisruptionbudgets + verbs: + - get + - list + - watch + - delete + - create + - patch +- apiGroups: + - "" + resources: + - pods + - configmaps + - endpoints + - services + verbs: + - get + - list + - watch + - delete + - update + - create + - patch +- apiGroups: + - "" + resources: + - events + verbs: + - update + - create + - patch +- apiGroups: + - "" + resources: + - secrets + verbs: + - create +- apiGroups: + - "" + resources: + - pods/finalizers + verbs: + - update +- apiGroups: + - "" + resources: + - pods/eviction + verbs: + - create +- apiGroups: + - "" + resources: + - pods/status + verbs: + - patch +- apiGroups: + - "" + resources: + - nodes + verbs: + - get + - list + - watch + - update + - patch +- apiGroups: + - apps + resources: + - daemonsets + verbs: + - list +- apiGroups: + - apps + resources: + - controllerrevisions + verbs: + - watch + - list + - create + - delete + - get + - update +- apiGroups: + - "" + resources: + - persistentvolumeclaims + verbs: + - get + - list + - watch + - create + - update + - delete + - patch +- apiGroups: + - snapshot.kubevirt.io + resources: + - '*' + verbs: + - '*' +- apiGroups: + - export.kubevirt.io + resources: + - '*' + verbs: + - '*' +- apiGroups: + - pool.kubevirt.io + resources: + - virtualmachinepools + - virtualmachinepools/finalizers + - virtualmachinepools/status + - virtualmachinepools/scale + verbs: + - watch + - list + - create + - delete + - update + - patch + - get +- apiGroups: + - kubevirt.io + resources: + - '*' + verbs: + - '*' +- apiGroups: + - subresources.kubevirt.io + resources: + - virtualmachineinstances/addvolume + - virtualmachineinstances/removevolume + - virtualmachineinstances/freeze + - virtualmachineinstances/unfreeze + - virtualmachineinstances/softreboot + - virtualmachineinstances/sev/setupsession + - virtualmachineinstances/sev/injectlaunchsecret + verbs: + - update +- apiGroups: + - cdi.kubevirt.io + resources: + - '*' + verbs: + - '*' +- apiGroups: + - k8s.cni.cncf.io + resources: + - network-attachment-definitions + verbs: + - get +- apiGroups: + - apiextensions.k8s.io + resources: + - customresourcedefinitions + verbs: + - get + - list + - watch +- apiGroups: + - authorization.k8s.io + resources: + - subjectaccessreviews + verbs: + - create +- apiGroups: + - snapshot.storage.k8s.io + resources: + - volumesnapshotclasses + verbs: + - get + - list + - watch +- apiGroups: + - snapshot.storage.k8s.io + resources: + - volumesnapshots + verbs: + - get + - list + - watch + - create + - update + - delete +- apiGroups: + - storage.k8s.io + resources: + - storageclasses + verbs: + - get + - list + - watch +- apiGroups: + - instancetype.kubevirt.io + resources: + - virtualmachineinstancetypes + - virtualmachineclusterinstancetypes + - virtualmachinepreferences + - virtualmachineclusterpreferences + verbs: + - get + - list + - watch +- apiGroups: + - migrations.kubevirt.io + resources: + - migrationpolicies + verbs: + - get + - list + - watch +- apiGroups: + - clone.kubevirt.io + resources: + - virtualmachineclones + - virtualmachineclones/status + - virtualmachineclones/finalizers + verbs: + - get + - list + - watch + - update + - patch + - delete +- apiGroups: + - "" + resources: + - namespaces + verbs: + - get +- apiGroups: + - "" + resources: + - resourcequotas + verbs: + - list + - watch +- apiGroups: + - route.openshift.io + resources: + - routes + verbs: + - list + - get + - watch +- apiGroups: + - "" + resources: + - secrets + verbs: + - list + - get + - watch +- apiGroups: + - networking.k8s.io + resources: + - ingresses + verbs: + - list + - get + - watch +- apiGroups: + - coordination.k8s.io + resources: + - leases + verbs: + - get + - list + - watch + - delete + - update + - create + - patch +- apiGroups: + - kubevirt.io + resources: + - virtualmachineinstances + verbs: + - update + - list + - watch +- apiGroups: + - "" + resources: + - nodes + verbs: + - patch + - list + - watch + - get +- apiGroups: + - "" + resources: + - configmaps + verbs: + - get + - list + - watch +- apiGroups: + - "" + resources: + - events + verbs: + - create + - patch +- apiGroups: + - apiextensions.k8s.io + resources: + - customresourcedefinitions + verbs: + - get + - list + - watch +- apiGroups: + - kubevirt.io + resources: + - kubevirts + verbs: + - get + - list + - watch +- apiGroups: + - migrations.kubevirt.io + resources: + - migrationpolicies + verbs: + - get + - list + - watch +- apiGroups: + - "" + resources: + - configmaps + verbs: + - get + - list + - watch +- apiGroups: + - export.kubevirt.io + resources: + - virtualmachineexports + verbs: + - get + - list + - watch +- apiGroups: + - kubevirt.io + resources: + - kubevirts + verbs: + - list + - watch +- apiGroups: + - "" + resourceNames: + - kubevirt-export-ca + resources: + - configmaps + verbs: + - get + - list + - watch +- apiGroups: + - subresources.kubevirt.io + resources: + - version + - guestfs + verbs: + - get + - list +- apiGroups: + - subresources.kubevirt.io + resources: + - virtualmachineinstances/console + - virtualmachineinstances/vnc + - virtualmachineinstances/vnc/screenshot + - virtualmachineinstances/portforward + - virtualmachineinstances/guestosinfo + - virtualmachineinstances/filesystemlist + - virtualmachineinstances/userlist + - virtualmachineinstances/sev/fetchcertchain + - virtualmachineinstances/sev/querylaunchmeasurement + verbs: + - get +- apiGroups: + - subresources.kubevirt.io + resources: + - virtualmachineinstances/pause + - virtualmachineinstances/unpause + - virtualmachineinstances/addvolume + - virtualmachineinstances/removevolume + - virtualmachineinstances/freeze + - virtualmachineinstances/unfreeze + - virtualmachineinstances/softreboot + - virtualmachineinstances/sev/setupsession + - virtualmachineinstances/sev/injectlaunchsecret + verbs: + - update +- apiGroups: + - subresources.kubevirt.io + resources: + - virtualmachines/expand-spec + - virtualmachines/portforward + verbs: + - get +- apiGroups: + - subresources.kubevirt.io + resources: + - virtualmachines/start + - virtualmachines/stop + - virtualmachines/restart + - virtualmachines/addvolume + - virtualmachines/removevolume + - virtualmachines/migrate + - virtualmachines/memorydump + verbs: + - update +- apiGroups: + - subresources.kubevirt.io + resources: + - expand-vm-spec + verbs: + - update +- apiGroups: + - kubevirt.io + resources: + - virtualmachines + - virtualmachineinstances + - virtualmachineinstancepresets + - virtualmachineinstancereplicasets + - virtualmachineinstancemigrations + verbs: + - get + - delete + - create + - update + - patch + - list + - watch + - deletecollection +- apiGroups: + - snapshot.kubevirt.io + resources: + - virtualmachinesnapshots + - virtualmachinesnapshotcontents + - virtualmachinerestores + verbs: + - get + - delete + - create + - update + - patch + - list + - watch + - deletecollection +- apiGroups: + - export.kubevirt.io + resources: + - virtualmachineexports + verbs: + - get + - delete + - create + - update + - patch + - list + - watch + - deletecollection +- apiGroups: + - clone.kubevirt.io + resources: + - virtualmachineclones + verbs: + - get + - delete + - create + - update + - patch + - list + - watch + - deletecollection +- apiGroups: + - instancetype.kubevirt.io + resources: + - virtualmachineinstancetypes + - virtualmachineclusterinstancetypes + - virtualmachinepreferences + - virtualmachineclusterpreferences + verbs: + - get + - delete + - create + - update + - patch + - list + - watch + - deletecollection +- apiGroups: + - pool.kubevirt.io + resources: + - virtualmachinepools + verbs: + - get + - delete + - create + - update + - patch + - list + - watch + - deletecollection +- apiGroups: + - migrations.kubevirt.io + resources: + - migrationpolicies + verbs: + - get + - list + - watch +- apiGroups: + - subresources.kubevirt.io + resources: + - virtualmachineinstances/console + - virtualmachineinstances/vnc + - virtualmachineinstances/vnc/screenshot + - virtualmachineinstances/portforward + - virtualmachineinstances/guestosinfo + - virtualmachineinstances/filesystemlist + - virtualmachineinstances/userlist + - virtualmachineinstances/sev/fetchcertchain + - virtualmachineinstances/sev/querylaunchmeasurement + verbs: + - get +- apiGroups: + - subresources.kubevirt.io + resources: + - virtualmachineinstances/pause + - virtualmachineinstances/unpause + - virtualmachineinstances/addvolume + - virtualmachineinstances/removevolume + - virtualmachineinstances/freeze + - virtualmachineinstances/unfreeze + - virtualmachineinstances/softreboot + - virtualmachineinstances/sev/setupsession + - virtualmachineinstances/sev/injectlaunchsecret + verbs: + - update +- apiGroups: + - subresources.kubevirt.io + resources: + - virtualmachines/expand-spec + - virtualmachines/portforward + verbs: + - get +- apiGroups: + - subresources.kubevirt.io + resources: + - virtualmachines/start + - virtualmachines/stop + - virtualmachines/restart + - virtualmachines/addvolume + - virtualmachines/removevolume + - virtualmachines/migrate + - virtualmachines/memorydump + verbs: + - update +- apiGroups: + - subresources.kubevirt.io + resources: + - expand-vm-spec + verbs: + - update +- apiGroups: + - kubevirt.io + resources: + - virtualmachines + - virtualmachineinstances + - virtualmachineinstancepresets + - virtualmachineinstancereplicasets + - virtualmachineinstancemigrations + verbs: + - get + - delete + - create + - update + - patch + - list + - watch +- apiGroups: + - snapshot.kubevirt.io + resources: + - virtualmachinesnapshots + - virtualmachinesnapshotcontents + - virtualmachinerestores + verbs: + - get + - delete + - create + - update + - patch + - list + - watch +- apiGroups: + - export.kubevirt.io + resources: + - virtualmachineexports + verbs: + - get + - delete + - create + - update + - patch + - list + - watch +- apiGroups: + - clone.kubevirt.io + resources: + - virtualmachineclones + verbs: + - get + - delete + - create + - update + - patch + - list + - watch +- apiGroups: + - instancetype.kubevirt.io + resources: + - virtualmachineinstancetypes + - virtualmachineclusterinstancetypes + - virtualmachinepreferences + - virtualmachineclusterpreferences + verbs: + - get + - delete + - create + - update + - patch + - list + - watch +- apiGroups: + - pool.kubevirt.io + resources: + - virtualmachinepools + verbs: + - get + - delete + - create + - update + - patch + - list + - watch +- apiGroups: + - kubevirt.io + resources: + - kubevirts + verbs: + - get + - list +- apiGroups: + - migrations.kubevirt.io + resources: + - migrationpolicies + verbs: + - get + - list + - watch +- apiGroups: + - subresources.kubevirt.io + resources: + - virtualmachines/expand-spec + - virtualmachineinstances/guestosinfo + - virtualmachineinstances/filesystemlist + - virtualmachineinstances/userlist + - virtualmachineinstances/sev/fetchcertchain + - virtualmachineinstances/sev/querylaunchmeasurement + verbs: + - get +- apiGroups: + - subresources.kubevirt.io + resources: + - expand-vm-spec + verbs: + - update +- apiGroups: + - kubevirt.io + resources: + - virtualmachines + - virtualmachineinstances + - virtualmachineinstancepresets + - virtualmachineinstancereplicasets + - virtualmachineinstancemigrations + verbs: + - get + - list + - watch +- apiGroups: + - snapshot.kubevirt.io + resources: + - virtualmachinesnapshots + - virtualmachinesnapshotcontents + - virtualmachinerestores + verbs: + - get + - list + - watch +- apiGroups: + - export.kubevirt.io + resources: + - virtualmachineexports + verbs: + - get + - list + - watch +- apiGroups: + - clone.kubevirt.io + resources: + - virtualmachineclones + verbs: + - get + - list + - watch +- apiGroups: + - instancetype.kubevirt.io + resources: + - virtualmachineinstancetypes + - virtualmachineclusterinstancetypes + - virtualmachinepreferences + - virtualmachineclusterpreferences + verbs: + - get + - list + - watch +- apiGroups: + - pool.kubevirt.io + resources: + - virtualmachinepools + verbs: + - get + - list + - watch +- apiGroups: + - migrations.kubevirt.io + resources: + - migrationpolicies + verbs: + - get + - list + - watch +- apiGroups: + - instancetype.kubevirt.io + resources: + - virtualmachineclusterinstancetypes + - virtualmachineclusterpreferences + verbs: + - get + - list + - watch +- apiGroups: + - authentication.k8s.io + resources: + - tokenreviews + verbs: + - create +- apiGroups: + - authorization.k8s.io + resources: + - subjectaccessreviews + verbs: + - create +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + labels: + kubevirt.io: "" + name: kubevirt-operator +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: kubevirt-operator +subjects: +- kind: ServiceAccount + name: kubevirt-operator + namespace: cozy-kubevirt + +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + kubevirt.io: virt-operator + name: virt-operator + namespace: cozy-kubevirt +spec: + replicas: 2 + selector: + matchLabels: + kubevirt.io: virt-operator + strategy: + type: RollingUpdate + template: + metadata: + labels: + kubevirt.io: virt-operator + name: virt-operator + prometheus.kubevirt.io: "true" + name: virt-operator + spec: + affinity: + podAntiAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - podAffinityTerm: + labelSelector: + matchExpressions: + - key: kubevirt.io + operator: In + values: + - virt-operator + topologyKey: kubernetes.io/hostname + weight: 1 + containers: + - args: + - --port + - "8443" + - -v + - "2" + command: + - virt-operator + env: + - name: VIRT_OPERATOR_IMAGE + value: quay.io/kubevirt/virt-operator:v1.1.0 + - name: WATCH_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.annotations['olm.targetNamespaces'] + - name: KUBEVIRT_VERSION + value: v1.1.0 + image: quay.io/kubevirt/virt-operator:v1.1.0 + imagePullPolicy: IfNotPresent + name: virt-operator + ports: + - containerPort: 8443 + name: metrics + protocol: TCP + - containerPort: 8444 + name: webhooks + protocol: TCP + readinessProbe: + httpGet: + path: /metrics + port: 8443 + scheme: HTTPS + initialDelaySeconds: 5 + timeoutSeconds: 10 + resources: + requests: + cpu: 10m + memory: 450Mi + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + seccompProfile: + type: RuntimeDefault + volumeMounts: + - mountPath: /etc/virt-operator/certificates + name: kubevirt-operator-certs + readOnly: true + - mountPath: /profile-data + name: profile-data + nodeSelector: + kubernetes.io/os: linux + priorityClassName: kubevirt-cluster-critical + securityContext: + runAsNonRoot: true + seccompProfile: + type: RuntimeDefault + serviceAccountName: kubevirt-operator + tolerations: + - key: CriticalAddonsOnly + operator: Exists + volumes: + - name: kubevirt-operator-certs + secret: + optional: true + secretName: kubevirt-operator-certs + - emptyDir: {} + name: profile-data +--- \ No newline at end of file diff --git a/packages/system/kubevirt-operator/values.yaml b/packages/system/kubevirt-operator/values.yaml new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/packages/system/kubevirt-operator/values.yaml @@ -0,0 +1 @@ + diff --git a/packages/system/kubevirt/Chart.yaml b/packages/system/kubevirt/Chart.yaml new file mode 100644 index 00000000..51a28e7c --- /dev/null +++ b/packages/system/kubevirt/Chart.yaml @@ -0,0 +1,2 @@ +name: cozy-kubevirt +version: 1.0.0 diff --git a/packages/system/kubevirt/Makefile b/packages/system/kubevirt/Makefile new file mode 100644 index 00000000..883c83ba --- /dev/null +++ b/packages/system/kubevirt/Makefile @@ -0,0 +1,18 @@ +NAME=kubevirt +NAMESPACE=cozy-kubevirt + +show: + helm template --dry-run=server -n $(NAMESPACE) $(NAME) . + +apply: + helm upgrade -i -n $(NAMESPACE) $(NAME) . + +diff: + helm diff upgrade --allow-unreleased --normalize-manifests -n $(NAMESPACE) $(NAME) . + +update: + rm -rf templates + mkdir templates + export RELEASE=$$(curl https://storage.googleapis.com/kubevirt-prow/release/kubevirt/kubevirt/stable.txt) && \ + wget https://github.com/kubevirt/kubevirt/releases/download/$${RELEASE}/kubevirt-cr.yaml -O templates/kubevirt-cr.yaml + sed -i 's/namespace: kubevirt/namespace: cozy-kubevirt/g' templates/kubevirt-cr.yaml diff --git a/packages/system/kubevirt/templates/kubevirt-cr.yaml b/packages/system/kubevirt/templates/kubevirt-cr.yaml new file mode 100644 index 00000000..f8b70ebd --- /dev/null +++ b/packages/system/kubevirt/templates/kubevirt-cr.yaml @@ -0,0 +1,15 @@ +--- +apiVersion: kubevirt.io/v1 +kind: KubeVirt +metadata: + name: kubevirt + namespace: cozy-kubevirt +spec: + certificateRotateStrategy: {} + configuration: + developerConfiguration: + featureGates: + - HotplugVolumes + customizeComponents: {} + imagePullPolicy: IfNotPresent + workloadUpdateStrategy: {} diff --git a/packages/system/kubevirt/values.yaml b/packages/system/kubevirt/values.yaml new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/packages/system/kubevirt/values.yaml @@ -0,0 +1 @@ + diff --git a/packages/system/linstor/.helmignore b/packages/system/linstor/.helmignore new file mode 100644 index 00000000..1e107f52 --- /dev/null +++ b/packages/system/linstor/.helmignore @@ -0,0 +1 @@ +examples diff --git a/packages/system/linstor/Chart.yaml b/packages/system/linstor/Chart.yaml new file mode 100644 index 00000000..aefaae64 --- /dev/null +++ b/packages/system/linstor/Chart.yaml @@ -0,0 +1,2 @@ +name: cozy-linstor +version: 1.0.0 diff --git a/packages/system/linstor/Makefile b/packages/system/linstor/Makefile new file mode 100644 index 00000000..e19d5f36 --- /dev/null +++ b/packages/system/linstor/Makefile @@ -0,0 +1,11 @@ +NAME=linstor +NAMESPACE=cozy-linstor + +show: + helm template --dry-run=server -n $(NAMESPACE) $(NAME) . + +apply: + helm upgrade -i -n $(NAMESPACE) $(NAME) . + +diff: + helm diff upgrade --allow-unreleased --normalize-manifests -n $(NAMESPACE) $(NAME) . diff --git a/packages/system/linstor/examples/1.yaml b/packages/system/linstor/examples/1.yaml new file mode 100644 index 00000000..e43081e8 --- /dev/null +++ b/packages/system/linstor/examples/1.yaml @@ -0,0 +1,28 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: myclaim +spec: + accessModes: + - ReadWriteOnce + volumeMode: Filesystem + resources: + requests: + storage: 8Gi + #storageClassName: linstor-lvm +--- +apiVersion: v1 +kind: Pod +metadata: + name: mypod +spec: + containers: + - name: myfrontend + image: nginx + volumeMounts: + - mountPath: "/var/www/html" + name: mypd + volumes: + - name: mypd + persistentVolumeClaim: + claimName: myclaim diff --git a/packages/system/linstor/hack/proxmox-install-module.sh b/packages/system/linstor/hack/proxmox-install-module.sh new file mode 100644 index 00000000..679a53ed --- /dev/null +++ b/packages/system/linstor/hack/proxmox-install-module.sh @@ -0,0 +1,9 @@ +wget -O /tmp/package-signing-pubkey.asc https://packages.linbit.com/package-signing-pubkey.asc +gpg --yes -o /etc/apt/trusted.gpg.d/linbit-keyring.gpg --dearmor /tmp/package-signing-pubkey.asc +PVERS=$(pveversion | awk -F'[/.]' '{print $2}') +echo "deb [signed-by=/etc/apt/trusted.gpg.d/linbit-keyring.gpg] http://packages.linbit.com/public/ proxmox-$PVERS drbd-9" > /etc/apt/sources.list +apt update && apt -y install drbd-dkms +echo "options drbd usermode_helper=disabled" > /etc/modprobe.d/drbd.conf +echo drbd > /etc/modules-load.d/drbd.conf +modprobe drbd +kubectl label node "${HOSTNAME}" node-role.kubernetes.io/linstor= --overwrite diff --git a/packages/system/linstor/templates/cluster.yaml b/packages/system/linstor/templates/cluster.yaml new file mode 100644 index 00000000..553d2716 --- /dev/null +++ b/packages/system/linstor/templates/cluster.yaml @@ -0,0 +1,15 @@ +apiVersion: piraeus.io/v1 +kind: LinstorCluster +metadata: + name: linstorcluster +spec: + #nodeSelector: + # node-role.kubernetes.io/linstor: "" + internalTLS: + certManager: + name: linstor-internal-ca + kind: Issuer + apiTLS: + certManager: + name: linstor-api-ca + kind: Issuer diff --git a/packages/system/linstor/templates/linstor-api-tls.yaml b/packages/system/linstor/templates/linstor-api-tls.yaml new file mode 100644 index 00000000..eeda9731 --- /dev/null +++ b/packages/system/linstor/templates/linstor-api-tls.yaml @@ -0,0 +1,27 @@ +--- +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: linstor-api-ca + namespace: {{ .Release.namespace }} +spec: + commonName: linstor-api-ca + secretName: linstor-api-ca + duration: 87600h # 10 years + isCA: true + usages: + - signing + - key encipherment + - cert sign + issuerRef: + name: ca-bootstrapper + kind: Issuer +--- +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + name: linstor-api-ca + namespace: {{ .Release.namespace }} +spec: + ca: + secretName: linstor-api-ca diff --git a/packages/system/linstor/templates/linstor-internal-tls.yaml b/packages/system/linstor/templates/linstor-internal-tls.yaml new file mode 100644 index 00000000..5d536625 --- /dev/null +++ b/packages/system/linstor/templates/linstor-internal-tls.yaml @@ -0,0 +1,27 @@ +--- +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: linstor-internal-ca + namespace: {{ .Release.namespace }} +spec: + commonName: linstor-internal-ca + secretName: linstor-internal-ca + duration: 87600h # 10 years + isCA: true + usages: + - signing + - key encipherment + - cert sign + issuerRef: + name: ca-bootstrapper + kind: Issuer +--- +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + name: linstor-internal-ca + namespace: {{ .Release.namespace }} +spec: + ca: + secretName: linstor-internal-ca diff --git a/packages/system/linstor/templates/satellites.yaml b/packages/system/linstor/templates/satellites.yaml new file mode 100644 index 00000000..dcfa5b3d --- /dev/null +++ b/packages/system/linstor/templates/satellites.yaml @@ -0,0 +1,48 @@ +apiVersion: piraeus.io/v1 +kind: LinstorSatelliteConfiguration +metadata: + name: linstor-satellites +spec: + internalTLS: + certManager: + name: linstor-internal-ca + kind: Issuer + #storagePools: + #- name: "data" + # lvmPool: + # volumeGroup: "data" + patches: + - target: + kind: Pod + name: satellite + patch: | + apiVersion: v1 + kind: Pod + metadata: + name: satellite + spec: + hostNetwork: true + initContainers: + - name: drbd-shutdown-guard + $patch: delete + - name: drbd-module-loader + $patch: delete + volumes: + - name: run-systemd-system + $patch: delete + - name: run-drbd-shutdown-guard + $patch: delete + - name: systemd-bus-socket + $patch: delete + - name: lib-modules + $patch: delete + - name: usr-src + $patch: delete + - name: etc-lvm-backup + hostPath: + path: /var/etc/lvm/backup + type: DirectoryOrCreate + - name: etc-lvm-archive + hostPath: + path: /var/etc/lvm/archive + type: DirectoryOrCreate diff --git a/packages/system/linstor/values.yaml b/packages/system/linstor/values.yaml new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/packages/system/linstor/values.yaml @@ -0,0 +1 @@ + diff --git a/packages/system/mariadb-operator/.helmignore b/packages/system/mariadb-operator/.helmignore new file mode 100644 index 00000000..d5c178e8 --- /dev/null +++ b/packages/system/mariadb-operator/.helmignore @@ -0,0 +1,3 @@ +images +hack +.gitkeep diff --git a/packages/system/mariadb-operator/Chart.yaml b/packages/system/mariadb-operator/Chart.yaml new file mode 100644 index 00000000..6494e0d1 --- /dev/null +++ b/packages/system/mariadb-operator/Chart.yaml @@ -0,0 +1,2 @@ +name: cozy-mariadb-operator +version: 1.0.0 diff --git a/packages/system/mariadb-operator/Makefile b/packages/system/mariadb-operator/Makefile new file mode 100644 index 00000000..ce589c71 --- /dev/null +++ b/packages/system/mariadb-operator/Makefile @@ -0,0 +1,17 @@ +NAME=mariadb-operator +NAMESPACE=cozy-mariadb-operator + +show: + helm template --dry-run=server -n $(NAMESPACE) $(NAME) . + +apply: + helm upgrade -i -n $(NAMESPACE) $(NAME) . + +diff: + helm diff upgrade --allow-unreleased --normalize-manifests -n $(NAMESPACE) $(NAME) . + +update: + rm -rf charts + helm repo add mariadb-operator https://mariadb-operator.github.io/mariadb-operator + helm repo update mariadb-operator + helm pull mariadb-operator/mariadb-operator --untar --untardir charts diff --git a/packages/system/mariadb-operator/charts/mariadb-operator/.helmignore b/packages/system/mariadb-operator/charts/mariadb-operator/.helmignore new file mode 100644 index 00000000..0e8a0eb3 --- /dev/null +++ b/packages/system/mariadb-operator/charts/mariadb-operator/.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/packages/system/mariadb-operator/charts/mariadb-operator/Chart.yaml b/packages/system/mariadb-operator/charts/mariadb-operator/Chart.yaml new file mode 100644 index 00000000..47b60e92 --- /dev/null +++ b/packages/system/mariadb-operator/charts/mariadb-operator/Chart.yaml @@ -0,0 +1,17 @@ +apiVersion: v2 +appVersion: v0.0.22 +description: Run and operate MariaDB in a cloud native way +home: https://github.com/mariadb-operator/mariadb-operator +icon: https://mariadb-operator.github.io/mariadb-operator/assets/mariadb.png +keywords: +- mariadb +- operator +- mariadb-operator +- database +kubeVersion: '>= 1.16.0-0' +maintainers: +- email: mariadb-operator@proton.me + name: mmontes11 +name: mariadb-operator +type: application +version: 0.22.0 diff --git a/packages/system/mariadb-operator/charts/mariadb-operator/README.md b/packages/system/mariadb-operator/charts/mariadb-operator/README.md new file mode 100644 index 00000000..c6d866a8 --- /dev/null +++ b/packages/system/mariadb-operator/charts/mariadb-operator/README.md @@ -0,0 +1,93 @@ + + +[//]: # (README.md generated by gotmpl. DO NOT EDIT.) + +

    +mariadb +

    + +![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![Version: 0.22.0](https://img.shields.io/badge/Version-0.22.0-informational?style=flat-square) ![AppVersion: v0.0.22](https://img.shields.io/badge/AppVersion-v0.0.22-informational?style=flat-square) + +Run and operate MariaDB in a cloud native way + +## Installing +```bash +helm repo add mariadb-operator https://mariadb-operator.github.io/mariadb-operator +helm install mariadb-operator mariadb-operator/mariadb-operator +``` + +## Uninstalling +```bash +helm uninstall mariadb-operator +``` + +## Values + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| affinity | object | `{}` | Affinity to add to controller Pod | +| clusterName | string | `"cluster.local"` | Cluster DNS name | +| extrArgs | list | `[]` | Extra arguments to be passed to the controller entrypoint | +| extraVolumeMounts | list | `[]` | Extra volumes to mount to the container. | +| extraVolumes | list | `[]` | Extra volumes to pass to pod. | +| fullnameOverride | string | `""` | | +| ha.enabled | bool | `false` | Enable high availability | +| ha.leaseId | string | `"mariadb.mmontes.io"` | Lease resource name to be used for leader election | +| ha.replicas | int | `3` | Number of replicas | +| image.pullPolicy | string | `"IfNotPresent"` | | +| image.repository | string | `"ghcr.io/mariadb-operator/mariadb-operator"` | | +| image.tag | string | `""` | Image tag to use. By default the chart appVersion is used | +| imagePullSecrets | list | `[]` | | +| logLevel | string | `"INFO"` | Controller log level | +| metrics.enabled | bool | `false` | Enable prometheus metrics. Prometheus must be installed in the cluster | +| metrics.serviceMonitor.additionalLabels | object | `{}` | Labels to be added to the controller ServiceMonitor | +| metrics.serviceMonitor.enabled | bool | `true` | Enable controller ServiceMonitor | +| metrics.serviceMonitor.interval | string | `"30s"` | Interval to scrape metrics | +| metrics.serviceMonitor.scrapeTimeout | string | `"25s"` | Timeout if metrics can't be retrieved in given time interval | +| nameOverride | string | `""` | | +| nodeSelector | object | `{}` | Node selectors to add to controller Pod | +| podAnnotations | object | `{}` | Annotations to add to controller Pod | +| podSecurityContext | object | `{}` | Security context to add to controller Pod | +| rbac.enabled | bool | `true` | Specifies whether RBAC resources should be created | +| resources | object | `{}` | Resources to add to controller container | +| securityContext | object | `{}` | Security context to add to controller container | +| serviceAccount.annotations | object | `{}` | Annotations to add to the service account | +| serviceAccount.automount | bool | `true` | Automounts the service account token in all containers of the Pod | +| serviceAccount.enabled | bool | `true` | Specifies whether a service account should be created | +| serviceAccount.extraLabels | object | `{}` | Extra Labels to add to the service account | +| serviceAccount.name | string | `""` | The name of the service account to use. If not set and enabled is true, a name is generated using the fullname template | +| tolerations | list | `[]` | Tolerations to add to controller Pod | +| webhook.affinity | object | `{}` | Affinity to add to controller Pod | +| webhook.annotations | object | `{}` | Annotations for webhook configurations. | +| webhook.certificate.certManager | bool | `false` | Use cert-manager to issue and rotate the certificate. If set to false, a default certificate will be used. | +| webhook.certificate.default | object | `{"annotations":{},"caExpirationDays":365,"certExpirationDays":365,"hook":""}` | Default certificate generated when the chart is installed or upgraded. | +| webhook.certificate.default.annotations | object | `{}` | Annotations for certificate Secret. | +| webhook.certificate.default.caExpirationDays | int | `365` | Certificate authority expiration in days. | +| webhook.certificate.default.certExpirationDays | int | `365` | Certificate expiration in days. | +| webhook.certificate.default.hook | string | `""` | Helm hook to be added to the default certificate. | +| webhook.certificate.path | string | `"/tmp/k8s-webhook-server/serving-certs"` | Path where the certificate will be mounted. | +| webhook.extrArgs | list | `[]` | Extra arguments to be passed to the webhook entrypoint | +| webhook.extraVolumeMounts | list | `[]` | Extra volumes to mount to webhook container | +| webhook.extraVolumes | list | `[]` | Extra volumes to pass to webhook Pod | +| webhook.hostNetwork | bool | `false` | Expose the webhook server in the host network | +| webhook.image.pullPolicy | string | `"IfNotPresent"` | | +| webhook.image.repository | string | `"ghcr.io/mariadb-operator/mariadb-operator"` | | +| webhook.image.tag | string | `""` | Image tag to use. By default the chart appVersion is used | +| webhook.imagePullSecrets | list | `[]` | | +| webhook.nodeSelector | object | `{}` | Node selectors to add to controller Pod | +| webhook.podAnnotations | object | `{}` | Annotations to add to webhook Pod | +| webhook.podSecurityContext | object | `{}` | Security context to add to webhook Pod | +| webhook.port | int | `10250` | Port to be used by the webhook server | +| webhook.resources | object | `{}` | Resources to add to webhook container | +| webhook.securityContext | object | `{}` | Security context to add to webhook container | +| webhook.serviceAccount.annotations | object | `{}` | Annotations to add to the service account | +| webhook.serviceAccount.automount | bool | `true` | Automounts the service account token in all containers of the Pod | +| webhook.serviceAccount.enabled | bool | `true` | Specifies whether a service account should be created | +| webhook.serviceAccount.extraLabels | object | `{}` | Extra Labels to add to the service account | +| webhook.serviceAccount.name | string | `""` | The name of the service account to use. If not set and enabled is true, a name is generated using the fullname template | +| webhook.serviceMonitor.additionalLabels | object | `{}` | Labels to be added to the webhook ServiceMonitor | +| webhook.serviceMonitor.enabled | bool | `true` | Enable webhook ServiceMonitor. Metrics must be enabled | +| webhook.serviceMonitor.interval | string | `"30s"` | Interval to scrape metrics | +| webhook.serviceMonitor.scrapeTimeout | string | `"25s"` | Timeout if metrics can't be retrieved in given time interval | +| webhook.tolerations | list | `[]` | Tolerations to add to controller Pod | + diff --git a/packages/system/mariadb-operator/charts/mariadb-operator/README.md.gotmpl b/packages/system/mariadb-operator/charts/mariadb-operator/README.md.gotmpl new file mode 100644 index 00000000..fe4320e2 --- /dev/null +++ b/packages/system/mariadb-operator/charts/mariadb-operator/README.md.gotmpl @@ -0,0 +1,26 @@ +{{ $chartRepo := "https://mariadb-operator.github.io/mariadb-operator" }} +{{ $org := "mariadb-operator" }} +{{ $release := "mariadb-operator" }} +[//]: # (README.md generated by gotmpl. DO NOT EDIT.) + +

    +mariadb +

    + +{{ template "chart.typeBadge" . }}{{ template "chart.versionBadge" . }}{{ template "chart.appVersionBadge" . }} + +{{ template "chart.description" . }} + +## Installing +```bash +helm repo add {{ $org }} {{ $chartRepo }} +helm install {{ $release }} {{ $org }}/{{ template "chart.name" . }} +``` + +## Uninstalling +```bash +helm uninstall {{ $release }} +``` + +{{ template "chart.valuesSection" . }} + diff --git a/packages/system/mariadb-operator/charts/mariadb-operator/crds/crds.yaml b/packages/system/mariadb-operator/charts/mariadb-operator/crds/crds.yaml new file mode 100644 index 00000000..96eb748e --- /dev/null +++ b/packages/system/mariadb-operator/charts/mariadb-operator/crds/crds.yaml @@ -0,0 +1,16586 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.11.1 + creationTimestamp: null + name: backups.mariadb.mmontes.io +spec: + group: mariadb.mmontes.io + names: + kind: Backup + listKind: BackupList + plural: backups + shortNames: + - bmdb + singular: backup + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .status.conditions[?(@.type=="Complete")].status + name: Complete + type: string + - jsonPath: .status.conditions[?(@.type=="Complete")].message + name: Status + type: string + - jsonPath: .spec.mariaDbRef.name + name: MariaDB + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + description: Backup is the Schema for the backups 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: BackupSpec defines the desired state of Backup + properties: + affinity: + description: Affinity is a group of affinity scheduling rules. + properties: + nodeAffinity: + description: Describes node affinity scheduling rules for the + pod. + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods to + nodes that satisfy the affinity expressions specified by + this field, but it may choose a node that violates one or + more of the expressions. The node that is most preferred + is the one with the greatest sum of weights, i.e. for each + node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, + etc.), compute a sum by iterating through the elements of + this field and adding "weight" to the sum if the node matches + the corresponding matchExpressions; the node(s) with the + highest sum are the most preferred. + items: + description: An empty preferred scheduling term matches + all objects with implicit weight 0 (i.e. it's a no-op). + A null preferred scheduling term matches no objects (i.e. + is also a no-op). + properties: + preference: + description: A node selector term, associated with the + corresponding weight. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists, DoesNotExist. Gt, and + Lt. + type: string + values: + description: 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. If the operator is Gt or + Lt, the values array must have a single + element, which will be interpreted as an + integer. This array is replaced during a + strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists, DoesNotExist. Gt, and + Lt. + type: string + values: + description: 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. If the operator is Gt or + Lt, the values array must have a single + element, which will be interpreted as an + integer. This array is replaced during a + strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + x-kubernetes-map-type: atomic + weight: + description: Weight associated with matching the corresponding + nodeSelectorTerm, in the range 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by this + field are not met at scheduling time, the pod will not be + scheduled onto the node. If the affinity requirements specified + by this field cease to be met at some point during pod execution + (e.g. due to an update), the system may or may not try to + eventually evict the pod from its node. + properties: + nodeSelectorTerms: + description: Required. A list of node selector terms. + The terms are ORed. + items: + description: A null or empty node selector term matches + no objects. The requirements of them are ANDed. The + TopologySelectorTerm type implements a subset of the + NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists, DoesNotExist. Gt, and + Lt. + type: string + values: + description: 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. If the operator is Gt or + Lt, the values array must have a single + element, which will be interpreted as an + integer. This array is replaced during a + strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists, DoesNotExist. Gt, and + Lt. + type: string + values: + description: 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. If the operator is Gt or + Lt, the values array must have a single + element, which will be interpreted as an + integer. This array is replaced during a + strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + x-kubernetes-map-type: atomic + type: array + required: + - nodeSelectorTerms + type: object + x-kubernetes-map-type: atomic + type: object + podAffinity: + description: Describes pod affinity scheduling rules (e.g. co-locate + this pod in the same node, zone, etc. as some other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods to + nodes that satisfy the affinity expressions specified by + this field, but it may choose a node that violates one or + more of the expressions. The node that is most preferred + is the one with the greatest sum of weights, i.e. for each + node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, + etc.), compute a sum by iterating through the elements of + this field and adding "weight" to the sum if the node has + pods which matches the corresponding podAffinityTerm; the + node(s) with the highest sum are the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by this + field and the ones listed in the namespaces field. + null selector and null or empty namespaces list + means "this pod's namespace". An empty selector + ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. The + term is applied to the union of the namespaces + listed in this field and the ones selected by + namespaceSelector. null or empty namespaces list + and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods + matching the labelSelector in the specified namespaces, + where co-located is defined as running on a node + whose value of the label with key topologyKey + matches that of any node on which any of the selected + pods is running. Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching the corresponding + podAffinityTerm, in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by this + field are not met at scheduling time, the pod will not be + scheduled onto the node. If the affinity requirements specified + by this field cease to be met at some point during pod execution + (e.g. due to a pod label update), the system may or may + not try to eventually evict the pod from its node. When + there are multiple elements, the lists of nodes corresponding + to each podAffinityTerm are intersected, i.e. all terms + must be satisfied. + items: + description: Defines a set of pods (namely those matching + the labelSelector relative to the given namespace(s)) + that this pod should be co-located (affinity) or not co-located + (anti-affinity) with, where co-located is defined as running + on a node whose value of the label with key + matches that of any node on which a pod of the set of + pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied to the + union of the namespaces selected by this field and + the ones listed in the namespaces field. null selector + and null or empty namespaces list means "this pod's + namespace". An empty selector ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list of namespace + names that the term applies to. The term is applied + to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. null or + empty namespaces list and null namespaceSelector means + "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where + co-located is defined as running on a node whose value + of the label with key topologyKey matches that of + any node on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + podAntiAffinity: + description: Describes pod anti-affinity scheduling rules (e.g. + avoid putting this pod in the same node, zone, etc. as some + other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods to + nodes that satisfy the anti-affinity expressions specified + by this field, but it may choose a node that violates one + or more of the expressions. The node that is most preferred + is the one with the greatest sum of weights, i.e. for each + node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling anti-affinity expressions, + etc.), compute a sum by iterating through the elements of + this field and adding "weight" to the sum if the node has + pods which matches the corresponding podAffinityTerm; the + node(s) with the highest sum are the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by this + field and the ones listed in the namespaces field. + null selector and null or empty namespaces list + means "this pod's namespace". An empty selector + ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. The + term is applied to the union of the namespaces + listed in this field and the ones selected by + namespaceSelector. null or empty namespaces list + and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods + matching the labelSelector in the specified namespaces, + where co-located is defined as running on a node + whose value of the label with key topologyKey + matches that of any node on which any of the selected + pods is running. Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching the corresponding + podAffinityTerm, in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the anti-affinity requirements specified by + this field are not met at scheduling time, the pod will + not be scheduled onto the node. If the anti-affinity requirements + specified by this field cease to be met at some point during + pod execution (e.g. due to a pod label update), the system + may or may not try to eventually evict the pod from its + node. When there are multiple elements, the lists of nodes + corresponding to each podAffinityTerm are intersected, i.e. + all terms must be satisfied. + items: + description: Defines a set of pods (namely those matching + the labelSelector relative to the given namespace(s)) + that this pod should be co-located (affinity) or not co-located + (anti-affinity) with, where co-located is defined as running + on a node whose value of the label with key + matches that of any node on which a pod of the set of + pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied to the + union of the namespaces selected by this field and + the ones listed in the namespaces field. null selector + and null or empty namespaces list means "this pod's + namespace". An empty selector ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list of namespace + names that the term applies to. The term is applied + to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. null or + empty namespaces list and null namespaceSelector means + "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where + co-located is defined as running on a node whose value + of the label with key topologyKey matches that of + any node on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + type: object + args: + items: + type: string + type: array + backoffLimit: + default: 5 + format: int32 + type: integer + mariaDbRef: + properties: + apiVersion: + description: API version of the referent. + type: string + fieldPath: + description: 'If referring to a piece of an object instead of + an entire object, this string should contain a valid JSON/Go + field access statement, such as desiredState.manifest.containers[2]. + For example, if the object reference is to a container within + a pod, this would take on a value like: "spec.containers{name}" + (where "name" refers to the name of the container that triggered + the event) or if no container name is specified "spec.containers[2]" + (container with index 2 in this pod). This syntax is chosen + only to have some well-defined way of referencing a part of + an object. TODO: this design is not final and this field is + subject to change in the future.' + type: string + kind: + description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + namespace: + description: 'Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/' + type: string + resourceVersion: + description: 'Specific resourceVersion to which this reference + is made, if any. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency' + type: string + uid: + description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids' + type: string + waitForIt: + default: true + type: boolean + type: object + x-kubernetes-map-type: atomic + maxRetentionDays: + default: 30 + format: int32 + type: integer + nodeSelector: + additionalProperties: + type: string + type: object + resources: + description: ResourceRequirements describes the compute resource requirements. + properties: + claims: + description: "Claims lists the names of resources, defined in + spec.resourceClaims, that are used by this container. \n This + is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n 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 + 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 + restartPolicy: + default: OnFailure + description: RestartPolicy describes how the container should be restarted. + Only one of the following restart policies may be specified. If + none of the following policies is specified, the default one is + RestartPolicyAlways. + type: string + schedule: + properties: + cron: + type: string + suspend: + default: false + type: boolean + required: + - cron + type: object + storage: + properties: + persistentVolumeClaim: + description: PersistentVolumeClaimSpec describes the common attributes + of storage devices and allows a Source for provider-specific + attributes + properties: + accessModes: + description: 'accessModes contains the desired access modes + the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' + items: + type: string + type: array + dataSource: + description: 'dataSource field can be used to specify either: + * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) + * An existing PVC (PersistentVolumeClaim) If the provisioner + or an external controller can support the specified data + source, it will create a new volume based on the contents + of the specified data source. When the AnyVolumeDataSource + feature gate is enabled, dataSource contents will be copied + to dataSourceRef, and dataSourceRef contents will be copied + to dataSource when dataSourceRef.namespace is not specified. + If the namespace is specified, then dataSourceRef will not + be copied to dataSource.' + properties: + apiGroup: + description: APIGroup is the group for the resource being + referenced. If APIGroup is not specified, the specified + Kind must be in the core API group. For any other third-party + types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource being referenced + type: string + name: + description: Name is the name of resource being referenced + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + description: 'dataSourceRef specifies the object from which + to populate the volume with data, if a non-empty volume + is desired. This may be any object from a non-empty API + group (non core object) or a PersistentVolumeClaim object. + When this field is specified, volume binding will only succeed + if the type of the specified object matches some installed + volume populator or dynamic provisioner. This field will + replace the functionality of the dataSource field and as + such if both fields are non-empty, they must have the same + value. For backwards compatibility, when namespace isn''t + specified in dataSourceRef, both fields (dataSource and + dataSourceRef) will be set to the same value automatically + if one of them is empty and the other is non-empty. When + namespace is specified in dataSourceRef, dataSource isn''t + set to the same value and must be empty. There are three + important differences between dataSource and dataSourceRef: + * While dataSource only allows two specific types of objects, + dataSourceRef allows any non-core object, as well as PersistentVolumeClaim + objects. * While dataSource ignores disallowed values (dropping + them), dataSourceRef preserves all values, and generates + an error if a disallowed value is specified. * While dataSource + only allows local objects, dataSourceRef allows objects + in any namespaces. (Beta) Using this field requires the + AnyVolumeDataSource feature gate to be enabled. (Alpha) + Using the namespace field of dataSourceRef requires the + CrossNamespaceVolumeDataSource feature gate to be enabled.' + properties: + apiGroup: + description: APIGroup is the group for the resource being + referenced. If APIGroup is not specified, the specified + Kind must be in the core API group. For any other third-party + types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource being referenced + type: string + name: + description: Name is the name of resource being referenced + type: string + namespace: + description: Namespace is the namespace of resource being + referenced Note that when a namespace is specified, + a gateway.networking.k8s.io/ReferenceGrant object is + required in the referent namespace to allow that namespace's + owner to accept the reference. See the ReferenceGrant + documentation for details. (Alpha) This field requires + the CrossNamespaceVolumeDataSource feature gate to be + enabled. + type: string + required: + - kind + - name + type: object + resources: + description: 'resources represents the minimum resources the + volume should have. If RecoverVolumeExpansionFailure feature + is enabled users are allowed to specify resource requirements + that are lower than previous value but must still be higher + than capacity recorded in the status field of the claim. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. \n 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 + 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 + selector: + description: selector is a label query over volumes to consider + for binding. + 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 + required: + - key + - operator + type: object + type: array + 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 + storageClassName: + description: 'storageClassName is the name of the StorageClass + required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' + type: string + volumeMode: + description: volumeMode defines what type of volume is required + by the claim. Value of Filesystem is implied when not included + in claim spec. + type: string + volumeName: + description: volumeName is the binding reference to the PersistentVolume + backing this claim. + type: string + type: object + volume: + description: Represents the source of a volume to mount. Only + one of its members may be specified. + properties: + awsElasticBlockStore: + description: 'awsElasticBlockStore represents an AWS Disk + resource that is attached to a kubelet''s host machine and + then exposed to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' + properties: + fsType: + description: 'fsType is the filesystem type of the volume + that you want to mount. Tip: Ensure that the filesystem + type is supported by the host operating system. Examples: + "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" + if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore + TODO: how do we prevent errors in the filesystem from + compromising the machine' + type: string + partition: + description: 'partition is the partition in the volume + that you want to mount. If omitted, the default is to + mount by volume name. Examples: For volume /dev/sda1, + you specify the partition as "1". Similarly, the volume + partition for /dev/sda is "0" (or you can leave the + property empty).' + format: int32 + type: integer + readOnly: + description: 'readOnly value true will force the readOnly + setting in VolumeMounts. More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' + type: boolean + volumeID: + description: 'volumeID is unique ID of the persistent + disk resource in AWS (Amazon EBS volume). More info: + https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' + type: string + required: + - volumeID + type: object + azureDisk: + description: azureDisk represents an Azure Data Disk mount + on the host and bind mount to the pod. + properties: + cachingMode: + description: 'cachingMode is the Host Caching mode: None, + Read Only, Read Write.' + type: string + diskName: + description: diskName is the Name of the data disk in + the blob storage + type: string + diskURI: + description: diskURI is the URI of data disk in the blob + storage + type: string + fsType: + description: fsType is Filesystem type to mount. Must + be a filesystem type supported by the host operating + system. Ex. "ext4", "xfs", "ntfs". Implicitly inferred + to be "ext4" if unspecified. + type: string + kind: + description: 'kind expected values are Shared: multiple + blob disks per storage account Dedicated: single blob + disk per storage account Managed: azure managed data + disk (only in managed availability set). defaults to + shared' + type: string + readOnly: + description: readOnly Defaults to false (read/write). + ReadOnly here will force the ReadOnly setting in VolumeMounts. + type: boolean + required: + - diskName + - diskURI + type: object + azureFile: + description: azureFile represents an Azure File Service mount + on the host and bind mount to the pod. + properties: + readOnly: + description: readOnly defaults to false (read/write). + ReadOnly here will force the ReadOnly setting in VolumeMounts. + type: boolean + secretName: + description: secretName is the name of secret that contains + Azure Storage Account Name and Key + type: string + shareName: + description: shareName is the azure share Name + type: string + required: + - secretName + - shareName + type: object + cephfs: + description: cephFS represents a Ceph FS mount on the host + that shares a pod's lifetime + properties: + monitors: + description: 'monitors is Required: Monitors is a collection + of Ceph monitors More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + items: + type: string + type: array + path: + description: 'path is Optional: Used as the mounted root, + rather than the full Ceph tree, default is /' + type: string + readOnly: + description: 'readOnly is Optional: Defaults to false + (read/write). ReadOnly here will force the ReadOnly + setting in VolumeMounts. More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + type: boolean + secretFile: + description: 'secretFile is Optional: SecretFile is the + path to key ring for User, default is /etc/ceph/user.secret + More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + type: string + secretRef: + description: 'secretRef is Optional: SecretRef is reference + to the authentication secret for User, default is empty. + More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + type: object + x-kubernetes-map-type: atomic + user: + description: 'user is optional: User is the rados user + name, default is admin More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + type: string + required: + - monitors + type: object + cinder: + description: 'cinder represents a cinder volume attached and + mounted on kubelets host machine. More info: https://examples.k8s.io/mysql-cinder-pd/README.md' + properties: + fsType: + description: 'fsType is the filesystem type to mount. + Must be a filesystem type supported by the host operating + system. Examples: "ext4", "xfs", "ntfs". Implicitly + inferred to be "ext4" if unspecified. More info: https://examples.k8s.io/mysql-cinder-pd/README.md' + type: string + readOnly: + description: 'readOnly defaults to false (read/write). + ReadOnly here will force the ReadOnly setting in VolumeMounts. + More info: https://examples.k8s.io/mysql-cinder-pd/README.md' + type: boolean + secretRef: + description: 'secretRef is optional: points to a secret + object containing parameters used to connect to OpenStack.' + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + type: object + x-kubernetes-map-type: atomic + volumeID: + description: 'volumeID used to identify the volume in + cinder. More info: https://examples.k8s.io/mysql-cinder-pd/README.md' + type: string + required: + - volumeID + type: object + configMap: + description: configMap represents a configMap that should + populate this volume + properties: + defaultMode: + description: 'defaultMode is optional: mode bits used + to set permissions on created files by default. Must + be an octal value between 0000 and 0777 or a decimal + value between 0 and 511. YAML accepts both octal and + decimal values, JSON requires decimal values for mode + bits. Defaults to 0644. Directories within the path + are not affected by this setting. This might be in conflict + with other options that affect the file mode, like fsGroup, + and the result can be other mode bits set.' + format: int32 + type: integer + items: + description: items if unspecified, each key-value pair + in the Data field of the referenced ConfigMap will be + projected into the volume as a file whose name is the + key and content is the value. If specified, the listed + keys will be projected into the specified paths, and + unlisted keys will not be present. If a key is specified + which is not present in the ConfigMap, the volume setup + will error unless it is marked optional. Paths must + be relative and may not contain the '..' path or start + with '..'. + items: + description: Maps a string key to a path within a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: mode bits used to + set permissions on this file. Must be an octal + value between 0000 and 0777 or a decimal value + between 0 and 511. YAML accepts both octal and + decimal values, JSON requires decimal values for + mode bits. If not specified, the volume defaultMode + will be used. This might be in conflict with other + options that affect the file mode, like fsGroup, + and the result can be other mode bits set.' + format: int32 + type: integer + path: + description: path is the relative path of the file + to map the key to. May not be an absolute path. + May not contain the path element '..'. May not + start with the string '..'. + type: string + required: + - key + - path + type: object + type: array + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + optional: + description: optional specify whether the ConfigMap or + its keys must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + csi: + description: csi (Container Storage Interface) represents + ephemeral storage that is handled by certain external CSI + drivers (Beta feature). + properties: + driver: + description: driver is the name of the CSI driver that + handles this volume. Consult with your admin for the + correct name as registered in the cluster. + type: string + fsType: + description: fsType to mount. Ex. "ext4", "xfs", "ntfs". + If not provided, the empty value is passed to the associated + CSI driver which will determine the default filesystem + to apply. + type: string + nodePublishSecretRef: + description: nodePublishSecretRef is a reference to the + secret object containing sensitive information to pass + to the CSI driver to complete the CSI NodePublishVolume + and NodeUnpublishVolume calls. This field is optional, + and may be empty if no secret is required. If the secret + object contains more than one secret, all secret references + are passed. + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + type: object + x-kubernetes-map-type: atomic + readOnly: + description: readOnly specifies a read-only configuration + for the volume. Defaults to false (read/write). + type: boolean + volumeAttributes: + additionalProperties: + type: string + description: volumeAttributes stores driver-specific properties + that are passed to the CSI driver. Consult your driver's + documentation for supported values. + type: object + required: + - driver + type: object + downwardAPI: + description: downwardAPI represents downward API about the + pod that should populate this volume + properties: + defaultMode: + description: 'Optional: mode bits to use on created files + by default. Must be a Optional: mode bits used to set + permissions on created files by default. Must be an + octal value between 0000 and 0777 or a decimal value + between 0 and 511. YAML accepts both octal and decimal + values, JSON requires decimal values for mode bits. + Defaults to 0644. Directories within the path are not + affected by this setting. This might be in conflict + with other options that affect the file mode, like fsGroup, + and the result can be other mode bits set.' + format: int32 + type: integer + items: + description: Items is a list of downward API volume file + items: + description: DownwardAPIVolumeFile represents information + to create the file containing the pod field + properties: + fieldRef: + description: 'Required: Selects a field of the pod: + only annotations, labels, name and namespace are + supported.' + 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 + mode: + description: 'Optional: mode bits used to set permissions + on this file, must be an octal value between 0000 + and 0777 or a decimal value between 0 and 511. + YAML accepts both octal and decimal values, JSON + requires decimal values for mode bits. If not + specified, the volume defaultMode will be used. + This might be in conflict with other options that + affect the file mode, like fsGroup, and the result + can be other mode bits set.' + format: int32 + type: integer + path: + description: 'Required: Path is the relative path + name of the file to be created. Must not be absolute + or contain the ''..'' path. Must be utf-8 encoded. + The first item of the relative path must not start + with ''..''' + type: string + resourceFieldRef: + description: 'Selects a resource of the container: + only resources limits and requests (limits.cpu, + limits.memory, requests.cpu and requests.memory) + 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 + required: + - path + type: object + type: array + type: object + emptyDir: + description: 'emptyDir represents a temporary directory that + shares a pod''s lifetime. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' + properties: + medium: + description: 'medium represents what type of storage medium + should back this directory. The default is "" which + means to use the node''s default medium. Must be an + empty string (default) or Memory. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' + type: string + sizeLimit: + anyOf: + - type: integer + - type: string + description: 'sizeLimit is the total amount of local storage + required for this EmptyDir volume. The size limit is + also applicable for memory medium. The maximum usage + on memory medium EmptyDir would be the minimum value + between the SizeLimit specified here and the sum of + memory limits of all containers in a pod. The default + is nil which means that the limit is undefined. More + info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + ephemeral: + description: "ephemeral represents a volume that is handled + by a cluster storage driver. The volume's lifecycle is tied + to the pod that defines it - it will be created before the + pod starts, and deleted when the pod is removed. \n Use + this if: a) the volume is only needed while the pod runs, + b) features of normal volumes like restoring from snapshot + or capacity tracking are needed, c) the storage driver is + specified through a storage class, and d) the storage driver + supports dynamic volume provisioning through a PersistentVolumeClaim + (see EphemeralVolumeSource for more information on the connection + between this volume type and PersistentVolumeClaim). \n + Use PersistentVolumeClaim or one of the vendor-specific + APIs for volumes that persist for longer than the lifecycle + of an individual pod. \n Use CSI for light-weight local + ephemeral volumes if the CSI driver is meant to be used + that way - see the documentation of the driver for more + information. \n A pod can use both types of ephemeral volumes + and persistent volumes at the same time." + properties: + volumeClaimTemplate: + description: "Will be used to create a stand-alone PVC + to provision the volume. The pod in which this EphemeralVolumeSource + is embedded will be the owner of the PVC, i.e. the PVC + will be deleted together with the pod. The name of + the PVC will be `-` where `` is the name from the `PodSpec.Volumes` array + entry. Pod validation will reject the pod if the concatenated + name is not valid for a PVC (for example, too long). + \n An existing PVC with that name that is not owned + by the pod will *not* be used for the pod to avoid using + an unrelated volume by mistake. Starting the pod is + then blocked until the unrelated PVC is removed. If + such a pre-created PVC is meant to be used by the pod, + the PVC has to updated with an owner reference to the + pod once the pod exists. Normally this should not be + necessary, but it may be useful when manually reconstructing + a broken cluster. \n This field is read-only and no + changes will be made by Kubernetes to the PVC after + it has been created. \n Required, must not be nil." + properties: + metadata: + description: May contain labels and annotations that + will be copied into the PVC when creating it. No + other fields are allowed and will be rejected during + validation. + type: object + spec: + description: The specification for the PersistentVolumeClaim. + The entire content is copied unchanged into the + PVC that gets created from this template. The same + fields as in a PersistentVolumeClaim are also valid + here. + properties: + accessModes: + description: 'accessModes contains the desired + access modes the volume should have. More info: + https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' + items: + type: string + type: array + dataSource: + description: 'dataSource field can be used to + specify either: * An existing VolumeSnapshot + object (snapshot.storage.k8s.io/VolumeSnapshot) + * An existing PVC (PersistentVolumeClaim) If + the provisioner or an external controller can + support the specified data source, it will create + a new volume based on the contents of the specified + data source. When the AnyVolumeDataSource feature + gate is enabled, dataSource contents will be + copied to dataSourceRef, and dataSourceRef contents + will be copied to dataSource when dataSourceRef.namespace + is not specified. If the namespace is specified, + then dataSourceRef will not be copied to dataSource.' + properties: + apiGroup: + description: APIGroup is the group for the + resource being referenced. If APIGroup is + not specified, the specified Kind must be + in the core API group. For any other third-party + types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource + being referenced + type: string + name: + description: Name is the name of resource + being referenced + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + description: 'dataSourceRef specifies the object + from which to populate the volume with data, + if a non-empty volume is desired. This may be + any object from a non-empty API group (non core + object) or a PersistentVolumeClaim object. When + this field is specified, volume binding will + only succeed if the type of the specified object + matches some installed volume populator or dynamic + provisioner. This field will replace the functionality + of the dataSource field and as such if both + fields are non-empty, they must have the same + value. For backwards compatibility, when namespace + isn''t specified in dataSourceRef, both fields + (dataSource and dataSourceRef) will be set to + the same value automatically if one of them + is empty and the other is non-empty. When namespace + is specified in dataSourceRef, dataSource isn''t + set to the same value and must be empty. There + are three important differences between dataSource + and dataSourceRef: * While dataSource only allows + two specific types of objects, dataSourceRef + allows any non-core object, as well as PersistentVolumeClaim + objects. * While dataSource ignores disallowed + values (dropping them), dataSourceRef preserves + all values, and generates an error if a disallowed + value is specified. * While dataSource only + allows local objects, dataSourceRef allows objects + in any namespaces. (Beta) Using this field requires + the AnyVolumeDataSource feature gate to be enabled. + (Alpha) Using the namespace field of dataSourceRef + requires the CrossNamespaceVolumeDataSource + feature gate to be enabled.' + properties: + apiGroup: + description: APIGroup is the group for the + resource being referenced. If APIGroup is + not specified, the specified Kind must be + in the core API group. For any other third-party + types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource + being referenced + type: string + name: + description: Name is the name of resource + being referenced + type: string + namespace: + description: Namespace is the namespace of + resource being referenced Note that when + a namespace is specified, a gateway.networking.k8s.io/ReferenceGrant + object is required in the referent namespace + to allow that namespace's owner to accept + the reference. See the ReferenceGrant documentation + for details. (Alpha) This field requires + the CrossNamespaceVolumeDataSource feature + gate to be enabled. + type: string + required: + - kind + - name + type: object + resources: + description: 'resources represents the minimum + resources the volume should have. If RecoverVolumeExpansionFailure + feature is enabled users are allowed to specify + resource requirements that are lower than previous + value but must still be higher than capacity + recorded in the status field of the claim. More + info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' + properties: + claims: + description: "Claims lists the names of resources, + defined in spec.resourceClaims, that are + used by this container. \n This is an alpha + field and requires enabling the DynamicResourceAllocation + feature gate. \n 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 + 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 + selector: + description: selector is a label query over volumes + to consider for binding. + 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 + required: + - key + - operator + type: object + type: array + 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 + storageClassName: + description: 'storageClassName is the name of + the StorageClass required by the claim. More + info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' + type: string + volumeMode: + description: volumeMode defines what type of volume + is required by the claim. Value of Filesystem + is implied when not included in claim spec. + type: string + volumeName: + description: volumeName is the binding reference + to the PersistentVolume backing this claim. + type: string + type: object + required: + - spec + type: object + type: object + fc: + description: fc represents a Fibre Channel resource that is + attached to a kubelet's host machine and then exposed to + the pod. + properties: + fsType: + description: 'fsType is the filesystem type to mount. + Must be a filesystem type supported by the host operating + system. Ex. "ext4", "xfs", "ntfs". Implicitly inferred + to be "ext4" if unspecified. TODO: how do we prevent + errors in the filesystem from compromising the machine' + type: string + lun: + description: 'lun is Optional: FC target lun number' + format: int32 + type: integer + readOnly: + description: 'readOnly is Optional: Defaults to false + (read/write). ReadOnly here will force the ReadOnly + setting in VolumeMounts.' + type: boolean + targetWWNs: + description: 'targetWWNs is Optional: FC target worldwide + names (WWNs)' + items: + type: string + type: array + wwids: + description: 'wwids Optional: FC volume world wide identifiers + (wwids) Either wwids or combination of targetWWNs and + lun must be set, but not both simultaneously.' + items: + type: string + type: array + type: object + flexVolume: + description: flexVolume represents a generic volume resource + that is provisioned/attached using an exec based plugin. + properties: + driver: + description: driver is the name of the driver to use for + this volume. + type: string + fsType: + description: fsType is the filesystem type to mount. Must + be a filesystem type supported by the host operating + system. Ex. "ext4", "xfs", "ntfs". The default filesystem + depends on FlexVolume script. + type: string + options: + additionalProperties: + type: string + description: 'options is Optional: this field holds extra + command options if any.' + type: object + readOnly: + description: 'readOnly is Optional: defaults to false + (read/write). ReadOnly here will force the ReadOnly + setting in VolumeMounts.' + type: boolean + secretRef: + description: 'secretRef is Optional: secretRef is reference + to the secret object containing sensitive information + to pass to the plugin scripts. This may be empty if + no secret object is specified. If the secret object + contains more than one secret, all secrets are passed + to the plugin scripts.' + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + type: object + x-kubernetes-map-type: atomic + required: + - driver + type: object + flocker: + description: flocker represents a Flocker volume attached + to a kubelet's host machine. This depends on the Flocker + control service being running + properties: + datasetName: + description: datasetName is Name of the dataset stored + as metadata -> name on the dataset for Flocker should + be considered as deprecated + type: string + datasetUUID: + description: datasetUUID is the UUID of the dataset. This + is unique identifier of a Flocker dataset + type: string + type: object + gcePersistentDisk: + description: 'gcePersistentDisk represents a GCE Disk resource + that is attached to a kubelet''s host machine and then exposed + to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' + properties: + fsType: + description: 'fsType is filesystem type of the volume + that you want to mount. Tip: Ensure that the filesystem + type is supported by the host operating system. Examples: + "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" + if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk + TODO: how do we prevent errors in the filesystem from + compromising the machine' + type: string + partition: + description: 'partition is the partition in the volume + that you want to mount. If omitted, the default is to + mount by volume name. Examples: For volume /dev/sda1, + you specify the partition as "1". Similarly, the volume + partition for /dev/sda is "0" (or you can leave the + property empty). More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' + format: int32 + type: integer + pdName: + description: 'pdName is unique name of the PD resource + in GCE. Used to identify the disk in GCE. More info: + https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' + type: string + readOnly: + description: 'readOnly here will force the ReadOnly setting + in VolumeMounts. Defaults to false. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' + type: boolean + required: + - pdName + type: object + gitRepo: + description: 'gitRepo represents a git repository at a particular + revision. DEPRECATED: GitRepo is deprecated. To provision + a container with a git repo, mount an EmptyDir into an InitContainer + that clones the repo using git, then mount the EmptyDir + into the Pod''s container.' + properties: + directory: + description: directory is the target directory name. Must + not contain or start with '..'. If '.' is supplied, + the volume directory will be the git repository. Otherwise, + if specified, the volume will contain the git repository + in the subdirectory with the given name. + type: string + repository: + description: repository is the URL + type: string + revision: + description: revision is the commit hash for the specified + revision. + type: string + required: + - repository + type: object + glusterfs: + description: 'glusterfs represents a Glusterfs mount on the + host that shares a pod''s lifetime. More info: https://examples.k8s.io/volumes/glusterfs/README.md' + properties: + endpoints: + description: 'endpoints is the endpoint name that details + Glusterfs topology. More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' + type: string + path: + description: 'path is the Glusterfs volume path. More + info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' + type: string + readOnly: + description: 'readOnly here will force the Glusterfs volume + to be mounted with read-only permissions. Defaults to + false. More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' + type: boolean + required: + - endpoints + - path + type: object + hostPath: + description: 'hostPath represents a pre-existing file or directory + on the host machine that is directly exposed to the container. + This is generally used for system agents or other privileged + things that are allowed to see the host machine. Most containers + will NOT need this. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath + --- TODO(jonesdl) We need to restrict who can use host directory + mounts and who can/can not mount host directories as read/write.' + properties: + path: + description: 'path of the directory on the host. If the + path is a symlink, it will follow the link to the real + path. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath' + type: string + type: + description: 'type for HostPath Volume Defaults to "" + More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath' + type: string + required: + - path + type: object + iscsi: + description: 'iscsi represents an ISCSI Disk resource that + is attached to a kubelet''s host machine and then exposed + to the pod. More info: https://examples.k8s.io/volumes/iscsi/README.md' + properties: + chapAuthDiscovery: + description: chapAuthDiscovery defines whether support + iSCSI Discovery CHAP authentication + type: boolean + chapAuthSession: + description: chapAuthSession defines whether support iSCSI + Session CHAP authentication + type: boolean + fsType: + description: 'fsType is the filesystem type of the volume + that you want to mount. Tip: Ensure that the filesystem + type is supported by the host operating system. Examples: + "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" + if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#iscsi + TODO: how do we prevent errors in the filesystem from + compromising the machine' + type: string + initiatorName: + description: initiatorName is the custom iSCSI Initiator + Name. If initiatorName is specified with iscsiInterface + simultaneously, new iSCSI interface : will be created for the connection. + type: string + iqn: + description: iqn is the target iSCSI Qualified Name. + type: string + iscsiInterface: + description: iscsiInterface is the interface Name that + uses an iSCSI transport. Defaults to 'default' (tcp). + type: string + lun: + description: lun represents iSCSI Target Lun number. + format: int32 + type: integer + portals: + description: portals is the iSCSI Target Portal List. + The portal is either an IP or ip_addr:port if the port + is other than default (typically TCP ports 860 and 3260). + items: + type: string + type: array + readOnly: + description: readOnly here will force the ReadOnly setting + in VolumeMounts. Defaults to false. + type: boolean + secretRef: + description: secretRef is the CHAP Secret for iSCSI target + and initiator authentication + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + type: object + x-kubernetes-map-type: atomic + targetPortal: + description: targetPortal is iSCSI Target Portal. The + Portal is either an IP or ip_addr:port if the port is + other than default (typically TCP ports 860 and 3260). + type: string + required: + - iqn + - lun + - targetPortal + type: object + nfs: + description: 'nfs represents an NFS mount on the host that + shares a pod''s lifetime More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' + properties: + path: + description: 'path that is exported by the NFS server. + More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' + type: string + readOnly: + description: 'readOnly here will force the NFS export + to be mounted with read-only permissions. Defaults to + false. More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' + type: boolean + server: + description: 'server is the hostname or IP address of + the NFS server. More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' + type: string + required: + - path + - server + type: object + persistentVolumeClaim: + description: 'persistentVolumeClaimVolumeSource represents + a reference to a PersistentVolumeClaim in the same namespace. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' + properties: + claimName: + description: 'claimName is the name of a PersistentVolumeClaim + in the same namespace as the pod using this volume. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' + type: string + readOnly: + description: readOnly Will force the ReadOnly setting + in VolumeMounts. Default false. + type: boolean + required: + - claimName + type: object + photonPersistentDisk: + description: photonPersistentDisk represents a PhotonController + persistent disk attached and mounted on kubelets host machine + properties: + fsType: + description: fsType is the filesystem type to mount. Must + be a filesystem type supported by the host operating + system. Ex. "ext4", "xfs", "ntfs". Implicitly inferred + to be "ext4" if unspecified. + type: string + pdID: + description: pdID is the ID that identifies Photon Controller + persistent disk + type: string + required: + - pdID + type: object + portworxVolume: + description: portworxVolume represents a portworx volume attached + and mounted on kubelets host machine + properties: + fsType: + description: fSType represents the filesystem type to + mount Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs". Implicitly inferred + to be "ext4" if unspecified. + type: string + readOnly: + description: readOnly defaults to false (read/write). + ReadOnly here will force the ReadOnly setting in VolumeMounts. + type: boolean + volumeID: + description: volumeID uniquely identifies a Portworx volume + type: string + required: + - volumeID + type: object + projected: + description: projected items for all in one resources secrets, + configmaps, and downward API + properties: + defaultMode: + description: defaultMode are the mode bits used to set + permissions on created files by default. Must be an + octal value between 0000 and 0777 or a decimal value + between 0 and 511. YAML accepts both octal and decimal + values, JSON requires decimal values for mode bits. + Directories within the path are not affected by this + setting. This might be in conflict with other options + that affect the file mode, like fsGroup, and the result + can be other mode bits set. + format: int32 + type: integer + sources: + description: sources is the list of volume projections + items: + description: Projection that may be projected along + with other supported volume types + properties: + configMap: + description: configMap information about the configMap + data to project + properties: + items: + description: items if unspecified, each key-value + pair in the Data field of the referenced ConfigMap + will be projected into the volume as a file + whose name is the key and content is the value. + If specified, the listed keys will be projected + into the specified paths, and unlisted keys + will not be present. If a key is specified + which is not present in the ConfigMap, the + volume setup will error unless it is marked + optional. Paths must be relative and may not + contain the '..' path or start with '..'. + items: + description: Maps a string key to a path within + a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: mode bits + used to set permissions on this file. + Must be an octal value between 0000 + and 0777 or a decimal value between + 0 and 511. YAML accepts both octal and + decimal values, JSON requires decimal + values for mode bits. If not specified, + the volume defaultMode will be used. + This might be in conflict with other + options that affect the file mode, like + fsGroup, and the result can be other + mode bits set.' + format: int32 + type: integer + path: + description: path is the relative path + of the file to map the key to. May not + be an absolute path. May not contain + the path element '..'. May not start + with the string '..'. + type: string + required: + - key + - path + type: object + type: array + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + optional: + description: optional specify whether the ConfigMap + or its keys must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + downwardAPI: + description: downwardAPI information about the downwardAPI + data to project + properties: + items: + description: Items is a list of DownwardAPIVolume + file + items: + description: DownwardAPIVolumeFile represents + information to create the file containing + the pod field + properties: + fieldRef: + description: 'Required: Selects a field + of the pod: only annotations, labels, + name and namespace are supported.' + 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 + mode: + description: 'Optional: mode bits used + to set permissions on this file, must + be an octal value between 0000 and 0777 + or a decimal value between 0 and 511. + YAML accepts both octal and decimal + values, JSON requires decimal values + for mode bits. If not specified, the + volume defaultMode will be used. This + might be in conflict with other options + that affect the file mode, like fsGroup, + and the result can be other mode bits + set.' + format: int32 + type: integer + path: + description: 'Required: Path is the relative + path name of the file to be created. + Must not be absolute or contain the + ''..'' path. Must be utf-8 encoded. + The first item of the relative path + must not start with ''..''' + type: string + resourceFieldRef: + description: 'Selects a resource of the + container: only resources limits and + requests (limits.cpu, limits.memory, + requests.cpu and requests.memory) 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 + required: + - path + type: object + type: array + type: object + secret: + description: secret information about the secret + data to project + properties: + items: + description: items if unspecified, each key-value + pair in the Data field of the referenced Secret + will be projected into the volume as a file + whose name is the key and content is the value. + If specified, the listed keys will be projected + into the specified paths, and unlisted keys + will not be present. If a key is specified + which is not present in the Secret, the volume + setup will error unless it is marked optional. + Paths must be relative and may not contain + the '..' path or start with '..'. + items: + description: Maps a string key to a path within + a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: mode bits + used to set permissions on this file. + Must be an octal value between 0000 + and 0777 or a decimal value between + 0 and 511. YAML accepts both octal and + decimal values, JSON requires decimal + values for mode bits. If not specified, + the volume defaultMode will be used. + This might be in conflict with other + options that affect the file mode, like + fsGroup, and the result can be other + mode bits set.' + format: int32 + type: integer + path: + description: path is the relative path + of the file to map the key to. May not + be an absolute path. May not contain + the path element '..'. May not start + with the string '..'. + type: string + required: + - key + - path + type: object + type: array + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + optional: + description: optional field specify whether + the Secret or its key must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + serviceAccountToken: + description: serviceAccountToken is information + about the serviceAccountToken data to project + properties: + audience: + description: audience is the intended audience + of the token. A recipient of a token must + identify itself with an identifier specified + in the audience of the token, and otherwise + should reject the token. The audience defaults + to the identifier of the apiserver. + type: string + expirationSeconds: + description: expirationSeconds is the requested + duration of validity of the service account + token. As the token approaches expiration, + the kubelet volume plugin will proactively + rotate the service account token. The kubelet + will start trying to rotate the token if the + token is older than 80 percent of its time + to live or if the token is older than 24 hours.Defaults + to 1 hour and must be at least 10 minutes. + format: int64 + type: integer + path: + description: path is the path relative to the + mount point of the file to project the token + into. + type: string + required: + - path + type: object + type: object + type: array + type: object + quobyte: + description: quobyte represents a Quobyte mount on the host + that shares a pod's lifetime + properties: + group: + description: group to map volume access to Default is + no group + type: string + readOnly: + description: readOnly here will force the Quobyte volume + to be mounted with read-only permissions. Defaults to + false. + type: boolean + registry: + description: registry represents a single or multiple + Quobyte Registry services specified as a string as host:port + pair (multiple entries are separated with commas) which + acts as the central registry for volumes + type: string + tenant: + description: tenant owning the given Quobyte volume in + the Backend Used with dynamically provisioned Quobyte + volumes, value is set by the plugin + type: string + user: + description: user to map volume access to Defaults to + serivceaccount user + type: string + volume: + description: volume is a string that references an already + created Quobyte volume by name. + type: string + required: + - registry + - volume + type: object + rbd: + description: 'rbd represents a Rados Block Device mount on + the host that shares a pod''s lifetime. More info: https://examples.k8s.io/volumes/rbd/README.md' + properties: + fsType: + description: 'fsType is the filesystem type of the volume + that you want to mount. Tip: Ensure that the filesystem + type is supported by the host operating system. Examples: + "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" + if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#rbd + TODO: how do we prevent errors in the filesystem from + compromising the machine' + type: string + image: + description: 'image is the rados image name. More info: + https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: string + keyring: + description: 'keyring is the path to key ring for RBDUser. + Default is /etc/ceph/keyring. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: string + monitors: + description: 'monitors is a collection of Ceph monitors. + More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + items: + type: string + type: array + pool: + description: 'pool is the rados pool name. Default is + rbd. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: string + readOnly: + description: 'readOnly here will force the ReadOnly setting + in VolumeMounts. Defaults to false. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: boolean + secretRef: + description: 'secretRef is name of the authentication + secret for RBDUser. If provided overrides keyring. Default + is nil. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + type: object + x-kubernetes-map-type: atomic + user: + description: 'user is the rados user name. Default is + admin. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: string + required: + - image + - monitors + type: object + scaleIO: + description: scaleIO represents a ScaleIO persistent volume + attached and mounted on Kubernetes nodes. + properties: + fsType: + description: fsType is the filesystem type to mount. Must + be a filesystem type supported by the host operating + system. Ex. "ext4", "xfs", "ntfs". Default is "xfs". + type: string + gateway: + description: gateway is the host address of the ScaleIO + API Gateway. + type: string + protectionDomain: + description: protectionDomain is the name of the ScaleIO + Protection Domain for the configured storage. + type: string + readOnly: + description: readOnly Defaults to false (read/write). + ReadOnly here will force the ReadOnly setting in VolumeMounts. + type: boolean + secretRef: + description: secretRef references to the secret for ScaleIO + user and other sensitive information. If this is not + provided, Login operation will fail. + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + type: object + x-kubernetes-map-type: atomic + sslEnabled: + description: sslEnabled Flag enable/disable SSL communication + with Gateway, default false + type: boolean + storageMode: + description: storageMode indicates whether the storage + for a volume should be ThickProvisioned or ThinProvisioned. + Default is ThinProvisioned. + type: string + storagePool: + description: storagePool is the ScaleIO Storage Pool associated + with the protection domain. + type: string + system: + description: system is the name of the storage system + as configured in ScaleIO. + type: string + volumeName: + description: volumeName is the name of a volume already + created in the ScaleIO system that is associated with + this volume source. + type: string + required: + - gateway + - secretRef + - system + type: object + secret: + description: 'secret represents a secret that should populate + this volume. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' + properties: + defaultMode: + description: 'defaultMode is Optional: mode bits used + to set permissions on created files by default. Must + be an octal value between 0000 and 0777 or a decimal + value between 0 and 511. YAML accepts both octal and + decimal values, JSON requires decimal values for mode + bits. Defaults to 0644. Directories within the path + are not affected by this setting. This might be in conflict + with other options that affect the file mode, like fsGroup, + and the result can be other mode bits set.' + format: int32 + type: integer + items: + description: items If unspecified, each key-value pair + in the Data field of the referenced Secret will be projected + into the volume as a file whose name is the key and + content is the value. If specified, the listed keys + will be projected into the specified paths, and unlisted + keys will not be present. If a key is specified which + is not present in the Secret, the volume setup will + error unless it is marked optional. Paths must be relative + and may not contain the '..' path or start with '..'. + items: + description: Maps a string key to a path within a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: mode bits used to + set permissions on this file. Must be an octal + value between 0000 and 0777 or a decimal value + between 0 and 511. YAML accepts both octal and + decimal values, JSON requires decimal values for + mode bits. If not specified, the volume defaultMode + will be used. This might be in conflict with other + options that affect the file mode, like fsGroup, + and the result can be other mode bits set.' + format: int32 + type: integer + path: + description: path is the relative path of the file + to map the key to. May not be an absolute path. + May not contain the path element '..'. May not + start with the string '..'. + type: string + required: + - key + - path + type: object + type: array + optional: + description: optional field specify whether the Secret + or its keys must be defined + type: boolean + secretName: + description: 'secretName is the name of the secret in + the pod''s namespace to use. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' + type: string + type: object + storageos: + description: storageOS represents a StorageOS volume attached + and mounted on Kubernetes nodes. + properties: + fsType: + description: fsType is the filesystem type to mount. Must + be a filesystem type supported by the host operating + system. Ex. "ext4", "xfs", "ntfs". Implicitly inferred + to be "ext4" if unspecified. + type: string + readOnly: + description: readOnly defaults to false (read/write). + ReadOnly here will force the ReadOnly setting in VolumeMounts. + type: boolean + secretRef: + description: secretRef specifies the secret to use for + obtaining the StorageOS API credentials. If not specified, + default values will be attempted. + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + type: object + x-kubernetes-map-type: atomic + volumeName: + description: volumeName is the human-readable name of + the StorageOS volume. Volume names are only unique + within a namespace. + type: string + volumeNamespace: + description: volumeNamespace specifies the scope of the + volume within StorageOS. If no namespace is specified + then the Pod's namespace will be used. This allows + the Kubernetes name scoping to be mirrored within StorageOS + for tighter integration. Set VolumeName to any name + to override the default behaviour. Set to "default" + if you are not using namespaces within StorageOS. Namespaces + that do not pre-exist within StorageOS will be created. + type: string + type: object + vsphereVolume: + description: vsphereVolume represents a vSphere volume attached + and mounted on kubelets host machine + properties: + fsType: + description: fsType is filesystem type to mount. Must + be a filesystem type supported by the host operating + system. Ex. "ext4", "xfs", "ntfs". Implicitly inferred + to be "ext4" if unspecified. + type: string + storagePolicyID: + description: storagePolicyID is the storage Policy Based + Management (SPBM) profile ID associated with the StoragePolicyName. + type: string + storagePolicyName: + description: storagePolicyName is the storage Policy Based + Management (SPBM) profile name. + type: string + volumePath: + description: volumePath is the path that identifies vSphere + volume vmdk + type: string + required: + - volumePath + type: object + type: object + type: object + tolerations: + 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 + required: + - mariaDbRef + - storage + type: object + status: + description: BackupStatus defines the observed state of Backup + properties: + conditions: + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + \n type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + 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 + 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.11.1 + creationTimestamp: null + name: connections.mariadb.mmontes.io +spec: + group: mariadb.mmontes.io + names: + kind: Connection + listKind: ConnectionList + plural: connections + shortNames: + - cmdb + singular: connection + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .status.conditions[?(@.type=="Ready")].status + name: Ready + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].message + name: Status + type: string + - jsonPath: .spec.secretName + name: Secret + type: string + - jsonPath: .spec.mariaDbRef.name + name: MariaDB + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + description: Connection is the Schema for the connections 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: ConnectionSpec defines the desired state of Connection + properties: + database: + type: string + healthCheck: + properties: + interval: + type: string + retryInterval: + type: string + type: object + mariaDbRef: + properties: + apiVersion: + description: API version of the referent. + type: string + fieldPath: + description: 'If referring to a piece of an object instead of + an entire object, this string should contain a valid JSON/Go + field access statement, such as desiredState.manifest.containers[2]. + For example, if the object reference is to a container within + a pod, this would take on a value like: "spec.containers{name}" + (where "name" refers to the name of the container that triggered + the event) or if no container name is specified "spec.containers[2]" + (container with index 2 in this pod). This syntax is chosen + only to have some well-defined way of referencing a part of + an object. TODO: this design is not final and this field is + subject to change in the future.' + type: string + kind: + description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + namespace: + description: 'Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/' + type: string + resourceVersion: + description: 'Specific resourceVersion to which this reference + is made, if any. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency' + type: string + uid: + description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids' + type: string + waitForIt: + default: true + type: boolean + type: object + x-kubernetes-map-type: atomic + params: + additionalProperties: + type: string + type: object + passwordSecretKeyRef: + description: SecretKeySelector selects a key of a Secret. + properties: + key: + description: The key of the secret to select from. Must be a + valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + secretName: + type: string + secretTemplate: + properties: + annotations: + additionalProperties: + type: string + type: object + databaseKey: + type: string + format: + type: string + hostKey: + type: string + key: + type: string + labels: + additionalProperties: + type: string + type: object + passwordKey: + type: string + portKey: + type: string + usernameKey: + type: string + type: object + serviceName: + type: string + username: + type: string + required: + - mariaDbRef + - passwordSecretKeyRef + - username + type: object + status: + description: ConnectionStatus defines the observed state of Connection + properties: + conditions: + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + \n type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + 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 + 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.11.1 + creationTimestamp: null + name: databases.mariadb.mmontes.io +spec: + group: mariadb.mmontes.io + names: + kind: Database + listKind: DatabaseList + plural: databases + shortNames: + - dmdb + singular: database + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .status.conditions[?(@.type=="Ready")].status + name: Ready + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].message + name: Status + type: string + - jsonPath: .spec.characterSet + name: CharSet + type: string + - jsonPath: .spec.collate + name: Collate + type: string + - jsonPath: .spec.mariaDbRef.name + name: MariaDB + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + - jsonPath: .spec.name + name: Name + type: string + name: v1alpha1 + schema: + openAPIV3Schema: + description: Database is the Schema for the databases 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: DatabaseSpec defines the desired state of Database + properties: + characterSet: + default: utf8 + type: string + collate: + default: utf8_general_ci + type: string + mariaDbRef: + properties: + apiVersion: + description: API version of the referent. + type: string + fieldPath: + description: 'If referring to a piece of an object instead of + an entire object, this string should contain a valid JSON/Go + field access statement, such as desiredState.manifest.containers[2]. + For example, if the object reference is to a container within + a pod, this would take on a value like: "spec.containers{name}" + (where "name" refers to the name of the container that triggered + the event) or if no container name is specified "spec.containers[2]" + (container with index 2 in this pod). This syntax is chosen + only to have some well-defined way of referencing a part of + an object. TODO: this design is not final and this field is + subject to change in the future.' + type: string + kind: + description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + namespace: + description: 'Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/' + type: string + resourceVersion: + description: 'Specific resourceVersion to which this reference + is made, if any. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency' + type: string + uid: + description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids' + type: string + waitForIt: + default: true + type: boolean + type: object + x-kubernetes-map-type: atomic + name: + maxLength: 80 + type: string + retryInterval: + type: string + required: + - mariaDbRef + type: object + status: + description: DatabaseStatus defines the observed state of Database + properties: + conditions: + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + \n type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + 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 + 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.11.1 + creationTimestamp: null + name: grants.mariadb.mmontes.io +spec: + group: mariadb.mmontes.io + names: + kind: Grant + listKind: GrantList + plural: grants + shortNames: + - gmdb + singular: grant + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .status.conditions[?(@.type=="Ready")].status + name: Ready + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].message + name: Status + type: string + - jsonPath: .spec.database + name: Database + type: string + - jsonPath: .spec.table + name: Table + type: string + - jsonPath: .spec.username + name: Username + type: string + - jsonPath: .spec.grantOption + name: GrantOpt + type: string + - jsonPath: .spec.mariaDbRef.name + name: MariaDB + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + description: Grant is the Schema for the grants 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: GrantSpec defines the desired state of Grant + properties: + database: + default: '*' + type: string + grantOption: + default: false + type: boolean + host: + type: string + mariaDbRef: + properties: + apiVersion: + description: API version of the referent. + type: string + fieldPath: + description: 'If referring to a piece of an object instead of + an entire object, this string should contain a valid JSON/Go + field access statement, such as desiredState.manifest.containers[2]. + For example, if the object reference is to a container within + a pod, this would take on a value like: "spec.containers{name}" + (where "name" refers to the name of the container that triggered + the event) or if no container name is specified "spec.containers[2]" + (container with index 2 in this pod). This syntax is chosen + only to have some well-defined way of referencing a part of + an object. TODO: this design is not final and this field is + subject to change in the future.' + type: string + kind: + description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + namespace: + description: 'Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/' + type: string + resourceVersion: + description: 'Specific resourceVersion to which this reference + is made, if any. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency' + type: string + uid: + description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids' + type: string + waitForIt: + default: true + type: boolean + type: object + x-kubernetes-map-type: atomic + privileges: + items: + type: string + minItems: 1 + type: array + retryInterval: + type: string + table: + default: '*' + type: string + username: + type: string + required: + - mariaDbRef + - privileges + - username + type: object + status: + description: GrantStatus defines the observed state of Grant + properties: + conditions: + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + \n type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + 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 + 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.11.1 + creationTimestamp: null + name: mariadbs.mariadb.mmontes.io +spec: + group: mariadb.mmontes.io + names: + kind: MariaDB + listKind: MariaDBList + plural: mariadbs + shortNames: + - mdb + singular: mariadb + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .status.conditions[?(@.type=="Ready")].status + name: Ready + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].message + name: Status + type: string + - jsonPath: .status.currentPrimary + name: Primary Pod + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + description: MariaDB is the Schema for the mariadbs 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: MariaDBSpec defines the desired state of MariaDB + properties: + affinity: + description: Affinity is a group of affinity scheduling rules. + properties: + nodeAffinity: + description: Describes node affinity scheduling rules for the + pod. + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods to + nodes that satisfy the affinity expressions specified by + this field, but it may choose a node that violates one or + more of the expressions. The node that is most preferred + is the one with the greatest sum of weights, i.e. for each + node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, + etc.), compute a sum by iterating through the elements of + this field and adding "weight" to the sum if the node matches + the corresponding matchExpressions; the node(s) with the + highest sum are the most preferred. + items: + description: An empty preferred scheduling term matches + all objects with implicit weight 0 (i.e. it's a no-op). + A null preferred scheduling term matches no objects (i.e. + is also a no-op). + properties: + preference: + description: A node selector term, associated with the + corresponding weight. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists, DoesNotExist. Gt, and + Lt. + type: string + values: + description: 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. If the operator is Gt or + Lt, the values array must have a single + element, which will be interpreted as an + integer. This array is replaced during a + strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists, DoesNotExist. Gt, and + Lt. + type: string + values: + description: 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. If the operator is Gt or + Lt, the values array must have a single + element, which will be interpreted as an + integer. This array is replaced during a + strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + x-kubernetes-map-type: atomic + weight: + description: Weight associated with matching the corresponding + nodeSelectorTerm, in the range 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by this + field are not met at scheduling time, the pod will not be + scheduled onto the node. If the affinity requirements specified + by this field cease to be met at some point during pod execution + (e.g. due to an update), the system may or may not try to + eventually evict the pod from its node. + properties: + nodeSelectorTerms: + description: Required. A list of node selector terms. + The terms are ORed. + items: + description: A null or empty node selector term matches + no objects. The requirements of them are ANDed. The + TopologySelectorTerm type implements a subset of the + NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists, DoesNotExist. Gt, and + Lt. + type: string + values: + description: 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. If the operator is Gt or + Lt, the values array must have a single + element, which will be interpreted as an + integer. This array is replaced during a + strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists, DoesNotExist. Gt, and + Lt. + type: string + values: + description: 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. If the operator is Gt or + Lt, the values array must have a single + element, which will be interpreted as an + integer. This array is replaced during a + strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + x-kubernetes-map-type: atomic + type: array + required: + - nodeSelectorTerms + type: object + x-kubernetes-map-type: atomic + type: object + podAffinity: + description: Describes pod affinity scheduling rules (e.g. co-locate + this pod in the same node, zone, etc. as some other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods to + nodes that satisfy the affinity expressions specified by + this field, but it may choose a node that violates one or + more of the expressions. The node that is most preferred + is the one with the greatest sum of weights, i.e. for each + node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, + etc.), compute a sum by iterating through the elements of + this field and adding "weight" to the sum if the node has + pods which matches the corresponding podAffinityTerm; the + node(s) with the highest sum are the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by this + field and the ones listed in the namespaces field. + null selector and null or empty namespaces list + means "this pod's namespace". An empty selector + ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. The + term is applied to the union of the namespaces + listed in this field and the ones selected by + namespaceSelector. null or empty namespaces list + and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods + matching the labelSelector in the specified namespaces, + where co-located is defined as running on a node + whose value of the label with key topologyKey + matches that of any node on which any of the selected + pods is running. Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching the corresponding + podAffinityTerm, in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by this + field are not met at scheduling time, the pod will not be + scheduled onto the node. If the affinity requirements specified + by this field cease to be met at some point during pod execution + (e.g. due to a pod label update), the system may or may + not try to eventually evict the pod from its node. When + there are multiple elements, the lists of nodes corresponding + to each podAffinityTerm are intersected, i.e. all terms + must be satisfied. + items: + description: Defines a set of pods (namely those matching + the labelSelector relative to the given namespace(s)) + that this pod should be co-located (affinity) or not co-located + (anti-affinity) with, where co-located is defined as running + on a node whose value of the label with key + matches that of any node on which a pod of the set of + pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied to the + union of the namespaces selected by this field and + the ones listed in the namespaces field. null selector + and null or empty namespaces list means "this pod's + namespace". An empty selector ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list of namespace + names that the term applies to. The term is applied + to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. null or + empty namespaces list and null namespaceSelector means + "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where + co-located is defined as running on a node whose value + of the label with key topologyKey matches that of + any node on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + podAntiAffinity: + description: Describes pod anti-affinity scheduling rules (e.g. + avoid putting this pod in the same node, zone, etc. as some + other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods to + nodes that satisfy the anti-affinity expressions specified + by this field, but it may choose a node that violates one + or more of the expressions. The node that is most preferred + is the one with the greatest sum of weights, i.e. for each + node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling anti-affinity expressions, + etc.), compute a sum by iterating through the elements of + this field and adding "weight" to the sum if the node has + pods which matches the corresponding podAffinityTerm; the + node(s) with the highest sum are the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by this + field and the ones listed in the namespaces field. + null selector and null or empty namespaces list + means "this pod's namespace". An empty selector + ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. The + term is applied to the union of the namespaces + listed in this field and the ones selected by + namespaceSelector. null or empty namespaces list + and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods + matching the labelSelector in the specified namespaces, + where co-located is defined as running on a node + whose value of the label with key topologyKey + matches that of any node on which any of the selected + pods is running. Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching the corresponding + podAffinityTerm, in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the anti-affinity requirements specified by + this field are not met at scheduling time, the pod will + not be scheduled onto the node. If the anti-affinity requirements + specified by this field cease to be met at some point during + pod execution (e.g. due to a pod label update), the system + may or may not try to eventually evict the pod from its + node. When there are multiple elements, the lists of nodes + corresponding to each podAffinityTerm are intersected, i.e. + all terms must be satisfied. + items: + description: Defines a set of pods (namely those matching + the labelSelector relative to the given namespace(s)) + that this pod should be co-located (affinity) or not co-located + (anti-affinity) with, where co-located is defined as running + on a node whose value of the label with key + matches that of any node on which a pod of the set of + pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied to the + union of the namespaces selected by this field and + the ones listed in the namespaces field. null selector + and null or empty namespaces list means "this pod's + namespace". An empty selector ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list of namespace + names that the term applies to. The term is applied + to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. null or + empty namespaces list and null namespaceSelector means + "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where + co-located is defined as running on a node whose value + of the label with key topologyKey matches that of + any node on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + type: object + args: + items: + type: string + type: array + bootstrapFrom: + properties: + backupRef: + description: LocalObjectReference contains enough information + to let you locate the referenced object inside the same namespace. + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + x-kubernetes-map-type: atomic + fileName: + type: string + volume: + description: Represents the source of a volume to mount. Only + one of its members may be specified. + properties: + awsElasticBlockStore: + description: 'awsElasticBlockStore represents an AWS Disk + resource that is attached to a kubelet''s host machine and + then exposed to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' + properties: + fsType: + description: 'fsType is the filesystem type of the volume + that you want to mount. Tip: Ensure that the filesystem + type is supported by the host operating system. Examples: + "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" + if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore + TODO: how do we prevent errors in the filesystem from + compromising the machine' + type: string + partition: + description: 'partition is the partition in the volume + that you want to mount. If omitted, the default is to + mount by volume name. Examples: For volume /dev/sda1, + you specify the partition as "1". Similarly, the volume + partition for /dev/sda is "0" (or you can leave the + property empty).' + format: int32 + type: integer + readOnly: + description: 'readOnly value true will force the readOnly + setting in VolumeMounts. More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' + type: boolean + volumeID: + description: 'volumeID is unique ID of the persistent + disk resource in AWS (Amazon EBS volume). More info: + https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' + type: string + required: + - volumeID + type: object + azureDisk: + description: azureDisk represents an Azure Data Disk mount + on the host and bind mount to the pod. + properties: + cachingMode: + description: 'cachingMode is the Host Caching mode: None, + Read Only, Read Write.' + type: string + diskName: + description: diskName is the Name of the data disk in + the blob storage + type: string + diskURI: + description: diskURI is the URI of data disk in the blob + storage + type: string + fsType: + description: fsType is Filesystem type to mount. Must + be a filesystem type supported by the host operating + system. Ex. "ext4", "xfs", "ntfs". Implicitly inferred + to be "ext4" if unspecified. + type: string + kind: + description: 'kind expected values are Shared: multiple + blob disks per storage account Dedicated: single blob + disk per storage account Managed: azure managed data + disk (only in managed availability set). defaults to + shared' + type: string + readOnly: + description: readOnly Defaults to false (read/write). + ReadOnly here will force the ReadOnly setting in VolumeMounts. + type: boolean + required: + - diskName + - diskURI + type: object + azureFile: + description: azureFile represents an Azure File Service mount + on the host and bind mount to the pod. + properties: + readOnly: + description: readOnly defaults to false (read/write). + ReadOnly here will force the ReadOnly setting in VolumeMounts. + type: boolean + secretName: + description: secretName is the name of secret that contains + Azure Storage Account Name and Key + type: string + shareName: + description: shareName is the azure share Name + type: string + required: + - secretName + - shareName + type: object + cephfs: + description: cephFS represents a Ceph FS mount on the host + that shares a pod's lifetime + properties: + monitors: + description: 'monitors is Required: Monitors is a collection + of Ceph monitors More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + items: + type: string + type: array + path: + description: 'path is Optional: Used as the mounted root, + rather than the full Ceph tree, default is /' + type: string + readOnly: + description: 'readOnly is Optional: Defaults to false + (read/write). ReadOnly here will force the ReadOnly + setting in VolumeMounts. More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + type: boolean + secretFile: + description: 'secretFile is Optional: SecretFile is the + path to key ring for User, default is /etc/ceph/user.secret + More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + type: string + secretRef: + description: 'secretRef is Optional: SecretRef is reference + to the authentication secret for User, default is empty. + More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + type: object + x-kubernetes-map-type: atomic + user: + description: 'user is optional: User is the rados user + name, default is admin More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + type: string + required: + - monitors + type: object + cinder: + description: 'cinder represents a cinder volume attached and + mounted on kubelets host machine. More info: https://examples.k8s.io/mysql-cinder-pd/README.md' + properties: + fsType: + description: 'fsType is the filesystem type to mount. + Must be a filesystem type supported by the host operating + system. Examples: "ext4", "xfs", "ntfs". Implicitly + inferred to be "ext4" if unspecified. More info: https://examples.k8s.io/mysql-cinder-pd/README.md' + type: string + readOnly: + description: 'readOnly defaults to false (read/write). + ReadOnly here will force the ReadOnly setting in VolumeMounts. + More info: https://examples.k8s.io/mysql-cinder-pd/README.md' + type: boolean + secretRef: + description: 'secretRef is optional: points to a secret + object containing parameters used to connect to OpenStack.' + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + type: object + x-kubernetes-map-type: atomic + volumeID: + description: 'volumeID used to identify the volume in + cinder. More info: https://examples.k8s.io/mysql-cinder-pd/README.md' + type: string + required: + - volumeID + type: object + configMap: + description: configMap represents a configMap that should + populate this volume + properties: + defaultMode: + description: 'defaultMode is optional: mode bits used + to set permissions on created files by default. Must + be an octal value between 0000 and 0777 or a decimal + value between 0 and 511. YAML accepts both octal and + decimal values, JSON requires decimal values for mode + bits. Defaults to 0644. Directories within the path + are not affected by this setting. This might be in conflict + with other options that affect the file mode, like fsGroup, + and the result can be other mode bits set.' + format: int32 + type: integer + items: + description: items if unspecified, each key-value pair + in the Data field of the referenced ConfigMap will be + projected into the volume as a file whose name is the + key and content is the value. If specified, the listed + keys will be projected into the specified paths, and + unlisted keys will not be present. If a key is specified + which is not present in the ConfigMap, the volume setup + will error unless it is marked optional. Paths must + be relative and may not contain the '..' path or start + with '..'. + items: + description: Maps a string key to a path within a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: mode bits used to + set permissions on this file. Must be an octal + value between 0000 and 0777 or a decimal value + between 0 and 511. YAML accepts both octal and + decimal values, JSON requires decimal values for + mode bits. If not specified, the volume defaultMode + will be used. This might be in conflict with other + options that affect the file mode, like fsGroup, + and the result can be other mode bits set.' + format: int32 + type: integer + path: + description: path is the relative path of the file + to map the key to. May not be an absolute path. + May not contain the path element '..'. May not + start with the string '..'. + type: string + required: + - key + - path + type: object + type: array + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + optional: + description: optional specify whether the ConfigMap or + its keys must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + csi: + description: csi (Container Storage Interface) represents + ephemeral storage that is handled by certain external CSI + drivers (Beta feature). + properties: + driver: + description: driver is the name of the CSI driver that + handles this volume. Consult with your admin for the + correct name as registered in the cluster. + type: string + fsType: + description: fsType to mount. Ex. "ext4", "xfs", "ntfs". + If not provided, the empty value is passed to the associated + CSI driver which will determine the default filesystem + to apply. + type: string + nodePublishSecretRef: + description: nodePublishSecretRef is a reference to the + secret object containing sensitive information to pass + to the CSI driver to complete the CSI NodePublishVolume + and NodeUnpublishVolume calls. This field is optional, + and may be empty if no secret is required. If the secret + object contains more than one secret, all secret references + are passed. + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + type: object + x-kubernetes-map-type: atomic + readOnly: + description: readOnly specifies a read-only configuration + for the volume. Defaults to false (read/write). + type: boolean + volumeAttributes: + additionalProperties: + type: string + description: volumeAttributes stores driver-specific properties + that are passed to the CSI driver. Consult your driver's + documentation for supported values. + type: object + required: + - driver + type: object + downwardAPI: + description: downwardAPI represents downward API about the + pod that should populate this volume + properties: + defaultMode: + description: 'Optional: mode bits to use on created files + by default. Must be a Optional: mode bits used to set + permissions on created files by default. Must be an + octal value between 0000 and 0777 or a decimal value + between 0 and 511. YAML accepts both octal and decimal + values, JSON requires decimal values for mode bits. + Defaults to 0644. Directories within the path are not + affected by this setting. This might be in conflict + with other options that affect the file mode, like fsGroup, + and the result can be other mode bits set.' + format: int32 + type: integer + items: + description: Items is a list of downward API volume file + items: + description: DownwardAPIVolumeFile represents information + to create the file containing the pod field + properties: + fieldRef: + description: 'Required: Selects a field of the pod: + only annotations, labels, name and namespace are + supported.' + 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 + mode: + description: 'Optional: mode bits used to set permissions + on this file, must be an octal value between 0000 + and 0777 or a decimal value between 0 and 511. + YAML accepts both octal and decimal values, JSON + requires decimal values for mode bits. If not + specified, the volume defaultMode will be used. + This might be in conflict with other options that + affect the file mode, like fsGroup, and the result + can be other mode bits set.' + format: int32 + type: integer + path: + description: 'Required: Path is the relative path + name of the file to be created. Must not be absolute + or contain the ''..'' path. Must be utf-8 encoded. + The first item of the relative path must not start + with ''..''' + type: string + resourceFieldRef: + description: 'Selects a resource of the container: + only resources limits and requests (limits.cpu, + limits.memory, requests.cpu and requests.memory) + 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 + required: + - path + type: object + type: array + type: object + emptyDir: + description: 'emptyDir represents a temporary directory that + shares a pod''s lifetime. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' + properties: + medium: + description: 'medium represents what type of storage medium + should back this directory. The default is "" which + means to use the node''s default medium. Must be an + empty string (default) or Memory. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' + type: string + sizeLimit: + anyOf: + - type: integer + - type: string + description: 'sizeLimit is the total amount of local storage + required for this EmptyDir volume. The size limit is + also applicable for memory medium. The maximum usage + on memory medium EmptyDir would be the minimum value + between the SizeLimit specified here and the sum of + memory limits of all containers in a pod. The default + is nil which means that the limit is undefined. More + info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + ephemeral: + description: "ephemeral represents a volume that is handled + by a cluster storage driver. The volume's lifecycle is tied + to the pod that defines it - it will be created before the + pod starts, and deleted when the pod is removed. \n Use + this if: a) the volume is only needed while the pod runs, + b) features of normal volumes like restoring from snapshot + or capacity tracking are needed, c) the storage driver is + specified through a storage class, and d) the storage driver + supports dynamic volume provisioning through a PersistentVolumeClaim + (see EphemeralVolumeSource for more information on the connection + between this volume type and PersistentVolumeClaim). \n + Use PersistentVolumeClaim or one of the vendor-specific + APIs for volumes that persist for longer than the lifecycle + of an individual pod. \n Use CSI for light-weight local + ephemeral volumes if the CSI driver is meant to be used + that way - see the documentation of the driver for more + information. \n A pod can use both types of ephemeral volumes + and persistent volumes at the same time." + properties: + volumeClaimTemplate: + description: "Will be used to create a stand-alone PVC + to provision the volume. The pod in which this EphemeralVolumeSource + is embedded will be the owner of the PVC, i.e. the PVC + will be deleted together with the pod. The name of + the PVC will be `-` where `` is the name from the `PodSpec.Volumes` array + entry. Pod validation will reject the pod if the concatenated + name is not valid for a PVC (for example, too long). + \n An existing PVC with that name that is not owned + by the pod will *not* be used for the pod to avoid using + an unrelated volume by mistake. Starting the pod is + then blocked until the unrelated PVC is removed. If + such a pre-created PVC is meant to be used by the pod, + the PVC has to updated with an owner reference to the + pod once the pod exists. Normally this should not be + necessary, but it may be useful when manually reconstructing + a broken cluster. \n This field is read-only and no + changes will be made by Kubernetes to the PVC after + it has been created. \n Required, must not be nil." + properties: + metadata: + description: May contain labels and annotations that + will be copied into the PVC when creating it. No + other fields are allowed and will be rejected during + validation. + type: object + spec: + description: The specification for the PersistentVolumeClaim. + The entire content is copied unchanged into the + PVC that gets created from this template. The same + fields as in a PersistentVolumeClaim are also valid + here. + properties: + accessModes: + description: 'accessModes contains the desired + access modes the volume should have. More info: + https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' + items: + type: string + type: array + dataSource: + description: 'dataSource field can be used to + specify either: * An existing VolumeSnapshot + object (snapshot.storage.k8s.io/VolumeSnapshot) + * An existing PVC (PersistentVolumeClaim) If + the provisioner or an external controller can + support the specified data source, it will create + a new volume based on the contents of the specified + data source. When the AnyVolumeDataSource feature + gate is enabled, dataSource contents will be + copied to dataSourceRef, and dataSourceRef contents + will be copied to dataSource when dataSourceRef.namespace + is not specified. If the namespace is specified, + then dataSourceRef will not be copied to dataSource.' + properties: + apiGroup: + description: APIGroup is the group for the + resource being referenced. If APIGroup is + not specified, the specified Kind must be + in the core API group. For any other third-party + types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource + being referenced + type: string + name: + description: Name is the name of resource + being referenced + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + description: 'dataSourceRef specifies the object + from which to populate the volume with data, + if a non-empty volume is desired. This may be + any object from a non-empty API group (non core + object) or a PersistentVolumeClaim object. When + this field is specified, volume binding will + only succeed if the type of the specified object + matches some installed volume populator or dynamic + provisioner. This field will replace the functionality + of the dataSource field and as such if both + fields are non-empty, they must have the same + value. For backwards compatibility, when namespace + isn''t specified in dataSourceRef, both fields + (dataSource and dataSourceRef) will be set to + the same value automatically if one of them + is empty and the other is non-empty. When namespace + is specified in dataSourceRef, dataSource isn''t + set to the same value and must be empty. There + are three important differences between dataSource + and dataSourceRef: * While dataSource only allows + two specific types of objects, dataSourceRef + allows any non-core object, as well as PersistentVolumeClaim + objects. * While dataSource ignores disallowed + values (dropping them), dataSourceRef preserves + all values, and generates an error if a disallowed + value is specified. * While dataSource only + allows local objects, dataSourceRef allows objects + in any namespaces. (Beta) Using this field requires + the AnyVolumeDataSource feature gate to be enabled. + (Alpha) Using the namespace field of dataSourceRef + requires the CrossNamespaceVolumeDataSource + feature gate to be enabled.' + properties: + apiGroup: + description: APIGroup is the group for the + resource being referenced. If APIGroup is + not specified, the specified Kind must be + in the core API group. For any other third-party + types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource + being referenced + type: string + name: + description: Name is the name of resource + being referenced + type: string + namespace: + description: Namespace is the namespace of + resource being referenced Note that when + a namespace is specified, a gateway.networking.k8s.io/ReferenceGrant + object is required in the referent namespace + to allow that namespace's owner to accept + the reference. See the ReferenceGrant documentation + for details. (Alpha) This field requires + the CrossNamespaceVolumeDataSource feature + gate to be enabled. + type: string + required: + - kind + - name + type: object + resources: + description: 'resources represents the minimum + resources the volume should have. If RecoverVolumeExpansionFailure + feature is enabled users are allowed to specify + resource requirements that are lower than previous + value but must still be higher than capacity + recorded in the status field of the claim. More + info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' + properties: + claims: + description: "Claims lists the names of resources, + defined in spec.resourceClaims, that are + used by this container. \n This is an alpha + field and requires enabling the DynamicResourceAllocation + feature gate. \n 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 + 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 + selector: + description: selector is a label query over volumes + to consider for binding. + 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 + required: + - key + - operator + type: object + type: array + 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 + storageClassName: + description: 'storageClassName is the name of + the StorageClass required by the claim. More + info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' + type: string + volumeMode: + description: volumeMode defines what type of volume + is required by the claim. Value of Filesystem + is implied when not included in claim spec. + type: string + volumeName: + description: volumeName is the binding reference + to the PersistentVolume backing this claim. + type: string + type: object + required: + - spec + type: object + type: object + fc: + description: fc represents a Fibre Channel resource that is + attached to a kubelet's host machine and then exposed to + the pod. + properties: + fsType: + description: 'fsType is the filesystem type to mount. + Must be a filesystem type supported by the host operating + system. Ex. "ext4", "xfs", "ntfs". Implicitly inferred + to be "ext4" if unspecified. TODO: how do we prevent + errors in the filesystem from compromising the machine' + type: string + lun: + description: 'lun is Optional: FC target lun number' + format: int32 + type: integer + readOnly: + description: 'readOnly is Optional: Defaults to false + (read/write). ReadOnly here will force the ReadOnly + setting in VolumeMounts.' + type: boolean + targetWWNs: + description: 'targetWWNs is Optional: FC target worldwide + names (WWNs)' + items: + type: string + type: array + wwids: + description: 'wwids Optional: FC volume world wide identifiers + (wwids) Either wwids or combination of targetWWNs and + lun must be set, but not both simultaneously.' + items: + type: string + type: array + type: object + flexVolume: + description: flexVolume represents a generic volume resource + that is provisioned/attached using an exec based plugin. + properties: + driver: + description: driver is the name of the driver to use for + this volume. + type: string + fsType: + description: fsType is the filesystem type to mount. Must + be a filesystem type supported by the host operating + system. Ex. "ext4", "xfs", "ntfs". The default filesystem + depends on FlexVolume script. + type: string + options: + additionalProperties: + type: string + description: 'options is Optional: this field holds extra + command options if any.' + type: object + readOnly: + description: 'readOnly is Optional: defaults to false + (read/write). ReadOnly here will force the ReadOnly + setting in VolumeMounts.' + type: boolean + secretRef: + description: 'secretRef is Optional: secretRef is reference + to the secret object containing sensitive information + to pass to the plugin scripts. This may be empty if + no secret object is specified. If the secret object + contains more than one secret, all secrets are passed + to the plugin scripts.' + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + type: object + x-kubernetes-map-type: atomic + required: + - driver + type: object + flocker: + description: flocker represents a Flocker volume attached + to a kubelet's host machine. This depends on the Flocker + control service being running + properties: + datasetName: + description: datasetName is Name of the dataset stored + as metadata -> name on the dataset for Flocker should + be considered as deprecated + type: string + datasetUUID: + description: datasetUUID is the UUID of the dataset. This + is unique identifier of a Flocker dataset + type: string + type: object + gcePersistentDisk: + description: 'gcePersistentDisk represents a GCE Disk resource + that is attached to a kubelet''s host machine and then exposed + to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' + properties: + fsType: + description: 'fsType is filesystem type of the volume + that you want to mount. Tip: Ensure that the filesystem + type is supported by the host operating system. Examples: + "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" + if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk + TODO: how do we prevent errors in the filesystem from + compromising the machine' + type: string + partition: + description: 'partition is the partition in the volume + that you want to mount. If omitted, the default is to + mount by volume name. Examples: For volume /dev/sda1, + you specify the partition as "1". Similarly, the volume + partition for /dev/sda is "0" (or you can leave the + property empty). More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' + format: int32 + type: integer + pdName: + description: 'pdName is unique name of the PD resource + in GCE. Used to identify the disk in GCE. More info: + https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' + type: string + readOnly: + description: 'readOnly here will force the ReadOnly setting + in VolumeMounts. Defaults to false. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' + type: boolean + required: + - pdName + type: object + gitRepo: + description: 'gitRepo represents a git repository at a particular + revision. DEPRECATED: GitRepo is deprecated. To provision + a container with a git repo, mount an EmptyDir into an InitContainer + that clones the repo using git, then mount the EmptyDir + into the Pod''s container.' + properties: + directory: + description: directory is the target directory name. Must + not contain or start with '..'. If '.' is supplied, + the volume directory will be the git repository. Otherwise, + if specified, the volume will contain the git repository + in the subdirectory with the given name. + type: string + repository: + description: repository is the URL + type: string + revision: + description: revision is the commit hash for the specified + revision. + type: string + required: + - repository + type: object + glusterfs: + description: 'glusterfs represents a Glusterfs mount on the + host that shares a pod''s lifetime. More info: https://examples.k8s.io/volumes/glusterfs/README.md' + properties: + endpoints: + description: 'endpoints is the endpoint name that details + Glusterfs topology. More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' + type: string + path: + description: 'path is the Glusterfs volume path. More + info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' + type: string + readOnly: + description: 'readOnly here will force the Glusterfs volume + to be mounted with read-only permissions. Defaults to + false. More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' + type: boolean + required: + - endpoints + - path + type: object + hostPath: + description: 'hostPath represents a pre-existing file or directory + on the host machine that is directly exposed to the container. + This is generally used for system agents or other privileged + things that are allowed to see the host machine. Most containers + will NOT need this. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath + --- TODO(jonesdl) We need to restrict who can use host directory + mounts and who can/can not mount host directories as read/write.' + properties: + path: + description: 'path of the directory on the host. If the + path is a symlink, it will follow the link to the real + path. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath' + type: string + type: + description: 'type for HostPath Volume Defaults to "" + More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath' + type: string + required: + - path + type: object + iscsi: + description: 'iscsi represents an ISCSI Disk resource that + is attached to a kubelet''s host machine and then exposed + to the pod. More info: https://examples.k8s.io/volumes/iscsi/README.md' + properties: + chapAuthDiscovery: + description: chapAuthDiscovery defines whether support + iSCSI Discovery CHAP authentication + type: boolean + chapAuthSession: + description: chapAuthSession defines whether support iSCSI + Session CHAP authentication + type: boolean + fsType: + description: 'fsType is the filesystem type of the volume + that you want to mount. Tip: Ensure that the filesystem + type is supported by the host operating system. Examples: + "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" + if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#iscsi + TODO: how do we prevent errors in the filesystem from + compromising the machine' + type: string + initiatorName: + description: initiatorName is the custom iSCSI Initiator + Name. If initiatorName is specified with iscsiInterface + simultaneously, new iSCSI interface : will be created for the connection. + type: string + iqn: + description: iqn is the target iSCSI Qualified Name. + type: string + iscsiInterface: + description: iscsiInterface is the interface Name that + uses an iSCSI transport. Defaults to 'default' (tcp). + type: string + lun: + description: lun represents iSCSI Target Lun number. + format: int32 + type: integer + portals: + description: portals is the iSCSI Target Portal List. + The portal is either an IP or ip_addr:port if the port + is other than default (typically TCP ports 860 and 3260). + items: + type: string + type: array + readOnly: + description: readOnly here will force the ReadOnly setting + in VolumeMounts. Defaults to false. + type: boolean + secretRef: + description: secretRef is the CHAP Secret for iSCSI target + and initiator authentication + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + type: object + x-kubernetes-map-type: atomic + targetPortal: + description: targetPortal is iSCSI Target Portal. The + Portal is either an IP or ip_addr:port if the port is + other than default (typically TCP ports 860 and 3260). + type: string + required: + - iqn + - lun + - targetPortal + type: object + nfs: + description: 'nfs represents an NFS mount on the host that + shares a pod''s lifetime More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' + properties: + path: + description: 'path that is exported by the NFS server. + More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' + type: string + readOnly: + description: 'readOnly here will force the NFS export + to be mounted with read-only permissions. Defaults to + false. More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' + type: boolean + server: + description: 'server is the hostname or IP address of + the NFS server. More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' + type: string + required: + - path + - server + type: object + persistentVolumeClaim: + description: 'persistentVolumeClaimVolumeSource represents + a reference to a PersistentVolumeClaim in the same namespace. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' + properties: + claimName: + description: 'claimName is the name of a PersistentVolumeClaim + in the same namespace as the pod using this volume. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' + type: string + readOnly: + description: readOnly Will force the ReadOnly setting + in VolumeMounts. Default false. + type: boolean + required: + - claimName + type: object + photonPersistentDisk: + description: photonPersistentDisk represents a PhotonController + persistent disk attached and mounted on kubelets host machine + properties: + fsType: + description: fsType is the filesystem type to mount. Must + be a filesystem type supported by the host operating + system. Ex. "ext4", "xfs", "ntfs". Implicitly inferred + to be "ext4" if unspecified. + type: string + pdID: + description: pdID is the ID that identifies Photon Controller + persistent disk + type: string + required: + - pdID + type: object + portworxVolume: + description: portworxVolume represents a portworx volume attached + and mounted on kubelets host machine + properties: + fsType: + description: fSType represents the filesystem type to + mount Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs". Implicitly inferred + to be "ext4" if unspecified. + type: string + readOnly: + description: readOnly defaults to false (read/write). + ReadOnly here will force the ReadOnly setting in VolumeMounts. + type: boolean + volumeID: + description: volumeID uniquely identifies a Portworx volume + type: string + required: + - volumeID + type: object + projected: + description: projected items for all in one resources secrets, + configmaps, and downward API + properties: + defaultMode: + description: defaultMode are the mode bits used to set + permissions on created files by default. Must be an + octal value between 0000 and 0777 or a decimal value + between 0 and 511. YAML accepts both octal and decimal + values, JSON requires decimal values for mode bits. + Directories within the path are not affected by this + setting. This might be in conflict with other options + that affect the file mode, like fsGroup, and the result + can be other mode bits set. + format: int32 + type: integer + sources: + description: sources is the list of volume projections + items: + description: Projection that may be projected along + with other supported volume types + properties: + configMap: + description: configMap information about the configMap + data to project + properties: + items: + description: items if unspecified, each key-value + pair in the Data field of the referenced ConfigMap + will be projected into the volume as a file + whose name is the key and content is the value. + If specified, the listed keys will be projected + into the specified paths, and unlisted keys + will not be present. If a key is specified + which is not present in the ConfigMap, the + volume setup will error unless it is marked + optional. Paths must be relative and may not + contain the '..' path or start with '..'. + items: + description: Maps a string key to a path within + a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: mode bits + used to set permissions on this file. + Must be an octal value between 0000 + and 0777 or a decimal value between + 0 and 511. YAML accepts both octal and + decimal values, JSON requires decimal + values for mode bits. If not specified, + the volume defaultMode will be used. + This might be in conflict with other + options that affect the file mode, like + fsGroup, and the result can be other + mode bits set.' + format: int32 + type: integer + path: + description: path is the relative path + of the file to map the key to. May not + be an absolute path. May not contain + the path element '..'. May not start + with the string '..'. + type: string + required: + - key + - path + type: object + type: array + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + optional: + description: optional specify whether the ConfigMap + or its keys must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + downwardAPI: + description: downwardAPI information about the downwardAPI + data to project + properties: + items: + description: Items is a list of DownwardAPIVolume + file + items: + description: DownwardAPIVolumeFile represents + information to create the file containing + the pod field + properties: + fieldRef: + description: 'Required: Selects a field + of the pod: only annotations, labels, + name and namespace are supported.' + 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 + mode: + description: 'Optional: mode bits used + to set permissions on this file, must + be an octal value between 0000 and 0777 + or a decimal value between 0 and 511. + YAML accepts both octal and decimal + values, JSON requires decimal values + for mode bits. If not specified, the + volume defaultMode will be used. This + might be in conflict with other options + that affect the file mode, like fsGroup, + and the result can be other mode bits + set.' + format: int32 + type: integer + path: + description: 'Required: Path is the relative + path name of the file to be created. + Must not be absolute or contain the + ''..'' path. Must be utf-8 encoded. + The first item of the relative path + must not start with ''..''' + type: string + resourceFieldRef: + description: 'Selects a resource of the + container: only resources limits and + requests (limits.cpu, limits.memory, + requests.cpu and requests.memory) 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 + required: + - path + type: object + type: array + type: object + secret: + description: secret information about the secret + data to project + properties: + items: + description: items if unspecified, each key-value + pair in the Data field of the referenced Secret + will be projected into the volume as a file + whose name is the key and content is the value. + If specified, the listed keys will be projected + into the specified paths, and unlisted keys + will not be present. If a key is specified + which is not present in the Secret, the volume + setup will error unless it is marked optional. + Paths must be relative and may not contain + the '..' path or start with '..'. + items: + description: Maps a string key to a path within + a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: mode bits + used to set permissions on this file. + Must be an octal value between 0000 + and 0777 or a decimal value between + 0 and 511. YAML accepts both octal and + decimal values, JSON requires decimal + values for mode bits. If not specified, + the volume defaultMode will be used. + This might be in conflict with other + options that affect the file mode, like + fsGroup, and the result can be other + mode bits set.' + format: int32 + type: integer + path: + description: path is the relative path + of the file to map the key to. May not + be an absolute path. May not contain + the path element '..'. May not start + with the string '..'. + type: string + required: + - key + - path + type: object + type: array + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + optional: + description: optional field specify whether + the Secret or its key must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + serviceAccountToken: + description: serviceAccountToken is information + about the serviceAccountToken data to project + properties: + audience: + description: audience is the intended audience + of the token. A recipient of a token must + identify itself with an identifier specified + in the audience of the token, and otherwise + should reject the token. The audience defaults + to the identifier of the apiserver. + type: string + expirationSeconds: + description: expirationSeconds is the requested + duration of validity of the service account + token. As the token approaches expiration, + the kubelet volume plugin will proactively + rotate the service account token. The kubelet + will start trying to rotate the token if the + token is older than 80 percent of its time + to live or if the token is older than 24 hours.Defaults + to 1 hour and must be at least 10 minutes. + format: int64 + type: integer + path: + description: path is the path relative to the + mount point of the file to project the token + into. + type: string + required: + - path + type: object + type: object + type: array + type: object + quobyte: + description: quobyte represents a Quobyte mount on the host + that shares a pod's lifetime + properties: + group: + description: group to map volume access to Default is + no group + type: string + readOnly: + description: readOnly here will force the Quobyte volume + to be mounted with read-only permissions. Defaults to + false. + type: boolean + registry: + description: registry represents a single or multiple + Quobyte Registry services specified as a string as host:port + pair (multiple entries are separated with commas) which + acts as the central registry for volumes + type: string + tenant: + description: tenant owning the given Quobyte volume in + the Backend Used with dynamically provisioned Quobyte + volumes, value is set by the plugin + type: string + user: + description: user to map volume access to Defaults to + serivceaccount user + type: string + volume: + description: volume is a string that references an already + created Quobyte volume by name. + type: string + required: + - registry + - volume + type: object + rbd: + description: 'rbd represents a Rados Block Device mount on + the host that shares a pod''s lifetime. More info: https://examples.k8s.io/volumes/rbd/README.md' + properties: + fsType: + description: 'fsType is the filesystem type of the volume + that you want to mount. Tip: Ensure that the filesystem + type is supported by the host operating system. Examples: + "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" + if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#rbd + TODO: how do we prevent errors in the filesystem from + compromising the machine' + type: string + image: + description: 'image is the rados image name. More info: + https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: string + keyring: + description: 'keyring is the path to key ring for RBDUser. + Default is /etc/ceph/keyring. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: string + monitors: + description: 'monitors is a collection of Ceph monitors. + More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + items: + type: string + type: array + pool: + description: 'pool is the rados pool name. Default is + rbd. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: string + readOnly: + description: 'readOnly here will force the ReadOnly setting + in VolumeMounts. Defaults to false. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: boolean + secretRef: + description: 'secretRef is name of the authentication + secret for RBDUser. If provided overrides keyring. Default + is nil. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + type: object + x-kubernetes-map-type: atomic + user: + description: 'user is the rados user name. Default is + admin. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: string + required: + - image + - monitors + type: object + scaleIO: + description: scaleIO represents a ScaleIO persistent volume + attached and mounted on Kubernetes nodes. + properties: + fsType: + description: fsType is the filesystem type to mount. Must + be a filesystem type supported by the host operating + system. Ex. "ext4", "xfs", "ntfs". Default is "xfs". + type: string + gateway: + description: gateway is the host address of the ScaleIO + API Gateway. + type: string + protectionDomain: + description: protectionDomain is the name of the ScaleIO + Protection Domain for the configured storage. + type: string + readOnly: + description: readOnly Defaults to false (read/write). + ReadOnly here will force the ReadOnly setting in VolumeMounts. + type: boolean + secretRef: + description: secretRef references to the secret for ScaleIO + user and other sensitive information. If this is not + provided, Login operation will fail. + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + type: object + x-kubernetes-map-type: atomic + sslEnabled: + description: sslEnabled Flag enable/disable SSL communication + with Gateway, default false + type: boolean + storageMode: + description: storageMode indicates whether the storage + for a volume should be ThickProvisioned or ThinProvisioned. + Default is ThinProvisioned. + type: string + storagePool: + description: storagePool is the ScaleIO Storage Pool associated + with the protection domain. + type: string + system: + description: system is the name of the storage system + as configured in ScaleIO. + type: string + volumeName: + description: volumeName is the name of a volume already + created in the ScaleIO system that is associated with + this volume source. + type: string + required: + - gateway + - secretRef + - system + type: object + secret: + description: 'secret represents a secret that should populate + this volume. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' + properties: + defaultMode: + description: 'defaultMode is Optional: mode bits used + to set permissions on created files by default. Must + be an octal value between 0000 and 0777 or a decimal + value between 0 and 511. YAML accepts both octal and + decimal values, JSON requires decimal values for mode + bits. Defaults to 0644. Directories within the path + are not affected by this setting. This might be in conflict + with other options that affect the file mode, like fsGroup, + and the result can be other mode bits set.' + format: int32 + type: integer + items: + description: items If unspecified, each key-value pair + in the Data field of the referenced Secret will be projected + into the volume as a file whose name is the key and + content is the value. If specified, the listed keys + will be projected into the specified paths, and unlisted + keys will not be present. If a key is specified which + is not present in the Secret, the volume setup will + error unless it is marked optional. Paths must be relative + and may not contain the '..' path or start with '..'. + items: + description: Maps a string key to a path within a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: mode bits used to + set permissions on this file. Must be an octal + value between 0000 and 0777 or a decimal value + between 0 and 511. YAML accepts both octal and + decimal values, JSON requires decimal values for + mode bits. If not specified, the volume defaultMode + will be used. This might be in conflict with other + options that affect the file mode, like fsGroup, + and the result can be other mode bits set.' + format: int32 + type: integer + path: + description: path is the relative path of the file + to map the key to. May not be an absolute path. + May not contain the path element '..'. May not + start with the string '..'. + type: string + required: + - key + - path + type: object + type: array + optional: + description: optional field specify whether the Secret + or its keys must be defined + type: boolean + secretName: + description: 'secretName is the name of the secret in + the pod''s namespace to use. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' + type: string + type: object + storageos: + description: storageOS represents a StorageOS volume attached + and mounted on Kubernetes nodes. + properties: + fsType: + description: fsType is the filesystem type to mount. Must + be a filesystem type supported by the host operating + system. Ex. "ext4", "xfs", "ntfs". Implicitly inferred + to be "ext4" if unspecified. + type: string + readOnly: + description: readOnly defaults to false (read/write). + ReadOnly here will force the ReadOnly setting in VolumeMounts. + type: boolean + secretRef: + description: secretRef specifies the secret to use for + obtaining the StorageOS API credentials. If not specified, + default values will be attempted. + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + type: object + x-kubernetes-map-type: atomic + volumeName: + description: volumeName is the human-readable name of + the StorageOS volume. Volume names are only unique + within a namespace. + type: string + volumeNamespace: + description: volumeNamespace specifies the scope of the + volume within StorageOS. If no namespace is specified + then the Pod's namespace will be used. This allows + the Kubernetes name scoping to be mirrored within StorageOS + for tighter integration. Set VolumeName to any name + to override the default behaviour. Set to "default" + if you are not using namespaces within StorageOS. Namespaces + that do not pre-exist within StorageOS will be created. + type: string + type: object + vsphereVolume: + description: vsphereVolume represents a vSphere volume attached + and mounted on kubelets host machine + properties: + fsType: + description: fsType is filesystem type to mount. Must + be a filesystem type supported by the host operating + system. Ex. "ext4", "xfs", "ntfs". Implicitly inferred + to be "ext4" if unspecified. + type: string + storagePolicyID: + description: storagePolicyID is the storage Policy Based + Management (SPBM) profile ID associated with the StoragePolicyName. + type: string + storagePolicyName: + description: storagePolicyName is the storage Policy Based + Management (SPBM) profile name. + type: string + volumePath: + description: volumePath is the path that identifies vSphere + volume vmdk + type: string + required: + - volumePath + type: object + type: object + type: object + command: + items: + type: string + type: array + connection: + properties: + healthCheck: + properties: + interval: + type: string + retryInterval: + type: string + type: object + params: + additionalProperties: + type: string + type: object + secretName: + type: string + secretTemplate: + properties: + annotations: + additionalProperties: + type: string + type: object + databaseKey: + type: string + format: + type: string + hostKey: + type: string + key: + type: string + labels: + additionalProperties: + type: string + type: object + passwordKey: + type: string + portKey: + type: string + usernameKey: + type: string + type: object + serviceName: + type: string + type: object + database: + type: string + env: + 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: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + envFrom: + items: + description: EnvFromSource represents the source of a set of ConfigMaps + properties: + configMapRef: + description: The ConfigMap to select from + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + optional: + description: Specify whether the ConfigMap must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + description: An optional identifier to prepend to each key in + the ConfigMap. Must be a C_IDENTIFIER. + type: string + secretRef: + description: The Secret to select from + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + optional: + description: Specify whether the Secret must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + galera: + description: Galera allows you to enable multi-master HA via Galera + in your MariaDB cluster. + properties: + agent: + description: 'GaleraAgent is a sidecar agent that co-operates + with mariadb-operator. More info: https://github.com/mariadb-operator/agent.' + properties: + args: + items: + type: string + type: array + command: + items: + type: string + type: array + env: + 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: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + 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: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + 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 + envFrom: + items: + description: EnvFromSource represents the source of a set + of ConfigMaps + properties: + configMapRef: + description: The ConfigMap to select from + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the ConfigMap must + be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + description: An optional identifier to prepend to each + key in the ConfigMap. Must be a C_IDENTIFIER. + type: string + secretRef: + description: The Secret to select from + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the Secret must be + defined + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + gracefulShutdownTimeout: + description: GracefulShutdownTimeout is the time we give to + the agent container in order to gracefully terminate in-flight + requests. + type: string + image: + type: string + imagePullPolicy: + default: IfNotPresent + description: PullPolicy describes a policy for if/when to + pull a container image + type: string + kubernetesAuth: + description: KubernetesAuth to be used by the agent container + properties: + authDelegatorRoleName: + description: AuthDelegatorRoleName is the name of the + ClusterRoleBinding that is associated with the "system:auth-delegator" + ClusterRole. It is necessary for creating TokenReview + objects in order for the agent to validate the service + account token. + type: string + enabled: + description: Enabled is a flag to enable KubernetesAuth + type: boolean + type: object + livenessProbe: + description: Probe describes a health check to be performed + against a container to determine whether it is alive or + ready to receive traffic. + properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to execute + inside the container, the working directory for + the command is root ('/') in the container's filesystem. + The command is simply exec'd, it is not run inside + a shell, so traditional shell instructions ('|', + etc) won't work. To use a shell, you need to explicitly + call out to that shell. Exit status of 0 is treated + as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + type: object + failureThreshold: + description: Minimum consecutive failures for the probe + to be considered failed after having succeeded. Defaults + to 3. Minimum value is 1. + format: int32 + type: integer + grpc: + description: GRPC specifies an action involving a GRPC + port. + properties: + port: + description: Port number of the gRPC service. Number + must be in the range 1 to 65535. + format: int32 + type: integer + service: + description: "Service is the name of the service to + place in the gRPC HealthCheckRequest (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + \n If this is not specified, the default behavior + is defined by gRPC." + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies the http request to perform. + properties: + host: + description: Host name to connect to, defaults to + the pod IP. You probably want to set "Host" in httpHeaders + instead. + type: string + httpHeaders: + description: Custom headers to set in the request. + HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom header + to be used in HTTP probes + properties: + name: + description: The header field name. This will + be canonicalized upon output, so case-variant + names will be understood as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access + on the container. Number must be in the range 1 + to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to the host. + Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: 'Number of seconds after the container has + started before liveness probes are initiated. More info: + https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + periodSeconds: + description: How often (in seconds) to perform the probe. + Default to 10 seconds. Minimum value is 1. + format: int32 + type: integer + successThreshold: + description: Minimum consecutive successes for the probe + to be considered successful after having failed. Defaults + to 1. Must be 1 for liveness and startup. Minimum value + is 1. + format: int32 + type: integer + tcpSocket: + description: TCPSocket specifies an action involving a + TCP port. + properties: + host: + description: 'Optional: Host name to connect to, defaults + to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access + on the container. Number must be in the range 1 + to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: Optional duration in seconds the pod needs + to terminate gracefully upon probe failure. The grace + period is the duration in seconds after the processes + running in the pod are sent a termination signal and + the time when the processes are forcibly halted with + a kill signal. Set this value longer than the expected + cleanup time for your process. If this value is nil, + the pod's terminationGracePeriodSeconds will be used. + Otherwise, this value overrides the value provided by + the pod spec. Value must be non-negative integer. The + value zero indicates stop immediately via the kill signal + (no opportunity to shut down). This is a beta field + and requires enabling ProbeTerminationGracePeriod feature + gate. Minimum value is 1. spec.terminationGracePeriodSeconds + is used if unset. + format: int64 + type: integer + timeoutSeconds: + description: 'Number of seconds after which the probe + times out. Defaults to 1 second. Minimum value is 1. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + type: object + port: + description: Port to be used by the agent container + format: int32 + type: integer + readinessProbe: + description: Probe describes a health check to be performed + against a container to determine whether it is alive or + ready to receive traffic. + properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to execute + inside the container, the working directory for + the command is root ('/') in the container's filesystem. + The command is simply exec'd, it is not run inside + a shell, so traditional shell instructions ('|', + etc) won't work. To use a shell, you need to explicitly + call out to that shell. Exit status of 0 is treated + as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + type: object + failureThreshold: + description: Minimum consecutive failures for the probe + to be considered failed after having succeeded. Defaults + to 3. Minimum value is 1. + format: int32 + type: integer + grpc: + description: GRPC specifies an action involving a GRPC + port. + properties: + port: + description: Port number of the gRPC service. Number + must be in the range 1 to 65535. + format: int32 + type: integer + service: + description: "Service is the name of the service to + place in the gRPC HealthCheckRequest (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + \n If this is not specified, the default behavior + is defined by gRPC." + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies the http request to perform. + properties: + host: + description: Host name to connect to, defaults to + the pod IP. You probably want to set "Host" in httpHeaders + instead. + type: string + httpHeaders: + description: Custom headers to set in the request. + HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom header + to be used in HTTP probes + properties: + name: + description: The header field name. This will + be canonicalized upon output, so case-variant + names will be understood as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access + on the container. Number must be in the range 1 + to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to the host. + Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: 'Number of seconds after the container has + started before liveness probes are initiated. More info: + https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + periodSeconds: + description: How often (in seconds) to perform the probe. + Default to 10 seconds. Minimum value is 1. + format: int32 + type: integer + successThreshold: + description: Minimum consecutive successes for the probe + to be considered successful after having failed. Defaults + to 1. Must be 1 for liveness and startup. Minimum value + is 1. + format: int32 + type: integer + tcpSocket: + description: TCPSocket specifies an action involving a + TCP port. + properties: + host: + description: 'Optional: Host name to connect to, defaults + to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access + on the container. Number must be in the range 1 + to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: Optional duration in seconds the pod needs + to terminate gracefully upon probe failure. The grace + period is the duration in seconds after the processes + running in the pod are sent a termination signal and + the time when the processes are forcibly halted with + a kill signal. Set this value longer than the expected + cleanup time for your process. If this value is nil, + the pod's terminationGracePeriodSeconds will be used. + Otherwise, this value overrides the value provided by + the pod spec. Value must be non-negative integer. The + value zero indicates stop immediately via the kill signal + (no opportunity to shut down). This is a beta field + and requires enabling ProbeTerminationGracePeriod feature + gate. Minimum value is 1. spec.terminationGracePeriodSeconds + is used if unset. + format: int64 + type: integer + timeoutSeconds: + description: 'Number of seconds after which the probe + times out. Defaults to 1 second. Minimum value is 1. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + type: object + resources: + description: ResourceRequirements describes the compute resource + requirements. + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. \n 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 + 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 + securityContext: + description: SecurityContext holds security configuration + that will be applied to a container. Some fields are present + in both SecurityContext and PodSecurityContext. When both + are set, the values in SecurityContext take precedence. + properties: + allowPrivilegeEscalation: + description: 'AllowPrivilegeEscalation controls whether + a process can gain more privileges than its parent process. + This bool directly controls if the no_new_privs flag + will be set on the container process. AllowPrivilegeEscalation + is true always when the container is: 1) run as Privileged + 2) has CAP_SYS_ADMIN Note that this field cannot be + set when spec.os.name is windows.' + type: boolean + capabilities: + description: The capabilities to add/drop when running + containers. Defaults to the default set of capabilities + granted by the container runtime. Note that this field + cannot be set when spec.os.name is windows. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + type: object + privileged: + description: Run container in privileged mode. Processes + in privileged containers are essentially equivalent + to root on the host. Defaults to false. Note that this + field cannot be set when spec.os.name is windows. + type: boolean + procMount: + description: procMount denotes the type of proc mount + to use for the containers. The default is DefaultProcMount + which uses the container runtime defaults for readonly + paths and masked paths. This requires the ProcMountType + feature flag to be enabled. Note that this field cannot + be set when spec.os.name is windows. + type: string + readOnlyRootFilesystem: + description: Whether this container has a read-only root + filesystem. Default is false. Note that this field cannot + be set when spec.os.name is windows. + type: boolean + runAsGroup: + description: The GID to run the entrypoint of the container + process. Uses runtime default if unset. May also be + set in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set + when spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as + a non-root user. If true, the Kubelet will validate + the image at runtime to ensure that it does not run + as UID 0 (root) and fail to start the container if it + does. If unset or false, no such validation will be + performed. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container + process. Defaults to user specified in image metadata + if unspecified. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name + is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to the + container. If unspecified, the container runtime will + allocate a random SELinux context for each container. May + also be set in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set + when spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by this container. + If seccomp options are provided at both the pod & container + level, the container options override the pod options. + Note that this field cannot be set when spec.os.name + is windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile + defined in a file on the node should be used. The + profile must be preconfigured on the node to work. + Must be a descending path, relative to the kubelet's + configured seccomp profile location. Must be set + if type is "Localhost". Must NOT be set for any + other type. + type: string + type: + description: "type indicates which kind of seccomp + profile will be applied. Valid options are: \n Localhost + - a profile defined in a file on the node should + be used. RuntimeDefault - the container runtime + default profile should be used. Unconfined - no + profile should be applied." + type: string + required: + - type + type: object + windowsOptions: + description: The Windows specific settings applied to + all containers. If unspecified, the options from the + PodSecurityContext will be used. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set + when spec.os.name is linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA + admission webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec + named by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of + the GMSA credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container + should be run as a 'Host Process' container. All + of a Pod's containers must have the same effective + HostProcess value (it is not allowed to have a mix + of HostProcess containers and non-HostProcess containers). + In addition, if HostProcess is true then HostNetwork + must also be set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set + in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. + type: string + type: object + type: object + volumeMounts: + items: + description: VolumeMount describes a mounting of a Volume + within a container. + properties: + mountPath: + description: Path within the container at which the + volume should be mounted. Must not contain ':'. + type: string + mountPropagation: + description: mountPropagation determines how mounts + are propagated from the host to container and the + other way around. When not set, MountPropagationNone + is used. This field is beta in 1.10. + type: string + name: + description: This must match the Name of a Volume. + type: string + readOnly: + description: Mounted read-only if true, read-write otherwise + (false or unspecified). Defaults to false. + type: boolean + subPath: + description: Path within the volume from which the container's + volume should be mounted. Defaults to "" (volume's + root). + type: string + subPathExpr: + description: Expanded path within the volume from which + the container's volume should be mounted. Behaves + similarly to SubPath but environment variable references + $(VAR_NAME) are expanded using the container's environment. + Defaults to "" (volume's root). SubPathExpr and SubPath + are mutually exclusive. + type: string + required: + - mountPath + - name + type: object + type: array + required: + - image + type: object + enabled: + description: Enabled is a flag to enable Galera. + type: boolean + initContainer: + description: 'InitContainer is an init container that co-operates + with mariadb-operator. More info: https://github.com/mariadb-operator/init.' + properties: + args: + items: + type: string + type: array + command: + items: + type: string + type: array + env: + 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: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + 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: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + 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 + envFrom: + items: + description: EnvFromSource represents the source of a set + of ConfigMaps + properties: + configMapRef: + description: The ConfigMap to select from + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the ConfigMap must + be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + description: An optional identifier to prepend to each + key in the ConfigMap. Must be a C_IDENTIFIER. + type: string + secretRef: + description: The Secret to select from + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the Secret must be + defined + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + image: + type: string + imagePullPolicy: + default: IfNotPresent + description: PullPolicy describes a policy for if/when to + pull a container image + type: string + livenessProbe: + description: Probe describes a health check to be performed + against a container to determine whether it is alive or + ready to receive traffic. + properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to execute + inside the container, the working directory for + the command is root ('/') in the container's filesystem. + The command is simply exec'd, it is not run inside + a shell, so traditional shell instructions ('|', + etc) won't work. To use a shell, you need to explicitly + call out to that shell. Exit status of 0 is treated + as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + type: object + failureThreshold: + description: Minimum consecutive failures for the probe + to be considered failed after having succeeded. Defaults + to 3. Minimum value is 1. + format: int32 + type: integer + grpc: + description: GRPC specifies an action involving a GRPC + port. + properties: + port: + description: Port number of the gRPC service. Number + must be in the range 1 to 65535. + format: int32 + type: integer + service: + description: "Service is the name of the service to + place in the gRPC HealthCheckRequest (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + \n If this is not specified, the default behavior + is defined by gRPC." + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies the http request to perform. + properties: + host: + description: Host name to connect to, defaults to + the pod IP. You probably want to set "Host" in httpHeaders + instead. + type: string + httpHeaders: + description: Custom headers to set in the request. + HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom header + to be used in HTTP probes + properties: + name: + description: The header field name. This will + be canonicalized upon output, so case-variant + names will be understood as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access + on the container. Number must be in the range 1 + to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to the host. + Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: 'Number of seconds after the container has + started before liveness probes are initiated. More info: + https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + periodSeconds: + description: How often (in seconds) to perform the probe. + Default to 10 seconds. Minimum value is 1. + format: int32 + type: integer + successThreshold: + description: Minimum consecutive successes for the probe + to be considered successful after having failed. Defaults + to 1. Must be 1 for liveness and startup. Minimum value + is 1. + format: int32 + type: integer + tcpSocket: + description: TCPSocket specifies an action involving a + TCP port. + properties: + host: + description: 'Optional: Host name to connect to, defaults + to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access + on the container. Number must be in the range 1 + to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: Optional duration in seconds the pod needs + to terminate gracefully upon probe failure. The grace + period is the duration in seconds after the processes + running in the pod are sent a termination signal and + the time when the processes are forcibly halted with + a kill signal. Set this value longer than the expected + cleanup time for your process. If this value is nil, + the pod's terminationGracePeriodSeconds will be used. + Otherwise, this value overrides the value provided by + the pod spec. Value must be non-negative integer. The + value zero indicates stop immediately via the kill signal + (no opportunity to shut down). This is a beta field + and requires enabling ProbeTerminationGracePeriod feature + gate. Minimum value is 1. spec.terminationGracePeriodSeconds + is used if unset. + format: int64 + type: integer + timeoutSeconds: + description: 'Number of seconds after which the probe + times out. Defaults to 1 second. Minimum value is 1. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + type: object + readinessProbe: + description: Probe describes a health check to be performed + against a container to determine whether it is alive or + ready to receive traffic. + properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to execute + inside the container, the working directory for + the command is root ('/') in the container's filesystem. + The command is simply exec'd, it is not run inside + a shell, so traditional shell instructions ('|', + etc) won't work. To use a shell, you need to explicitly + call out to that shell. Exit status of 0 is treated + as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + type: object + failureThreshold: + description: Minimum consecutive failures for the probe + to be considered failed after having succeeded. Defaults + to 3. Minimum value is 1. + format: int32 + type: integer + grpc: + description: GRPC specifies an action involving a GRPC + port. + properties: + port: + description: Port number of the gRPC service. Number + must be in the range 1 to 65535. + format: int32 + type: integer + service: + description: "Service is the name of the service to + place in the gRPC HealthCheckRequest (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + \n If this is not specified, the default behavior + is defined by gRPC." + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies the http request to perform. + properties: + host: + description: Host name to connect to, defaults to + the pod IP. You probably want to set "Host" in httpHeaders + instead. + type: string + httpHeaders: + description: Custom headers to set in the request. + HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom header + to be used in HTTP probes + properties: + name: + description: The header field name. This will + be canonicalized upon output, so case-variant + names will be understood as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access + on the container. Number must be in the range 1 + to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to the host. + Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: 'Number of seconds after the container has + started before liveness probes are initiated. More info: + https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + periodSeconds: + description: How often (in seconds) to perform the probe. + Default to 10 seconds. Minimum value is 1. + format: int32 + type: integer + successThreshold: + description: Minimum consecutive successes for the probe + to be considered successful after having failed. Defaults + to 1. Must be 1 for liveness and startup. Minimum value + is 1. + format: int32 + type: integer + tcpSocket: + description: TCPSocket specifies an action involving a + TCP port. + properties: + host: + description: 'Optional: Host name to connect to, defaults + to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access + on the container. Number must be in the range 1 + to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: Optional duration in seconds the pod needs + to terminate gracefully upon probe failure. The grace + period is the duration in seconds after the processes + running in the pod are sent a termination signal and + the time when the processes are forcibly halted with + a kill signal. Set this value longer than the expected + cleanup time for your process. If this value is nil, + the pod's terminationGracePeriodSeconds will be used. + Otherwise, this value overrides the value provided by + the pod spec. Value must be non-negative integer. The + value zero indicates stop immediately via the kill signal + (no opportunity to shut down). This is a beta field + and requires enabling ProbeTerminationGracePeriod feature + gate. Minimum value is 1. spec.terminationGracePeriodSeconds + is used if unset. + format: int64 + type: integer + timeoutSeconds: + description: 'Number of seconds after which the probe + times out. Defaults to 1 second. Minimum value is 1. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + type: object + resources: + description: ResourceRequirements describes the compute resource + requirements. + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. \n 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 + 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 + securityContext: + description: SecurityContext holds security configuration + that will be applied to a container. Some fields are present + in both SecurityContext and PodSecurityContext. When both + are set, the values in SecurityContext take precedence. + properties: + allowPrivilegeEscalation: + description: 'AllowPrivilegeEscalation controls whether + a process can gain more privileges than its parent process. + This bool directly controls if the no_new_privs flag + will be set on the container process. AllowPrivilegeEscalation + is true always when the container is: 1) run as Privileged + 2) has CAP_SYS_ADMIN Note that this field cannot be + set when spec.os.name is windows.' + type: boolean + capabilities: + description: The capabilities to add/drop when running + containers. Defaults to the default set of capabilities + granted by the container runtime. Note that this field + cannot be set when spec.os.name is windows. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + type: object + privileged: + description: Run container in privileged mode. Processes + in privileged containers are essentially equivalent + to root on the host. Defaults to false. Note that this + field cannot be set when spec.os.name is windows. + type: boolean + procMount: + description: procMount denotes the type of proc mount + to use for the containers. The default is DefaultProcMount + which uses the container runtime defaults for readonly + paths and masked paths. This requires the ProcMountType + feature flag to be enabled. Note that this field cannot + be set when spec.os.name is windows. + type: string + readOnlyRootFilesystem: + description: Whether this container has a read-only root + filesystem. Default is false. Note that this field cannot + be set when spec.os.name is windows. + type: boolean + runAsGroup: + description: The GID to run the entrypoint of the container + process. Uses runtime default if unset. May also be + set in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set + when spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as + a non-root user. If true, the Kubelet will validate + the image at runtime to ensure that it does not run + as UID 0 (root) and fail to start the container if it + does. If unset or false, no such validation will be + performed. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container + process. Defaults to user specified in image metadata + if unspecified. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name + is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to the + container. If unspecified, the container runtime will + allocate a random SELinux context for each container. May + also be set in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set + when spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by this container. + If seccomp options are provided at both the pod & container + level, the container options override the pod options. + Note that this field cannot be set when spec.os.name + is windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile + defined in a file on the node should be used. The + profile must be preconfigured on the node to work. + Must be a descending path, relative to the kubelet's + configured seccomp profile location. Must be set + if type is "Localhost". Must NOT be set for any + other type. + type: string + type: + description: "type indicates which kind of seccomp + profile will be applied. Valid options are: \n Localhost + - a profile defined in a file on the node should + be used. RuntimeDefault - the container runtime + default profile should be used. Unconfined - no + profile should be applied." + type: string + required: + - type + type: object + windowsOptions: + description: The Windows specific settings applied to + all containers. If unspecified, the options from the + PodSecurityContext will be used. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set + when spec.os.name is linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA + admission webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec + named by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of + the GMSA credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container + should be run as a 'Host Process' container. All + of a Pod's containers must have the same effective + HostProcess value (it is not allowed to have a mix + of HostProcess containers and non-HostProcess containers). + In addition, if HostProcess is true then HostNetwork + must also be set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set + in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. + type: string + type: object + type: object + volumeMounts: + items: + description: VolumeMount describes a mounting of a Volume + within a container. + properties: + mountPath: + description: Path within the container at which the + volume should be mounted. Must not contain ':'. + type: string + mountPropagation: + description: mountPropagation determines how mounts + are propagated from the host to container and the + other way around. When not set, MountPropagationNone + is used. This field is beta in 1.10. + type: string + name: + description: This must match the Name of a Volume. + type: string + readOnly: + description: Mounted read-only if true, read-write otherwise + (false or unspecified). Defaults to false. + type: boolean + subPath: + description: Path within the volume from which the container's + volume should be mounted. Defaults to "" (volume's + root). + type: string + subPathExpr: + description: Expanded path within the volume from which + the container's volume should be mounted. Behaves + similarly to SubPath but environment variable references + $(VAR_NAME) are expanded using the container's environment. + Defaults to "" (volume's root). SubPathExpr and SubPath + are mutually exclusive. + type: string + required: + - mountPath + - name + type: object + type: array + required: + - image + type: object + primary: + description: Primary is the Galera configuration for the primary + node. + properties: + automaticFailover: + description: AutomaticFailover indicates whether the operator + should automatically update PodIndex to perform an automatic + primary failover. + type: boolean + podIndex: + description: PodIndex is the StatefulSet index of the primary + node. The user may change this field to perform a manual + switchover. + type: integer + type: object + recovery: + description: 'GaleraRecovery is the recovery process performed + by the operator whenever the Galera cluster is not healthy. + More info: https://galeracluster.com/library/documentation/crash-recovery.html.' + properties: + clusterBootstrapTimeout: + description: ClusterBootstrapTimeout is the time limit for + bootstrapping a cluster. Once this timeout is reached, the + Galera recovery state is reset and a new cluster bootstrap + will be attempted. + type: string + clusterHealthyTimeout: + description: ClusterHealthyTimeout represents the duration + at which a Galera cluster, that consistently failed health + checks, is considered unhealthy, and consequently the Galera + recovery process will be initiated by the operator. + type: string + enabled: + description: Enabled is a flag to enable GaleraRecovery. + type: boolean + podRecoveryTimeout: + description: PodRecoveryTimeout is the time limit for executing + the recovery sequence within a Pod. This process includes + enabling the recovery mode in the Galera configuration file, + restarting the Pod and retrieving the sequence from a log + file. + type: string + podSyncTimeout: + description: PodSyncTimeout is the time limit we give to a + Pod to reach the Sync state. Once this timeout is reached, + the Pod is restarted. + type: string + type: object + replicaThreads: + description: 'ReplicaThreads is the number of replica threads + used to apply Galera write sets in parallel. More info: https://mariadb.com/kb/en/galera-cluster-system-variables/#wsrep_slave_threads.' + type: integer + sst: + description: 'SST is the Snapshot State Transfer used when new + Pods join the cluster. More info: https://galeracluster.com/library/documentation/sst.html.' + type: string + volumeClaimTemplate: + description: VolumeClaimTemplate is a template for the PVC that + will contain the Galera configuration files shared between the + InitContainer, Agent and MariaDB. + properties: + accessModes: + description: 'accessModes contains the desired access modes + the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' + items: + type: string + type: array + annotations: + additionalProperties: + type: string + type: object + dataSource: + description: 'dataSource field can be used to specify either: + * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) + * An existing PVC (PersistentVolumeClaim) If the provisioner + or an external controller can support the specified data + source, it will create a new volume based on the contents + of the specified data source. When the AnyVolumeDataSource + feature gate is enabled, dataSource contents will be copied + to dataSourceRef, and dataSourceRef contents will be copied + to dataSource when dataSourceRef.namespace is not specified. + If the namespace is specified, then dataSourceRef will not + be copied to dataSource.' + properties: + apiGroup: + description: APIGroup is the group for the resource being + referenced. If APIGroup is not specified, the specified + Kind must be in the core API group. For any other third-party + types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource being referenced + type: string + name: + description: Name is the name of resource being referenced + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + description: 'dataSourceRef specifies the object from which + to populate the volume with data, if a non-empty volume + is desired. This may be any object from a non-empty API + group (non core object) or a PersistentVolumeClaim object. + When this field is specified, volume binding will only succeed + if the type of the specified object matches some installed + volume populator or dynamic provisioner. This field will + replace the functionality of the dataSource field and as + such if both fields are non-empty, they must have the same + value. For backwards compatibility, when namespace isn''t + specified in dataSourceRef, both fields (dataSource and + dataSourceRef) will be set to the same value automatically + if one of them is empty and the other is non-empty. When + namespace is specified in dataSourceRef, dataSource isn''t + set to the same value and must be empty. There are three + important differences between dataSource and dataSourceRef: + * While dataSource only allows two specific types of objects, + dataSourceRef allows any non-core object, as well as PersistentVolumeClaim + objects. * While dataSource ignores disallowed values (dropping + them), dataSourceRef preserves all values, and generates + an error if a disallowed value is specified. * While dataSource + only allows local objects, dataSourceRef allows objects + in any namespaces. (Beta) Using this field requires the + AnyVolumeDataSource feature gate to be enabled. (Alpha) + Using the namespace field of dataSourceRef requires the + CrossNamespaceVolumeDataSource feature gate to be enabled.' + properties: + apiGroup: + description: APIGroup is the group for the resource being + referenced. If APIGroup is not specified, the specified + Kind must be in the core API group. For any other third-party + types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource being referenced + type: string + name: + description: Name is the name of resource being referenced + type: string + namespace: + description: Namespace is the namespace of resource being + referenced Note that when a namespace is specified, + a gateway.networking.k8s.io/ReferenceGrant object is + required in the referent namespace to allow that namespace's + owner to accept the reference. See the ReferenceGrant + documentation for details. (Alpha) This field requires + the CrossNamespaceVolumeDataSource feature gate to be + enabled. + type: string + required: + - kind + - name + type: object + labels: + additionalProperties: + type: string + type: object + resources: + description: 'resources represents the minimum resources the + volume should have. If RecoverVolumeExpansionFailure feature + is enabled users are allowed to specify resource requirements + that are lower than previous value but must still be higher + than capacity recorded in the status field of the claim. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. \n 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 + 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 + selector: + description: selector is a label query over volumes to consider + for binding. + 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 + required: + - key + - operator + type: object + type: array + 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 + storageClassName: + description: 'storageClassName is the name of the StorageClass + required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' + type: string + volumeMode: + description: volumeMode defines what type of volume is required + by the claim. Value of Filesystem is implied when not included + in claim spec. + type: string + volumeName: + description: volumeName is the binding reference to the PersistentVolume + backing this claim. + type: string + type: object + type: object + image: + type: string + imagePullPolicy: + default: IfNotPresent + description: PullPolicy describes a policy for if/when to pull a container + image + type: string + imagePullSecrets: + items: + description: LocalObjectReference contains enough information to + let you locate the referenced object inside the same namespace. + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + x-kubernetes-map-type: atomic + type: array + inheritMetadata: + properties: + annotations: + additionalProperties: + type: string + type: object + labels: + additionalProperties: + type: string + type: object + type: object + initContainers: + items: + properties: + args: + items: + type: string + type: array + command: + items: + type: string + type: array + env: + 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: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + 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: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + 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 + envFrom: + items: + description: EnvFromSource represents the source of a set + of ConfigMaps + properties: + configMapRef: + description: The ConfigMap to select from + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the ConfigMap must be + defined + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + description: An optional identifier to prepend to each + key in the ConfigMap. Must be a C_IDENTIFIER. + type: string + secretRef: + description: The Secret to select from + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the Secret must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + image: + type: string + imagePullPolicy: + default: IfNotPresent + description: PullPolicy describes a policy for if/when to pull + a container image + type: string + livenessProbe: + description: Probe describes a health check to be performed + against a container to determine whether it is alive or ready + to receive traffic. + properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to execute + inside the container, the working directory for the + command is root ('/') in the container's filesystem. + The command is simply exec'd, it is not run inside + a shell, so traditional shell instructions ('|', etc) + won't work. To use a shell, you need to explicitly + call out to that shell. Exit status of 0 is treated + as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + type: object + failureThreshold: + description: Minimum consecutive failures for the probe + to be considered failed after having succeeded. Defaults + to 3. Minimum value is 1. + format: int32 + type: integer + grpc: + description: GRPC specifies an action involving a GRPC port. + properties: + port: + description: Port number of the gRPC service. Number + must be in the range 1 to 65535. + format: int32 + type: integer + service: + description: "Service is the name of the service to + place in the gRPC HealthCheckRequest (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + \n If this is not specified, the default behavior + is defined by gRPC." + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies the http request to perform. + properties: + host: + description: Host name to connect to, defaults to the + pod IP. You probably want to set "Host" in httpHeaders + instead. + type: string + httpHeaders: + description: Custom headers to set in the request. HTTP + allows repeated headers. + items: + description: HTTPHeader describes a custom header + to be used in HTTP probes + properties: + name: + description: The header field name. This will + be canonicalized upon output, so case-variant + names will be understood as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access on + the container. Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to the host. + Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: 'Number of seconds after the container has + started before liveness probes are initiated. More info: + https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + periodSeconds: + description: How often (in seconds) to perform the probe. + Default to 10 seconds. Minimum value is 1. + format: int32 + type: integer + successThreshold: + description: Minimum consecutive successes for the probe + to be considered successful after having failed. Defaults + to 1. Must be 1 for liveness and startup. Minimum value + is 1. + format: int32 + type: integer + tcpSocket: + description: TCPSocket specifies an action involving a TCP + port. + properties: + host: + description: 'Optional: Host name to connect to, defaults + to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access on + the container. Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: Optional duration in seconds the pod needs + to terminate gracefully upon probe failure. The grace + period is the duration in seconds after the processes + running in the pod are sent a termination signal and the + time when the processes are forcibly halted with a kill + signal. Set this value longer than the expected cleanup + time for your process. If this value is nil, the pod's + terminationGracePeriodSeconds will be used. Otherwise, + this value overrides the value provided by the pod spec. + Value must be non-negative integer. The value zero indicates + stop immediately via the kill signal (no opportunity to + shut down). This is a beta field and requires enabling + ProbeTerminationGracePeriod feature gate. Minimum value + is 1. spec.terminationGracePeriodSeconds is used if unset. + format: int64 + type: integer + timeoutSeconds: + description: 'Number of seconds after which the probe times + out. Defaults to 1 second. Minimum value is 1. More info: + https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + type: object + readinessProbe: + description: Probe describes a health check to be performed + against a container to determine whether it is alive or ready + to receive traffic. + properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to execute + inside the container, the working directory for the + command is root ('/') in the container's filesystem. + The command is simply exec'd, it is not run inside + a shell, so traditional shell instructions ('|', etc) + won't work. To use a shell, you need to explicitly + call out to that shell. Exit status of 0 is treated + as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + type: object + failureThreshold: + description: Minimum consecutive failures for the probe + to be considered failed after having succeeded. Defaults + to 3. Minimum value is 1. + format: int32 + type: integer + grpc: + description: GRPC specifies an action involving a GRPC port. + properties: + port: + description: Port number of the gRPC service. Number + must be in the range 1 to 65535. + format: int32 + type: integer + service: + description: "Service is the name of the service to + place in the gRPC HealthCheckRequest (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + \n If this is not specified, the default behavior + is defined by gRPC." + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies the http request to perform. + properties: + host: + description: Host name to connect to, defaults to the + pod IP. You probably want to set "Host" in httpHeaders + instead. + type: string + httpHeaders: + description: Custom headers to set in the request. HTTP + allows repeated headers. + items: + description: HTTPHeader describes a custom header + to be used in HTTP probes + properties: + name: + description: The header field name. This will + be canonicalized upon output, so case-variant + names will be understood as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access on + the container. Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to the host. + Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: 'Number of seconds after the container has + started before liveness probes are initiated. More info: + https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + periodSeconds: + description: How often (in seconds) to perform the probe. + Default to 10 seconds. Minimum value is 1. + format: int32 + type: integer + successThreshold: + description: Minimum consecutive successes for the probe + to be considered successful after having failed. Defaults + to 1. Must be 1 for liveness and startup. Minimum value + is 1. + format: int32 + type: integer + tcpSocket: + description: TCPSocket specifies an action involving a TCP + port. + properties: + host: + description: 'Optional: Host name to connect to, defaults + to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access on + the container. Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: Optional duration in seconds the pod needs + to terminate gracefully upon probe failure. The grace + period is the duration in seconds after the processes + running in the pod are sent a termination signal and the + time when the processes are forcibly halted with a kill + signal. Set this value longer than the expected cleanup + time for your process. If this value is nil, the pod's + terminationGracePeriodSeconds will be used. Otherwise, + this value overrides the value provided by the pod spec. + Value must be non-negative integer. The value zero indicates + stop immediately via the kill signal (no opportunity to + shut down). This is a beta field and requires enabling + ProbeTerminationGracePeriod feature gate. Minimum value + is 1. spec.terminationGracePeriodSeconds is used if unset. + format: int64 + type: integer + timeoutSeconds: + description: 'Number of seconds after which the probe times + out. Defaults to 1 second. Minimum value is 1. More info: + https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + type: object + resources: + description: ResourceRequirements describes the compute resource + requirements. + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n 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 + 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 + securityContext: + description: SecurityContext holds security configuration that + will be applied to a container. Some fields are present in + both SecurityContext and PodSecurityContext. When both are + set, the values in SecurityContext take precedence. + properties: + allowPrivilegeEscalation: + description: 'AllowPrivilegeEscalation controls whether + a process can gain more privileges than its parent process. + This bool directly controls if the no_new_privs flag will + be set on the container process. AllowPrivilegeEscalation + is true always when the container is: 1) run as Privileged + 2) has CAP_SYS_ADMIN Note that this field cannot be set + when spec.os.name is windows.' + type: boolean + capabilities: + description: The capabilities to add/drop when running containers. + Defaults to the default set of capabilities granted by + the container runtime. Note that this field cannot be + set when spec.os.name is windows. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + type: object + privileged: + description: Run container in privileged mode. Processes + in privileged containers are essentially equivalent to + root on the host. Defaults to false. Note that this field + cannot be set when spec.os.name is windows. + type: boolean + procMount: + description: procMount denotes the type of proc mount to + use for the containers. The default is DefaultProcMount + which uses the container runtime defaults for readonly + paths and masked paths. This requires the ProcMountType + feature flag to be enabled. Note that this field cannot + be set when spec.os.name is windows. + type: string + readOnlyRootFilesystem: + description: Whether this container has a read-only root + filesystem. Default is false. Note that this field cannot + be set when spec.os.name is windows. + type: boolean + runAsGroup: + description: The GID to run the entrypoint of the container + process. Uses runtime default if unset. May also be set + in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as a + non-root user. If true, the Kubelet will validate the + image at runtime to ensure that it does not run as UID + 0 (root) and fail to start the container if it does. If + unset or false, no such validation will be performed. + May also be set in PodSecurityContext. If set in both + SecurityContext and PodSecurityContext, the value specified + in SecurityContext takes precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container + process. Defaults to user specified in image metadata + if unspecified. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. Note + that this field cannot be set when spec.os.name is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to the container. + If unspecified, the container runtime will allocate a + random SELinux context for each container. May also be + set in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by this container. + If seccomp options are provided at both the pod & container + level, the container options override the pod options. + Note that this field cannot be set when spec.os.name is + windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile defined + in a file on the node should be used. The profile + must be preconfigured on the node to work. Must be + a descending path, relative to the kubelet's configured + seccomp profile location. Must be set if type is "Localhost". + Must NOT be set for any other type. + type: string + type: + description: "type indicates which kind of seccomp profile + will be applied. Valid options are: \n Localhost - + a profile defined in a file on the node should be + used. RuntimeDefault - the container runtime default + profile should be used. Unconfined - no profile should + be applied." + type: string + required: + - type + type: object + windowsOptions: + description: The Windows specific settings applied to all + containers. If unspecified, the options from the PodSecurityContext + will be used. If set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is + linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA admission + webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec named + by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of the + GMSA credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container should + be run as a 'Host Process' container. All of a Pod's + containers must have the same effective HostProcess + value (it is not allowed to have a mix of HostProcess + containers and non-HostProcess containers). In addition, + if HostProcess is true then HostNetwork must also + be set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set + in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. + type: string + type: object + type: object + volumeMounts: + items: + description: VolumeMount describes a mounting of a Volume + within a container. + properties: + mountPath: + description: Path within the container at which the volume + should be mounted. Must not contain ':'. + type: string + mountPropagation: + description: mountPropagation determines how mounts are + propagated from the host to container and the other + way around. When not set, MountPropagationNone is used. + This field is beta in 1.10. + type: string + name: + description: This must match the Name of a Volume. + type: string + readOnly: + description: Mounted read-only if true, read-write otherwise + (false or unspecified). Defaults to false. + type: boolean + subPath: + description: Path within the volume from which the container's + volume should be mounted. Defaults to "" (volume's root). + type: string + subPathExpr: + description: Expanded path within the volume from which + the container's volume should be mounted. Behaves similarly + to SubPath but environment variable references $(VAR_NAME) + are expanded using the container's environment. Defaults + to "" (volume's root). SubPathExpr and SubPath are mutually + exclusive. + type: string + required: + - mountPath + - name + type: object + type: array + required: + - image + type: object + type: array + livenessProbe: + description: Probe describes a health check to be performed against + a container to determine whether it is alive or ready to receive + traffic. + properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to execute inside + the container, the working directory for the command is + root ('/') in the container's filesystem. The command is + simply exec'd, it is not run inside a shell, so traditional + shell instructions ('|', etc) won't work. To use a shell, + you need to explicitly call out to that shell. Exit status + of 0 is treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + type: object + failureThreshold: + description: Minimum consecutive failures for the probe to be + considered failed after having succeeded. Defaults to 3. Minimum + value is 1. + format: int32 + type: integer + grpc: + description: GRPC specifies an action involving a GRPC port. + properties: + port: + description: Port number of the gRPC service. Number must + be in the range 1 to 65535. + format: int32 + type: integer + service: + description: "Service is the name of the service to place + in the gRPC HealthCheckRequest (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + \n If this is not specified, the default behavior is defined + by gRPC." + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies the http request to perform. + properties: + host: + description: Host name to connect to, defaults to the pod + IP. You probably want to set "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the request. HTTP allows + repeated headers. + items: + description: HTTPHeader describes a custom header to be + used in HTTP probes + properties: + name: + description: The header field name. This will be canonicalized + upon output, so case-variant names will be understood + as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access on the container. + Number must be in the range 1 to 65535. Name must be an + IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to the host. Defaults + to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: 'Number of seconds after the container has started + before liveness probes are initiated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + periodSeconds: + description: How often (in seconds) to perform the probe. Default + to 10 seconds. Minimum value is 1. + format: int32 + type: integer + successThreshold: + description: Minimum consecutive successes for the probe to be + considered successful after having failed. Defaults to 1. Must + be 1 for liveness and startup. Minimum value is 1. + format: int32 + type: integer + tcpSocket: + description: TCPSocket specifies an action involving a TCP port. + properties: + host: + description: 'Optional: Host name to connect to, defaults + to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access on the container. + Number must be in the range 1 to 65535. Name must be an + IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: Optional duration in seconds the pod needs to terminate + gracefully upon probe failure. The grace period is the duration + in seconds after the processes running in the pod are sent a + termination signal and the time when the processes are forcibly + halted with a kill signal. Set this value longer than the expected + cleanup time for your process. If this value is nil, the pod's + terminationGracePeriodSeconds will be used. Otherwise, this + value overrides the value provided by the pod spec. Value must + be non-negative integer. The value zero indicates stop immediately + via the kill signal (no opportunity to shut down). This is a + beta field and requires enabling ProbeTerminationGracePeriod + feature gate. Minimum value is 1. spec.terminationGracePeriodSeconds + is used if unset. + format: int64 + type: integer + timeoutSeconds: + description: 'Number of seconds after which the probe times out. + Defaults to 1 second. Minimum value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + type: object + metrics: + properties: + exporter: + properties: + args: + items: + type: string + type: array + command: + items: + type: string + type: array + env: + 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: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + 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: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + 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 + envFrom: + items: + description: EnvFromSource represents the source of a set + of ConfigMaps + properties: + configMapRef: + description: The ConfigMap to select from + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the ConfigMap must + be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + description: An optional identifier to prepend to each + key in the ConfigMap. Must be a C_IDENTIFIER. + type: string + secretRef: + description: The Secret to select from + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the Secret must be + defined + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + image: + type: string + imagePullPolicy: + default: IfNotPresent + description: PullPolicy describes a policy for if/when to + pull a container image + type: string + livenessProbe: + description: Probe describes a health check to be performed + against a container to determine whether it is alive or + ready to receive traffic. + properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to execute + inside the container, the working directory for + the command is root ('/') in the container's filesystem. + The command is simply exec'd, it is not run inside + a shell, so traditional shell instructions ('|', + etc) won't work. To use a shell, you need to explicitly + call out to that shell. Exit status of 0 is treated + as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + type: object + failureThreshold: + description: Minimum consecutive failures for the probe + to be considered failed after having succeeded. Defaults + to 3. Minimum value is 1. + format: int32 + type: integer + grpc: + description: GRPC specifies an action involving a GRPC + port. + properties: + port: + description: Port number of the gRPC service. Number + must be in the range 1 to 65535. + format: int32 + type: integer + service: + description: "Service is the name of the service to + place in the gRPC HealthCheckRequest (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + \n If this is not specified, the default behavior + is defined by gRPC." + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies the http request to perform. + properties: + host: + description: Host name to connect to, defaults to + the pod IP. You probably want to set "Host" in httpHeaders + instead. + type: string + httpHeaders: + description: Custom headers to set in the request. + HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom header + to be used in HTTP probes + properties: + name: + description: The header field name. This will + be canonicalized upon output, so case-variant + names will be understood as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access + on the container. Number must be in the range 1 + to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to the host. + Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: 'Number of seconds after the container has + started before liveness probes are initiated. More info: + https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + periodSeconds: + description: How often (in seconds) to perform the probe. + Default to 10 seconds. Minimum value is 1. + format: int32 + type: integer + successThreshold: + description: Minimum consecutive successes for the probe + to be considered successful after having failed. Defaults + to 1. Must be 1 for liveness and startup. Minimum value + is 1. + format: int32 + type: integer + tcpSocket: + description: TCPSocket specifies an action involving a + TCP port. + properties: + host: + description: 'Optional: Host name to connect to, defaults + to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access + on the container. Number must be in the range 1 + to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: Optional duration in seconds the pod needs + to terminate gracefully upon probe failure. The grace + period is the duration in seconds after the processes + running in the pod are sent a termination signal and + the time when the processes are forcibly halted with + a kill signal. Set this value longer than the expected + cleanup time for your process. If this value is nil, + the pod's terminationGracePeriodSeconds will be used. + Otherwise, this value overrides the value provided by + the pod spec. Value must be non-negative integer. The + value zero indicates stop immediately via the kill signal + (no opportunity to shut down). This is a beta field + and requires enabling ProbeTerminationGracePeriod feature + gate. Minimum value is 1. spec.terminationGracePeriodSeconds + is used if unset. + format: int64 + type: integer + timeoutSeconds: + description: 'Number of seconds after which the probe + times out. Defaults to 1 second. Minimum value is 1. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + type: object + port: + default: 9104 + format: int32 + type: integer + readinessProbe: + description: Probe describes a health check to be performed + against a container to determine whether it is alive or + ready to receive traffic. + properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to execute + inside the container, the working directory for + the command is root ('/') in the container's filesystem. + The command is simply exec'd, it is not run inside + a shell, so traditional shell instructions ('|', + etc) won't work. To use a shell, you need to explicitly + call out to that shell. Exit status of 0 is treated + as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + type: object + failureThreshold: + description: Minimum consecutive failures for the probe + to be considered failed after having succeeded. Defaults + to 3. Minimum value is 1. + format: int32 + type: integer + grpc: + description: GRPC specifies an action involving a GRPC + port. + properties: + port: + description: Port number of the gRPC service. Number + must be in the range 1 to 65535. + format: int32 + type: integer + service: + description: "Service is the name of the service to + place in the gRPC HealthCheckRequest (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + \n If this is not specified, the default behavior + is defined by gRPC." + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies the http request to perform. + properties: + host: + description: Host name to connect to, defaults to + the pod IP. You probably want to set "Host" in httpHeaders + instead. + type: string + httpHeaders: + description: Custom headers to set in the request. + HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom header + to be used in HTTP probes + properties: + name: + description: The header field name. This will + be canonicalized upon output, so case-variant + names will be understood as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access + on the container. Number must be in the range 1 + to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to the host. + Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: 'Number of seconds after the container has + started before liveness probes are initiated. More info: + https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + periodSeconds: + description: How often (in seconds) to perform the probe. + Default to 10 seconds. Minimum value is 1. + format: int32 + type: integer + successThreshold: + description: Minimum consecutive successes for the probe + to be considered successful after having failed. Defaults + to 1. Must be 1 for liveness and startup. Minimum value + is 1. + format: int32 + type: integer + tcpSocket: + description: TCPSocket specifies an action involving a + TCP port. + properties: + host: + description: 'Optional: Host name to connect to, defaults + to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access + on the container. Number must be in the range 1 + to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: Optional duration in seconds the pod needs + to terminate gracefully upon probe failure. The grace + period is the duration in seconds after the processes + running in the pod are sent a termination signal and + the time when the processes are forcibly halted with + a kill signal. Set this value longer than the expected + cleanup time for your process. If this value is nil, + the pod's terminationGracePeriodSeconds will be used. + Otherwise, this value overrides the value provided by + the pod spec. Value must be non-negative integer. The + value zero indicates stop immediately via the kill signal + (no opportunity to shut down). This is a beta field + and requires enabling ProbeTerminationGracePeriod feature + gate. Minimum value is 1. spec.terminationGracePeriodSeconds + is used if unset. + format: int64 + type: integer + timeoutSeconds: + description: 'Number of seconds after which the probe + times out. Defaults to 1 second. Minimum value is 1. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + type: object + resources: + description: ResourceRequirements describes the compute resource + requirements. + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. \n 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 + 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 + securityContext: + description: SecurityContext holds security configuration + that will be applied to a container. Some fields are present + in both SecurityContext and PodSecurityContext. When both + are set, the values in SecurityContext take precedence. + properties: + allowPrivilegeEscalation: + description: 'AllowPrivilegeEscalation controls whether + a process can gain more privileges than its parent process. + This bool directly controls if the no_new_privs flag + will be set on the container process. AllowPrivilegeEscalation + is true always when the container is: 1) run as Privileged + 2) has CAP_SYS_ADMIN Note that this field cannot be + set when spec.os.name is windows.' + type: boolean + capabilities: + description: The capabilities to add/drop when running + containers. Defaults to the default set of capabilities + granted by the container runtime. Note that this field + cannot be set when spec.os.name is windows. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + type: object + privileged: + description: Run container in privileged mode. Processes + in privileged containers are essentially equivalent + to root on the host. Defaults to false. Note that this + field cannot be set when spec.os.name is windows. + type: boolean + procMount: + description: procMount denotes the type of proc mount + to use for the containers. The default is DefaultProcMount + which uses the container runtime defaults for readonly + paths and masked paths. This requires the ProcMountType + feature flag to be enabled. Note that this field cannot + be set when spec.os.name is windows. + type: string + readOnlyRootFilesystem: + description: Whether this container has a read-only root + filesystem. Default is false. Note that this field cannot + be set when spec.os.name is windows. + type: boolean + runAsGroup: + description: The GID to run the entrypoint of the container + process. Uses runtime default if unset. May also be + set in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set + when spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as + a non-root user. If true, the Kubelet will validate + the image at runtime to ensure that it does not run + as UID 0 (root) and fail to start the container if it + does. If unset or false, no such validation will be + performed. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container + process. Defaults to user specified in image metadata + if unspecified. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name + is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to the + container. If unspecified, the container runtime will + allocate a random SELinux context for each container. May + also be set in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set + when spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by this container. + If seccomp options are provided at both the pod & container + level, the container options override the pod options. + Note that this field cannot be set when spec.os.name + is windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile + defined in a file on the node should be used. The + profile must be preconfigured on the node to work. + Must be a descending path, relative to the kubelet's + configured seccomp profile location. Must be set + if type is "Localhost". Must NOT be set for any + other type. + type: string + type: + description: "type indicates which kind of seccomp + profile will be applied. Valid options are: \n Localhost + - a profile defined in a file on the node should + be used. RuntimeDefault - the container runtime + default profile should be used. Unconfined - no + profile should be applied." + type: string + required: + - type + type: object + windowsOptions: + description: The Windows specific settings applied to + all containers. If unspecified, the options from the + PodSecurityContext will be used. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set + when spec.os.name is linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA + admission webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec + named by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of + the GMSA credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container + should be run as a 'Host Process' container. All + of a Pod's containers must have the same effective + HostProcess value (it is not allowed to have a mix + of HostProcess containers and non-HostProcess containers). + In addition, if HostProcess is true then HostNetwork + must also be set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set + in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. + type: string + type: object + type: object + volumeMounts: + items: + description: VolumeMount describes a mounting of a Volume + within a container. + properties: + mountPath: + description: Path within the container at which the + volume should be mounted. Must not contain ':'. + type: string + mountPropagation: + description: mountPropagation determines how mounts + are propagated from the host to container and the + other way around. When not set, MountPropagationNone + is used. This field is beta in 1.10. + type: string + name: + description: This must match the Name of a Volume. + type: string + readOnly: + description: Mounted read-only if true, read-write otherwise + (false or unspecified). Defaults to false. + type: boolean + subPath: + description: Path within the volume from which the container's + volume should be mounted. Defaults to "" (volume's + root). + type: string + subPathExpr: + description: Expanded path within the volume from which + the container's volume should be mounted. Behaves + similarly to SubPath but environment variable references + $(VAR_NAME) are expanded using the container's environment. + Defaults to "" (volume's root). SubPathExpr and SubPath + are mutually exclusive. + type: string + required: + - mountPath + - name + type: object + type: array + required: + - image + type: object + serviceMonitor: + properties: + interval: + type: string + prometheusRelease: + type: string + scrapeTimeout: + type: string + required: + - prometheusRelease + type: object + required: + - exporter + - serviceMonitor + type: object + myCnf: + type: string + myCnfConfigMapKeyRef: + description: Selects a key from a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + nodeSelector: + additionalProperties: + type: string + type: object + passwordSecretKeyRef: + description: SecretKeySelector selects a key of a Secret. + properties: + key: + description: The key of the secret to select from. Must be a + valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + podAnnotations: + additionalProperties: + type: string + type: object + podDisruptionBudget: + properties: + maxUnavailable: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + minAvailable: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + type: object + podSecurityContext: + description: PodSecurityContext holds pod-level security attributes + and common container settings. Some fields are also present in container.securityContext. Field + values of container.securityContext take precedence over field values + of PodSecurityContext. + properties: + fsGroup: + description: "A special supplemental group that applies to all + containers in a pod. Some volume types allow the Kubelet to + change the ownership of that volume to be owned by the pod: + \n 1. The owning GID will be the FSGroup 2. The setgid bit is + set (new files created in the volume will be owned by FSGroup) + 3. The permission bits are OR'd with rw-rw---- \n If unset, + the Kubelet will not modify the ownership and permissions of + any volume. Note that this field cannot be set when spec.os.name + is windows." + format: int64 + type: integer + fsGroupChangePolicy: + description: 'fsGroupChangePolicy defines behavior of changing + ownership and permission of the volume before being exposed + inside Pod. This field will only apply to volume types which + support fsGroup based ownership(and permissions). It will have + no effect on ephemeral volume types such as: secret, configmaps + and emptydir. Valid values are "OnRootMismatch" and "Always". + If not specified, "Always" is used. Note that this field cannot + be set when spec.os.name is windows.' + type: string + runAsGroup: + description: The GID to run the entrypoint of the container process. + Uses runtime default if unset. May also be set in SecurityContext. If + set in both SecurityContext and PodSecurityContext, the value + specified in SecurityContext takes precedence for that container. + Note that this field cannot be set when spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as a non-root + user. If true, the Kubelet will validate the image at runtime + to ensure that it does not run as UID 0 (root) and fail to start + the container if it does. If unset or false, no such validation + will be performed. May also be set in SecurityContext. If set + in both SecurityContext and PodSecurityContext, the value specified + in SecurityContext takes precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container process. + Defaults to user specified in image metadata if unspecified. + May also be set in SecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence for that container. Note that this field cannot + be set when spec.os.name is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to all containers. + If unspecified, the container runtime will allocate a random + SELinux context for each container. May also be set in SecurityContext. If + set in both SecurityContext and PodSecurityContext, the value + specified in SecurityContext takes precedence for that container. + Note that this field cannot be set when spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies to + the container. + type: string + role: + description: Role is a SELinux role label that applies to + the container. + type: string + type: + description: Type is a SELinux type label that applies to + the container. + type: string + user: + description: User is a SELinux user label that applies to + the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by the containers in this + pod. Note that this field cannot be set when spec.os.name is + windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile defined + in a file on the node should be used. The profile must be + preconfigured on the node to work. Must be a descending + path, relative to the kubelet's configured seccomp profile + location. Must be set if type is "Localhost". Must NOT be + set for any other type. + type: string + type: + description: "type indicates which kind of seccomp profile + will be applied. Valid options are: \n Localhost - a profile + defined in a file on the node should be used. RuntimeDefault + - the container runtime default profile should be used. + Unconfined - no profile should be applied." + type: string + required: + - type + type: object + supplementalGroups: + description: A list of groups applied to the first process run + in each container, in addition to the container's primary GID, + the fsGroup (if specified), and group memberships defined in + the container image for the uid of the container process. If + unspecified, no additional groups are added to any container. + Note that group memberships defined in the container image for + the uid of the container process are still effective, even if + they are not included in this list. Note that this field cannot + be set when spec.os.name is windows. + items: + format: int64 + type: integer + type: array + sysctls: + description: Sysctls hold a list of namespaced sysctls used for + the pod. Pods with unsupported sysctls (by the container runtime) + might fail to launch. Note that this field cannot be set when + spec.os.name is windows. + items: + description: Sysctl defines a kernel parameter to be set + properties: + name: + description: Name of a property to set + type: string + value: + description: Value of a property to set + type: string + required: + - name + - value + type: object + type: array + windowsOptions: + description: The Windows specific settings applied to all containers. + If unspecified, the options within a container's SecurityContext + will be used. If set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. Note + that this field cannot be set when spec.os.name is linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA admission + webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec named by + the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of the GMSA + credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container should + be run as a 'Host Process' container. All of a Pod's containers + must have the same effective HostProcess value (it is not + allowed to have a mix of HostProcess containers and non-HostProcess + containers). In addition, if HostProcess is true then HostNetwork + must also be set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set in PodSecurityContext. + If set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. + type: string + type: object + type: object + port: + default: 3306 + format: int32 + type: integer + primaryConnection: + properties: + healthCheck: + properties: + interval: + type: string + retryInterval: + type: string + type: object + params: + additionalProperties: + type: string + type: object + secretName: + type: string + secretTemplate: + properties: + annotations: + additionalProperties: + type: string + type: object + databaseKey: + type: string + format: + type: string + hostKey: + type: string + key: + type: string + labels: + additionalProperties: + type: string + type: object + passwordKey: + type: string + portKey: + type: string + usernameKey: + type: string + type: object + serviceName: + type: string + type: object + primaryService: + properties: + annotations: + additionalProperties: + type: string + type: object + externalTrafficPolicy: + description: ServiceExternalTrafficPolicy describes how nodes + distribute service traffic they receive on one of the Service's + "externally-facing" addresses (NodePorts, ExternalIPs, and LoadBalancer + IPs. + type: string + labels: + additionalProperties: + type: string + type: object + loadBalancerIP: + type: string + loadBalancerSourceRanges: + items: + type: string + type: array + sessionAffinity: + description: Session Affinity Type string + type: string + type: + description: Service Type string describes ingress methods for + a service + type: string + type: object + readinessProbe: + description: Probe describes a health check to be performed against + a container to determine whether it is alive or ready to receive + traffic. + properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to execute inside + the container, the working directory for the command is + root ('/') in the container's filesystem. The command is + simply exec'd, it is not run inside a shell, so traditional + shell instructions ('|', etc) won't work. To use a shell, + you need to explicitly call out to that shell. Exit status + of 0 is treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + type: object + failureThreshold: + description: Minimum consecutive failures for the probe to be + considered failed after having succeeded. Defaults to 3. Minimum + value is 1. + format: int32 + type: integer + grpc: + description: GRPC specifies an action involving a GRPC port. + properties: + port: + description: Port number of the gRPC service. Number must + be in the range 1 to 65535. + format: int32 + type: integer + service: + description: "Service is the name of the service to place + in the gRPC HealthCheckRequest (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + \n If this is not specified, the default behavior is defined + by gRPC." + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies the http request to perform. + properties: + host: + description: Host name to connect to, defaults to the pod + IP. You probably want to set "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the request. HTTP allows + repeated headers. + items: + description: HTTPHeader describes a custom header to be + used in HTTP probes + properties: + name: + description: The header field name. This will be canonicalized + upon output, so case-variant names will be understood + as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access on the container. + Number must be in the range 1 to 65535. Name must be an + IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to the host. Defaults + to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: 'Number of seconds after the container has started + before liveness probes are initiated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + periodSeconds: + description: How often (in seconds) to perform the probe. Default + to 10 seconds. Minimum value is 1. + format: int32 + type: integer + successThreshold: + description: Minimum consecutive successes for the probe to be + considered successful after having failed. Defaults to 1. Must + be 1 for liveness and startup. Minimum value is 1. + format: int32 + type: integer + tcpSocket: + description: TCPSocket specifies an action involving a TCP port. + properties: + host: + description: 'Optional: Host name to connect to, defaults + to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access on the container. + Number must be in the range 1 to 65535. Name must be an + IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: Optional duration in seconds the pod needs to terminate + gracefully upon probe failure. The grace period is the duration + in seconds after the processes running in the pod are sent a + termination signal and the time when the processes are forcibly + halted with a kill signal. Set this value longer than the expected + cleanup time for your process. If this value is nil, the pod's + terminationGracePeriodSeconds will be used. Otherwise, this + value overrides the value provided by the pod spec. Value must + be non-negative integer. The value zero indicates stop immediately + via the kill signal (no opportunity to shut down). This is a + beta field and requires enabling ProbeTerminationGracePeriod + feature gate. Minimum value is 1. spec.terminationGracePeriodSeconds + is used if unset. + format: int64 + type: integer + timeoutSeconds: + description: 'Number of seconds after which the probe times out. + Defaults to 1 second. Minimum value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + type: object + replicas: + default: 1 + format: int32 + type: integer + replication: + description: Replication allows you to enable single-master HA via + semi-synchronours replication in your MariaDB cluster. + properties: + enabled: + description: Enabled is a flag to enable Replication. + type: boolean + primary: + description: Primary is the replication configuration for the + primary node. + properties: + automaticFailover: + description: AutomaticFailover indicates whether the operator + should automatically update PodIndex to perform an automatic + primary failover. + type: boolean + podIndex: + description: PodIndex is the StatefulSet index of the primary + node. The user may change this field to perform a manual + switchover. + type: integer + type: object + replica: + description: ReplicaReplication is the replication configuration + for the replica nodes. + properties: + connectionRetries: + description: ConnectionRetries to be used when the replica + connects to the primary. + type: integer + connectionTimeout: + description: ConnectionTimeout to be used when the replica + connects to the primary. + type: string + gtid: + description: 'Gtid indicates which Global Transaction ID should + be used when connecting a replica to the master. See: https://mariadb.com/kb/en/gtid/#using-current_pos-vs-slave_pos.' + type: string + replPasswordSecretKeyRef: + description: ReplPasswordSecretKeyRef provides a reference + to the Secret to use as password for the replication user. + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + syncTimeout: + description: SyncTimeout defines the timeout for a replica + to be synced with the primary when performing a primary + switchover. If the timeout is reached, the replica GTID + will be reset and the switchover will continue. + type: string + waitPoint: + description: 'WaitPoint defines whether the transaction should + wait for ACK before committing to the storage engine. More + info: https://mariadb.com/kb/en/semisynchronous-replication/#rpl_semi_sync_master_wait_point.' + type: string + type: object + syncBinlog: + description: 'SyncBinlog indicates whether the binary log should + be synchronized to the disk after every event. It trades off + performance for consistency. See: https://mariadb.com/kb/en/replication-and-binary-log-system-variables/#sync_binlog.' + type: boolean + type: object + resources: + description: ResourceRequirements describes the compute resource requirements. + properties: + claims: + description: "Claims lists the names of resources, defined in + spec.resourceClaims, that are used by this container. \n This + is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n 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 + 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 + rootPasswordSecretKeyRef: + description: SecretKeySelector selects a key of a Secret. + properties: + key: + description: The key of the secret to select from. Must be a + valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + secondaryConnection: + properties: + healthCheck: + properties: + interval: + type: string + retryInterval: + type: string + type: object + params: + additionalProperties: + type: string + type: object + secretName: + type: string + secretTemplate: + properties: + annotations: + additionalProperties: + type: string + type: object + databaseKey: + type: string + format: + type: string + hostKey: + type: string + key: + type: string + labels: + additionalProperties: + type: string + type: object + passwordKey: + type: string + portKey: + type: string + usernameKey: + type: string + type: object + serviceName: + type: string + type: object + secondaryService: + properties: + annotations: + additionalProperties: + type: string + type: object + externalTrafficPolicy: + description: ServiceExternalTrafficPolicy describes how nodes + distribute service traffic they receive on one of the Service's + "externally-facing" addresses (NodePorts, ExternalIPs, and LoadBalancer + IPs. + type: string + labels: + additionalProperties: + type: string + type: object + loadBalancerIP: + type: string + loadBalancerSourceRanges: + items: + type: string + type: array + sessionAffinity: + description: Session Affinity Type string + type: string + type: + description: Service Type string describes ingress methods for + a service + type: string + type: object + securityContext: + description: SecurityContext holds security configuration that will + be applied to a container. Some fields are present in both SecurityContext + and PodSecurityContext. When both are set, the values in SecurityContext + take precedence. + properties: + allowPrivilegeEscalation: + description: 'AllowPrivilegeEscalation controls whether a process + can gain more privileges than its parent process. This bool + directly controls if the no_new_privs flag will be set on the + container process. AllowPrivilegeEscalation is true always when + the container is: 1) run as Privileged 2) has CAP_SYS_ADMIN + Note that this field cannot be set when spec.os.name is windows.' + type: boolean + capabilities: + description: The capabilities to add/drop when running containers. + Defaults to the default set of capabilities granted by the container + runtime. Note that this field cannot be set when spec.os.name + is windows. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX capabilities type + type: string + type: array + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities type + type: string + type: array + type: object + privileged: + description: Run container in privileged mode. Processes in privileged + containers are essentially equivalent to root on the host. Defaults + to false. Note that this field cannot be set when spec.os.name + is windows. + type: boolean + procMount: + description: procMount denotes the type of proc mount to use for + the containers. The default is DefaultProcMount which uses the + container runtime defaults for readonly paths and masked paths. + This requires the ProcMountType feature flag to be enabled. + Note that this field cannot be set when spec.os.name is windows. + type: string + readOnlyRootFilesystem: + description: Whether this container has a read-only root filesystem. + Default is false. Note that this field cannot be set when spec.os.name + is windows. + type: boolean + runAsGroup: + description: The GID to run the entrypoint of the container process. + Uses runtime default if unset. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the value + specified in SecurityContext takes precedence. Note that this + field cannot be set when spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as a non-root + user. If true, the Kubelet will validate the image at runtime + to ensure that it does not run as UID 0 (root) and fail to start + the container if it does. If unset or false, no such validation + will be performed. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the value + specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container process. + Defaults to user specified in image metadata if unspecified. + May also be set in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when spec.os.name + is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to the container. + If unspecified, the container runtime will allocate a random + SELinux context for each container. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the value + specified in SecurityContext takes precedence. Note that this + field cannot be set when spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies to + the container. + type: string + role: + description: Role is a SELinux role label that applies to + the container. + type: string + type: + description: Type is a SELinux type label that applies to + the container. + type: string + user: + description: User is a SELinux user label that applies to + the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by this container. If + seccomp options are provided at both the pod & container level, + the container options override the pod options. Note that this + field cannot be set when spec.os.name is windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile defined + in a file on the node should be used. The profile must be + preconfigured on the node to work. Must be a descending + path, relative to the kubelet's configured seccomp profile + location. Must be set if type is "Localhost". Must NOT be + set for any other type. + type: string + type: + description: "type indicates which kind of seccomp profile + will be applied. Valid options are: \n Localhost - a profile + defined in a file on the node should be used. RuntimeDefault + - the container runtime default profile should be used. + Unconfined - no profile should be applied." + type: string + required: + - type + type: object + windowsOptions: + description: The Windows specific settings applied to all containers. + If unspecified, the options from the PodSecurityContext will + be used. If set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. Note + that this field cannot be set when spec.os.name is linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA admission + webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec named by + the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of the GMSA + credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container should + be run as a 'Host Process' container. All of a Pod's containers + must have the same effective HostProcess value (it is not + allowed to have a mix of HostProcess containers and non-HostProcess + containers). In addition, if HostProcess is true then HostNetwork + must also be set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set in PodSecurityContext. + If set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. + type: string + type: object + type: object + service: + properties: + annotations: + additionalProperties: + type: string + type: object + externalTrafficPolicy: + description: ServiceExternalTrafficPolicy describes how nodes + distribute service traffic they receive on one of the Service's + "externally-facing" addresses (NodePorts, ExternalIPs, and LoadBalancer + IPs. + type: string + labels: + additionalProperties: + type: string + type: object + loadBalancerIP: + type: string + loadBalancerSourceRanges: + items: + type: string + type: array + sessionAffinity: + description: Session Affinity Type string + type: string + type: + description: Service Type string describes ingress methods for + a service + type: string + type: object + tolerations: + 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 + updateStrategy: + description: StatefulSetUpdateStrategy indicates the strategy that + the StatefulSet controller will use to perform updates. It includes + any additional parameters necessary to perform the update for the + indicated strategy. + properties: + rollingUpdate: + description: RollingUpdate is used to communicate parameters when + Type is RollingUpdateStatefulSetStrategyType. + properties: + maxUnavailable: + anyOf: + - type: integer + - type: string + description: 'The maximum number of pods that can be unavailable + during the update. Value can be an absolute number (ex: + 5) or a percentage of desired pods (ex: 10%). Absolute number + is calculated from percentage by rounding up. This can not + be 0. Defaults to 1. This field is alpha-level and is only + honored by servers that enable the MaxUnavailableStatefulSet + feature. The field applies to all pods in the range 0 to + Replicas-1. That means if there is any unavailable pod in + the range 0 to Replicas-1, it will be counted towards MaxUnavailable.' + x-kubernetes-int-or-string: true + partition: + description: Partition indicates the ordinal at which the + StatefulSet should be partitioned for updates. During a + rolling update, all pods from ordinal Replicas-1 to Partition + are updated. All pods from ordinal Partition-1 to 0 remain + untouched. This is helpful in being able to do a canary + based deployment. The default value is 0. + format: int32 + type: integer + type: object + type: + description: Type indicates the type of the StatefulSetUpdateStrategy. + Default is RollingUpdate. + type: string + type: object + username: + type: string + volumeClaimTemplate: + properties: + accessModes: + description: 'accessModes contains the desired access modes the + volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' + items: + type: string + type: array + annotations: + additionalProperties: + type: string + type: object + dataSource: + description: 'dataSource field can be used to specify either: + * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) + * An existing PVC (PersistentVolumeClaim) If the provisioner + or an external controller can support the specified data source, + it will create a new volume based on the contents of the specified + data source. When the AnyVolumeDataSource feature gate is enabled, + dataSource contents will be copied to dataSourceRef, and dataSourceRef + contents will be copied to dataSource when dataSourceRef.namespace + is not specified. If the namespace is specified, then dataSourceRef + will not be copied to dataSource.' + properties: + apiGroup: + description: APIGroup is the group for the resource being + referenced. If APIGroup is not specified, the specified + Kind must be in the core API group. For any other third-party + types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource being referenced + type: string + name: + description: Name is the name of resource being referenced + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + description: 'dataSourceRef specifies the object from which to + populate the volume with data, if a non-empty volume is desired. + This may be any object from a non-empty API group (non core + object) or a PersistentVolumeClaim object. When this field is + specified, volume binding will only succeed if the type of the + specified object matches some installed volume populator or + dynamic provisioner. This field will replace the functionality + of the dataSource field and as such if both fields are non-empty, + they must have the same value. For backwards compatibility, + when namespace isn''t specified in dataSourceRef, both fields + (dataSource and dataSourceRef) will be set to the same value + automatically if one of them is empty and the other is non-empty. + When namespace is specified in dataSourceRef, dataSource isn''t + set to the same value and must be empty. There are three important + differences between dataSource and dataSourceRef: * While dataSource + only allows two specific types of objects, dataSourceRef allows + any non-core object, as well as PersistentVolumeClaim objects. + * While dataSource ignores disallowed values (dropping them), + dataSourceRef preserves all values, and generates an error if + a disallowed value is specified. * While dataSource only allows + local objects, dataSourceRef allows objects in any namespaces. + (Beta) Using this field requires the AnyVolumeDataSource feature + gate to be enabled. (Alpha) Using the namespace field of dataSourceRef + requires the CrossNamespaceVolumeDataSource feature gate to + be enabled.' + properties: + apiGroup: + description: APIGroup is the group for the resource being + referenced. If APIGroup is not specified, the specified + Kind must be in the core API group. For any other third-party + types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource being referenced + type: string + name: + description: Name is the name of resource being referenced + type: string + namespace: + description: Namespace is the namespace of resource being + referenced Note that when a namespace is specified, a gateway.networking.k8s.io/ReferenceGrant + object is required in the referent namespace to allow that + namespace's owner to accept the reference. See the ReferenceGrant + documentation for details. (Alpha) This field requires the + CrossNamespaceVolumeDataSource feature gate to be enabled. + type: string + required: + - kind + - name + type: object + labels: + additionalProperties: + type: string + type: object + resources: + description: 'resources represents the minimum resources the volume + should have. If RecoverVolumeExpansionFailure feature is enabled + users are allowed to specify resource requirements that are + lower than previous value but must still be higher than capacity + recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n 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 + 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 + selector: + description: selector is a label query over volumes to consider + for binding. + 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 + required: + - key + - operator + type: object + type: array + 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 + storageClassName: + description: 'storageClassName is the name of the StorageClass + required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' + type: string + volumeMode: + description: volumeMode defines what type of volume is required + by the claim. Value of Filesystem is implied when not included + in claim spec. + type: string + volumeName: + description: volumeName is the binding reference to the PersistentVolume + backing this claim. + type: string + type: object + volumeMounts: + items: + description: VolumeMount describes a mounting of a Volume within + a container. + properties: + mountPath: + description: Path within the container at which the volume should + be mounted. Must not contain ':'. + type: string + mountPropagation: + description: mountPropagation determines how mounts are propagated + from the host to container and the other way around. When + not set, MountPropagationNone is used. This field is beta + in 1.10. + type: string + name: + description: This must match the Name of a Volume. + type: string + readOnly: + description: Mounted read-only if true, read-write otherwise + (false or unspecified). Defaults to false. + type: boolean + subPath: + description: Path within the volume from which the container's + volume should be mounted. Defaults to "" (volume's root). + type: string + subPathExpr: + description: Expanded path within the volume from which the + container's volume should be mounted. Behaves similarly to + SubPath but environment variable references $(VAR_NAME) are + expanded using the container's environment. Defaults to "" + (volume's root). SubPathExpr and SubPath are mutually exclusive. + type: string + required: + - mountPath + - name + type: object + type: array + volumes: + items: + description: Volume represents a named volume in a pod that may + be accessed by any container in the pod. + properties: + awsElasticBlockStore: + description: 'awsElasticBlockStore represents an AWS Disk resource + that is attached to a kubelet''s host machine and then exposed + to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' + properties: + fsType: + description: 'fsType is the filesystem type of the volume + that you want to mount. Tip: Ensure that the filesystem + type is supported by the host operating system. Examples: + "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" + if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore + TODO: how do we prevent errors in the filesystem from + compromising the machine' + type: string + partition: + description: 'partition is the partition in the volume that + you want to mount. If omitted, the default is to mount + by volume name. Examples: For volume /dev/sda1, you specify + the partition as "1". Similarly, the volume partition + for /dev/sda is "0" (or you can leave the property empty).' + format: int32 + type: integer + readOnly: + description: 'readOnly value true will force the readOnly + setting in VolumeMounts. More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' + type: boolean + volumeID: + description: 'volumeID is unique ID of the persistent disk + resource in AWS (Amazon EBS volume). More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' + type: string + required: + - volumeID + type: object + azureDisk: + description: azureDisk represents an Azure Data Disk mount on + the host and bind mount to the pod. + properties: + cachingMode: + description: 'cachingMode is the Host Caching mode: None, + Read Only, Read Write.' + type: string + diskName: + description: diskName is the Name of the data disk in the + blob storage + type: string + diskURI: + description: diskURI is the URI of data disk in the blob + storage + type: string + fsType: + description: fsType is Filesystem type to mount. Must be + a filesystem type supported by the host operating system. + Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" + if unspecified. + type: string + kind: + description: 'kind expected values are Shared: multiple + blob disks per storage account Dedicated: single blob + disk per storage account Managed: azure managed data + disk (only in managed availability set). defaults to shared' + type: string + readOnly: + description: readOnly Defaults to false (read/write). ReadOnly + here will force the ReadOnly setting in VolumeMounts. + type: boolean + required: + - diskName + - diskURI + type: object + azureFile: + description: azureFile represents an Azure File Service mount + on the host and bind mount to the pod. + properties: + readOnly: + description: readOnly defaults to false (read/write). ReadOnly + here will force the ReadOnly setting in VolumeMounts. + type: boolean + secretName: + description: secretName is the name of secret that contains + Azure Storage Account Name and Key + type: string + shareName: + description: shareName is the azure share Name + type: string + required: + - secretName + - shareName + type: object + cephfs: + description: cephFS represents a Ceph FS mount on the host that + shares a pod's lifetime + properties: + monitors: + description: 'monitors is Required: Monitors is a collection + of Ceph monitors More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + items: + type: string + type: array + path: + description: 'path is Optional: Used as the mounted root, + rather than the full Ceph tree, default is /' + type: string + readOnly: + description: 'readOnly is Optional: Defaults to false (read/write). + ReadOnly here will force the ReadOnly setting in VolumeMounts. + More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + type: boolean + secretFile: + description: 'secretFile is Optional: SecretFile is the + path to key ring for User, default is /etc/ceph/user.secret + More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + type: string + secretRef: + description: 'secretRef is Optional: SecretRef is reference + to the authentication secret for User, default is empty. + More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + x-kubernetes-map-type: atomic + user: + description: 'user is optional: User is the rados user name, + default is admin More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + type: string + required: + - monitors + type: object + cinder: + description: 'cinder represents a cinder volume attached and + mounted on kubelets host machine. More info: https://examples.k8s.io/mysql-cinder-pd/README.md' + properties: + fsType: + description: 'fsType is the filesystem type to mount. Must + be a filesystem type supported by the host operating system. + Examples: "ext4", "xfs", "ntfs". Implicitly inferred to + be "ext4" if unspecified. More info: https://examples.k8s.io/mysql-cinder-pd/README.md' + type: string + readOnly: + description: 'readOnly defaults to false (read/write). ReadOnly + here will force the ReadOnly setting in VolumeMounts. + More info: https://examples.k8s.io/mysql-cinder-pd/README.md' + type: boolean + secretRef: + description: 'secretRef is optional: points to a secret + object containing parameters used to connect to OpenStack.' + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + x-kubernetes-map-type: atomic + volumeID: + description: 'volumeID used to identify the volume in cinder. + More info: https://examples.k8s.io/mysql-cinder-pd/README.md' + type: string + required: + - volumeID + type: object + configMap: + description: configMap represents a configMap that should populate + this volume + properties: + defaultMode: + description: 'defaultMode is optional: mode bits used to + set permissions on created files by default. Must be an + octal value between 0000 and 0777 or a decimal value between + 0 and 511. YAML accepts both octal and decimal values, + JSON requires decimal values for mode bits. Defaults to + 0644. Directories within the path are not affected by + this setting. This might be in conflict with other options + that affect the file mode, like fsGroup, and the result + can be other mode bits set.' + format: int32 + type: integer + items: + description: items if unspecified, each key-value pair in + the Data field of the referenced ConfigMap will be projected + into the volume as a file whose name is the key and content + is the value. If specified, the listed keys will be projected + into the specified paths, and unlisted keys will not be + present. If a key is specified which is not present in + the ConfigMap, the volume setup will error unless it is + marked optional. Paths must be relative and may not contain + the '..' path or start with '..'. + items: + description: Maps a string key to a path within a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: mode bits used to + set permissions on this file. Must be an octal value + between 0000 and 0777 or a decimal value between + 0 and 511. YAML accepts both octal and decimal values, + JSON requires decimal values for mode bits. If not + specified, the volume defaultMode will be used. + This might be in conflict with other options that + affect the file mode, like fsGroup, and the result + can be other mode bits set.' + format: int32 + type: integer + path: + description: path is the relative path of the file + to map the key to. May not be an absolute path. + May not contain the path element '..'. May not start + with the string '..'. + type: string + required: + - key + - path + type: object + type: array + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + optional: + description: optional specify whether the ConfigMap or its + keys must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + csi: + description: csi (Container Storage Interface) represents ephemeral + storage that is handled by certain external CSI drivers (Beta + feature). + properties: + driver: + description: driver is the name of the CSI driver that handles + this volume. Consult with your admin for the correct name + as registered in the cluster. + type: string + fsType: + description: fsType to mount. Ex. "ext4", "xfs", "ntfs". + If not provided, the empty value is passed to the associated + CSI driver which will determine the default filesystem + to apply. + type: string + nodePublishSecretRef: + description: nodePublishSecretRef is a reference to the + secret object containing sensitive information to pass + to the CSI driver to complete the CSI NodePublishVolume + and NodeUnpublishVolume calls. This field is optional, + and may be empty if no secret is required. If the secret + object contains more than one secret, all secret references + are passed. + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + x-kubernetes-map-type: atomic + readOnly: + description: readOnly specifies a read-only configuration + for the volume. Defaults to false (read/write). + type: boolean + volumeAttributes: + additionalProperties: + type: string + description: volumeAttributes stores driver-specific properties + that are passed to the CSI driver. Consult your driver's + documentation for supported values. + type: object + required: + - driver + type: object + downwardAPI: + description: downwardAPI represents downward API about the pod + that should populate this volume + properties: + defaultMode: + description: 'Optional: mode bits to use on created files + by default. Must be a Optional: mode bits used to set + permissions on created files by default. Must be an octal + value between 0000 and 0777 or a decimal value between + 0 and 511. YAML accepts both octal and decimal values, + JSON requires decimal values for mode bits. Defaults to + 0644. Directories within the path are not affected by + this setting. This might be in conflict with other options + that affect the file mode, like fsGroup, and the result + can be other mode bits set.' + format: int32 + type: integer + items: + description: Items is a list of downward API volume file + items: + description: DownwardAPIVolumeFile represents information + to create the file containing the pod field + properties: + fieldRef: + description: 'Required: Selects a field of the pod: + only annotations, labels, name and namespace are + supported.' + 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 + mode: + description: 'Optional: mode bits used to set permissions + on this file, must be an octal value between 0000 + and 0777 or a decimal value between 0 and 511. YAML + accepts both octal and decimal values, JSON requires + decimal values for mode bits. If not specified, + the volume defaultMode will be used. This might + be in conflict with other options that affect the + file mode, like fsGroup, and the result can be other + mode bits set.' + format: int32 + type: integer + path: + description: 'Required: Path is the relative path + name of the file to be created. Must not be absolute + or contain the ''..'' path. Must be utf-8 encoded. + The first item of the relative path must not start + with ''..''' + type: string + resourceFieldRef: + description: 'Selects a resource of the container: + only resources limits and requests (limits.cpu, + limits.memory, requests.cpu and requests.memory) + 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 + required: + - path + type: object + type: array + type: object + emptyDir: + description: 'emptyDir represents a temporary directory that + shares a pod''s lifetime. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' + properties: + medium: + description: 'medium represents what type of storage medium + should back this directory. The default is "" which means + to use the node''s default medium. Must be an empty string + (default) or Memory. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' + type: string + sizeLimit: + anyOf: + - type: integer + - type: string + description: 'sizeLimit is the total amount of local storage + required for this EmptyDir volume. The size limit is also + applicable for memory medium. The maximum usage on memory + medium EmptyDir would be the minimum value between the + SizeLimit specified here and the sum of memory limits + of all containers in a pod. The default is nil which means + that the limit is undefined. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + ephemeral: + description: "ephemeral represents a volume that is handled + by a cluster storage driver. The volume's lifecycle is tied + to the pod that defines it - it will be created before the + pod starts, and deleted when the pod is removed. \n Use this + if: a) the volume is only needed while the pod runs, b) features + of normal volumes like restoring from snapshot or capacity + tracking are needed, c) the storage driver is specified through + a storage class, and d) the storage driver supports dynamic + volume provisioning through a PersistentVolumeClaim (see EphemeralVolumeSource + for more information on the connection between this volume + type and PersistentVolumeClaim). \n Use PersistentVolumeClaim + or one of the vendor-specific APIs for volumes that persist + for longer than the lifecycle of an individual pod. \n Use + CSI for light-weight local ephemeral volumes if the CSI driver + is meant to be used that way - see the documentation of the + driver for more information. \n A pod can use both types of + ephemeral volumes and persistent volumes at the same time." + properties: + volumeClaimTemplate: + description: "Will be used to create a stand-alone PVC to + provision the volume. The pod in which this EphemeralVolumeSource + is embedded will be the owner of the PVC, i.e. the PVC + will be deleted together with the pod. The name of the + PVC will be `-` where `` is the name from the `PodSpec.Volumes` array entry. + Pod validation will reject the pod if the concatenated + name is not valid for a PVC (for example, too long). \n + An existing PVC with that name that is not owned by the + pod will *not* be used for the pod to avoid using an unrelated + volume by mistake. Starting the pod is then blocked until + the unrelated PVC is removed. If such a pre-created PVC + is meant to be used by the pod, the PVC has to updated + with an owner reference to the pod once the pod exists. + Normally this should not be necessary, but it may be useful + when manually reconstructing a broken cluster. \n This + field is read-only and no changes will be made by Kubernetes + to the PVC after it has been created. \n Required, must + not be nil." + properties: + metadata: + description: May contain labels and annotations that + will be copied into the PVC when creating it. No other + fields are allowed and will be rejected during validation. + type: object + spec: + description: The specification for the PersistentVolumeClaim. + The entire content is copied unchanged into the PVC + that gets created from this template. The same fields + as in a PersistentVolumeClaim are also valid here. + properties: + accessModes: + description: 'accessModes contains the desired access + modes the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' + items: + type: string + type: array + dataSource: + description: 'dataSource field can be used to specify + either: * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) + * An existing PVC (PersistentVolumeClaim) If the + provisioner or an external controller can support + the specified data source, it will create a new + volume based on the contents of the specified + data source. When the AnyVolumeDataSource feature + gate is enabled, dataSource contents will be copied + to dataSourceRef, and dataSourceRef contents will + be copied to dataSource when dataSourceRef.namespace + is not specified. If the namespace is specified, + then dataSourceRef will not be copied to dataSource.' + properties: + apiGroup: + description: APIGroup is the group for the resource + being referenced. If APIGroup is not specified, + the specified Kind must be in the core API + group. For any other third-party types, APIGroup + is required. + type: string + kind: + description: Kind is the type of resource being + referenced + type: string + name: + description: Name is the name of resource being + referenced + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + description: 'dataSourceRef specifies the object + from which to populate the volume with data, if + a non-empty volume is desired. This may be any + object from a non-empty API group (non core object) + or a PersistentVolumeClaim object. When this field + is specified, volume binding will only succeed + if the type of the specified object matches some + installed volume populator or dynamic provisioner. + This field will replace the functionality of the + dataSource field and as such if both fields are + non-empty, they must have the same value. For + backwards compatibility, when namespace isn''t + specified in dataSourceRef, both fields (dataSource + and dataSourceRef) will be set to the same value + automatically if one of them is empty and the + other is non-empty. When namespace is specified + in dataSourceRef, dataSource isn''t set to the + same value and must be empty. There are three + important differences between dataSource and dataSourceRef: + * While dataSource only allows two specific types + of objects, dataSourceRef allows any non-core + object, as well as PersistentVolumeClaim objects. + * While dataSource ignores disallowed values (dropping + them), dataSourceRef preserves all values, and + generates an error if a disallowed value is specified. + * While dataSource only allows local objects, + dataSourceRef allows objects in any namespaces. + (Beta) Using this field requires the AnyVolumeDataSource + feature gate to be enabled. (Alpha) Using the + namespace field of dataSourceRef requires the + CrossNamespaceVolumeDataSource feature gate to + be enabled.' + properties: + apiGroup: + description: APIGroup is the group for the resource + being referenced. If APIGroup is not specified, + the specified Kind must be in the core API + group. For any other third-party types, APIGroup + is required. + type: string + kind: + description: Kind is the type of resource being + referenced + type: string + name: + description: Name is the name of resource being + referenced + type: string + namespace: + description: Namespace is the namespace of resource + being referenced Note that when a namespace + is specified, a gateway.networking.k8s.io/ReferenceGrant + object is required in the referent namespace + to allow that namespace's owner to accept + the reference. See the ReferenceGrant documentation + for details. (Alpha) This field requires the + CrossNamespaceVolumeDataSource feature gate + to be enabled. + type: string + required: + - kind + - name + type: object + resources: + description: 'resources represents the minimum resources + the volume should have. If RecoverVolumeExpansionFailure + feature is enabled users are allowed to specify + resource requirements that are lower than previous + value but must still be higher than capacity recorded + in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' + properties: + claims: + description: "Claims lists the names of resources, + defined in spec.resourceClaims, that are used + by this container. \n This is an alpha field + and requires enabling the DynamicResourceAllocation + feature gate. \n 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 + 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 + selector: + description: selector is a label query over volumes + to consider for binding. + 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 + required: + - key + - operator + type: object + type: array + 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 + storageClassName: + description: 'storageClassName is the name of the + StorageClass required by the claim. More info: + https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' + type: string + volumeMode: + description: volumeMode defines what type of volume + is required by the claim. Value of Filesystem + is implied when not included in claim spec. + type: string + volumeName: + description: volumeName is the binding reference + to the PersistentVolume backing this claim. + type: string + type: object + required: + - spec + type: object + type: object + fc: + description: fc represents a Fibre Channel resource that is + attached to a kubelet's host machine and then exposed to the + pod. + properties: + fsType: + description: 'fsType is the filesystem type to mount. Must + be a filesystem type supported by the host operating system. + Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" + if unspecified. TODO: how do we prevent errors in the + filesystem from compromising the machine' + type: string + lun: + description: 'lun is Optional: FC target lun number' + format: int32 + type: integer + readOnly: + description: 'readOnly is Optional: Defaults to false (read/write). + ReadOnly here will force the ReadOnly setting in VolumeMounts.' + type: boolean + targetWWNs: + description: 'targetWWNs is Optional: FC target worldwide + names (WWNs)' + items: + type: string + type: array + wwids: + description: 'wwids Optional: FC volume world wide identifiers + (wwids) Either wwids or combination of targetWWNs and + lun must be set, but not both simultaneously.' + items: + type: string + type: array + type: object + flexVolume: + description: flexVolume represents a generic volume resource + that is provisioned/attached using an exec based plugin. + properties: + driver: + description: driver is the name of the driver to use for + this volume. + type: string + fsType: + description: fsType is the filesystem type to mount. Must + be a filesystem type supported by the host operating system. + Ex. "ext4", "xfs", "ntfs". The default filesystem depends + on FlexVolume script. + type: string + options: + additionalProperties: + type: string + description: 'options is Optional: this field holds extra + command options if any.' + type: object + readOnly: + description: 'readOnly is Optional: defaults to false (read/write). + ReadOnly here will force the ReadOnly setting in VolumeMounts.' + type: boolean + secretRef: + description: 'secretRef is Optional: secretRef is reference + to the secret object containing sensitive information + to pass to the plugin scripts. This may be empty if no + secret object is specified. If the secret object contains + more than one secret, all secrets are passed to the plugin + scripts.' + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + x-kubernetes-map-type: atomic + required: + - driver + type: object + flocker: + description: flocker represents a Flocker volume attached to + a kubelet's host machine. This depends on the Flocker control + service being running + properties: + datasetName: + description: datasetName is Name of the dataset stored as + metadata -> name on the dataset for Flocker should be + considered as deprecated + type: string + datasetUUID: + description: datasetUUID is the UUID of the dataset. This + is unique identifier of a Flocker dataset + type: string + type: object + gcePersistentDisk: + description: 'gcePersistentDisk represents a GCE Disk resource + that is attached to a kubelet''s host machine and then exposed + to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' + properties: + fsType: + description: 'fsType is filesystem type of the volume that + you want to mount. Tip: Ensure that the filesystem type + is supported by the host operating system. Examples: "ext4", + "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. + More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk + TODO: how do we prevent errors in the filesystem from + compromising the machine' + type: string + partition: + description: 'partition is the partition in the volume that + you want to mount. If omitted, the default is to mount + by volume name. Examples: For volume /dev/sda1, you specify + the partition as "1". Similarly, the volume partition + for /dev/sda is "0" (or you can leave the property empty). + More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' + format: int32 + type: integer + pdName: + description: 'pdName is unique name of the PD resource in + GCE. Used to identify the disk in GCE. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' + type: string + readOnly: + description: 'readOnly here will force the ReadOnly setting + in VolumeMounts. Defaults to false. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' + type: boolean + required: + - pdName + type: object + gitRepo: + description: 'gitRepo represents a git repository at a particular + revision. DEPRECATED: GitRepo is deprecated. To provision + a container with a git repo, mount an EmptyDir into an InitContainer + that clones the repo using git, then mount the EmptyDir into + the Pod''s container.' + properties: + directory: + description: directory is the target directory name. Must + not contain or start with '..'. If '.' is supplied, the + volume directory will be the git repository. Otherwise, + if specified, the volume will contain the git repository + in the subdirectory with the given name. + type: string + repository: + description: repository is the URL + type: string + revision: + description: revision is the commit hash for the specified + revision. + type: string + required: + - repository + type: object + glusterfs: + description: 'glusterfs represents a Glusterfs mount on the + host that shares a pod''s lifetime. More info: https://examples.k8s.io/volumes/glusterfs/README.md' + properties: + endpoints: + description: 'endpoints is the endpoint name that details + Glusterfs topology. More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' + type: string + path: + description: 'path is the Glusterfs volume path. More info: + https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' + type: string + readOnly: + description: 'readOnly here will force the Glusterfs volume + to be mounted with read-only permissions. Defaults to + false. More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' + type: boolean + required: + - endpoints + - path + type: object + hostPath: + description: 'hostPath represents a pre-existing file or directory + on the host machine that is directly exposed to the container. + This is generally used for system agents or other privileged + things that are allowed to see the host machine. Most containers + will NOT need this. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath + --- TODO(jonesdl) We need to restrict who can use host directory + mounts and who can/can not mount host directories as read/write.' + properties: + path: + description: 'path of the directory on the host. If the + path is a symlink, it will follow the link to the real + path. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath' + type: string + type: + description: 'type for HostPath Volume Defaults to "" More + info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath' + type: string + required: + - path + type: object + iscsi: + description: 'iscsi represents an ISCSI Disk resource that is + attached to a kubelet''s host machine and then exposed to + the pod. More info: https://examples.k8s.io/volumes/iscsi/README.md' + properties: + chapAuthDiscovery: + description: chapAuthDiscovery defines whether support iSCSI + Discovery CHAP authentication + type: boolean + chapAuthSession: + description: chapAuthSession defines whether support iSCSI + Session CHAP authentication + type: boolean + fsType: + description: 'fsType is the filesystem type of the volume + that you want to mount. Tip: Ensure that the filesystem + type is supported by the host operating system. Examples: + "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" + if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#iscsi + TODO: how do we prevent errors in the filesystem from + compromising the machine' + type: string + initiatorName: + description: initiatorName is the custom iSCSI Initiator + Name. If initiatorName is specified with iscsiInterface + simultaneously, new iSCSI interface : will be created for the connection. + type: string + iqn: + description: iqn is the target iSCSI Qualified Name. + type: string + iscsiInterface: + description: iscsiInterface is the interface Name that uses + an iSCSI transport. Defaults to 'default' (tcp). + type: string + lun: + description: lun represents iSCSI Target Lun number. + format: int32 + type: integer + portals: + description: portals is the iSCSI Target Portal List. The + portal is either an IP or ip_addr:port if the port is + other than default (typically TCP ports 860 and 3260). + items: + type: string + type: array + readOnly: + description: readOnly here will force the ReadOnly setting + in VolumeMounts. Defaults to false. + type: boolean + secretRef: + description: secretRef is the CHAP Secret for iSCSI target + and initiator authentication + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + x-kubernetes-map-type: atomic + targetPortal: + description: targetPortal is iSCSI Target Portal. The Portal + is either an IP or ip_addr:port if the port is other than + default (typically TCP ports 860 and 3260). + type: string + required: + - iqn + - lun + - targetPortal + type: object + name: + description: 'name of the volume. Must be a DNS_LABEL and unique + within the pod. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + nfs: + description: 'nfs represents an NFS mount on the host that shares + a pod''s lifetime More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' + properties: + path: + description: 'path that is exported by the NFS server. More + info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' + type: string + readOnly: + description: 'readOnly here will force the NFS export to + be mounted with read-only permissions. Defaults to false. + More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' + type: boolean + server: + description: 'server is the hostname or IP address of the + NFS server. More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' + type: string + required: + - path + - server + type: object + persistentVolumeClaim: + description: 'persistentVolumeClaimVolumeSource represents a + reference to a PersistentVolumeClaim in the same namespace. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' + properties: + claimName: + description: 'claimName is the name of a PersistentVolumeClaim + in the same namespace as the pod using this volume. More + info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' + type: string + readOnly: + description: readOnly Will force the ReadOnly setting in + VolumeMounts. Default false. + type: boolean + required: + - claimName + type: object + photonPersistentDisk: + description: photonPersistentDisk represents a PhotonController + persistent disk attached and mounted on kubelets host machine + properties: + fsType: + description: fsType is the filesystem type to mount. Must + be a filesystem type supported by the host operating system. + Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" + if unspecified. + type: string + pdID: + description: pdID is the ID that identifies Photon Controller + persistent disk + type: string + required: + - pdID + type: object + portworxVolume: + description: portworxVolume represents a portworx volume attached + and mounted on kubelets host machine + properties: + fsType: + description: fSType represents the filesystem type to mount + Must be a filesystem type supported by the host operating + system. Ex. "ext4", "xfs". Implicitly inferred to be "ext4" + if unspecified. + type: string + readOnly: + description: readOnly defaults to false (read/write). ReadOnly + here will force the ReadOnly setting in VolumeMounts. + type: boolean + volumeID: + description: volumeID uniquely identifies a Portworx volume + type: string + required: + - volumeID + type: object + projected: + description: projected items for all in one resources secrets, + configmaps, and downward API + properties: + defaultMode: + description: defaultMode are the mode bits used to set permissions + on created files by default. Must be an octal value between + 0000 and 0777 or a decimal value between 0 and 511. YAML + accepts both octal and decimal values, JSON requires decimal + values for mode bits. Directories within the path are + not affected by this setting. This might be in conflict + with other options that affect the file mode, like fsGroup, + and the result can be other mode bits set. + format: int32 + type: integer + sources: + description: sources is the list of volume projections + items: + description: Projection that may be projected along with + other supported volume types + properties: + configMap: + description: configMap information about the configMap + data to project + properties: + items: + description: items if unspecified, each key-value + pair in the Data field of the referenced ConfigMap + will be projected into the volume as a file + whose name is the key and content is the value. + If specified, the listed keys will be projected + into the specified paths, and unlisted keys + will not be present. If a key is specified which + is not present in the ConfigMap, the volume + setup will error unless it is marked optional. + Paths must be relative and may not contain the + '..' path or start with '..'. + items: + description: Maps a string key to a path within + a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: mode bits + used to set permissions on this file. + Must be an octal value between 0000 and + 0777 or a decimal value between 0 and + 511. YAML accepts both octal and decimal + values, JSON requires decimal values for + mode bits. If not specified, the volume + defaultMode will be used. This might be + in conflict with other options that affect + the file mode, like fsGroup, and the result + can be other mode bits set.' + format: int32 + type: integer + path: + description: path is the relative path of + the file to map the key to. May not be + an absolute path. May not contain the + path element '..'. May not start with + the string '..'. + type: string + required: + - key + - path + type: object + type: array + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: optional specify whether the ConfigMap + or its keys must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + downwardAPI: + description: downwardAPI information about the downwardAPI + data to project + properties: + items: + description: Items is a list of DownwardAPIVolume + file + items: + description: DownwardAPIVolumeFile represents + information to create the file containing + the pod field + properties: + fieldRef: + description: 'Required: Selects a field + of the pod: only annotations, labels, + name and namespace are supported.' + 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 + mode: + description: 'Optional: mode bits used to + set permissions on this file, must be + an octal value between 0000 and 0777 or + a decimal value between 0 and 511. YAML + accepts both octal and decimal values, + JSON requires decimal values for mode + bits. If not specified, the volume defaultMode + will be used. This might be in conflict + with other options that affect the file + mode, like fsGroup, and the result can + be other mode bits set.' + format: int32 + type: integer + path: + description: 'Required: Path is the relative + path name of the file to be created. Must + not be absolute or contain the ''..'' + path. Must be utf-8 encoded. The first + item of the relative path must not start + with ''..''' + type: string + resourceFieldRef: + description: 'Selects a resource of the + container: only resources limits and requests + (limits.cpu, limits.memory, requests.cpu + and requests.memory) 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 + required: + - path + type: object + type: array + type: object + secret: + description: secret information about the secret data + to project + properties: + items: + description: items if unspecified, each key-value + pair in the Data field of the referenced Secret + will be projected into the volume as a file + whose name is the key and content is the value. + If specified, the listed keys will be projected + into the specified paths, and unlisted keys + will not be present. If a key is specified which + is not present in the Secret, the volume setup + will error unless it is marked optional. Paths + must be relative and may not contain the '..' + path or start with '..'. + items: + description: Maps a string key to a path within + a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: mode bits + used to set permissions on this file. + Must be an octal value between 0000 and + 0777 or a decimal value between 0 and + 511. YAML accepts both octal and decimal + values, JSON requires decimal values for + mode bits. If not specified, the volume + defaultMode will be used. This might be + in conflict with other options that affect + the file mode, like fsGroup, and the result + can be other mode bits set.' + format: int32 + type: integer + path: + description: path is the relative path of + the file to map the key to. May not be + an absolute path. May not contain the + path element '..'. May not start with + the string '..'. + type: string + required: + - key + - path + type: object + type: array + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: optional field specify whether the + Secret or its key must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + serviceAccountToken: + description: serviceAccountToken is information about + the serviceAccountToken data to project + properties: + audience: + description: audience is the intended audience + of the token. A recipient of a token must identify + itself with an identifier specified in the audience + of the token, and otherwise should reject the + token. The audience defaults to the identifier + of the apiserver. + type: string + expirationSeconds: + description: expirationSeconds is the requested + duration of validity of the service account + token. As the token approaches expiration, the + kubelet volume plugin will proactively rotate + the service account token. The kubelet will + start trying to rotate the token if the token + is older than 80 percent of its time to live + or if the token is older than 24 hours.Defaults + to 1 hour and must be at least 10 minutes. + format: int64 + type: integer + path: + description: path is the path relative to the + mount point of the file to project the token + into. + type: string + required: + - path + type: object + type: object + type: array + type: object + quobyte: + description: quobyte represents a Quobyte mount on the host + that shares a pod's lifetime + properties: + group: + description: group to map volume access to Default is no + group + type: string + readOnly: + description: readOnly here will force the Quobyte volume + to be mounted with read-only permissions. Defaults to + false. + type: boolean + registry: + description: registry represents a single or multiple Quobyte + Registry services specified as a string as host:port pair + (multiple entries are separated with commas) which acts + as the central registry for volumes + type: string + tenant: + description: tenant owning the given Quobyte volume in the + Backend Used with dynamically provisioned Quobyte volumes, + value is set by the plugin + type: string + user: + description: user to map volume access to Defaults to serivceaccount + user + type: string + volume: + description: volume is a string that references an already + created Quobyte volume by name. + type: string + required: + - registry + - volume + type: object + rbd: + description: 'rbd represents a Rados Block Device mount on the + host that shares a pod''s lifetime. More info: https://examples.k8s.io/volumes/rbd/README.md' + properties: + fsType: + description: 'fsType is the filesystem type of the volume + that you want to mount. Tip: Ensure that the filesystem + type is supported by the host operating system. Examples: + "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" + if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#rbd + TODO: how do we prevent errors in the filesystem from + compromising the machine' + type: string + image: + description: 'image is the rados image name. More info: + https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: string + keyring: + description: 'keyring is the path to key ring for RBDUser. + Default is /etc/ceph/keyring. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: string + monitors: + description: 'monitors is a collection of Ceph monitors. + More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + items: + type: string + type: array + pool: + description: 'pool is the rados pool name. Default is rbd. + More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: string + readOnly: + description: 'readOnly here will force the ReadOnly setting + in VolumeMounts. Defaults to false. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: boolean + secretRef: + description: 'secretRef is name of the authentication secret + for RBDUser. If provided overrides keyring. Default is + nil. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + x-kubernetes-map-type: atomic + user: + description: 'user is the rados user name. Default is admin. + More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: string + required: + - image + - monitors + type: object + scaleIO: + description: scaleIO represents a ScaleIO persistent volume + attached and mounted on Kubernetes nodes. + properties: + fsType: + description: fsType is the filesystem type to mount. Must + be a filesystem type supported by the host operating system. + Ex. "ext4", "xfs", "ntfs". Default is "xfs". + type: string + gateway: + description: gateway is the host address of the ScaleIO + API Gateway. + type: string + protectionDomain: + description: protectionDomain is the name of the ScaleIO + Protection Domain for the configured storage. + type: string + readOnly: + description: readOnly Defaults to false (read/write). ReadOnly + here will force the ReadOnly setting in VolumeMounts. + type: boolean + secretRef: + description: secretRef references to the secret for ScaleIO + user and other sensitive information. If this is not provided, + Login operation will fail. + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + x-kubernetes-map-type: atomic + sslEnabled: + description: sslEnabled Flag enable/disable SSL communication + with Gateway, default false + type: boolean + storageMode: + description: storageMode indicates whether the storage for + a volume should be ThickProvisioned or ThinProvisioned. + Default is ThinProvisioned. + type: string + storagePool: + description: storagePool is the ScaleIO Storage Pool associated + with the protection domain. + type: string + system: + description: system is the name of the storage system as + configured in ScaleIO. + type: string + volumeName: + description: volumeName is the name of a volume already + created in the ScaleIO system that is associated with + this volume source. + type: string + required: + - gateway + - secretRef + - system + type: object + secret: + description: 'secret represents a secret that should populate + this volume. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' + properties: + defaultMode: + description: 'defaultMode is Optional: mode bits used to + set permissions on created files by default. Must be an + octal value between 0000 and 0777 or a decimal value between + 0 and 511. YAML accepts both octal and decimal values, + JSON requires decimal values for mode bits. Defaults to + 0644. Directories within the path are not affected by + this setting. This might be in conflict with other options + that affect the file mode, like fsGroup, and the result + can be other mode bits set.' + format: int32 + type: integer + items: + description: items If unspecified, each key-value pair in + the Data field of the referenced Secret will be projected + into the volume as a file whose name is the key and content + is the value. If specified, the listed keys will be projected + into the specified paths, and unlisted keys will not be + present. If a key is specified which is not present in + the Secret, the volume setup will error unless it is marked + optional. Paths must be relative and may not contain the + '..' path or start with '..'. + items: + description: Maps a string key to a path within a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: mode bits used to + set permissions on this file. Must be an octal value + between 0000 and 0777 or a decimal value between + 0 and 511. YAML accepts both octal and decimal values, + JSON requires decimal values for mode bits. If not + specified, the volume defaultMode will be used. + This might be in conflict with other options that + affect the file mode, like fsGroup, and the result + can be other mode bits set.' + format: int32 + type: integer + path: + description: path is the relative path of the file + to map the key to. May not be an absolute path. + May not contain the path element '..'. May not start + with the string '..'. + type: string + required: + - key + - path + type: object + type: array + optional: + description: optional field specify whether the Secret or + its keys must be defined + type: boolean + secretName: + description: 'secretName is the name of the secret in the + pod''s namespace to use. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' + type: string + type: object + storageos: + description: storageOS represents a StorageOS volume attached + and mounted on Kubernetes nodes. + properties: + fsType: + description: fsType is the filesystem type to mount. Must + be a filesystem type supported by the host operating system. + Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" + if unspecified. + type: string + readOnly: + description: readOnly defaults to false (read/write). ReadOnly + here will force the ReadOnly setting in VolumeMounts. + type: boolean + secretRef: + description: secretRef specifies the secret to use for obtaining + the StorageOS API credentials. If not specified, default + values will be attempted. + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + x-kubernetes-map-type: atomic + volumeName: + description: volumeName is the human-readable name of the + StorageOS volume. Volume names are only unique within + a namespace. + type: string + volumeNamespace: + description: volumeNamespace specifies the scope of the + volume within StorageOS. If no namespace is specified + then the Pod's namespace will be used. This allows the + Kubernetes name scoping to be mirrored within StorageOS + for tighter integration. Set VolumeName to any name to + override the default behaviour. Set to "default" if you + are not using namespaces within StorageOS. Namespaces + that do not pre-exist within StorageOS will be created. + type: string + type: object + vsphereVolume: + description: vsphereVolume represents a vSphere volume attached + and mounted on kubelets host machine + properties: + fsType: + description: fsType is filesystem type to mount. Must be + a filesystem type supported by the host operating system. + Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" + if unspecified. + type: string + storagePolicyID: + description: storagePolicyID is the storage Policy Based + Management (SPBM) profile ID associated with the StoragePolicyName. + type: string + storagePolicyName: + description: storagePolicyName is the storage Policy Based + Management (SPBM) profile name. + type: string + volumePath: + description: volumePath is the path that identifies vSphere + volume vmdk + type: string + required: + - volumePath + type: object + required: + - name + type: object + type: array + required: + - image + - rootPasswordSecretKeyRef + - volumeClaimTemplate + type: object + status: + description: MariaDBStatus defines the observed state of MariaDB + properties: + conditions: + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + \n type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + 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 + currentPrimary: + type: string + currentPrimaryPodIndex: + type: integer + galeraRecovery: + description: GaleraRecoveryStatus is the current state of the Galera + recovery process. + properties: + bootstrap: + description: Bootstrap indicates when and in which Pod the cluster + bootstrap process has been performed. + properties: + pod: + type: string + time: + format: date-time + type: string + type: object + recovered: + additionalProperties: + properties: + seqno: + type: integer + uuid: + type: string + required: + - seqno + - uuid + type: object + description: State is a per Pod representation of the sequence + recovery process. + type: object + state: + additionalProperties: + properties: + safeToBootstrap: + type: boolean + seqno: + type: integer + uuid: + type: string + version: + type: string + required: + - safeToBootstrap + - seqno + - uuid + - version + type: object + description: State is a per Pod representation of the Galera state + file (grastate.dat). + type: object + type: object + type: object + required: + - spec + type: object + served: true + storage: true + subresources: + status: {} +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.11.1 + creationTimestamp: null + name: restores.mariadb.mmontes.io +spec: + group: mariadb.mmontes.io + names: + kind: Restore + listKind: RestoreList + plural: restores + shortNames: + - rmdb + singular: restore + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .status.conditions[?(@.type=="Complete")].status + name: Complete + type: string + - jsonPath: .status.conditions[?(@.type=="Complete")].message + name: Status + type: string + - jsonPath: .spec.mariaDbRef.name + name: MariaDB + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + description: Restore is the Schema for the restores 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: RestoreSpec defines the desired state of restore + properties: + affinity: + description: Affinity is a group of affinity scheduling rules. + properties: + nodeAffinity: + description: Describes node affinity scheduling rules for the + pod. + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods to + nodes that satisfy the affinity expressions specified by + this field, but it may choose a node that violates one or + more of the expressions. The node that is most preferred + is the one with the greatest sum of weights, i.e. for each + node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, + etc.), compute a sum by iterating through the elements of + this field and adding "weight" to the sum if the node matches + the corresponding matchExpressions; the node(s) with the + highest sum are the most preferred. + items: + description: An empty preferred scheduling term matches + all objects with implicit weight 0 (i.e. it's a no-op). + A null preferred scheduling term matches no objects (i.e. + is also a no-op). + properties: + preference: + description: A node selector term, associated with the + corresponding weight. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists, DoesNotExist. Gt, and + Lt. + type: string + values: + description: 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. If the operator is Gt or + Lt, the values array must have a single + element, which will be interpreted as an + integer. This array is replaced during a + strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists, DoesNotExist. Gt, and + Lt. + type: string + values: + description: 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. If the operator is Gt or + Lt, the values array must have a single + element, which will be interpreted as an + integer. This array is replaced during a + strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + x-kubernetes-map-type: atomic + weight: + description: Weight associated with matching the corresponding + nodeSelectorTerm, in the range 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by this + field are not met at scheduling time, the pod will not be + scheduled onto the node. If the affinity requirements specified + by this field cease to be met at some point during pod execution + (e.g. due to an update), the system may or may not try to + eventually evict the pod from its node. + properties: + nodeSelectorTerms: + description: Required. A list of node selector terms. + The terms are ORed. + items: + description: A null or empty node selector term matches + no objects. The requirements of them are ANDed. The + TopologySelectorTerm type implements a subset of the + NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists, DoesNotExist. Gt, and + Lt. + type: string + values: + description: 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. If the operator is Gt or + Lt, the values array must have a single + element, which will be interpreted as an + integer. This array is replaced during a + strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists, DoesNotExist. Gt, and + Lt. + type: string + values: + description: 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. If the operator is Gt or + Lt, the values array must have a single + element, which will be interpreted as an + integer. This array is replaced during a + strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + x-kubernetes-map-type: atomic + type: array + required: + - nodeSelectorTerms + type: object + x-kubernetes-map-type: atomic + type: object + podAffinity: + description: Describes pod affinity scheduling rules (e.g. co-locate + this pod in the same node, zone, etc. as some other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods to + nodes that satisfy the affinity expressions specified by + this field, but it may choose a node that violates one or + more of the expressions. The node that is most preferred + is the one with the greatest sum of weights, i.e. for each + node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, + etc.), compute a sum by iterating through the elements of + this field and adding "weight" to the sum if the node has + pods which matches the corresponding podAffinityTerm; the + node(s) with the highest sum are the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by this + field and the ones listed in the namespaces field. + null selector and null or empty namespaces list + means "this pod's namespace". An empty selector + ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. The + term is applied to the union of the namespaces + listed in this field and the ones selected by + namespaceSelector. null or empty namespaces list + and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods + matching the labelSelector in the specified namespaces, + where co-located is defined as running on a node + whose value of the label with key topologyKey + matches that of any node on which any of the selected + pods is running. Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching the corresponding + podAffinityTerm, in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by this + field are not met at scheduling time, the pod will not be + scheduled onto the node. If the affinity requirements specified + by this field cease to be met at some point during pod execution + (e.g. due to a pod label update), the system may or may + not try to eventually evict the pod from its node. When + there are multiple elements, the lists of nodes corresponding + to each podAffinityTerm are intersected, i.e. all terms + must be satisfied. + items: + description: Defines a set of pods (namely those matching + the labelSelector relative to the given namespace(s)) + that this pod should be co-located (affinity) or not co-located + (anti-affinity) with, where co-located is defined as running + on a node whose value of the label with key + matches that of any node on which a pod of the set of + pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied to the + union of the namespaces selected by this field and + the ones listed in the namespaces field. null selector + and null or empty namespaces list means "this pod's + namespace". An empty selector ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list of namespace + names that the term applies to. The term is applied + to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. null or + empty namespaces list and null namespaceSelector means + "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where + co-located is defined as running on a node whose value + of the label with key topologyKey matches that of + any node on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + podAntiAffinity: + description: Describes pod anti-affinity scheduling rules (e.g. + avoid putting this pod in the same node, zone, etc. as some + other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods to + nodes that satisfy the anti-affinity expressions specified + by this field, but it may choose a node that violates one + or more of the expressions. The node that is most preferred + is the one with the greatest sum of weights, i.e. for each + node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling anti-affinity expressions, + etc.), compute a sum by iterating through the elements of + this field and adding "weight" to the sum if the node has + pods which matches the corresponding podAffinityTerm; the + node(s) with the highest sum are the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by this + field and the ones listed in the namespaces field. + null selector and null or empty namespaces list + means "this pod's namespace". An empty selector + ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. The + term is applied to the union of the namespaces + listed in this field and the ones selected by + namespaceSelector. null or empty namespaces list + and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods + matching the labelSelector in the specified namespaces, + where co-located is defined as running on a node + whose value of the label with key topologyKey + matches that of any node on which any of the selected + pods is running. Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching the corresponding + podAffinityTerm, in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the anti-affinity requirements specified by + this field are not met at scheduling time, the pod will + not be scheduled onto the node. If the anti-affinity requirements + specified by this field cease to be met at some point during + pod execution (e.g. due to a pod label update), the system + may or may not try to eventually evict the pod from its + node. When there are multiple elements, the lists of nodes + corresponding to each podAffinityTerm are intersected, i.e. + all terms must be satisfied. + items: + description: Defines a set of pods (namely those matching + the labelSelector relative to the given namespace(s)) + that this pod should be co-located (affinity) or not co-located + (anti-affinity) with, where co-located is defined as running + on a node whose value of the label with key + matches that of any node on which a pod of the set of + pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied to the + union of the namespaces selected by this field and + the ones listed in the namespaces field. null selector + and null or empty namespaces list means "this pod's + namespace". An empty selector ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list of namespace + names that the term applies to. The term is applied + to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. null or + empty namespaces list and null namespaceSelector means + "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where + co-located is defined as running on a node whose value + of the label with key topologyKey matches that of + any node on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + type: object + backoffLimit: + default: 5 + format: int32 + type: integer + backupRef: + description: LocalObjectReference contains enough information to let + you locate the referenced object inside the same namespace. + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + x-kubernetes-map-type: atomic + fileName: + type: string + mariaDbRef: + properties: + apiVersion: + description: API version of the referent. + type: string + fieldPath: + description: 'If referring to a piece of an object instead of + an entire object, this string should contain a valid JSON/Go + field access statement, such as desiredState.manifest.containers[2]. + For example, if the object reference is to a container within + a pod, this would take on a value like: "spec.containers{name}" + (where "name" refers to the name of the container that triggered + the event) or if no container name is specified "spec.containers[2]" + (container with index 2 in this pod). This syntax is chosen + only to have some well-defined way of referencing a part of + an object. TODO: this design is not final and this field is + subject to change in the future.' + type: string + kind: + description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + namespace: + description: 'Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/' + type: string + resourceVersion: + description: 'Specific resourceVersion to which this reference + is made, if any. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency' + type: string + uid: + description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids' + type: string + waitForIt: + default: true + type: boolean + type: object + x-kubernetes-map-type: atomic + nodeSelector: + additionalProperties: + type: string + type: object + resources: + description: ResourceRequirements describes the compute resource requirements. + properties: + claims: + description: "Claims lists the names of resources, defined in + spec.resourceClaims, that are used by this container. \n This + is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n 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 + 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 + restartPolicy: + default: OnFailure + description: RestartPolicy describes how the container should be restarted. + Only one of the following restart policies may be specified. If + none of the following policies is specified, the default one is + RestartPolicyAlways. + type: string + tolerations: + 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 + volume: + description: Represents the source of a volume to mount. Only one + of its members may be specified. + properties: + awsElasticBlockStore: + description: 'awsElasticBlockStore represents an AWS Disk resource + that is attached to a kubelet''s host machine and then exposed + to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' + properties: + fsType: + description: 'fsType is the filesystem type of the volume + that you want to mount. Tip: Ensure that the filesystem + type is supported by the host operating system. Examples: + "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" + if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore + TODO: how do we prevent errors in the filesystem from compromising + the machine' + type: string + partition: + description: 'partition is the partition in the volume that + you want to mount. If omitted, the default is to mount by + volume name. Examples: For volume /dev/sda1, you specify + the partition as "1". Similarly, the volume partition for + /dev/sda is "0" (or you can leave the property empty).' + format: int32 + type: integer + readOnly: + description: 'readOnly value true will force the readOnly + setting in VolumeMounts. More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' + type: boolean + volumeID: + description: 'volumeID is unique ID of the persistent disk + resource in AWS (Amazon EBS volume). More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' + type: string + required: + - volumeID + type: object + azureDisk: + description: azureDisk represents an Azure Data Disk mount on + the host and bind mount to the pod. + properties: + cachingMode: + description: 'cachingMode is the Host Caching mode: None, + Read Only, Read Write.' + type: string + diskName: + description: diskName is the Name of the data disk in the + blob storage + type: string + diskURI: + description: diskURI is the URI of data disk in the blob storage + type: string + fsType: + description: fsType is Filesystem type to mount. Must be a + filesystem type supported by the host operating system. + Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" + if unspecified. + type: string + kind: + description: 'kind expected values are Shared: multiple blob + disks per storage account Dedicated: single blob disk per + storage account Managed: azure managed data disk (only + in managed availability set). defaults to shared' + type: string + readOnly: + description: readOnly Defaults to false (read/write). ReadOnly + here will force the ReadOnly setting in VolumeMounts. + type: boolean + required: + - diskName + - diskURI + type: object + azureFile: + description: azureFile represents an Azure File Service mount + on the host and bind mount to the pod. + properties: + readOnly: + description: readOnly defaults to false (read/write). ReadOnly + here will force the ReadOnly setting in VolumeMounts. + type: boolean + secretName: + description: secretName is the name of secret that contains + Azure Storage Account Name and Key + type: string + shareName: + description: shareName is the azure share Name + type: string + required: + - secretName + - shareName + type: object + cephfs: + description: cephFS represents a Ceph FS mount on the host that + shares a pod's lifetime + properties: + monitors: + description: 'monitors is Required: Monitors is a collection + of Ceph monitors More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + items: + type: string + type: array + path: + description: 'path is Optional: Used as the mounted root, + rather than the full Ceph tree, default is /' + type: string + readOnly: + description: 'readOnly is Optional: Defaults to false (read/write). + ReadOnly here will force the ReadOnly setting in VolumeMounts. + More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + type: boolean + secretFile: + description: 'secretFile is Optional: SecretFile is the path + to key ring for User, default is /etc/ceph/user.secret More + info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + type: string + secretRef: + description: 'secretRef is Optional: SecretRef is reference + to the authentication secret for User, default is empty. + More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + x-kubernetes-map-type: atomic + user: + description: 'user is optional: User is the rados user name, + default is admin More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + type: string + required: + - monitors + type: object + cinder: + description: 'cinder represents a cinder volume attached and mounted + on kubelets host machine. More info: https://examples.k8s.io/mysql-cinder-pd/README.md' + properties: + fsType: + description: 'fsType is the filesystem type to mount. Must + be a filesystem type supported by the host operating system. + Examples: "ext4", "xfs", "ntfs". Implicitly inferred to + be "ext4" if unspecified. More info: https://examples.k8s.io/mysql-cinder-pd/README.md' + type: string + readOnly: + description: 'readOnly defaults to false (read/write). ReadOnly + here will force the ReadOnly setting in VolumeMounts. More + info: https://examples.k8s.io/mysql-cinder-pd/README.md' + type: boolean + secretRef: + description: 'secretRef is optional: points to a secret object + containing parameters used to connect to OpenStack.' + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + x-kubernetes-map-type: atomic + volumeID: + description: 'volumeID used to identify the volume in cinder. + More info: https://examples.k8s.io/mysql-cinder-pd/README.md' + type: string + required: + - volumeID + type: object + configMap: + description: configMap represents a configMap that should populate + this volume + properties: + defaultMode: + description: 'defaultMode is optional: mode bits used to set + permissions on created files by default. Must be an octal + value between 0000 and 0777 or a decimal value between 0 + and 511. YAML accepts both octal and decimal values, JSON + requires decimal values for mode bits. Defaults to 0644. + Directories within the path are not affected by this setting. + This might be in conflict with other options that affect + the file mode, like fsGroup, and the result can be other + mode bits set.' + format: int32 + type: integer + items: + description: items if unspecified, each key-value pair in + the Data field of the referenced ConfigMap will be projected + into the volume as a file whose name is the key and content + is the value. If specified, the listed keys will be projected + into the specified paths, and unlisted keys will not be + present. If a key is specified which is not present in the + ConfigMap, the volume setup will error unless it is marked + optional. Paths must be relative and may not contain the + '..' path or start with '..'. + items: + description: Maps a string key to a path within a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: mode bits used to set + permissions on this file. Must be an octal value between + 0000 and 0777 or a decimal value between 0 and 511. + YAML accepts both octal and decimal values, JSON requires + decimal values for mode bits. If not specified, the + volume defaultMode will be used. This might be in + conflict with other options that affect the file mode, + like fsGroup, and the result can be other mode bits + set.' + format: int32 + type: integer + path: + description: path is the relative path of the file to + map the key to. May not be an absolute path. May not + contain the path element '..'. May not start with + the string '..'. + type: string + required: + - key + - path + type: object + type: array + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + optional: + description: optional specify whether the ConfigMap or its + keys must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + csi: + description: csi (Container Storage Interface) represents ephemeral + storage that is handled by certain external CSI drivers (Beta + feature). + properties: + driver: + description: driver is the name of the CSI driver that handles + this volume. Consult with your admin for the correct name + as registered in the cluster. + type: string + fsType: + description: fsType to mount. Ex. "ext4", "xfs", "ntfs". If + not provided, the empty value is passed to the associated + CSI driver which will determine the default filesystem to + apply. + type: string + nodePublishSecretRef: + description: nodePublishSecretRef is a reference to the secret + object containing sensitive information to pass to the CSI + driver to complete the CSI NodePublishVolume and NodeUnpublishVolume + calls. This field is optional, and may be empty if no secret + is required. If the secret object contains more than one + secret, all secret references are passed. + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + x-kubernetes-map-type: atomic + readOnly: + description: readOnly specifies a read-only configuration + for the volume. Defaults to false (read/write). + type: boolean + volumeAttributes: + additionalProperties: + type: string + description: volumeAttributes stores driver-specific properties + that are passed to the CSI driver. Consult your driver's + documentation for supported values. + type: object + required: + - driver + type: object + downwardAPI: + description: downwardAPI represents downward API about the pod + that should populate this volume + properties: + defaultMode: + description: 'Optional: mode bits to use on created files + by default. Must be a Optional: mode bits used to set permissions + on created files by default. Must be an octal value between + 0000 and 0777 or a decimal value between 0 and 511. YAML + accepts both octal and decimal values, JSON requires decimal + values for mode bits. Defaults to 0644. Directories within + the path are not affected by this setting. This might be + in conflict with other options that affect the file mode, + like fsGroup, and the result can be other mode bits set.' + format: int32 + type: integer + items: + description: Items is a list of downward API volume file + items: + description: DownwardAPIVolumeFile represents information + to create the file containing the pod field + properties: + fieldRef: + description: 'Required: Selects a field of the pod: + only annotations, labels, name and namespace are supported.' + 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 + mode: + description: 'Optional: mode bits used to set permissions + on this file, must be an octal value between 0000 + and 0777 or a decimal value between 0 and 511. YAML + accepts both octal and decimal values, JSON requires + decimal values for mode bits. If not specified, the + volume defaultMode will be used. This might be in + conflict with other options that affect the file mode, + like fsGroup, and the result can be other mode bits + set.' + format: int32 + type: integer + path: + description: 'Required: Path is the relative path name + of the file to be created. Must not be absolute or + contain the ''..'' path. Must be utf-8 encoded. The + first item of the relative path must not start with + ''..''' + type: string + resourceFieldRef: + description: 'Selects a resource of the container: only + resources limits and requests (limits.cpu, limits.memory, + requests.cpu and requests.memory) 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 + required: + - path + type: object + type: array + type: object + emptyDir: + description: 'emptyDir represents a temporary directory that shares + a pod''s lifetime. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' + properties: + medium: + description: 'medium represents what type of storage medium + should back this directory. The default is "" which means + to use the node''s default medium. Must be an empty string + (default) or Memory. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' + type: string + sizeLimit: + anyOf: + - type: integer + - type: string + description: 'sizeLimit is the total amount of local storage + required for this EmptyDir volume. The size limit is also + applicable for memory medium. The maximum usage on memory + medium EmptyDir would be the minimum value between the SizeLimit + specified here and the sum of memory limits of all containers + in a pod. The default is nil which means that the limit + is undefined. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + ephemeral: + description: "ephemeral represents a volume that is handled by + a cluster storage driver. The volume's lifecycle is tied to + the pod that defines it - it will be created before the pod + starts, and deleted when the pod is removed. \n Use this if: + a) the volume is only needed while the pod runs, b) features + of normal volumes like restoring from snapshot or capacity tracking + are needed, c) the storage driver is specified through a storage + class, and d) the storage driver supports dynamic volume provisioning + through a PersistentVolumeClaim (see EphemeralVolumeSource for + more information on the connection between this volume type + and PersistentVolumeClaim). \n Use PersistentVolumeClaim or + one of the vendor-specific APIs for volumes that persist for + longer than the lifecycle of an individual pod. \n Use CSI for + light-weight local ephemeral volumes if the CSI driver is meant + to be used that way - see the documentation of the driver for + more information. \n A pod can use both types of ephemeral volumes + and persistent volumes at the same time." + properties: + volumeClaimTemplate: + description: "Will be used to create a stand-alone PVC to + provision the volume. The pod in which this EphemeralVolumeSource + is embedded will be the owner of the PVC, i.e. the PVC will + be deleted together with the pod. The name of the PVC will + be `-` where `` is the + name from the `PodSpec.Volumes` array entry. Pod validation + will reject the pod if the concatenated name is not valid + for a PVC (for example, too long). \n An existing PVC with + that name that is not owned by the pod will *not* be used + for the pod to avoid using an unrelated volume by mistake. + Starting the pod is then blocked until the unrelated PVC + is removed. If such a pre-created PVC is meant to be used + by the pod, the PVC has to updated with an owner reference + to the pod once the pod exists. Normally this should not + be necessary, but it may be useful when manually reconstructing + a broken cluster. \n This field is read-only and no changes + will be made by Kubernetes to the PVC after it has been + created. \n Required, must not be nil." + properties: + metadata: + description: May contain labels and annotations that will + be copied into the PVC when creating it. No other fields + are allowed and will be rejected during validation. + type: object + spec: + description: The specification for the PersistentVolumeClaim. + The entire content is copied unchanged into the PVC + that gets created from this template. The same fields + as in a PersistentVolumeClaim are also valid here. + properties: + accessModes: + description: 'accessModes contains the desired access + modes the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' + items: + type: string + type: array + dataSource: + description: 'dataSource field can be used to specify + either: * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) + * An existing PVC (PersistentVolumeClaim) If the + provisioner or an external controller can support + the specified data source, it will create a new + volume based on the contents of the specified data + source. When the AnyVolumeDataSource feature gate + is enabled, dataSource contents will be copied to + dataSourceRef, and dataSourceRef contents will be + copied to dataSource when dataSourceRef.namespace + is not specified. If the namespace is specified, + then dataSourceRef will not be copied to dataSource.' + properties: + apiGroup: + description: APIGroup is the group for the resource + being referenced. If APIGroup is not specified, + the specified Kind must be in the core API group. + For any other third-party types, APIGroup is + required. + type: string + kind: + description: Kind is the type of resource being + referenced + type: string + name: + description: Name is the name of resource being + referenced + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + description: 'dataSourceRef specifies the object from + which to populate the volume with data, if a non-empty + volume is desired. This may be any object from a + non-empty API group (non core object) or a PersistentVolumeClaim + object. When this field is specified, volume binding + will only succeed if the type of the specified object + matches some installed volume populator or dynamic + provisioner. This field will replace the functionality + of the dataSource field and as such if both fields + are non-empty, they must have the same value. For + backwards compatibility, when namespace isn''t specified + in dataSourceRef, both fields (dataSource and dataSourceRef) + will be set to the same value automatically if one + of them is empty and the other is non-empty. When + namespace is specified in dataSourceRef, dataSource + isn''t set to the same value and must be empty. + There are three important differences between dataSource + and dataSourceRef: * While dataSource only allows + two specific types of objects, dataSourceRef allows + any non-core object, as well as PersistentVolumeClaim + objects. * While dataSource ignores disallowed values + (dropping them), dataSourceRef preserves all values, + and generates an error if a disallowed value is + specified. * While dataSource only allows local + objects, dataSourceRef allows objects in any namespaces. + (Beta) Using this field requires the AnyVolumeDataSource + feature gate to be enabled. (Alpha) Using the namespace + field of dataSourceRef requires the CrossNamespaceVolumeDataSource + feature gate to be enabled.' + properties: + apiGroup: + description: APIGroup is the group for the resource + being referenced. If APIGroup is not specified, + the specified Kind must be in the core API group. + For any other third-party types, APIGroup is + required. + type: string + kind: + description: Kind is the type of resource being + referenced + type: string + name: + description: Name is the name of resource being + referenced + type: string + namespace: + description: Namespace is the namespace of resource + being referenced Note that when a namespace + is specified, a gateway.networking.k8s.io/ReferenceGrant + object is required in the referent namespace + to allow that namespace's owner to accept the + reference. See the ReferenceGrant documentation + for details. (Alpha) This field requires the + CrossNamespaceVolumeDataSource feature gate + to be enabled. + type: string + required: + - kind + - name + type: object + resources: + description: 'resources represents the minimum resources + the volume should have. If RecoverVolumeExpansionFailure + feature is enabled users are allowed to specify + resource requirements that are lower than previous + value but must still be higher than capacity recorded + in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' + properties: + claims: + description: "Claims lists the names of resources, + defined in spec.resourceClaims, that are used + by this container. \n This is an alpha field + and requires enabling the DynamicResourceAllocation + feature gate. \n 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 + 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 + selector: + description: selector is a label query over volumes + to consider for binding. + 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 + required: + - key + - operator + type: object + type: array + 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 + storageClassName: + description: 'storageClassName is the name of the + StorageClass required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' + type: string + volumeMode: + description: volumeMode defines what type of volume + is required by the claim. Value of Filesystem is + implied when not included in claim spec. + type: string + volumeName: + description: volumeName is the binding reference to + the PersistentVolume backing this claim. + type: string + type: object + required: + - spec + type: object + type: object + fc: + description: fc represents a Fibre Channel resource that is attached + to a kubelet's host machine and then exposed to the pod. + properties: + fsType: + description: 'fsType is the filesystem type to mount. Must + be a filesystem type supported by the host operating system. + Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" + if unspecified. TODO: how do we prevent errors in the filesystem + from compromising the machine' + type: string + lun: + description: 'lun is Optional: FC target lun number' + format: int32 + type: integer + readOnly: + description: 'readOnly is Optional: Defaults to false (read/write). + ReadOnly here will force the ReadOnly setting in VolumeMounts.' + type: boolean + targetWWNs: + description: 'targetWWNs is Optional: FC target worldwide + names (WWNs)' + items: + type: string + type: array + wwids: + description: 'wwids Optional: FC volume world wide identifiers + (wwids) Either wwids or combination of targetWWNs and lun + must be set, but not both simultaneously.' + items: + type: string + type: array + type: object + flexVolume: + description: flexVolume represents a generic volume resource that + is provisioned/attached using an exec based plugin. + properties: + driver: + description: driver is the name of the driver to use for this + volume. + type: string + fsType: + description: fsType is the filesystem type to mount. Must + be a filesystem type supported by the host operating system. + Ex. "ext4", "xfs", "ntfs". The default filesystem depends + on FlexVolume script. + type: string + options: + additionalProperties: + type: string + description: 'options is Optional: this field holds extra + command options if any.' + type: object + readOnly: + description: 'readOnly is Optional: defaults to false (read/write). + ReadOnly here will force the ReadOnly setting in VolumeMounts.' + type: boolean + secretRef: + description: 'secretRef is Optional: secretRef is reference + to the secret object containing sensitive information to + pass to the plugin scripts. This may be empty if no secret + object is specified. If the secret object contains more + than one secret, all secrets are passed to the plugin scripts.' + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + x-kubernetes-map-type: atomic + required: + - driver + type: object + flocker: + description: flocker represents a Flocker volume attached to a + kubelet's host machine. This depends on the Flocker control + service being running + properties: + datasetName: + description: datasetName is Name of the dataset stored as + metadata -> name on the dataset for Flocker should be considered + as deprecated + type: string + datasetUUID: + description: datasetUUID is the UUID of the dataset. This + is unique identifier of a Flocker dataset + type: string + type: object + gcePersistentDisk: + description: 'gcePersistentDisk represents a GCE Disk resource + that is attached to a kubelet''s host machine and then exposed + to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' + properties: + fsType: + description: 'fsType is filesystem type of the volume that + you want to mount. Tip: Ensure that the filesystem type + is supported by the host operating system. Examples: "ext4", + "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. + More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk + TODO: how do we prevent errors in the filesystem from compromising + the machine' + type: string + partition: + description: 'partition is the partition in the volume that + you want to mount. If omitted, the default is to mount by + volume name. Examples: For volume /dev/sda1, you specify + the partition as "1". Similarly, the volume partition for + /dev/sda is "0" (or you can leave the property empty). More + info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' + format: int32 + type: integer + pdName: + description: 'pdName is unique name of the PD resource in + GCE. Used to identify the disk in GCE. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' + type: string + readOnly: + description: 'readOnly here will force the ReadOnly setting + in VolumeMounts. Defaults to false. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' + type: boolean + required: + - pdName + type: object + gitRepo: + description: 'gitRepo represents a git repository at a particular + revision. DEPRECATED: GitRepo is deprecated. To provision a + container with a git repo, mount an EmptyDir into an InitContainer + that clones the repo using git, then mount the EmptyDir into + the Pod''s container.' + properties: + directory: + description: directory is the target directory name. Must + not contain or start with '..'. If '.' is supplied, the + volume directory will be the git repository. Otherwise, + if specified, the volume will contain the git repository + in the subdirectory with the given name. + type: string + repository: + description: repository is the URL + type: string + revision: + description: revision is the commit hash for the specified + revision. + type: string + required: + - repository + type: object + glusterfs: + description: 'glusterfs represents a Glusterfs mount on the host + that shares a pod''s lifetime. More info: https://examples.k8s.io/volumes/glusterfs/README.md' + properties: + endpoints: + description: 'endpoints is the endpoint name that details + Glusterfs topology. More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' + type: string + path: + description: 'path is the Glusterfs volume path. More info: + https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' + type: string + readOnly: + description: 'readOnly here will force the Glusterfs volume + to be mounted with read-only permissions. Defaults to false. + More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' + type: boolean + required: + - endpoints + - path + type: object + hostPath: + description: 'hostPath represents a pre-existing file or directory + on the host machine that is directly exposed to the container. + This is generally used for system agents or other privileged + things that are allowed to see the host machine. Most containers + will NOT need this. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath + --- TODO(jonesdl) We need to restrict who can use host directory + mounts and who can/can not mount host directories as read/write.' + properties: + path: + description: 'path of the directory on the host. If the path + is a symlink, it will follow the link to the real path. + More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath' + type: string + type: + description: 'type for HostPath Volume Defaults to "" More + info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath' + type: string + required: + - path + type: object + iscsi: + description: 'iscsi represents an ISCSI Disk resource that is + attached to a kubelet''s host machine and then exposed to the + pod. More info: https://examples.k8s.io/volumes/iscsi/README.md' + properties: + chapAuthDiscovery: + description: chapAuthDiscovery defines whether support iSCSI + Discovery CHAP authentication + type: boolean + chapAuthSession: + description: chapAuthSession defines whether support iSCSI + Session CHAP authentication + type: boolean + fsType: + description: 'fsType is the filesystem type of the volume + that you want to mount. Tip: Ensure that the filesystem + type is supported by the host operating system. Examples: + "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" + if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#iscsi + TODO: how do we prevent errors in the filesystem from compromising + the machine' + type: string + initiatorName: + description: initiatorName is the custom iSCSI Initiator Name. + If initiatorName is specified with iscsiInterface simultaneously, + new iSCSI interface : will be + created for the connection. + type: string + iqn: + description: iqn is the target iSCSI Qualified Name. + type: string + iscsiInterface: + description: iscsiInterface is the interface Name that uses + an iSCSI transport. Defaults to 'default' (tcp). + type: string + lun: + description: lun represents iSCSI Target Lun number. + format: int32 + type: integer + portals: + description: portals is the iSCSI Target Portal List. The + portal is either an IP or ip_addr:port if the port is other + than default (typically TCP ports 860 and 3260). + items: + type: string + type: array + readOnly: + description: readOnly here will force the ReadOnly setting + in VolumeMounts. Defaults to false. + type: boolean + secretRef: + description: secretRef is the CHAP Secret for iSCSI target + and initiator authentication + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + x-kubernetes-map-type: atomic + targetPortal: + description: targetPortal is iSCSI Target Portal. The Portal + is either an IP or ip_addr:port if the port is other than + default (typically TCP ports 860 and 3260). + type: string + required: + - iqn + - lun + - targetPortal + type: object + nfs: + description: 'nfs represents an NFS mount on the host that shares + a pod''s lifetime More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' + properties: + path: + description: 'path that is exported by the NFS server. More + info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' + type: string + readOnly: + description: 'readOnly here will force the NFS export to be + mounted with read-only permissions. Defaults to false. More + info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' + type: boolean + server: + description: 'server is the hostname or IP address of the + NFS server. More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' + type: string + required: + - path + - server + type: object + persistentVolumeClaim: + description: 'persistentVolumeClaimVolumeSource represents a reference + to a PersistentVolumeClaim in the same namespace. More info: + https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' + properties: + claimName: + description: 'claimName is the name of a PersistentVolumeClaim + in the same namespace as the pod using this volume. More + info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' + type: string + readOnly: + description: readOnly Will force the ReadOnly setting in VolumeMounts. + Default false. + type: boolean + required: + - claimName + type: object + photonPersistentDisk: + description: photonPersistentDisk represents a PhotonController + persistent disk attached and mounted on kubelets host machine + properties: + fsType: + description: fsType is the filesystem type to mount. Must + be a filesystem type supported by the host operating system. + Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" + if unspecified. + type: string + pdID: + description: pdID is the ID that identifies Photon Controller + persistent disk + type: string + required: + - pdID + type: object + portworxVolume: + description: portworxVolume represents a portworx volume attached + and mounted on kubelets host machine + properties: + fsType: + description: fSType represents the filesystem type to mount + Must be a filesystem type supported by the host operating + system. Ex. "ext4", "xfs". Implicitly inferred to be "ext4" + if unspecified. + type: string + readOnly: + description: readOnly defaults to false (read/write). ReadOnly + here will force the ReadOnly setting in VolumeMounts. + type: boolean + volumeID: + description: volumeID uniquely identifies a Portworx volume + type: string + required: + - volumeID + type: object + projected: + description: projected items for all in one resources secrets, + configmaps, and downward API + properties: + defaultMode: + description: defaultMode are the mode bits used to set permissions + on created files by default. Must be an octal value between + 0000 and 0777 or a decimal value between 0 and 511. YAML + accepts both octal and decimal values, JSON requires decimal + values for mode bits. Directories within the path are not + affected by this setting. This might be in conflict with + other options that affect the file mode, like fsGroup, and + the result can be other mode bits set. + format: int32 + type: integer + sources: + description: sources is the list of volume projections + items: + description: Projection that may be projected along with + other supported volume types + properties: + configMap: + description: configMap information about the configMap + data to project + properties: + items: + description: items if unspecified, each key-value + pair in the Data field of the referenced ConfigMap + will be projected into the volume as a file whose + name is the key and content is the value. If specified, + the listed keys will be projected into the specified + paths, and unlisted keys will not be present. + If a key is specified which is not present in + the ConfigMap, the volume setup will error unless + it is marked optional. Paths must be relative + and may not contain the '..' path or start with + '..'. + items: + description: Maps a string key to a path within + a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: mode bits + used to set permissions on this file. Must + be an octal value between 0000 and 0777 + or a decimal value between 0 and 511. YAML + accepts both octal and decimal values, JSON + requires decimal values for mode bits. If + not specified, the volume defaultMode will + be used. This might be in conflict with + other options that affect the file mode, + like fsGroup, and the result can be other + mode bits set.' + format: int32 + type: integer + path: + description: path is the relative path of + the file to map the key to. May not be an + absolute path. May not contain the path + element '..'. May not start with the string + '..'. + type: string + required: + - key + - path + type: object + type: array + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: optional specify whether the ConfigMap + or its keys must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + downwardAPI: + description: downwardAPI information about the downwardAPI + data to project + properties: + items: + description: Items is a list of DownwardAPIVolume + file + items: + description: DownwardAPIVolumeFile represents + information to create the file containing the + pod field + properties: + fieldRef: + description: 'Required: Selects a field of + the pod: only annotations, labels, name + and namespace are supported.' + 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 + mode: + description: 'Optional: mode bits used to + set permissions on this file, must be an + octal value between 0000 and 0777 or a decimal + value between 0 and 511. YAML accepts both + octal and decimal values, JSON requires + decimal values for mode bits. If not specified, + the volume defaultMode will be used. This + might be in conflict with other options + that affect the file mode, like fsGroup, + and the result can be other mode bits set.' + format: int32 + type: integer + path: + description: 'Required: Path is the relative + path name of the file to be created. Must + not be absolute or contain the ''..'' path. + Must be utf-8 encoded. The first item of + the relative path must not start with ''..''' + type: string + resourceFieldRef: + description: 'Selects a resource of the container: + only resources limits and requests (limits.cpu, + limits.memory, requests.cpu and requests.memory) + 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 + required: + - path + type: object + type: array + type: object + secret: + description: secret information about the secret data + to project + properties: + items: + description: items if unspecified, each key-value + pair in the Data field of the referenced Secret + will be projected into the volume as a file whose + name is the key and content is the value. If specified, + the listed keys will be projected into the specified + paths, and unlisted keys will not be present. + If a key is specified which is not present in + the Secret, the volume setup will error unless + it is marked optional. Paths must be relative + and may not contain the '..' path or start with + '..'. + items: + description: Maps a string key to a path within + a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: mode bits + used to set permissions on this file. Must + be an octal value between 0000 and 0777 + or a decimal value between 0 and 511. YAML + accepts both octal and decimal values, JSON + requires decimal values for mode bits. If + not specified, the volume defaultMode will + be used. This might be in conflict with + other options that affect the file mode, + like fsGroup, and the result can be other + mode bits set.' + format: int32 + type: integer + path: + description: path is the relative path of + the file to map the key to. May not be an + absolute path. May not contain the path + element '..'. May not start with the string + '..'. + type: string + required: + - key + - path + type: object + type: array + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: optional field specify whether the + Secret or its key must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + serviceAccountToken: + description: serviceAccountToken is information about + the serviceAccountToken data to project + properties: + audience: + description: audience is the intended audience of + the token. A recipient of a token must identify + itself with an identifier specified in the audience + of the token, and otherwise should reject the + token. The audience defaults to the identifier + of the apiserver. + type: string + expirationSeconds: + description: expirationSeconds is the requested + duration of validity of the service account token. + As the token approaches expiration, the kubelet + volume plugin will proactively rotate the service + account token. The kubelet will start trying to + rotate the token if the token is older than 80 + percent of its time to live or if the token is + older than 24 hours.Defaults to 1 hour and must + be at least 10 minutes. + format: int64 + type: integer + path: + description: path is the path relative to the mount + point of the file to project the token into. + type: string + required: + - path + type: object + type: object + type: array + type: object + quobyte: + description: quobyte represents a Quobyte mount on the host that + shares a pod's lifetime + properties: + group: + description: group to map volume access to Default is no group + type: string + readOnly: + description: readOnly here will force the Quobyte volume to + be mounted with read-only permissions. Defaults to false. + type: boolean + registry: + description: registry represents a single or multiple Quobyte + Registry services specified as a string as host:port pair + (multiple entries are separated with commas) which acts + as the central registry for volumes + type: string + tenant: + description: tenant owning the given Quobyte volume in the + Backend Used with dynamically provisioned Quobyte volumes, + value is set by the plugin + type: string + user: + description: user to map volume access to Defaults to serivceaccount + user + type: string + volume: + description: volume is a string that references an already + created Quobyte volume by name. + type: string + required: + - registry + - volume + type: object + rbd: + description: 'rbd represents a Rados Block Device mount on the + host that shares a pod''s lifetime. More info: https://examples.k8s.io/volumes/rbd/README.md' + properties: + fsType: + description: 'fsType is the filesystem type of the volume + that you want to mount. Tip: Ensure that the filesystem + type is supported by the host operating system. Examples: + "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" + if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#rbd + TODO: how do we prevent errors in the filesystem from compromising + the machine' + type: string + image: + description: 'image is the rados image name. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: string + keyring: + description: 'keyring is the path to key ring for RBDUser. + Default is /etc/ceph/keyring. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: string + monitors: + description: 'monitors is a collection of Ceph monitors. More + info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + items: + type: string + type: array + pool: + description: 'pool is the rados pool name. Default is rbd. + More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: string + readOnly: + description: 'readOnly here will force the ReadOnly setting + in VolumeMounts. Defaults to false. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: boolean + secretRef: + description: 'secretRef is name of the authentication secret + for RBDUser. If provided overrides keyring. Default is nil. + More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + x-kubernetes-map-type: atomic + user: + description: 'user is the rados user name. Default is admin. + More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: string + required: + - image + - monitors + type: object + scaleIO: + description: scaleIO represents a ScaleIO persistent volume attached + and mounted on Kubernetes nodes. + properties: + fsType: + description: fsType is the filesystem type to mount. Must + be a filesystem type supported by the host operating system. + Ex. "ext4", "xfs", "ntfs". Default is "xfs". + type: string + gateway: + description: gateway is the host address of the ScaleIO API + Gateway. + type: string + protectionDomain: + description: protectionDomain is the name of the ScaleIO Protection + Domain for the configured storage. + type: string + readOnly: + description: readOnly Defaults to false (read/write). ReadOnly + here will force the ReadOnly setting in VolumeMounts. + type: boolean + secretRef: + description: secretRef references to the secret for ScaleIO + user and other sensitive information. If this is not provided, + Login operation will fail. + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + x-kubernetes-map-type: atomic + sslEnabled: + description: sslEnabled Flag enable/disable SSL communication + with Gateway, default false + type: boolean + storageMode: + description: storageMode indicates whether the storage for + a volume should be ThickProvisioned or ThinProvisioned. + Default is ThinProvisioned. + type: string + storagePool: + description: storagePool is the ScaleIO Storage Pool associated + with the protection domain. + type: string + system: + description: system is the name of the storage system as configured + in ScaleIO. + type: string + volumeName: + description: volumeName is the name of a volume already created + in the ScaleIO system that is associated with this volume + source. + type: string + required: + - gateway + - secretRef + - system + type: object + secret: + description: 'secret represents a secret that should populate + this volume. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' + properties: + defaultMode: + description: 'defaultMode is Optional: mode bits used to set + permissions on created files by default. Must be an octal + value between 0000 and 0777 or a decimal value between 0 + and 511. YAML accepts both octal and decimal values, JSON + requires decimal values for mode bits. Defaults to 0644. + Directories within the path are not affected by this setting. + This might be in conflict with other options that affect + the file mode, like fsGroup, and the result can be other + mode bits set.' + format: int32 + type: integer + items: + description: items If unspecified, each key-value pair in + the Data field of the referenced Secret will be projected + into the volume as a file whose name is the key and content + is the value. If specified, the listed keys will be projected + into the specified paths, and unlisted keys will not be + present. If a key is specified which is not present in the + Secret, the volume setup will error unless it is marked + optional. Paths must be relative and may not contain the + '..' path or start with '..'. + items: + description: Maps a string key to a path within a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: mode bits used to set + permissions on this file. Must be an octal value between + 0000 and 0777 or a decimal value between 0 and 511. + YAML accepts both octal and decimal values, JSON requires + decimal values for mode bits. If not specified, the + volume defaultMode will be used. This might be in + conflict with other options that affect the file mode, + like fsGroup, and the result can be other mode bits + set.' + format: int32 + type: integer + path: + description: path is the relative path of the file to + map the key to. May not be an absolute path. May not + contain the path element '..'. May not start with + the string '..'. + type: string + required: + - key + - path + type: object + type: array + optional: + description: optional field specify whether the Secret or + its keys must be defined + type: boolean + secretName: + description: 'secretName is the name of the secret in the + pod''s namespace to use. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' + type: string + type: object + storageos: + description: storageOS represents a StorageOS volume attached + and mounted on Kubernetes nodes. + properties: + fsType: + description: fsType is the filesystem type to mount. Must + be a filesystem type supported by the host operating system. + Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" + if unspecified. + type: string + readOnly: + description: readOnly defaults to false (read/write). ReadOnly + here will force the ReadOnly setting in VolumeMounts. + type: boolean + secretRef: + description: secretRef specifies the secret to use for obtaining + the StorageOS API credentials. If not specified, default + values will be attempted. + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + x-kubernetes-map-type: atomic + volumeName: + description: volumeName is the human-readable name of the + StorageOS volume. Volume names are only unique within a + namespace. + type: string + volumeNamespace: + description: volumeNamespace specifies the scope of the volume + within StorageOS. If no namespace is specified then the + Pod's namespace will be used. This allows the Kubernetes + name scoping to be mirrored within StorageOS for tighter + integration. Set VolumeName to any name to override the + default behaviour. Set to "default" if you are not using + namespaces within StorageOS. Namespaces that do not pre-exist + within StorageOS will be created. + type: string + type: object + vsphereVolume: + description: vsphereVolume represents a vSphere volume attached + and mounted on kubelets host machine + properties: + fsType: + description: fsType is filesystem type to mount. Must be a + filesystem type supported by the host operating system. + Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" + if unspecified. + type: string + storagePolicyID: + description: storagePolicyID is the storage Policy Based Management + (SPBM) profile ID associated with the StoragePolicyName. + type: string + storagePolicyName: + description: storagePolicyName is the storage Policy Based + Management (SPBM) profile name. + type: string + volumePath: + description: volumePath is the path that identifies vSphere + volume vmdk + type: string + required: + - volumePath + type: object + type: object + required: + - mariaDbRef + type: object + status: + description: RestoreStatus defines the observed state of restore + properties: + conditions: + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + \n type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + 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 + 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.11.1 + creationTimestamp: null + name: sqljobs.mariadb.mmontes.io +spec: + group: mariadb.mmontes.io + names: + kind: SqlJob + listKind: SqlJobList + plural: sqljobs + shortNames: + - smdb + singular: sqljob + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .status.conditions[?(@.type=="Complete")].status + name: Complete + type: string + - jsonPath: .status.conditions[?(@.type=="Complete")].message + name: Status + type: string + - jsonPath: .spec.mariaDbRef.name + name: MariaDB + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + description: SqlJob is the Schema for the sqljobs 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: SqlJobSpec defines the desired state of SqlJob + properties: + affinity: + description: Affinity is a group of affinity scheduling rules. + properties: + nodeAffinity: + description: Describes node affinity scheduling rules for the + pod. + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods to + nodes that satisfy the affinity expressions specified by + this field, but it may choose a node that violates one or + more of the expressions. The node that is most preferred + is the one with the greatest sum of weights, i.e. for each + node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, + etc.), compute a sum by iterating through the elements of + this field and adding "weight" to the sum if the node matches + the corresponding matchExpressions; the node(s) with the + highest sum are the most preferred. + items: + description: An empty preferred scheduling term matches + all objects with implicit weight 0 (i.e. it's a no-op). + A null preferred scheduling term matches no objects (i.e. + is also a no-op). + properties: + preference: + description: A node selector term, associated with the + corresponding weight. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists, DoesNotExist. Gt, and + Lt. + type: string + values: + description: 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. If the operator is Gt or + Lt, the values array must have a single + element, which will be interpreted as an + integer. This array is replaced during a + strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists, DoesNotExist. Gt, and + Lt. + type: string + values: + description: 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. If the operator is Gt or + Lt, the values array must have a single + element, which will be interpreted as an + integer. This array is replaced during a + strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + x-kubernetes-map-type: atomic + weight: + description: Weight associated with matching the corresponding + nodeSelectorTerm, in the range 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by this + field are not met at scheduling time, the pod will not be + scheduled onto the node. If the affinity requirements specified + by this field cease to be met at some point during pod execution + (e.g. due to an update), the system may or may not try to + eventually evict the pod from its node. + properties: + nodeSelectorTerms: + description: Required. A list of node selector terms. + The terms are ORed. + items: + description: A null or empty node selector term matches + no objects. The requirements of them are ANDed. The + TopologySelectorTerm type implements a subset of the + NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists, DoesNotExist. Gt, and + Lt. + type: string + values: + description: 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. If the operator is Gt or + Lt, the values array must have a single + element, which will be interpreted as an + integer. This array is replaced during a + strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists, DoesNotExist. Gt, and + Lt. + type: string + values: + description: 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. If the operator is Gt or + Lt, the values array must have a single + element, which will be interpreted as an + integer. This array is replaced during a + strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + x-kubernetes-map-type: atomic + type: array + required: + - nodeSelectorTerms + type: object + x-kubernetes-map-type: atomic + type: object + podAffinity: + description: Describes pod affinity scheduling rules (e.g. co-locate + this pod in the same node, zone, etc. as some other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods to + nodes that satisfy the affinity expressions specified by + this field, but it may choose a node that violates one or + more of the expressions. The node that is most preferred + is the one with the greatest sum of weights, i.e. for each + node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, + etc.), compute a sum by iterating through the elements of + this field and adding "weight" to the sum if the node has + pods which matches the corresponding podAffinityTerm; the + node(s) with the highest sum are the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by this + field and the ones listed in the namespaces field. + null selector and null or empty namespaces list + means "this pod's namespace". An empty selector + ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. The + term is applied to the union of the namespaces + listed in this field and the ones selected by + namespaceSelector. null or empty namespaces list + and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods + matching the labelSelector in the specified namespaces, + where co-located is defined as running on a node + whose value of the label with key topologyKey + matches that of any node on which any of the selected + pods is running. Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching the corresponding + podAffinityTerm, in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by this + field are not met at scheduling time, the pod will not be + scheduled onto the node. If the affinity requirements specified + by this field cease to be met at some point during pod execution + (e.g. due to a pod label update), the system may or may + not try to eventually evict the pod from its node. When + there are multiple elements, the lists of nodes corresponding + to each podAffinityTerm are intersected, i.e. all terms + must be satisfied. + items: + description: Defines a set of pods (namely those matching + the labelSelector relative to the given namespace(s)) + that this pod should be co-located (affinity) or not co-located + (anti-affinity) with, where co-located is defined as running + on a node whose value of the label with key + matches that of any node on which a pod of the set of + pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied to the + union of the namespaces selected by this field and + the ones listed in the namespaces field. null selector + and null or empty namespaces list means "this pod's + namespace". An empty selector ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list of namespace + names that the term applies to. The term is applied + to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. null or + empty namespaces list and null namespaceSelector means + "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where + co-located is defined as running on a node whose value + of the label with key topologyKey matches that of + any node on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + podAntiAffinity: + description: Describes pod anti-affinity scheduling rules (e.g. + avoid putting this pod in the same node, zone, etc. as some + other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods to + nodes that satisfy the anti-affinity expressions specified + by this field, but it may choose a node that violates one + or more of the expressions. The node that is most preferred + is the one with the greatest sum of weights, i.e. for each + node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling anti-affinity expressions, + etc.), compute a sum by iterating through the elements of + this field and adding "weight" to the sum if the node has + pods which matches the corresponding podAffinityTerm; the + node(s) with the highest sum are the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by this + field and the ones listed in the namespaces field. + null selector and null or empty namespaces list + means "this pod's namespace". An empty selector + ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. The + term is applied to the union of the namespaces + listed in this field and the ones selected by + namespaceSelector. null or empty namespaces list + and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods + matching the labelSelector in the specified namespaces, + where co-located is defined as running on a node + whose value of the label with key topologyKey + matches that of any node on which any of the selected + pods is running. Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching the corresponding + podAffinityTerm, in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the anti-affinity requirements specified by + this field are not met at scheduling time, the pod will + not be scheduled onto the node. If the anti-affinity requirements + specified by this field cease to be met at some point during + pod execution (e.g. due to a pod label update), the system + may or may not try to eventually evict the pod from its + node. When there are multiple elements, the lists of nodes + corresponding to each podAffinityTerm are intersected, i.e. + all terms must be satisfied. + items: + description: Defines a set of pods (namely those matching + the labelSelector relative to the given namespace(s)) + that this pod should be co-located (affinity) or not co-located + (anti-affinity) with, where co-located is defined as running + on a node whose value of the label with key + matches that of any node on which a pod of the set of + pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied to the + union of the namespaces selected by this field and + the ones listed in the namespaces field. null selector + and null or empty namespaces list means "this pod's + namespace". An empty selector ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list of namespace + names that the term applies to. The term is applied + to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. null or + empty namespaces list and null namespaceSelector means + "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where + co-located is defined as running on a node whose value + of the label with key topologyKey matches that of + any node on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + type: object + backoffLimit: + default: 5 + format: int32 + type: integer + database: + type: string + dependsOn: + items: + description: LocalObjectReference contains enough information to + let you locate the referenced object inside the same namespace. + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + x-kubernetes-map-type: atomic + type: array + mariaDbRef: + properties: + apiVersion: + description: API version of the referent. + type: string + fieldPath: + description: 'If referring to a piece of an object instead of + an entire object, this string should contain a valid JSON/Go + field access statement, such as desiredState.manifest.containers[2]. + For example, if the object reference is to a container within + a pod, this would take on a value like: "spec.containers{name}" + (where "name" refers to the name of the container that triggered + the event) or if no container name is specified "spec.containers[2]" + (container with index 2 in this pod). This syntax is chosen + only to have some well-defined way of referencing a part of + an object. TODO: this design is not final and this field is + subject to change in the future.' + type: string + kind: + description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + namespace: + description: 'Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/' + type: string + resourceVersion: + description: 'Specific resourceVersion to which this reference + is made, if any. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency' + type: string + uid: + description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids' + type: string + waitForIt: + default: true + type: boolean + type: object + x-kubernetes-map-type: atomic + nodeSelector: + additionalProperties: + type: string + type: object + passwordSecretKeyRef: + description: SecretKeySelector selects a key of a Secret. + properties: + key: + description: The key of the secret to select from. Must be a + valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + resources: + description: ResourceRequirements describes the compute resource requirements. + properties: + claims: + description: "Claims lists the names of resources, defined in + spec.resourceClaims, that are used by this container. \n This + is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n 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 + 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 + restartPolicy: + default: OnFailure + description: RestartPolicy describes how the container should be restarted. + Only one of the following restart policies may be specified. If + none of the following policies is specified, the default one is + RestartPolicyAlways. + type: string + schedule: + properties: + cron: + type: string + suspend: + default: false + type: boolean + required: + - cron + type: object + sql: + type: string + sqlConfigMapKeyRef: + description: Selects a key from a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + tolerations: + 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 + username: + type: string + required: + - mariaDbRef + - passwordSecretKeyRef + - username + type: object + status: + description: SqlJobStatus defines the observed state of SqlJob + properties: + conditions: + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + \n type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + 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 + 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.11.1 + creationTimestamp: null + name: users.mariadb.mmontes.io +spec: + group: mariadb.mmontes.io + names: + kind: User + listKind: UserList + plural: users + shortNames: + - umdb + singular: user + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .status.conditions[?(@.type=="Ready")].status + name: Ready + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].message + name: Status + type: string + - jsonPath: .spec.maxUserConnections + name: MaxConns + type: string + - jsonPath: .spec.mariaDbRef.name + name: MariaDB + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + description: User is the Schema for the users 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: UserSpec defines the desired state of User + properties: + host: + maxLength: 255 + type: string + mariaDbRef: + properties: + apiVersion: + description: API version of the referent. + type: string + fieldPath: + description: 'If referring to a piece of an object instead of + an entire object, this string should contain a valid JSON/Go + field access statement, such as desiredState.manifest.containers[2]. + For example, if the object reference is to a container within + a pod, this would take on a value like: "spec.containers{name}" + (where "name" refers to the name of the container that triggered + the event) or if no container name is specified "spec.containers[2]" + (container with index 2 in this pod). This syntax is chosen + only to have some well-defined way of referencing a part of + an object. TODO: this design is not final and this field is + subject to change in the future.' + type: string + kind: + description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + namespace: + description: 'Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/' + type: string + resourceVersion: + description: 'Specific resourceVersion to which this reference + is made, if any. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency' + type: string + uid: + description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids' + type: string + waitForIt: + default: true + type: boolean + type: object + x-kubernetes-map-type: atomic + maxUserConnections: + default: 10 + format: int32 + type: integer + name: + maxLength: 80 + type: string + passwordSecretKeyRef: + description: SecretKeySelector selects a key of a Secret. + properties: + key: + description: The key of the secret to select from. Must be a + valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + retryInterval: + type: string + required: + - mariaDbRef + - passwordSecretKeyRef + type: object + status: + description: UserStatus defines the observed state of User + properties: + conditions: + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + \n type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + 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 + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/packages/system/mariadb-operator/charts/mariadb-operator/templates/NOTES.txt b/packages/system/mariadb-operator/charts/mariadb-operator/templates/NOTES.txt new file mode 100644 index 00000000..ff5e0bb1 --- /dev/null +++ b/packages/system/mariadb-operator/charts/mariadb-operator/templates/NOTES.txt @@ -0,0 +1,4 @@ +mariadb-operator has been successfully deployed! 🦭 + +Not sure what to do next? 😅 Check out: +https://github.com/mariadb-operator/mariadb-operator#quickstart \ No newline at end of file diff --git a/packages/system/mariadb-operator/charts/mariadb-operator/templates/_helpers.tpl b/packages/system/mariadb-operator/charts/mariadb-operator/templates/_helpers.tpl new file mode 100644 index 00000000..4403ad32 --- /dev/null +++ b/packages/system/mariadb-operator/charts/mariadb-operator/templates/_helpers.tpl @@ -0,0 +1,118 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "mariadb-operator.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | 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 "mariadb-operator.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "mariadb-operator.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "mariadb-operator.labels" -}} +helm.sh/chart: {{ include "mariadb-operator.chart" . }} +{{ include "mariadb-operator.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "mariadb-operator.selectorLabels" -}} +app.kubernetes.io/name: {{ include "mariadb-operator.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Webhook common labels +*/}} +{{- define "mariadb-operator-webhook.labels" -}} +helm.sh/chart: {{ include "mariadb-operator.chart" . }} +{{ include "mariadb-operator-webhook.selectorLabels" . }} +{{ if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{ end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Webhook selector labels +*/}} +{{- define "mariadb-operator-webhook.selectorLabels" -}} +app.kubernetes.io/name: {{ include "mariadb-operator.name" . }}-webhook +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Webhook certificate +*/}} +{{- define "mariadb-operator-webhook.certificate" -}} +{{- if .Values.webhook.certificate.certManager }} +{{- include "mariadb-operator.fullname" . }}-webhook-cert +{{- else }} +{{- include "mariadb-operator.fullname" . }}-webhook-default-cert +{{- end }} +{{- end }} + +{{/* +Webhook certificate subject name +*/}} +{{- define "mariadb-operator-webhook.subjectName" -}} +{{- include "mariadb-operator.fullname" . }}-webhook.{{ .Release.Namespace }}.svc +{{- end }} + +{{/* +Webhook certificate subject alternative name +*/}} +{{- define "mariadb-operator-webhook.altName" -}} +{{- include "mariadb-operator.fullname" . }}-webhook.{{ .Release.Namespace }}.svc.{{ .Values.clusterName }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "mariadb-operator.serviceAccountName" -}} +{{- if .Values.serviceAccount.enabled }} +{{- default (include "mariadb-operator.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} + +{{/* +Create the name of the webhook service account to use +*/}} +{{- define "mariadb-operator-webhook.serviceAccountName" -}} +{{- if .Values.webhook.serviceAccount.enabled }} +{{- default (printf "%s-webhook" (include "mariadb-operator.fullname" .)) .Values.webhook.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.webhook.serviceAccount.name }} +{{- end }} +{{- end }} diff --git a/packages/system/mariadb-operator/charts/mariadb-operator/templates/deployment.yaml b/packages/system/mariadb-operator/charts/mariadb-operator/templates/deployment.yaml new file mode 100644 index 00000000..d47d4326 --- /dev/null +++ b/packages/system/mariadb-operator/charts/mariadb-operator/templates/deployment.yaml @@ -0,0 +1,109 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "mariadb-operator.fullname" . }} + labels: + {{ include "mariadb-operator.labels" . | nindent 4 }} +spec: + {{ if .Values.ha.enabled }} + replicas: {{ .Values.ha.replicas}} + {{ end }} + selector: + matchLabels: + {{ include "mariadb-operator.selectorLabels" . | nindent 6 }} + template: + metadata: + {{ with .Values.podAnnotations }} + annotations: + {{ toYaml . | nindent 8 }} + {{ end }} + labels: + {{ include "mariadb-operator.selectorLabels" . | nindent 8 }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "mariadb-operator.serviceAccountName" . }} + automountServiceAccountToken: {{ .Values.serviceAccount.automount }} + terminationGracePeriodSeconds: 10 + {{ with .Values.nodeSelector }} + nodeSelector: + {{ toYaml . | nindent 8 }} + {{ end }} + {{ with .Values.tolerations }} + tolerations: + {{ toYaml . | nindent 8 }} + {{ end }} + {{ with .Values.affinity }} + affinity: + {{ toYaml . | nindent 8 }} + {{ end }} + {{ with .Values.podSecurityContext }} + securityContext: + {{ toYaml . | nindent 8 }} + {{ end }} + containers: + - image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + name: controller + args: + - --metrics-addr=:8080 + - --log-level={{ .Values.logLevel }} + {{- if .Values.ha.enabled }} + - --leader-elect + {{- end }} + {{- if .Values.metrics.enabled }} + - --service-monitor-reconciler + {{- end }} + {{- range .Values.extrArgs }} + - {{ . }} + {{- end }} + ports: + - containerPort: 8080 + protocol: TCP + name: metrics + env: + - name: CLUSTER_NAME + value: {{ .Values.clusterName }} + - name: MARIADB_OPERATOR_NAME + valueFrom: + fieldRef: + fieldPath: spec.serviceAccountName + - name: MARIADB_OPERATOR_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: MARIADB_OPERATOR_SA_PATH + value: /var/run/secrets/kubernetes.io/serviceaccount/token + {{- if .Values.extraVolumeMounts }} + volumeMounts: + {{- toYaml .Values.extraVolumeMounts | nindent 12 }} + {{- end }} + {{ with .Values.resources }} + resources: + {{ toYaml . | nindent 12 }} + {{ end }} + {{ with .Values.securityContext}} + securityContext: + {{ toYaml . | nindent 12 }} + {{ end }} + readinessProbe: + tcpSocket: + port: 8080 + initialDelaySeconds: 30 + periodSeconds: 10 + livenessProbe: + tcpSocket: + port: 8080 + initialDelaySeconds: 30 + periodSeconds: 10 + startupProbe: + tcpSocket: + port: 8080 + initialDelaySeconds: 20 + periodSeconds: 10 + {{- if .Values.extraVolumes }} + volumes: + {{- toYaml .Values.extraVolumes | nindent 8 }} + {{- end }} diff --git a/packages/system/mariadb-operator/charts/mariadb-operator/templates/rbac.yaml b/packages/system/mariadb-operator/charts/mariadb-operator/templates/rbac.yaml new file mode 100644 index 00000000..27f51097 --- /dev/null +++ b/packages/system/mariadb-operator/charts/mariadb-operator/templates/rbac.yaml @@ -0,0 +1,434 @@ +{{- if .Values.rbac.enabled -}} +{{ $fullName := include "mariadb-operator.fullname" . }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ $fullName }} +rules: +- apiGroups: + - "" + resources: + - configmaps + verbs: + - get + - list + - watch + - create + - update + - patch + - delete +- apiGroups: + - coordination.k8s.io + resources: + - leases + verbs: + - get + - list + - watch + - create + - update + - patch + - delete +- apiGroups: + - "" + resources: + - events + verbs: + - create + - patch +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ $fullName }} +rules: +- apiGroups: + - "" + resources: + - configmaps + verbs: + - create + - get + - list + - patch + - watch +- apiGroups: + - "" + resources: + - endpoints + - endpoints/restricted + verbs: + - create + - get + - list + - patch + - watch +- apiGroups: + - "" + resources: + - events + verbs: + - create + - list + - patch + - watch +- apiGroups: + - "" + resources: + - persistentvolumeclaims + verbs: + - create + - list + - patch + - watch +- apiGroups: + - "" + resources: + - pods + verbs: + - delete + - get + - list + - watch +- apiGroups: + - "" + resources: + - secrets + verbs: + - create + - list + - patch + - watch +- apiGroups: + - "" + resources: + - serviceaccounts + verbs: + - create + - list + - patch + - watch +- apiGroups: + - "" + resources: + - services + verbs: + - create + - list + - patch + - watch +- apiGroups: + - apps + resources: + - statefulsets + verbs: + - create + - get + - list + - patch + - watch +- apiGroups: + - batch + resources: + - cronjobs + verbs: + - create + - list + - patch + - watch +- apiGroups: + - batch + resources: + - jobs + verbs: + - create + - list + - patch + - watch +- apiGroups: + - mariadb.mmontes.io + resources: + - backups + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - mariadb.mmontes.io + resources: + - backups/finalizers + verbs: + - update +- apiGroups: + - mariadb.mmontes.io + resources: + - backups/status + verbs: + - get + - patch + - update +- apiGroups: + - mariadb.mmontes.io + resources: + - connections + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - mariadb.mmontes.io + resources: + - connections + - restores + verbs: + - create + - list + - patch + - watch +- apiGroups: + - mariadb.mmontes.io + resources: + - connections/finalizers + verbs: + - update +- apiGroups: + - mariadb.mmontes.io + resources: + - connections/status + verbs: + - get + - patch + - update +- apiGroups: + - mariadb.mmontes.io + resources: + - databases + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - mariadb.mmontes.io + resources: + - databases/finalizers + verbs: + - update +- apiGroups: + - mariadb.mmontes.io + resources: + - databases/status + verbs: + - get + - patch + - update +- apiGroups: + - mariadb.mmontes.io + resources: + - grants + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - mariadb.mmontes.io + resources: + - grants/finalizers + verbs: + - update +- apiGroups: + - mariadb.mmontes.io + resources: + - grants/status + verbs: + - get + - patch + - update +- apiGroups: + - mariadb.mmontes.io + resources: + - mariadbs + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - mariadb.mmontes.io + resources: + - mariadbs/finalizers + verbs: + - update +- apiGroups: + - mariadb.mmontes.io + resources: + - mariadbs/status + verbs: + - get + - patch + - update +- apiGroups: + - mariadb.mmontes.io + resources: + - restores + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - mariadb.mmontes.io + resources: + - restores/finalizers + verbs: + - update +- apiGroups: + - mariadb.mmontes.io + resources: + - restores/status + verbs: + - get + - patch + - update +- apiGroups: + - mariadb.mmontes.io + resources: + - sqljobs + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - mariadb.mmontes.io + resources: + - sqljobs/finalizers + verbs: + - update +- apiGroups: + - mariadb.mmontes.io + resources: + - sqljobs/status + verbs: + - get + - patch + - update +- apiGroups: + - mariadb.mmontes.io + resources: + - users + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - mariadb.mmontes.io + resources: + - users/finalizers + verbs: + - update +- apiGroups: + - mariadb.mmontes.io + resources: + - users/status + verbs: + - get + - patch + - update +- apiGroups: + - monitoring.coreos.com + resources: + - servicemonitors + verbs: + - create + - list + - patch + - watch +- apiGroups: + - policy + resources: + - poddisruptionbudgets + verbs: + - create + - list + - patch + - watch +- apiGroups: + - rbac.authorization.k8s.io + resources: + - clusterrolebindings + - rolebindings + - roles + verbs: + - create + - list + - patch + - watch +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ $fullName }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ $fullName }} +subjects: +- kind: ServiceAccount + name: {{ include "mariadb-operator.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ $fullName }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ $fullName }} +subjects: +- kind: ServiceAccount + name: {{ include "mariadb-operator.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ $fullName }}:auth-delegator +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: system:auth-delegator +subjects: +- kind: ServiceAccount + name: {{ include "mariadb-operator.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} +{{- end }} \ No newline at end of file diff --git a/packages/system/mariadb-operator/charts/mariadb-operator/templates/serviceaccount.yaml b/packages/system/mariadb-operator/charts/mariadb-operator/templates/serviceaccount.yaml new file mode 100644 index 00000000..94e36303 --- /dev/null +++ b/packages/system/mariadb-operator/charts/mariadb-operator/templates/serviceaccount.yaml @@ -0,0 +1,15 @@ +{{- if .Values.serviceAccount.enabled -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "mariadb-operator.serviceAccountName" . }} + labels: + {{- include "mariadb-operator.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.extraLabels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} \ No newline at end of file diff --git a/packages/system/mariadb-operator/charts/mariadb-operator/templates/servicemonitor.yaml b/packages/system/mariadb-operator/charts/mariadb-operator/templates/servicemonitor.yaml new file mode 100644 index 00000000..8fb37602 --- /dev/null +++ b/packages/system/mariadb-operator/charts/mariadb-operator/templates/servicemonitor.yaml @@ -0,0 +1,36 @@ +{{ if and .Values.metrics.enabled .Values.metrics.serviceMonitor.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "mariadb-operator.fullname" . }}-metrics + labels: + {{ include "mariadb-operator.labels" . | nindent 4 }} +spec: + ports: + - port: 8080 + protocol: TCP + name: metrics + selector: + {{ include "mariadb-operator.selectorLabels" . | nindent 4 }} +--- +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ include "mariadb-operator.fullname" . }} + labels: + {{ include "mariadb-operator.labels" . | nindent 4 }} + {{ with .Values.metrics.serviceMonitor.additionalLabels }} + {{ toYaml . | nindent 4 }} + {{ end }} +spec: + selector: + matchLabels: + {{ include "mariadb-operator.selectorLabels" . | nindent 6 }} + namespaceSelector: + matchNames: + - {{ .Release.Namespace | quote }} + endpoints: + - port: metrics + interval: {{ .Values.metrics.serviceMonitor.interval }} + scrapeTimeout: {{ .Values.metrics.serviceMonitor.scrapeTimeout }} +{{ end }} \ No newline at end of file diff --git a/packages/system/mariadb-operator/charts/mariadb-operator/templates/webhook-certificate.yaml b/packages/system/mariadb-operator/charts/mariadb-operator/templates/webhook-certificate.yaml new file mode 100644 index 00000000..a536fbf5 --- /dev/null +++ b/packages/system/mariadb-operator/charts/mariadb-operator/templates/webhook-certificate.yaml @@ -0,0 +1,25 @@ +{{ if .Values.webhook.certificate.certManager }} +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + name: {{ include "mariadb-operator.fullname" . }}-selfsigned-issuer + labels: + {{ include "mariadb-operator-webhook.labels" . | nindent 4 }} +spec: + selfSigned: {} +--- +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: {{ include "mariadb-operator.fullname" . }}-webhook-cert + labels: + {{ include "mariadb-operator-webhook.labels" . | nindent 4 }} +spec: + dnsNames: + - {{ include "mariadb-operator-webhook.subjectName" . }} + - {{ include "mariadb-operator-webhook.altName" . }} + issuerRef: + kind: Issuer + name: {{ include "mariadb-operator.fullname" . }}-selfsigned-issuer + secretName: {{ include "mariadb-operator.fullname" . }}-webhook-cert +{{ end }} \ No newline at end of file diff --git a/packages/system/mariadb-operator/charts/mariadb-operator/templates/webhook-config.yaml b/packages/system/mariadb-operator/charts/mariadb-operator/templates/webhook-config.yaml new file mode 100644 index 00000000..7ace39a4 --- /dev/null +++ b/packages/system/mariadb-operator/charts/mariadb-operator/templates/webhook-config.yaml @@ -0,0 +1,269 @@ +{{ $fullName := include "mariadb-operator.fullname" . }} +{{ $subjectName := include "mariadb-operator-webhook.subjectName" . }} +{{ $altNames := list }} +{{ $altNames := append $altNames $subjectName }} +{{ $altNames := append $altNames (include "mariadb-operator-webhook.altName" . ) }} +{{ $ca := genCA $fullName (.Values.webhook.certificate.default.caExpirationDays | int) }} +{{ $cert := genSignedCert $subjectName nil $altNames (.Values.webhook.certificate.default.certExpirationDays | int) $ca }} +{{ if not .Values.webhook.certificate.certManager }} +apiVersion: v1 +kind: Secret +type: kubernetes.io/tls +metadata: + name: {{ $fullName }}-webhook-default-cert + labels: + {{ include "mariadb-operator-webhook.labels" . | nindent 4 }} + annotations: + {{ with .Values.webhook.certificate.default.hook }} + helm.sh/hook: {{ . }} + {{ end }} + {{ with .Values.webhook.certificate.default.annotations }} + {{ toYaml . | nindent 4 }} + {{ end }} +data: + tls.crt: {{ $cert.Cert | b64enc }} + tls.key: {{ $cert.Key | b64enc }} +{{ end }} +--- +apiVersion: admissionregistration.k8s.io/v1 +kind: MutatingWebhookConfiguration +metadata: + name: {{ $fullName }}-webhook + labels: + {{ include "mariadb-operator-webhook.labels" . | nindent 4 }} + annotations: + {{ if .Values.webhook.certificate.certManager }} + cert-manager.io/inject-ca-from: {{ .Release.Namespace }}/{{ include "mariadb-operator.fullname" . }}-webhook-cert + {{ end }} + {{ with .Values.webhook.certificate.default.hook }} + helm.sh/hook: {{ . }} + {{ end }} + {{ with .Values.webhook.annotations }} + {{ toYaml . | indent 4 }} + {{ end }} +webhooks: +- admissionReviewVersions: + - v1 + clientConfig: + service: + name: {{ $fullName }}-webhook + namespace: {{ .Release.Namespace }} + path: /mutate-mariadb-mmontes-io-v1alpha1-mariadb + {{ if not .Values.webhook.certificate.certManager }} + caBundle: {{ $ca.Cert | b64enc }} + {{ end }} + failurePolicy: Fail + name: mmariadb.kb.io + rules: + - apiGroups: + - mariadb.mmontes.io + apiVersions: + - v1alpha1 + operations: + - CREATE + - UPDATE + resources: + - mariadbs + sideEffects: None +--- +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingWebhookConfiguration +metadata: + name: {{ $fullName }}-webhook + labels: + {{ include "mariadb-operator-webhook.labels" . | nindent 4 }} + annotations: + {{ if .Values.webhook.certificate.certManager }} + cert-manager.io/inject-ca-from: {{ .Release.Namespace }}/{{ include "mariadb-operator.fullname" . }}-webhook-cert + {{ end }} + {{ with .Values.webhook.certificate.default.hook }} + helm.sh/hook: {{ . }} + {{ end }} + {{ with .Values.webhook.annotations }} + {{ toYaml . | indent 4 }} + {{ end }} +webhooks: + - admissionReviewVersions: + - v1 + clientConfig: + service: + name: {{ $fullName }}-webhook + namespace: {{ .Release.Namespace }} + path: /validate-mariadb-mmontes-io-v1alpha1-backup + {{ if not .Values.webhook.certificate.certManager }} + caBundle: {{ $ca.Cert | b64enc }} + {{ end }} + failurePolicy: Fail + name: vbackup.kb.io + rules: + - apiGroups: + - mariadb.mmontes.io + apiVersions: + - v1alpha1 + operations: + - CREATE + - UPDATE + resources: + - backups + sideEffects: None + - admissionReviewVersions: + - v1 + clientConfig: + service: + name: {{ $fullName }}-webhook + namespace: {{ .Release.Namespace }} + path: /validate-mariadb-mmontes-io-v1alpha1-connection + {{ if not .Values.webhook.certificate.certManager }} + caBundle: {{ $ca.Cert | b64enc }} + {{ end }} + failurePolicy: Fail + name: vconnection.kb.io + rules: + - apiGroups: + - mariadb.mmontes.io + apiVersions: + - v1alpha1 + operations: + - CREATE + - UPDATE + resources: + - connections + sideEffects: None + - admissionReviewVersions: + - v1 + clientConfig: + service: + name: {{ $fullName }}-webhook + namespace: {{ .Release.Namespace }} + path: /validate-mariadb-mmontes-io-v1alpha1-database + {{ if not .Values.webhook.certificate.certManager }} + caBundle: {{ $ca.Cert | b64enc }} + {{ end }} + failurePolicy: Fail + name: vdatabase.kb.io + rules: + - apiGroups: + - mariadb.mmontes.io + apiVersions: + - v1alpha1 + operations: + - CREATE + - UPDATE + resources: + - databases + sideEffects: None + - admissionReviewVersions: + - v1 + clientConfig: + service: + name: {{ $fullName }}-webhook + namespace: {{ .Release.Namespace }} + path: /validate-mariadb-mmontes-io-v1alpha1-grant + {{ if not .Values.webhook.certificate.certManager }} + caBundle: {{ $ca.Cert | b64enc }} + {{ end }} + failurePolicy: Fail + name: vgrant.kb.io + rules: + - apiGroups: + - mariadb.mmontes.io + apiVersions: + - v1alpha1 + operations: + - CREATE + - UPDATE + resources: + - grants + sideEffects: None + - admissionReviewVersions: + - v1 + clientConfig: + service: + name: {{ $fullName }}-webhook + namespace: {{ .Release.Namespace }} + path: /validate-mariadb-mmontes-io-v1alpha1-mariadb + {{ if not .Values.webhook.certificate.certManager }} + caBundle: {{ $ca.Cert | b64enc }} + {{ end }} + failurePolicy: Fail + name: vmariadb.kb.io + rules: + - apiGroups: + - mariadb.mmontes.io + apiVersions: + - v1alpha1 + operations: + - CREATE + - UPDATE + resources: + - mariadbs + sideEffects: None + - admissionReviewVersions: + - v1 + clientConfig: + service: + name: {{ $fullName }}-webhook + namespace: {{ .Release.Namespace }} + path: /validate-mariadb-mmontes-io-v1alpha1-restore + {{ if not .Values.webhook.certificate.certManager }} + caBundle: {{ $ca.Cert | b64enc }} + {{ end }} + failurePolicy: Fail + name: vrestore.kb.io + rules: + - apiGroups: + - mariadb.mmontes.io + apiVersions: + - v1alpha1 + operations: + - CREATE + - UPDATE + resources: + - restores + sideEffects: None + - admissionReviewVersions: + - v1 + clientConfig: + service: + name: {{ $fullName }}-webhook + namespace: {{ .Release.Namespace }} + path: /validate-mariadb-mmontes-io-v1alpha1-sqljob + {{ if not .Values.webhook.certificate.certManager }} + caBundle: {{ $ca.Cert | b64enc }} + {{ end }} + failurePolicy: Fail + name: vsqljob.kb.io + rules: + - apiGroups: + - mariadb.mmontes.io + apiVersions: + - v1alpha1 + operations: + - CREATE + - UPDATE + resources: + - sqljobs + sideEffects: None + - admissionReviewVersions: + - v1 + clientConfig: + service: + name: {{ $fullName }}-webhook + namespace: {{ .Release.Namespace }} + path: /validate-mariadb-mmontes-io-v1alpha1-user + {{ if not .Values.webhook.certificate.certManager }} + caBundle: {{ $ca.Cert | b64enc }} + {{ end }} + failurePolicy: Fail + name: vuser.kb.io + rules: + - apiGroups: + - mariadb.mmontes.io + apiVersions: + - v1alpha1 + operations: + - CREATE + - UPDATE + resources: + - users + sideEffects: None \ No newline at end of file diff --git a/packages/system/mariadb-operator/charts/mariadb-operator/templates/webhook-deployment.yaml b/packages/system/mariadb-operator/charts/mariadb-operator/templates/webhook-deployment.yaml new file mode 100644 index 00000000..0b3bf200 --- /dev/null +++ b/packages/system/mariadb-operator/charts/mariadb-operator/templates/webhook-deployment.yaml @@ -0,0 +1,107 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "mariadb-operator.fullname" . }}-webhook + labels: + {{ include "mariadb-operator-webhook.labels" . | nindent 4 }} +spec: + selector: + matchLabels: + {{ include "mariadb-operator-webhook.selectorLabels" . | nindent 6 }} + template: + metadata: + {{ with .Values.webhook.podAnnotations }} + annotations: + {{ toYaml . | nindent 8 }} + {{ end }} + labels: + {{ include "mariadb-operator-webhook.selectorLabels" . | nindent 8 }} + spec: + {{- with .Values.webhook.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "mariadb-operator-webhook.serviceAccountName" . }} + automountServiceAccountToken: {{ .Values.webhook.serviceAccount.automount }} + {{ with .Values.webhook.nodeSelector }} + nodeSelector: + {{ toYaml . | nindent 8 }} + {{ end }} + {{ with .Values.webhook.tolerations }} + tolerations: + {{ toYaml . | nindent 8 }} + {{ end }} + {{ with .Values.webhook.affinity }} + affinity: + {{ toYaml . | nindent 8 }} + {{ end }} + {{ with .Values.webhook.podSecurityContext }} + securityContext: + {{ toYaml . | nindent 8 }} + {{ end }} + hostNetwork: {{ .Values.webhook.hostNetwork }} + containers: + - image: "{{ .Values.webhook.image.repository }}:{{ .Values.webhook.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.webhook.image.pullPolicy }} + name: webhook + args: + - webhook + - --cert-dir={{ .Values.webhook.certificate.path }} + - --port={{ .Values.webhook.port }} + - --metrics-addr=:8080 + - --health-addr=:8081 + - --log-level={{ .Values.logLevel }} + {{- range .Values.extrArgs }} + - {{ . }} + {{- end }} + ports: + - containerPort: {{ .Values.webhook.port }} + protocol: TCP + name: https + - containerPort: 8080 + protocol: TCP + name: metrics + - containerPort: 8081 + protocol: TCP + name: health + volumeMounts: + - mountPath: {{ .Values.webhook.certificate.path }} + name: cert + readOnly: true + {{- if .Values.webhook.extraVolumeMounts }} + {{- toYaml .Values.webhook.extraVolumeMounts | nindent 12 }} + {{- end }} + readinessProbe: + httpGet: + path: /healthz + port: 8081 + initialDelaySeconds: 5 + periodSeconds: 10 + livenessProbe: + httpGet: + path: /healthz + port: 8081 + initialDelaySeconds: 5 + periodSeconds: 10 + startupProbe: + httpGet: + path: /healthz + port: 8081 + initialDelaySeconds: 5 + periodSeconds: 10 + {{ with .Values.webhook.resources }} + resources: + {{ toYaml . | nindent 12 }} + {{ end }} + {{ with .Values.webhook.securityContext}} + securityContext: + {{ toYaml . | nindent 12 }} + {{ end }} + volumes: + - name: cert + secret: + defaultMode: 420 + secretName: {{ include "mariadb-operator-webhook.certificate" . }} + {{- if .Values.webhook.extraVolumes }} + {{- toYaml .Values.webhook.extraVolumes | nindent 8 }} + {{- end }} diff --git a/packages/system/mariadb-operator/charts/mariadb-operator/templates/webhook-service.yaml b/packages/system/mariadb-operator/charts/mariadb-operator/templates/webhook-service.yaml new file mode 100644 index 00000000..2217e1d2 --- /dev/null +++ b/packages/system/mariadb-operator/charts/mariadb-operator/templates/webhook-service.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "mariadb-operator.fullname" . }}-webhook + labels: + {{ include "mariadb-operator-webhook.labels" . | nindent 4 }} +spec: + ports: + - port: 443 + protocol: TCP + targetPort: {{ .Values.webhook.port }} + selector: + {{ include "mariadb-operator-webhook.selectorLabels" . | nindent 4 }} \ No newline at end of file diff --git a/packages/system/mariadb-operator/charts/mariadb-operator/templates/webhook-serviceaccount.yaml b/packages/system/mariadb-operator/charts/mariadb-operator/templates/webhook-serviceaccount.yaml new file mode 100644 index 00000000..669a0d19 --- /dev/null +++ b/packages/system/mariadb-operator/charts/mariadb-operator/templates/webhook-serviceaccount.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "mariadb-operator-webhook.serviceAccountName" . }} + labels: + {{- include "mariadb-operator-webhook.labels" . | nindent 4 }} + {{- with .Values.webhook.serviceAccount.extraLabels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.webhook.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} \ No newline at end of file diff --git a/packages/system/mariadb-operator/charts/mariadb-operator/templates/webhook-servicemonitor.yaml b/packages/system/mariadb-operator/charts/mariadb-operator/templates/webhook-servicemonitor.yaml new file mode 100644 index 00000000..b251dd5f --- /dev/null +++ b/packages/system/mariadb-operator/charts/mariadb-operator/templates/webhook-servicemonitor.yaml @@ -0,0 +1,36 @@ +{{ if and .Values.metrics.enabled .Values.webhook.serviceMonitor.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "mariadb-operator.fullname" . }}-webhook-metrics + labels: + {{ include "mariadb-operator-webhook.labels" . | nindent 4 }} +spec: + ports: + - port: 8080 + protocol: TCP + name: metrics + selector: + {{ include "mariadb-operator-webhook.selectorLabels" . | nindent 4 }} +--- +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ include "mariadb-operator.fullname" . }}-webhook + labels: + {{ include "mariadb-operator-webhook.labels" . | nindent 4 }} + {{ with .Values.webhook.serviceMonitor.additionalLabels }} + {{ toYaml . | nindent 4 }} + {{ end }} +spec: + selector: + matchLabels: + {{ include "mariadb-operator-webhook.selectorLabels" . | nindent 6 }} + namespaceSelector: + matchNames: + - {{ .Release.Namespace | quote }} + endpoints: + - port: metrics + interval: {{ .Values.webhook.serviceMonitor.interval }} + scrapeTimeout: {{ .Values.webhook.serviceMonitor.scrapeTimeout }} +{{ end }} \ No newline at end of file diff --git a/packages/system/mariadb-operator/charts/mariadb-operator/values.yaml b/packages/system/mariadb-operator/charts/mariadb-operator/values.yaml new file mode 100644 index 00000000..d3ecf5e6 --- /dev/null +++ b/packages/system/mariadb-operator/charts/mariadb-operator/values.yaml @@ -0,0 +1,161 @@ +nameOverride: "" +fullnameOverride: "" + +image: + repository: ghcr.io/mariadb-operator/mariadb-operator + pullPolicy: IfNotPresent + # -- Image tag to use. By default the chart appVersion is used + tag: "" +imagePullSecrets: [] + +# -- Controller log level +logLevel: INFO + +# -- Cluster DNS name +clusterName: cluster.local + +ha: + # -- Enable high availability + enabled: false + # -- Number of replicas + replicas: 3 + # -- Lease resource name to be used for leader election + leaseId: mariadb.mmontes.io + +metrics: + # -- Enable prometheus metrics. Prometheus must be installed in the cluster + enabled: false + serviceMonitor: + # -- Enable controller ServiceMonitor + enabled: true + # -- Labels to be added to the controller ServiceMonitor + additionalLabels: {} + # release: kube-prometheus-stack + # -- Interval to scrape metrics + interval: 30s + # -- Timeout if metrics can't be retrieved in given time interval + scrapeTimeout: 25s + +serviceAccount: + # -- Specifies whether a service account should be created + enabled: true + # -- Automounts the service account token in all containers of the Pod + automount: true + # -- Annotations to add to the service account + annotations: {} + # -- Extra Labels to add to the service account + extraLabels: {} + # -- The name of the service account to use. + # If not set and enabled is true, a name is generated using the fullname template + name: "" + +rbac: + # -- Specifies whether RBAC resources should be created + enabled: true + +# -- Extra arguments to be passed to the controller entrypoint +extrArgs: [] + +# -- Extra volumes to pass to pod. +extraVolumes: [] + +# -- Extra volumes to mount to the container. +extraVolumeMounts: [] + +# -- Annotations to add to controller Pod +podAnnotations: {} + +# -- Security context to add to controller Pod +podSecurityContext: {} + +# -- Security context to add to controller container +securityContext: {} + +# -- Resources to add to controller container +resources: {} +# requests: +# cpu: 10m +# memory: 32Mi + +# -- Node selectors to add to controller Pod +nodeSelector: {} + +# -- Tolerations to add to controller Pod +tolerations: [] + +# -- Affinity to add to controller Pod +affinity: {} + +webhook: + # -- Annotations for webhook configurations. + annotations: {} + image: + repository: ghcr.io/mariadb-operator/mariadb-operator + pullPolicy: IfNotPresent + # -- Image tag to use. By default the chart appVersion is used + tag: "" + imagePullSecrets: [] + certificate: + # -- Use cert-manager to issue and rotate the certificate. If set to false, a default certificate will be used. + certManager: false + # -- Default certificate generated when the chart is installed or upgraded. + default: + # -- Certificate authority expiration in days. + caExpirationDays: 365 + # -- Certificate expiration in days. + certExpirationDays: 365 + # -- Annotations for certificate Secret. + annotations: {} + # -- Helm hook to be added to the default certificate. + hook: "" + # -- Path where the certificate will be mounted. + path: /tmp/k8s-webhook-server/serving-certs + # -- Port to be used by the webhook server + port: 10250 + # -- Expose the webhook server in the host network + hostNetwork: false + serviceMonitor: + # -- Enable webhook ServiceMonitor. Metrics must be enabled + enabled: true + # -- Labels to be added to the webhook ServiceMonitor + additionalLabels: {} + # release: kube-prometheus-stack + # -- Interval to scrape metrics + interval: 30s + # -- Timeout if metrics can't be retrieved in given time interval + scrapeTimeout: 25s + serviceAccount: + # -- Specifies whether a service account should be created + enabled: true + # -- Automounts the service account token in all containers of the Pod + automount: true + # -- Annotations to add to the service account + annotations: {} + # -- Extra Labels to add to the service account + extraLabels: {} + # -- The name of the service account to use. + # If not set and enabled is true, a name is generated using the fullname template + name: "" + # -- Extra arguments to be passed to the webhook entrypoint + extrArgs: [] + # -- Extra volumes to pass to webhook Pod + extraVolumes: [] + # -- Extra volumes to mount to webhook container + extraVolumeMounts: [] + # -- Annotations to add to webhook Pod + podAnnotations: {} + # -- Security context to add to webhook Pod + podSecurityContext: {} + # -- Security context to add to webhook container + securityContext: {} + # -- Resources to add to webhook container + resources: {} + # requests: + # cpu: 10m + # memory: 32Mi + # -- Node selectors to add to controller Pod + nodeSelector: {} + # -- Tolerations to add to controller Pod + tolerations: [] + # -- Affinity to add to controller Pod + affinity: {} diff --git a/packages/system/mariadb-operator/values.yaml b/packages/system/mariadb-operator/values.yaml new file mode 100644 index 00000000..8ec0bfce --- /dev/null +++ b/packages/system/mariadb-operator/values.yaml @@ -0,0 +1,6 @@ +mariadb-operator: + metrics: + enabled: true + webhook: + certificate: + certManager: true diff --git a/packages/system/metallb/Chart.yaml b/packages/system/metallb/Chart.yaml new file mode 100644 index 00000000..233b617e --- /dev/null +++ b/packages/system/metallb/Chart.yaml @@ -0,0 +1,2 @@ +name: cozy-metallb +version: 1.0.0 diff --git a/packages/system/metallb/Makefile b/packages/system/metallb/Makefile new file mode 100644 index 00000000..95755e94 --- /dev/null +++ b/packages/system/metallb/Makefile @@ -0,0 +1,17 @@ +NAME=metallb +NAMESPACE=cozy-metallb + +show: + helm template --dry-run=server -n $(NAMESPACE) $(NAME) . + +apply: + helm upgrade -i -n $(NAMESPACE) $(NAME) . + +diff: + helm diff upgrade --allow-unreleased --normalize-manifests -n $(NAMESPACE) $(NAME) . + +update: + rm -rf charts + helm repo add metallb https://metallb.github.io/metallb + helm repo update metallb + helm pull metallb/metallb --untar --untardir charts diff --git a/packages/system/metallb/charts/metallb/.helmignore b/packages/system/metallb/charts/metallb/.helmignore new file mode 100644 index 00000000..0e8a0eb3 --- /dev/null +++ b/packages/system/metallb/charts/metallb/.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/packages/system/metallb/charts/metallb/Chart.lock b/packages/system/metallb/charts/metallb/Chart.lock new file mode 100644 index 00000000..7d3b2e40 --- /dev/null +++ b/packages/system/metallb/charts/metallb/Chart.lock @@ -0,0 +1,6 @@ +dependencies: +- name: crds + repository: "" + version: 0.13.10 +digest: sha256:afb2e9d5b709e7ded68c21f9d033a0a14a1232be270b0966e5ef2722575afc77 +generated: "2023-05-31T15:40:56.282100173+02:00" diff --git a/packages/system/metallb/charts/metallb/Chart.yaml b/packages/system/metallb/charts/metallb/Chart.yaml new file mode 100644 index 00000000..f7ffd3a8 --- /dev/null +++ b/packages/system/metallb/charts/metallb/Chart.yaml @@ -0,0 +1,17 @@ +apiVersion: v2 +appVersion: v0.13.10 +dependencies: +- condition: crds.enabled + name: crds + repository: "" + version: 0.13.10 +description: A network load-balancer implementation for Kubernetes using standard + routing protocols +home: https://metallb.universe.tf +icon: https://metallb.universe.tf/images/logo/metallb-white.png +kubeVersion: '>= 1.19.0-0' +name: metallb +sources: +- https://github.com/metallb/metallb +type: application +version: 0.13.10 diff --git a/packages/system/metallb/charts/metallb/README.md b/packages/system/metallb/charts/metallb/README.md new file mode 100644 index 00000000..85c19de6 --- /dev/null +++ b/packages/system/metallb/charts/metallb/README.md @@ -0,0 +1,158 @@ +# metallb + +![Version: 0.0.0](https://img.shields.io/badge/Version-0.0.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: v0.0.0](https://img.shields.io/badge/AppVersion-v0.0.0-informational?style=flat-square) + +A network load-balancer implementation for Kubernetes using standard routing protocols + +**Homepage:** + +## Source Code + +* + +## Requirements + +Kubernetes: `>= 1.19.0-0` + +| Repository | Name | Version | +|------------|------|---------| +| | crds | 0.0.0 | + +## Values + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| controller.affinity | object | `{}` | | +| controller.enabled | bool | `true` | | +| controller.image.pullPolicy | string | `nil` | | +| controller.image.repository | string | `"quay.io/metallb/controller"` | | +| controller.image.tag | string | `nil` | | +| controller.labels | object | `{}` | | +| controller.livenessProbe.enabled | bool | `true` | | +| controller.livenessProbe.failureThreshold | int | `3` | | +| controller.livenessProbe.initialDelaySeconds | int | `10` | | +| controller.livenessProbe.periodSeconds | int | `10` | | +| controller.livenessProbe.successThreshold | int | `1` | | +| controller.livenessProbe.timeoutSeconds | int | `1` | | +| controller.logLevel | string | `"info"` | Controller log level. Must be one of: `all`, `debug`, `info`, `warn`, `error` or `none` | +| controller.nodeSelector | object | `{}` | | +| controller.podAnnotations | object | `{}` | | +| controller.priorityClassName | string | `""` | | +| controller.readinessProbe.enabled | bool | `true` | | +| controller.readinessProbe.failureThreshold | int | `3` | | +| controller.readinessProbe.initialDelaySeconds | int | `10` | | +| controller.readinessProbe.periodSeconds | int | `10` | | +| controller.readinessProbe.successThreshold | int | `1` | | +| controller.readinessProbe.timeoutSeconds | int | `1` | | +| controller.resources | object | `{}` | | +| controller.runtimeClassName | string | `""` | | +| controller.securityContext.fsGroup | int | `65534` | | +| controller.securityContext.runAsNonRoot | bool | `true` | | +| controller.securityContext.runAsUser | int | `65534` | | +| controller.serviceAccount.annotations | object | `{}` | | +| controller.serviceAccount.create | bool | `true` | | +| controller.serviceAccount.name | string | `""` | | +| controller.strategy.type | string | `"RollingUpdate"` | | +| controller.tolerations | list | `[]` | | +| crds.enabled | bool | `true` | | +| crds.validationFailurePolicy | string | `"Fail"` | | +| fullnameOverride | string | `""` | | +| imagePullSecrets | list | `[]` | | +| loadBalancerClass | string | `""` | | +| nameOverride | string | `""` | | +| prometheus.controllerMetricsTLSSecret | string | `""` | | +| prometheus.metricsPort | int | `7472` | | +| prometheus.namespace | string | `""` | | +| prometheus.podMonitor.additionalLabels | object | `{}` | | +| prometheus.podMonitor.annotations | object | `{}` | | +| prometheus.podMonitor.enabled | bool | `false` | | +| prometheus.podMonitor.interval | string | `nil` | | +| prometheus.podMonitor.jobLabel | string | `"app.kubernetes.io/name"` | | +| prometheus.podMonitor.metricRelabelings | list | `[]` | | +| prometheus.podMonitor.relabelings | list | `[]` | | +| prometheus.prometheusRule.additionalLabels | object | `{}` | | +| prometheus.prometheusRule.addressPoolExhausted.enabled | bool | `true` | | +| prometheus.prometheusRule.addressPoolExhausted.labels.severity | string | `"alert"` | | +| prometheus.prometheusRule.addressPoolUsage.enabled | bool | `true` | | +| prometheus.prometheusRule.addressPoolUsage.thresholds[0].labels.severity | string | `"warning"` | | +| prometheus.prometheusRule.addressPoolUsage.thresholds[0].percent | int | `75` | | +| prometheus.prometheusRule.addressPoolUsage.thresholds[1].labels.severity | string | `"warning"` | | +| prometheus.prometheusRule.addressPoolUsage.thresholds[1].percent | int | `85` | | +| prometheus.prometheusRule.addressPoolUsage.thresholds[2].labels.severity | string | `"alert"` | | +| prometheus.prometheusRule.addressPoolUsage.thresholds[2].percent | int | `95` | | +| prometheus.prometheusRule.annotations | object | `{}` | | +| prometheus.prometheusRule.bgpSessionDown.enabled | bool | `true` | | +| prometheus.prometheusRule.bgpSessionDown.labels.severity | string | `"alert"` | | +| prometheus.prometheusRule.configNotLoaded.enabled | bool | `true` | | +| prometheus.prometheusRule.configNotLoaded.labels.severity | string | `"warning"` | | +| prometheus.prometheusRule.enabled | bool | `false` | | +| prometheus.prometheusRule.extraAlerts | list | `[]` | | +| prometheus.prometheusRule.staleConfig.enabled | bool | `true` | | +| prometheus.prometheusRule.staleConfig.labels.severity | string | `"warning"` | | +| prometheus.rbacPrometheus | bool | `true` | | +| prometheus.rbacProxy.pullPolicy | string | `nil` | | +| prometheus.rbacProxy.repository | string | `"gcr.io/kubebuilder/kube-rbac-proxy"` | | +| prometheus.rbacProxy.tag | string | `"v0.12.0"` | | +| prometheus.scrapeAnnotations | bool | `false` | | +| prometheus.serviceAccount | string | `""` | | +| prometheus.serviceMonitor.controller.additionalLabels | object | `{}` | | +| prometheus.serviceMonitor.controller.annotations | object | `{}` | | +| prometheus.serviceMonitor.controller.tlsConfig.insecureSkipVerify | bool | `true` | | +| prometheus.serviceMonitor.enabled | bool | `false` | | +| prometheus.serviceMonitor.interval | string | `nil` | | +| prometheus.serviceMonitor.jobLabel | string | `"app.kubernetes.io/name"` | | +| prometheus.serviceMonitor.metricRelabelings | list | `[]` | | +| prometheus.serviceMonitor.relabelings | list | `[]` | | +| prometheus.serviceMonitor.speaker.additionalLabels | object | `{}` | | +| prometheus.serviceMonitor.speaker.annotations | object | `{}` | | +| prometheus.serviceMonitor.speaker.tlsConfig.insecureSkipVerify | bool | `true` | | +| prometheus.speakerMetricsTLSSecret | string | `""` | | +| rbac.create | bool | `true` | | +| speaker.affinity | object | `{}` | | +| speaker.enabled | bool | `true` | | +| speaker.excludeInterfaces.enabled | bool | `true` | | +| speaker.frr.enabled | bool | `true` | | +| speaker.frr.image.pullPolicy | string | `nil` | | +| speaker.frr.image.repository | string | `"quay.io/frrouting/frr"` | | +| speaker.frr.image.tag | string | `"8.4.2"` | | +| speaker.frr.metricsPort | int | `7473` | | +| speaker.frr.resources | object | `{}` | | +| speaker.frrMetrics.resources | object | `{}` | | +| speaker.image.pullPolicy | string | `nil` | | +| speaker.image.repository | string | `"quay.io/metallb/speaker"` | | +| speaker.image.tag | string | `nil` | | +| speaker.labels | object | `{}` | | +| speaker.livenessProbe.enabled | bool | `true` | | +| speaker.livenessProbe.failureThreshold | int | `3` | | +| speaker.livenessProbe.initialDelaySeconds | int | `10` | | +| speaker.livenessProbe.periodSeconds | int | `10` | | +| speaker.livenessProbe.successThreshold | int | `1` | | +| speaker.livenessProbe.timeoutSeconds | int | `1` | | +| speaker.logLevel | string | `"info"` | Speaker log level. Must be one of: `all`, `debug`, `info`, `warn`, `error` or `none` | +| speaker.memberlist.enabled | bool | `true` | | +| speaker.memberlist.mlBindPort | int | `7946` | | +| speaker.memberlist.mlSecretKeyPath | string | `"/etc/ml_secret_key"` | | +| speaker.nodeSelector | object | `{}` | | +| speaker.podAnnotations | object | `{}` | | +| speaker.priorityClassName | string | `""` | | +| speaker.readinessProbe.enabled | bool | `true` | | +| speaker.readinessProbe.failureThreshold | int | `3` | | +| speaker.readinessProbe.initialDelaySeconds | int | `10` | | +| speaker.readinessProbe.periodSeconds | int | `10` | | +| speaker.readinessProbe.successThreshold | int | `1` | | +| speaker.readinessProbe.timeoutSeconds | int | `1` | | +| speaker.reloader.resources | object | `{}` | | +| speaker.resources | object | `{}` | | +| speaker.runtimeClassName | string | `""` | | +| speaker.serviceAccount.annotations | object | `{}` | | +| speaker.serviceAccount.create | bool | `true` | | +| speaker.serviceAccount.name | string | `""` | | +| speaker.startupProbe.enabled | bool | `true` | | +| speaker.startupProbe.failureThreshold | int | `30` | | +| speaker.startupProbe.periodSeconds | int | `5` | | +| speaker.tolerateMaster | bool | `true` | | +| speaker.tolerations | list | `[]` | | +| speaker.updateStrategy.type | string | `"RollingUpdate"` | | + +---------------------------------------------- +Autogenerated from chart metadata using [helm-docs v1.10.0](https://github.com/norwoodj/helm-docs/releases/v1.10.0) diff --git a/packages/system/metallb/charts/metallb/charts/crds/.helmignore b/packages/system/metallb/charts/metallb/charts/crds/.helmignore new file mode 100644 index 00000000..0e8a0eb3 --- /dev/null +++ b/packages/system/metallb/charts/metallb/charts/crds/.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/packages/system/metallb/charts/metallb/charts/crds/Chart.yaml b/packages/system/metallb/charts/metallb/charts/crds/Chart.yaml new file mode 100644 index 00000000..0b504402 --- /dev/null +++ b/packages/system/metallb/charts/metallb/charts/crds/Chart.yaml @@ -0,0 +1,10 @@ +apiVersion: v2 +appVersion: v0.13.10 +description: MetalLB CRDs +home: https://metallb.universe.tf +icon: https://metallb.universe.tf/images/logo/metallb-white.png +name: crds +sources: +- https://github.com/metallb/metallb +type: application +version: 0.13.10 diff --git a/packages/system/metallb/charts/metallb/charts/crds/README.md b/packages/system/metallb/charts/metallb/charts/crds/README.md new file mode 100644 index 00000000..15bf8a7b --- /dev/null +++ b/packages/system/metallb/charts/metallb/charts/crds/README.md @@ -0,0 +1,14 @@ +# crds + +![Version: 0.0.0](https://img.shields.io/badge/Version-0.0.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: v0.0.0](https://img.shields.io/badge/AppVersion-v0.0.0-informational?style=flat-square) + +MetalLB CRDs + +**Homepage:** + +## Source Code + +* + +---------------------------------------------- +Autogenerated from chart metadata using [helm-docs v1.10.0](https://github.com/norwoodj/helm-docs/releases/v1.10.0) diff --git a/packages/system/metallb/charts/metallb/charts/crds/templates/crds.yaml b/packages/system/metallb/charts/metallb/charts/crds/templates/crds.yaml new file mode 100644 index 00000000..9b415acf --- /dev/null +++ b/packages/system/metallb/charts/metallb/charts/crds/templates/crds.yaml @@ -0,0 +1,1233 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.7.0 + creationTimestamp: null + name: addresspools.metallb.io +spec: + group: metallb.io + names: + kind: AddressPool + listKind: AddressPoolList + plural: addresspools + singular: addresspool + scope: Namespaced + conversion: + strategy: Webhook + webhook: + conversionReviewVersions: ["v1alpha1", "v1beta1"] + clientConfig: + # this is a valid pem format, otherwise the apiserver will reject the deletion of the crds + # with "unable to parse bytes as PEM block", The controller will patch it with the right content after it starts + caBundle: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQpNSUlGWlRDQ0EwMmdBd0lCQWdJVU5GRW1XcTM3MVpKdGkrMmlSQzk1WmpBV1MxZ3dEUVlKS29aSWh2Y05BUUVMDQpCUUF3UWpFTE1Ba0dBMVVFQmhNQ1dGZ3hGVEFUQmdOVkJBY01ERVJsWm1GMWJIUWdRMmwwZVRFY01Cb0dBMVVFDQpDZ3dUUkdWbVlYVnNkQ0JEYjIxd1lXNTVJRXgwWkRBZUZ3MHlNakEzTVRrd09UTXlNek5hRncweU1qQTRNVGd3DQpPVE15TXpOYU1FSXhDekFKQmdOVkJBWVRBbGhZTVJVd0V3WURWUVFIREF4RVpXWmhkV3gwSUVOcGRIa3hIREFhDQpCZ05WQkFvTUUwUmxabUYxYkhRZ1EyOXRjR0Z1ZVNCTWRHUXdnZ0lpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElDDQpEd0F3Z2dJS0FvSUNBUUNxVFpxMWZRcC9vYkdlenhES0o3OVB3Ny94azJwellualNzMlkzb1ZYSm5sRmM4YjVlDQpma2ZZQnY2bndscW1keW5PL2phWFBaQmRQSS82aFdOUDBkdVhadEtWU0NCUUpyZzEyOGNXb3F0MGNTN3pLb1VpDQpvcU1tQ0QvRXVBeFFNZjhRZDF2c1gvVllkZ0poVTZBRXJLZEpIaXpFOUJtUkNkTDBGMW1OVW55Rk82UnRtWFZUDQpidkxsTDVYeTc2R0FaQVBLOFB4aVlDa0NtbDdxN0VnTWNiOXlLWldCYmlxQ3VkTXE5TGJLNmdKNzF6YkZnSXV4DQo1L1pXK2JraTB2RlplWk9ZODUxb1psckFUNzJvMDI4NHNTWW9uN0pHZVZkY3NoUnh5R1VpSFpSTzdkaXZVTDVTDQpmM2JmSDFYbWY1ZDQzT0NWTWRuUUV2NWVaOG8zeWVLa3ZrbkZQUGVJMU9BbjdGbDlFRVNNR2dhOGFaSG1URSttDQpsLzlMSmdDYjBnQmtPT0M0WnV4bWh2aERKV1EzWnJCS3pMQlNUZXN0NWlLNVlwcXRWVVk2THRyRW9FelVTK1lsDQpwWndXY2VQWHlHeHM5ZURsR3lNVmQraW15Y3NTU1UvVno2Mmx6MnZCS21NTXBkYldDQWhud0RsRTVqU2dyMjRRDQp0eGNXLys2N3d5KzhuQlI3UXdqVTFITndVRjBzeERWdEwrZ1NHVERnSEVZSlhZelYvT05zMy94TkpoVFNPSkxNDQpoeXNVdyttaGdackdhbUdXcHVIVU1DUitvTWJzMTc1UkcrQjJnUFFHVytPTjJnUTRyOXN2b0ZBNHBBQm8xd1dLDQpRYjRhY3pmeVVscElBOVFoSmFsZEY3S3dPSHVlV3gwRUNrNXg0T2tvVDBvWVp0dzFiR0JjRGtaSmF3SURBUUFCDQpvMU13VVRBZEJnTlZIUTRFRmdRVW90UlNIUm9IWTEyRFZ4R0NCdEhpb1g2ZmVFQXdId1lEVlIwakJCZ3dGb0FVDQpvdFJTSFJvSFkxMkRWeEdDQnRIaW9YNmZlRUF3RHdZRFZSMFRBUUgvQkFVd0F3RUIvekFOQmdrcWhraUc5dzBCDQpBUXNGQUFPQ0FnRUFSbkpsWWRjMTFHd0VxWnh6RDF2R3BDR2pDN2VWTlQ3aVY1d3IybXlybHdPYi9aUWFEa0xYDQpvVStaOVVXT1VlSXJTdzUydDdmQUpvVVAwSm5iYkMveVIrU1lqUGhvUXNiVHduOTc2ZldBWTduM3FMOXhCd1Y0DQphek41OXNjeUp0dlhMeUtOL2N5ak1ReDRLajBIMFg0bWJ6bzVZNUtzWWtYVU0vOEFPdWZMcEd0S1NGVGgrSEFDDQpab1Q5YnZHS25adnNHd0tYZFF0Wnh0akhaUjVqK3U3ZGtQOTJBT051RFNabS8rWVV4b2tBK09JbzdSR3BwSHNXDQo1ZTdNY0FTVXRtb1FORXd6dVFoVkJaRWQ1OGtKYjUrV0VWbGNzanlXNnRTbzErZ25tTWNqR1BsMWgxR2hVbjV4DQpFY0lWRnBIWXM5YWo1NmpBSjk1MVQvZjhMaWxmTlVnanBLQ0c1bnl0SUt3emxhOHNtdGlPdm1UNEpYbXBwSkI2DQo4bmdHRVluVjUrUTYwWFJ2OEhSSGp1VG9CRHVhaERrVDA2R1JGODU1d09FR2V4bkZpMXZYWUxLVllWb1V2MXRKDQo4dVdUR1pwNllDSVJldlBqbzg5ZytWTlJSaVFYUThJd0dybXE5c0RoVTlqTjA0SjdVL1RvRDFpNHE3VnlsRUc5DQorV1VGNkNLaEdBeTJIaEhwVncyTGFoOS9lUzdZMUZ1YURrWmhPZG1laG1BOCtqdHNZamJadnR5Mm1SWlF0UUZzDQpUU1VUUjREbUR2bVVPRVRmeStpRHdzK2RkWXVNTnJGeVVYV2dkMnpBQU4ydVl1UHFGY2pRcFNPODFzVTJTU3R3DQoxVzAyeUtYOGJEYmZFdjBzbUh3UzliQnFlSGo5NEM1Mjg0YXpsdTBmaUdpTm1OUEM4ckJLRmhBPQ0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ== + service: + namespace: {{ .Release.Namespace }} + name: metallb-webhook-service + path: /convert + versions: + - deprecated: true + deprecationWarning: metallb.io v1alpha1 AddressPool is deprecated + name: v1alpha1 + schema: + openAPIV3Schema: + description: AddressPool is the Schema for the addresspools 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: AddressPoolSpec defines the desired state of AddressPool. + properties: + addresses: + description: A list of IP address ranges over which MetalLB has authority. + You can list multiple ranges in a single pool, they will all share + the same settings. Each range can be either a CIDR prefix, or an + explicit start-end range of IPs. + items: + type: string + type: array + autoAssign: + default: true + description: AutoAssign flag used to prevent MetallB from automatic + allocation for a pool. + type: boolean + bgpAdvertisements: + description: When an IP is allocated from this pool, how should it + be translated into BGP announcements? + items: + properties: + aggregationLength: + default: 32 + description: The aggregation-length advertisement option lets + you “roll up” the /32s into a larger prefix. + format: int32 + minimum: 1 + type: integer + aggregationLengthV6: + default: 128 + description: Optional, defaults to 128 (i.e. no aggregation) + if not specified. + format: int32 + type: integer + communities: + description: BGP communities + items: + type: string + type: array + localPref: + description: BGP LOCAL_PREF attribute which is used by BGP best + path algorithm, Path with higher localpref is preferred over + one with lower localpref. + format: int32 + type: integer + type: object + type: array + protocol: + description: Protocol can be used to select how the announcement is + done. + enum: + - layer2 + - bgp + type: string + required: + - addresses + - protocol + type: object + status: + description: AddressPoolStatus defines the observed state of AddressPool. + type: object + required: + - spec + type: object + served: true + storage: false + subresources: + status: {} + - deprecated: true + deprecationWarning: metallb.io v1beta1 AddressPool is deprecated, consider using + IPAddressPool + name: v1beta1 + schema: + openAPIV3Schema: + description: AddressPool represents a pool of IP addresses that can be allocated + to LoadBalancer services. AddressPool is deprecated and being replaced by + IPAddressPool. + 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: AddressPoolSpec defines the desired state of AddressPool. + properties: + addresses: + description: A list of IP address ranges over which MetalLB has authority. + You can list multiple ranges in a single pool, they will all share + the same settings. Each range can be either a CIDR prefix, or an + explicit start-end range of IPs. + items: + type: string + type: array + autoAssign: + default: true + description: AutoAssign flag used to prevent MetallB from automatic + allocation for a pool. + type: boolean + bgpAdvertisements: + description: Drives how an IP allocated from this pool should translated + into BGP announcements. + items: + properties: + aggregationLength: + default: 32 + description: The aggregation-length advertisement option lets + you “roll up” the /32s into a larger prefix. + format: int32 + minimum: 1 + type: integer + aggregationLengthV6: + default: 128 + description: Optional, defaults to 128 (i.e. no aggregation) + if not specified. + format: int32 + type: integer + communities: + description: BGP communities to be associated with the given + advertisement. + items: + type: string + type: array + localPref: + description: BGP LOCAL_PREF attribute which is used by BGP best + path algorithm, Path with higher localpref is preferred over + one with lower localpref. + format: int32 + type: integer + type: object + type: array + protocol: + description: Protocol can be used to select how the announcement is + done. + enum: + - layer2 + - bgp + type: string + required: + - addresses + - protocol + type: object + status: + description: AddressPoolStatus defines the observed state of AddressPool. + type: object + required: + - spec + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.7.0 + creationTimestamp: null + name: bfdprofiles.metallb.io +spec: + group: metallb.io + names: + kind: BFDProfile + listKind: BFDProfileList + plural: bfdprofiles + singular: bfdprofile + scope: Namespaced + versions: + - name: v1beta1 + schema: + openAPIV3Schema: + description: BFDProfile represents the settings of the bfd session that can + be optionally associated with a BGP session. + 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: BFDProfileSpec defines the desired state of BFDProfile. + properties: + detectMultiplier: + description: Configures the detection multiplier to determine packet + loss. The remote transmission interval will be multiplied by this + value to determine the connection loss detection timer. + format: int32 + maximum: 255 + minimum: 2 + type: integer + echoInterval: + description: Configures the minimal echo receive transmission interval + that this system is capable of handling in milliseconds. Defaults + to 50ms + format: int32 + maximum: 60000 + minimum: 10 + type: integer + echoMode: + description: Enables or disables the echo transmission mode. This + mode is disabled by default, and not supported on multi hops setups. + type: boolean + minimumTtl: + description: 'For multi hop sessions only: configure the minimum expected + TTL for an incoming BFD control packet.' + format: int32 + maximum: 254 + minimum: 1 + type: integer + passiveMode: + description: 'Mark session as passive: a passive session will not + attempt to start the connection and will wait for control packets + from peer before it begins replying.' + type: boolean + receiveInterval: + description: The minimum interval that this system is capable of receiving + control packets in milliseconds. Defaults to 300ms. + format: int32 + maximum: 60000 + minimum: 10 + type: integer + transmitInterval: + description: The minimum transmission interval (less jitter) that + this system wants to use to send BFD control packets in milliseconds. + Defaults to 300ms + format: int32 + maximum: 60000 + minimum: 10 + type: integer + type: object + status: + description: BFDProfileStatus defines the observed state of BFDProfile. + type: object + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.7.0 + creationTimestamp: null + name: bgpadvertisements.metallb.io +spec: + group: metallb.io + names: + kind: BGPAdvertisement + listKind: BGPAdvertisementList + plural: bgpadvertisements + singular: bgpadvertisement + scope: Namespaced + versions: + - name: v1beta1 + schema: + openAPIV3Schema: + description: BGPAdvertisement allows to advertise the IPs coming from the + selected IPAddressPools via BGP, setting the parameters of the BGP Advertisement. + 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: BGPAdvertisementSpec defines the desired state of BGPAdvertisement. + properties: + aggregationLength: + default: 32 + description: The aggregation-length advertisement option lets you + “roll up” the /32s into a larger prefix. Defaults to 32. Works for + IPv4 addresses. + format: int32 + minimum: 1 + type: integer + aggregationLengthV6: + default: 128 + description: The aggregation-length advertisement option lets you + “roll up” the /128s into a larger prefix. Defaults to 128. Works + for IPv6 addresses. + format: int32 + type: integer + communities: + description: The BGP communities to be associated with the announcement. + Each item can be a community of the form 1234:1234 or the name of + an alias defined in the Community CRD. + items: + type: string + type: array + ipAddressPoolSelectors: + description: A selector for the IPAddressPools which would get advertised + via this advertisement. If no IPAddressPool is selected by this + or by the list, the advertisement is applied to all the IPAddressPools. + items: + description: A label selector is a label query over a set of resources. + The result of matchLabels and matchExpressions are ANDed. An empty + label selector matches all objects. A null label selector matches + no objects. + 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 + required: + - key + - operator + type: object + type: array + 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 + type: array + ipAddressPools: + description: The list of IPAddressPools to advertise via this advertisement, + selected by name. + items: + type: string + type: array + localPref: + description: The BGP LOCAL_PREF attribute which is used by BGP best + path algorithm, Path with higher localpref is preferred over one + with lower localpref. + format: int32 + type: integer + nodeSelectors: + description: NodeSelectors allows to limit the nodes to announce as + next hops for the LoadBalancer IP. When empty, all the nodes having are + announced as next hops. + items: + description: A label selector is a label query over a set of resources. + The result of matchLabels and matchExpressions are ANDed. An empty + label selector matches all objects. A null label selector matches + no objects. + 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 + required: + - key + - operator + type: object + type: array + 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 + type: array + peers: + description: Peers limits the bgppeer to advertise the ips of the + selected pools to. When empty, the loadbalancer IP is announced + to all the BGPPeers configured. + items: + type: string + type: array + type: object + status: + description: BGPAdvertisementStatus defines the observed state of BGPAdvertisement. + type: object + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.7.0 + creationTimestamp: null + name: bgppeers.metallb.io +spec: + group: metallb.io + names: + kind: BGPPeer + listKind: BGPPeerList + plural: bgppeers + singular: bgppeer + scope: Namespaced + conversion: + strategy: Webhook + webhook: + conversionReviewVersions: ["v1beta1", "v1beta2"] + clientConfig: + # this is a valid pem format, otherwise the apiserver will reject the deletion of the crds + # with "unable to parse bytes as PEM block", The controller will patch it with the right content after it starts + caBundle: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQpNSUlGWlRDQ0EwMmdBd0lCQWdJVU5GRW1XcTM3MVpKdGkrMmlSQzk1WmpBV1MxZ3dEUVlKS29aSWh2Y05BUUVMDQpCUUF3UWpFTE1Ba0dBMVVFQmhNQ1dGZ3hGVEFUQmdOVkJBY01ERVJsWm1GMWJIUWdRMmwwZVRFY01Cb0dBMVVFDQpDZ3dUUkdWbVlYVnNkQ0JEYjIxd1lXNTVJRXgwWkRBZUZ3MHlNakEzTVRrd09UTXlNek5hRncweU1qQTRNVGd3DQpPVE15TXpOYU1FSXhDekFKQmdOVkJBWVRBbGhZTVJVd0V3WURWUVFIREF4RVpXWmhkV3gwSUVOcGRIa3hIREFhDQpCZ05WQkFvTUUwUmxabUYxYkhRZ1EyOXRjR0Z1ZVNCTWRHUXdnZ0lpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElDDQpEd0F3Z2dJS0FvSUNBUUNxVFpxMWZRcC9vYkdlenhES0o3OVB3Ny94azJwellualNzMlkzb1ZYSm5sRmM4YjVlDQpma2ZZQnY2bndscW1keW5PL2phWFBaQmRQSS82aFdOUDBkdVhadEtWU0NCUUpyZzEyOGNXb3F0MGNTN3pLb1VpDQpvcU1tQ0QvRXVBeFFNZjhRZDF2c1gvVllkZ0poVTZBRXJLZEpIaXpFOUJtUkNkTDBGMW1OVW55Rk82UnRtWFZUDQpidkxsTDVYeTc2R0FaQVBLOFB4aVlDa0NtbDdxN0VnTWNiOXlLWldCYmlxQ3VkTXE5TGJLNmdKNzF6YkZnSXV4DQo1L1pXK2JraTB2RlplWk9ZODUxb1psckFUNzJvMDI4NHNTWW9uN0pHZVZkY3NoUnh5R1VpSFpSTzdkaXZVTDVTDQpmM2JmSDFYbWY1ZDQzT0NWTWRuUUV2NWVaOG8zeWVLa3ZrbkZQUGVJMU9BbjdGbDlFRVNNR2dhOGFaSG1URSttDQpsLzlMSmdDYjBnQmtPT0M0WnV4bWh2aERKV1EzWnJCS3pMQlNUZXN0NWlLNVlwcXRWVVk2THRyRW9FelVTK1lsDQpwWndXY2VQWHlHeHM5ZURsR3lNVmQraW15Y3NTU1UvVno2Mmx6MnZCS21NTXBkYldDQWhud0RsRTVqU2dyMjRRDQp0eGNXLys2N3d5KzhuQlI3UXdqVTFITndVRjBzeERWdEwrZ1NHVERnSEVZSlhZelYvT05zMy94TkpoVFNPSkxNDQpoeXNVdyttaGdackdhbUdXcHVIVU1DUitvTWJzMTc1UkcrQjJnUFFHVytPTjJnUTRyOXN2b0ZBNHBBQm8xd1dLDQpRYjRhY3pmeVVscElBOVFoSmFsZEY3S3dPSHVlV3gwRUNrNXg0T2tvVDBvWVp0dzFiR0JjRGtaSmF3SURBUUFCDQpvMU13VVRBZEJnTlZIUTRFRmdRVW90UlNIUm9IWTEyRFZ4R0NCdEhpb1g2ZmVFQXdId1lEVlIwakJCZ3dGb0FVDQpvdFJTSFJvSFkxMkRWeEdDQnRIaW9YNmZlRUF3RHdZRFZSMFRBUUgvQkFVd0F3RUIvekFOQmdrcWhraUc5dzBCDQpBUXNGQUFPQ0FnRUFSbkpsWWRjMTFHd0VxWnh6RDF2R3BDR2pDN2VWTlQ3aVY1d3IybXlybHdPYi9aUWFEa0xYDQpvVStaOVVXT1VlSXJTdzUydDdmQUpvVVAwSm5iYkMveVIrU1lqUGhvUXNiVHduOTc2ZldBWTduM3FMOXhCd1Y0DQphek41OXNjeUp0dlhMeUtOL2N5ak1ReDRLajBIMFg0bWJ6bzVZNUtzWWtYVU0vOEFPdWZMcEd0S1NGVGgrSEFDDQpab1Q5YnZHS25adnNHd0tYZFF0Wnh0akhaUjVqK3U3ZGtQOTJBT051RFNabS8rWVV4b2tBK09JbzdSR3BwSHNXDQo1ZTdNY0FTVXRtb1FORXd6dVFoVkJaRWQ1OGtKYjUrV0VWbGNzanlXNnRTbzErZ25tTWNqR1BsMWgxR2hVbjV4DQpFY0lWRnBIWXM5YWo1NmpBSjk1MVQvZjhMaWxmTlVnanBLQ0c1bnl0SUt3emxhOHNtdGlPdm1UNEpYbXBwSkI2DQo4bmdHRVluVjUrUTYwWFJ2OEhSSGp1VG9CRHVhaERrVDA2R1JGODU1d09FR2V4bkZpMXZYWUxLVllWb1V2MXRKDQo4dVdUR1pwNllDSVJldlBqbzg5ZytWTlJSaVFYUThJd0dybXE5c0RoVTlqTjA0SjdVL1RvRDFpNHE3VnlsRUc5DQorV1VGNkNLaEdBeTJIaEhwVncyTGFoOS9lUzdZMUZ1YURrWmhPZG1laG1BOCtqdHNZamJadnR5Mm1SWlF0UUZzDQpUU1VUUjREbUR2bVVPRVRmeStpRHdzK2RkWXVNTnJGeVVYV2dkMnpBQU4ydVl1UHFGY2pRcFNPODFzVTJTU3R3DQoxVzAyeUtYOGJEYmZFdjBzbUh3UzliQnFlSGo5NEM1Mjg0YXpsdTBmaUdpTm1OUEM4ckJLRmhBPQ0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ== + service: + namespace: {{ .Release.Namespace }} + name: metallb-webhook-service + path: /convert + versions: + - name: v1beta1 + schema: + openAPIV3Schema: + description: BGPPeer is the Schema for the peers 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: BGPPeerSpec defines the desired state of Peer. + properties: + bfdProfile: + type: string + ebgpMultiHop: + description: EBGP peer is multi-hops away + type: boolean + holdTime: + description: Requested BGP hold time, per RFC4271. + type: string + keepaliveTime: + description: Requested BGP keepalive time, per RFC4271. + type: string + myASN: + description: AS number to use for the local end of the session. + format: int32 + maximum: 4294967295 + minimum: 0 + type: integer + nodeSelectors: + description: Only connect to this peer on nodes that match one of + these selectors. + items: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + minItems: 1 + type: array + required: + - key + - operator + - values + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + type: array + password: + description: Authentication password for routers enforcing TCP MD5 + authenticated sessions + type: string + peerASN: + description: AS number to expect from the remote end of the session. + format: int32 + maximum: 4294967295 + minimum: 0 + type: integer + peerAddress: + description: Address to dial when establishing the session. + type: string + peerPort: + description: Port to dial when establishing the session. + maximum: 16384 + minimum: 0 + type: integer + routerID: + description: BGP router ID to advertise to the peer + type: string + sourceAddress: + description: Source address to use when establishing the session. + type: string + required: + - myASN + - peerASN + - peerAddress + type: object + status: + description: BGPPeerStatus defines the observed state of Peer. + type: object + type: object + served: true + storage: false + subresources: + status: {} + - name: v1beta2 + schema: + openAPIV3Schema: + description: BGPPeer is the Schema for the peers 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: BGPPeerSpec defines the desired state of Peer. + properties: + bfdProfile: + description: The name of the BFD Profile to be used for the BFD session + associated to the BGP session. If not set, the BFD session won't + be set up. + type: string + ebgpMultiHop: + description: To set if the BGPPeer is multi-hops away. Needed for + FRR mode only. + type: boolean + holdTime: + description: Requested BGP hold time, per RFC4271. + type: string + keepaliveTime: + description: Requested BGP keepalive time, per RFC4271. + type: string + myASN: + description: AS number to use for the local end of the session. + format: int32 + maximum: 4294967295 + minimum: 0 + type: integer + nodeSelectors: + description: Only connect to this peer on nodes that match one of + these selectors. + items: + description: A label selector is a label query over a set of resources. + The result of matchLabels and matchExpressions are ANDed. An empty + label selector matches all objects. A null label selector matches + no objects. + 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 + required: + - key + - operator + type: object + type: array + 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 + type: array + password: + description: Authentication password for routers enforcing TCP MD5 + authenticated sessions + type: string + passwordSecret: + description: passwordSecret is name of the authentication secret for + BGP Peer. the secret must be of type "kubernetes.io/basic-auth", + and created in the same namespace as the MetalLB deployment. The + password is stored in the secret as the key "password". + properties: + name: + description: Name is unique within a namespace to reference a + secret resource. + type: string + namespace: + description: Namespace defines the space within which the secret + name must be unique. + type: string + type: object + peerASN: + description: AS number to expect from the remote end of the session. + format: int32 + maximum: 4294967295 + minimum: 0 + type: integer + peerAddress: + description: Address to dial when establishing the session. + type: string + peerPort: + default: 179 + description: Port to dial when establishing the session. + maximum: 16384 + minimum: 0 + type: integer + routerID: + description: BGP router ID to advertise to the peer + type: string + sourceAddress: + description: Source address to use when establishing the session. + type: string + vrf: + description: To set if we want to peer with the BGPPeer using an interface + belonging to a host vrf + type: string + required: + - myASN + - peerASN + - peerAddress + type: object + status: + description: BGPPeerStatus defines the observed state of Peer. + type: object + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] +--- + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.7.0 + creationTimestamp: null + name: ipaddresspools.metallb.io +spec: + group: metallb.io + names: + kind: IPAddressPool + listKind: IPAddressPoolList + plural: ipaddresspools + singular: ipaddresspool + scope: Namespaced + versions: + - name: v1beta1 + schema: + openAPIV3Schema: + description: IPAddressPool represents a pool of IP addresses that can be allocated + to LoadBalancer services. + 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: IPAddressPoolSpec defines the desired state of IPAddressPool. + properties: + addresses: + description: A list of IP address ranges over which MetalLB has authority. + You can list multiple ranges in a single pool, they will all share + the same settings. Each range can be either a CIDR prefix, or an + explicit start-end range of IPs. + items: + type: string + type: array + autoAssign: + default: true + description: AutoAssign flag used to prevent MetallB from automatic + allocation for a pool. + type: boolean + avoidBuggyIPs: + default: false + description: AvoidBuggyIPs prevents addresses ending with .0 and .255 + to be used by a pool. + type: boolean + serviceAllocation: + description: AllocateTo makes ip pool allocation to specific namespace + and/or service. The controller will use the pool with lowest value + of priority in case of multiple matches. A pool with no priority + set will be used only if the pools with priority can't be used. + If multiple matching IPAddressPools are available it will check + for the availability of IPs sorting the matching IPAddressPools + by priority, starting from the highest to the lowest. If multiple + IPAddressPools have the same priority, choice will be random. + properties: + namespaceSelectors: + description: NamespaceSelectors list of label selectors to select + namespace(s) for ip pool, an alternative to using namespace + list. + items: + description: A label selector is a label query over a set of + resources. The result of matchLabels and matchExpressions + are ANDed. An empty label selector matches all objects. A + null label selector matches no objects. + 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 + required: + - key + - operator + type: object + type: array + 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 + type: array + namespaces: + description: Namespaces list of namespace(s) on which ip pool + can be attached. + items: + type: string + type: array + priority: + description: Priority priority given for ip pool while ip allocation + on a service. + type: integer + serviceSelectors: + description: ServiceSelectors list of label selector to select + service(s) for which ip pool can be used for ip allocation. + items: + description: A label selector is a label query over a set of + resources. The result of matchLabels and matchExpressions + are ANDed. An empty label selector matches all objects. A + null label selector matches no objects. + 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 + required: + - key + - operator + type: object + type: array + 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 + type: array + type: object + required: + - addresses + type: object + status: + description: IPAddressPoolStatus defines the observed state of IPAddressPool. + type: object + required: + - spec + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.7.0 + creationTimestamp: null + name: l2advertisements.metallb.io +spec: + group: metallb.io + names: + kind: L2Advertisement + listKind: L2AdvertisementList + plural: l2advertisements + singular: l2advertisement + scope: Namespaced + versions: + - name: v1beta1 + schema: + openAPIV3Schema: + description: L2Advertisement allows to advertise the LoadBalancer IPs provided + by the selected pools via L2. + 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: L2AdvertisementSpec defines the desired state of L2Advertisement. + properties: + interfaces: + description: A list of interfaces to announce from. The LB IP will + be announced only from these interfaces. If the field is not set, + we advertise from all the interfaces on the host. + items: + type: string + type: array + ipAddressPoolSelectors: + description: A selector for the IPAddressPools which would get advertised + via this advertisement. If no IPAddressPool is selected by this + or by the list, the advertisement is applied to all the IPAddressPools. + items: + description: A label selector is a label query over a set of resources. + The result of matchLabels and matchExpressions are ANDed. An empty + label selector matches all objects. A null label selector matches + no objects. + 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 + required: + - key + - operator + type: object + type: array + 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 + type: array + ipAddressPools: + description: The list of IPAddressPools to advertise via this advertisement, + selected by name. + items: + type: string + type: array + nodeSelectors: + description: NodeSelectors allows to limit the nodes to announce as + next hops for the LoadBalancer IP. When empty, all the nodes having are + announced as next hops. + items: + description: A label selector is a label query over a set of resources. + The result of matchLabels and matchExpressions are ANDed. An empty + label selector matches all objects. A null label selector matches + no objects. + 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 + required: + - key + - operator + type: object + type: array + 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 + type: array + type: object + status: + description: L2AdvertisementStatus defines the observed state of L2Advertisement. + type: object + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.7.0 + creationTimestamp: null + name: communities.metallb.io +spec: + group: metallb.io + names: + kind: Community + listKind: CommunityList + plural: communities + singular: community + scope: Namespaced + versions: + - name: v1beta1 + schema: + openAPIV3Schema: + description: Community is a collection of aliases for communities. Users can + define named aliases to be used in the BGPPeer CRD. + 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: CommunitySpec defines the desired state of Community. + properties: + communities: + items: + properties: + name: + description: The name of the alias for the community. + type: string + value: + description: The BGP community value corresponding to the given + name. + type: string + type: object + type: array + type: object + status: + description: CommunityStatus defines the observed state of Community. + type: object + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/packages/system/metallb/charts/metallb/policy/controller.rego b/packages/system/metallb/charts/metallb/policy/controller.rego new file mode 100644 index 00000000..716eeb7a --- /dev/null +++ b/packages/system/metallb/charts/metallb/policy/controller.rego @@ -0,0 +1,16 @@ +package main + +# validate serviceAccountName +deny[msg] { + input.kind == "Deployment" + serviceAccountName := input.spec.template.spec.serviceAccountName + not serviceAccountName == "RELEASE-NAME-metallb-controller" + msg = sprintf("controller serviceAccountName '%s' does not match expected value", [serviceAccountName]) +} + +# validate node selector includes builtin when custom ones are provided +deny[msg] { + input.kind == "Deployment" + not input.spec.template.spec.nodeSelector["kubernetes.io/os"] == "linux" + msg = "controller nodeSelector does not include '\"kubernetes.io/os\": linux'" +} diff --git a/packages/system/metallb/charts/metallb/policy/rbac.rego b/packages/system/metallb/charts/metallb/policy/rbac.rego new file mode 100644 index 00000000..047345eb --- /dev/null +++ b/packages/system/metallb/charts/metallb/policy/rbac.rego @@ -0,0 +1,27 @@ +package main + +# Validate PSP exists in ClusterRole :controller +deny[msg] { + input.kind == "ClusterRole" + input.metadata.name == "metallb:controller" + input.rules[3] == { + "apiGroups": ["policy"], + "resources": ["podsecuritypolicies"], + "resourceNames": ["metallb-controller"], + "verbs": ["use"] + } + msg = "ClusterRole metallb:controller does not include PSP rule" +} + +# Validate PSP exists in ClusterRole :speaker +deny[msg] { + input.kind == "ClusterRole" + input.metadata.name == "metallb:speaker" + input.rules[3] == { + "apiGroups": ["policy"], + "resources": ["podsecuritypolicies"], + "resourceNames": ["metallb-controller"], + "verbs": ["use"] + } + msg = "ClusterRole metallb:speaker does not include PSP rule" +} diff --git a/packages/system/metallb/charts/metallb/policy/speaker.rego b/packages/system/metallb/charts/metallb/policy/speaker.rego new file mode 100644 index 00000000..d4d8137f --- /dev/null +++ b/packages/system/metallb/charts/metallb/policy/speaker.rego @@ -0,0 +1,30 @@ +package main + +# validate serviceAccountName +deny[msg] { + input.kind == "DaemonSet" + serviceAccountName := input.spec.template.spec.serviceAccountName + not serviceAccountName == "RELEASE-NAME-metallb-speaker" + msg = sprintf("speaker serviceAccountName '%s' does not match expected value", [serviceAccountName]) +} + +# validate METALLB_ML_SECRET_KEY (memberlist) +deny[msg] { + input.kind == "DaemonSet" + not input.spec.template.spec.containers[0].env[5].name == "METALLB_ML_SECRET_KEY_PATH" + msg = "speaker env does not contain METALLB_ML_SECRET_KEY_PATH at env[5]" +} + +# validate node selector includes builtin when custom ones are provided +deny[msg] { + input.kind == "DaemonSet" + not input.spec.template.spec.nodeSelector["kubernetes.io/os"] == "linux" + msg = "controller nodeSelector does not include '\"kubernetes.io/os\": linux'" +} + +# validate tolerations include the builtins when custom ones are provided +deny[msg] { + input.kind == "DaemonSet" + not input.spec.template.spec.tolerations[0] == { "key": "node-role.kubernetes.io/master", "effect": "NoSchedule", "operator": "Exists" } + msg = "controller tolerations does not include node-role.kubernetes.io/master:NoSchedule" +} diff --git a/packages/system/metallb/charts/metallb/templates/NOTES.txt b/packages/system/metallb/charts/metallb/templates/NOTES.txt new file mode 100644 index 00000000..23d1d5bc --- /dev/null +++ b/packages/system/metallb/charts/metallb/templates/NOTES.txt @@ -0,0 +1,4 @@ +MetalLB is now running in the cluster. + +Now you can configure it via its CRs. Please refer to the metallb official docs +on how to use the CRs. diff --git a/packages/system/metallb/charts/metallb/templates/_helpers.tpl b/packages/system/metallb/charts/metallb/templates/_helpers.tpl new file mode 100644 index 00000000..53d9528d --- /dev/null +++ b/packages/system/metallb/charts/metallb/templates/_helpers.tpl @@ -0,0 +1,113 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "metallb.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | 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 "metallb.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "metallb.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "metallb.labels" -}} +helm.sh/chart: {{ include "metallb.chart" . }} +{{ include "metallb.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "metallb.selectorLabels" -}} +app.kubernetes.io/name: {{ include "metallb.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the controller service account to use +*/}} +{{- define "metallb.controller.serviceAccountName" -}} +{{- if .Values.controller.serviceAccount.create }} +{{- default (printf "%s-controller" (include "metallb.fullname" .)) .Values.controller.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.controller.serviceAccount.name }} +{{- end }} +{{- end }} + +{{/* +Create the name of the speaker service account to use +*/}} +{{- define "metallb.speaker.serviceAccountName" -}} +{{- if .Values.speaker.serviceAccount.create }} +{{- default (printf "%s-speaker" (include "metallb.fullname" .)) .Values.speaker.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.speaker.serviceAccount.name }} +{{- end }} +{{- end }} + +{{/* +Create the name of the settings Secret to use. +*/}} +{{- define "metallb.secretName" -}} + {{ default ( printf "%s-memberlist" (include "metallb.fullname" .)) .Values.speaker.secretName | trunc 63 | trimSuffix "-" }} +{{- end -}} + +{{- define "metrics.exposedportname" -}} +{{- if .Values.prometheus.secureMetricsPort -}} +"metricshttps" +{{- else -}} +"metrics" +{{- end -}} +{{- end -}} + +{{- define "metrics.exposedfrrportname" -}} +{{- if .Values.speaker.frr.secureMetricsPort -}} +"frrmetricshttps" +{{- else -}} +"frrmetrics" +{{- end }} +{{- end }} + +{{- define "metrics.exposedport" -}} +{{- if .Values.prometheus.secureMetricsPort -}} +{{ .Values.prometheus.secureMetricsPort }} +{{- else -}} +{{ .Values.prometheus.metricsPort }} +{{- end -}} +{{- end }} + +{{- define "metrics.exposedfrrport" -}} +{{- if .Values.speaker.frr.secureMetricsPort -}} +{{ .Values.speaker.frr.secureMetricsPort }} +{{- else -}} +{{ .Values.speaker.frr.metricsPort }} +{{- end }} +{{- end }} diff --git a/packages/system/metallb/charts/metallb/templates/controller.yaml b/packages/system/metallb/charts/metallb/templates/controller.yaml new file mode 100644 index 00000000..5ba71891 --- /dev/null +++ b/packages/system/metallb/charts/metallb/templates/controller.yaml @@ -0,0 +1,181 @@ +{{- if .Values.controller.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ template "metallb.fullname" . }}-controller + labels: + {{- include "metallb.labels" . | nindent 4 }} + app.kubernetes.io/component: controller + {{- range $key, $value := .Values.controller.labels }} + {{ $key }}: {{ $value | quote }} + {{- end }} +spec: + {{- if .Values.controller.strategy }} + strategy: {{- toYaml .Values.controller.strategy | nindent 4 }} + {{- end }} + selector: + matchLabels: + {{- include "metallb.selectorLabels" . | nindent 6 }} + app.kubernetes.io/component: controller + template: + metadata: + {{- if or .Values.prometheus.scrapeAnnotations .Values.controller.podAnnotations }} + annotations: + {{- if .Values.prometheus.scrapeAnnotations }} + prometheus.io/scrape: "true" + prometheus.io/port: "{{ .Values.prometheus.metricsPort }}" + {{- end }} + {{- with .Values.controller.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- end }} + labels: + {{- include "metallb.selectorLabels" . | nindent 8 }} + app.kubernetes.io/component: controller + {{- range $key, $value := .Values.controller.labels }} + {{ $key }}: {{ $value | quote }} + {{- end }} + spec: + {{- with .Values.controller.runtimeClassName }} + runtimeClassName: {{ . | quote }} + {{- end }} + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ template "metallb.controller.serviceAccountName" . }} + terminationGracePeriodSeconds: 0 +{{- if .Values.controller.securityContext }} + securityContext: +{{ toYaml .Values.controller.securityContext | indent 8 }} +{{- end }} + containers: + - name: controller + image: {{ .Values.controller.image.repository }}:{{ .Values.controller.image.tag | default .Chart.AppVersion }} + {{- if .Values.controller.image.pullPolicy }} + imagePullPolicy: {{ .Values.controller.image.pullPolicy }} + {{- end }} + {{- if .Values.controller.command }} + command: + - {{ .Values.controller.command }} + {{- end }} + args: + - --port={{ .Values.prometheus.metricsPort }} + {{- with .Values.controller.logLevel }} + - --log-level={{ . }} + {{- end }} + - --cert-service-name=metallb-webhook-service + {{- if .Values.loadBalancerClass }} + - --lb-class={{ .Values.loadBalancerClass }} + {{- end }} + {{- if .Values.controller.webhookMode }} + - --webhook-mode={{ .Values.controller.webhookMode }} + {{- end }} + env: + {{- if and .Values.speaker.enabled .Values.speaker.memberlist.enabled }} + - name: METALLB_ML_SECRET_NAME + value: {{ include "metallb.secretName" . }} + - name: METALLB_DEPLOYMENT + value: {{ template "metallb.fullname" . }}-controller + {{- end }} + {{- if .Values.speaker.frr.enabled }} + - name: METALLB_BGP_TYPE + value: frr + {{- end }} + ports: + - name: monitoring + containerPort: {{ .Values.prometheus.metricsPort }} + - containerPort: 9443 + name: webhook-server + protocol: TCP + volumeMounts: + - mountPath: /tmp/k8s-webhook-server/serving-certs + name: cert + readOnly: true + {{- if .Values.controller.livenessProbe.enabled }} + livenessProbe: + httpGet: + path: /metrics + port: monitoring + initialDelaySeconds: {{ .Values.controller.livenessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.controller.livenessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.controller.livenessProbe.timeoutSeconds }} + successThreshold: {{ .Values.controller.livenessProbe.successThreshold }} + failureThreshold: {{ .Values.controller.livenessProbe.failureThreshold }} + {{- end }} + {{- if .Values.controller.readinessProbe.enabled }} + readinessProbe: + httpGet: + path: /metrics + port: monitoring + initialDelaySeconds: {{ .Values.controller.readinessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.controller.readinessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.controller.readinessProbe.timeoutSeconds }} + successThreshold: {{ .Values.controller.readinessProbe.successThreshold }} + failureThreshold: {{ .Values.controller.readinessProbe.failureThreshold }} + {{- end }} + {{- with .Values.controller.resources }} + resources: + {{- toYaml . | nindent 10 }} + {{- end }} + securityContext: + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + capabilities: + drop: + - ALL + {{- if .Values.prometheus.secureMetricsPort }} + - name: kube-rbac-proxy + image: {{ .Values.prometheus.rbacProxy.repository }}:{{ .Values.prometheus.rbacProxy.tag }} + imagePullPolicy: {{ .Values.prometheus.rbacProxy.pullPolicy }} + args: + - --logtostderr + - --secure-listen-address=:{{ .Values.prometheus.secureMetricsPort }} + - --upstream=http://127.0.0.1:{{ .Values.prometheus.metricsPort }}/ + - --tls-cipher-suites=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_RSA_WITH_AES_128_CBC_SHA256,TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 + {{- if .Values.prometheus.controllerMetricsTLSSecret }} + - --tls-private-key-file=/etc/metrics/tls.key + - --tls-cert-file=/etc/metrics/tls.crt + {{- end }} + ports: + - containerPort: {{ .Values.prometheus.secureMetricsPort }} + name: metricshttps + resources: + requests: + cpu: 10m + memory: 20Mi + terminationMessagePolicy: FallbackToLogsOnError + {{- if .Values.prometheus.controllerMetricsTLSSecret }} + volumeMounts: + - name: metrics-certs + mountPath: /etc/metrics + readOnly: true + {{- end }} + {{ end }} + nodeSelector: + "kubernetes.io/os": linux + {{- with .Values.controller.nodeSelector }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.controller.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.controller.tolerations }} + tolerations: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.controller.priorityClassName }} + priorityClassName: {{ . | quote }} + {{- end }} + volumes: + - name: cert + secret: + defaultMode: 420 + secretName: webhook-server-cert + {{- if .Values.prometheus.controllerMetricsTLSSecret }} + - name: metrics-certs + secret: + secretName: {{ .Values.prometheus.controllerMetricsTLSSecret }} + {{- end }} +{{- end }} diff --git a/packages/system/metallb/charts/metallb/templates/deprecated_configInline.yaml b/packages/system/metallb/charts/metallb/templates/deprecated_configInline.yaml new file mode 100644 index 00000000..8a1a551c --- /dev/null +++ b/packages/system/metallb/charts/metallb/templates/deprecated_configInline.yaml @@ -0,0 +1,3 @@ +{{- if .Values.configInline }} +{{- fail "Starting from v0.13.0 configInline is no longer supported. Please see https://metallb.universe.tf/#backward-compatibility" }} +{{- end }} diff --git a/packages/system/metallb/charts/metallb/templates/exclude-l2-config.yaml b/packages/system/metallb/charts/metallb/templates/exclude-l2-config.yaml new file mode 100644 index 00000000..7cc2ff34 --- /dev/null +++ b/packages/system/metallb/charts/metallb/templates/exclude-l2-config.yaml @@ -0,0 +1,22 @@ +{{- if .Values.speaker.excludeInterfaces.enabled }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: metallb-excludel2 +data: + excludel2.yaml: | + announcedInterfacesToExclude: + - docker.* + - cbr.* + - dummy.* + - virbr.* + - lxcbr.* + - veth.* + - lo + - ^cali.* + - ^tunl.* + - flannel.* + - kube-ipvs.* + - cni.* + - ^nodelocaldns.* +{{- end }} \ No newline at end of file diff --git a/packages/system/metallb/charts/metallb/templates/podmonitor.yaml b/packages/system/metallb/charts/metallb/templates/podmonitor.yaml new file mode 100644 index 00000000..93a7fd69 --- /dev/null +++ b/packages/system/metallb/charts/metallb/templates/podmonitor.yaml @@ -0,0 +1,106 @@ +{{- if .Values.prometheus.podMonitor.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: PodMonitor +metadata: + name: {{ template "metallb.fullname" . }}-controller + labels: + {{- include "metallb.labels" . | nindent 4 }} + app.kubernetes.io/component: controller + {{- if .Values.prometheus.podMonitor.additionalLabels }} +{{ toYaml .Values.prometheus.podMonitor.additionalLabels | indent 4 }} + {{- end }} + {{- if .Values.prometheus.podMonitor.annotations }} + annotations: +{{ toYaml .Values.prometheus.podMonitor.annotations | indent 4 }} + {{- end }} +spec: + jobLabel: {{ .Values.prometheus.podMonitor.jobLabel | quote }} + selector: + matchLabels: + {{- include "metallb.selectorLabels" . | nindent 6 }} + app.kubernetes.io/component: controller + namespaceSelector: + matchNames: + - {{ .Release.Namespace }} + podMetricsEndpoints: + - port: monitoring + path: /metrics + {{- if .Values.prometheus.podMonitor.interval }} + interval: {{ .Values.prometheus.podMonitor.interval }} + {{- end }} +{{- if .Values.prometheus.podMonitor.metricRelabelings }} + metricRelabelings: +{{- toYaml .Values.prometheus.podMonitor.metricRelabelings | nindent 4 }} +{{- end }} +{{- if .Values.prometheus.podMonitor.relabelings }} + relabelings: +{{- toYaml .Values.prometheus.podMonitor.relabelings | nindent 4 }} +{{- end }} +--- +apiVersion: monitoring.coreos.com/v1 +kind: PodMonitor +metadata: + name: {{ template "metallb.fullname" . }}-speaker + labels: + {{- include "metallb.labels" . | nindent 4 }} + app.kubernetes.io/component: speaker + {{- if .Values.prometheus.podMonitor.additionalLabels }} +{{ toYaml .Values.prometheus.podMonitor.additionalLabels | indent 4 }} + {{- end }} + {{- if .Values.prometheus.podMonitor.annotations }} + annotations: +{{ toYaml .Values.prometheus.podMonitor.annotations | indent 4 }} + {{- end }} +spec: + jobLabel: {{ .Values.prometheus.podMonitor.jobLabel | quote }} + selector: + matchLabels: + {{- include "metallb.selectorLabels" . | nindent 6 }} + app.kubernetes.io/component: speaker + namespaceSelector: + matchNames: + - {{ .Release.Namespace }} + podMetricsEndpoints: + - port: monitoring + path: /metrics + {{- if .Values.prometheus.podMonitor.interval }} + interval: {{ .Values.prometheus.podMonitor.interval }} + {{- end }} +{{- if .Values.prometheus.podMonitor.metricRelabelings }} + metricRelabelings: +{{- toYaml .Values.prometheus.podMonitor.metricRelabelings | nindent 4 }} +{{- end }} +{{- if .Values.prometheus.podMonitor.relabelings }} + relabelings: +{{- toYaml .Values.prometheus.podMonitor.relabelings | nindent 4 }} +{{- end }} +--- +{{- if .Values.prometheus.rbacPrometheus }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ template "metallb.fullname" . }}-prometheus +rules: + - apiGroups: + - "" + resources: + - pods + verbs: + - get + - list + - watch +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ template "metallb.fullname" . }}-prometheus +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ template "metallb.fullname" . }}-prometheus +subjects: + - kind: ServiceAccount + name: {{ required ".Values.prometheus.serviceAccount must be defined when .Values.prometheus.podMonitor.enabled == true" .Values.prometheus.serviceAccount }} + namespace: {{ required ".Values.prometheus.namespace must be defined when .Values.prometheus.podMonitor.enabled == true" .Values.prometheus.namespace }} +{{- end }} +{{- end }} diff --git a/packages/system/metallb/charts/metallb/templates/prometheusrules.yaml b/packages/system/metallb/charts/metallb/templates/prometheusrules.yaml new file mode 100644 index 00000000..463aacaf --- /dev/null +++ b/packages/system/metallb/charts/metallb/templates/prometheusrules.yaml @@ -0,0 +1,84 @@ +{{- if .Values.prometheus.prometheusRule.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: PrometheusRule +metadata: + name: {{ template "metallb.fullname" . }} + labels: + {{- include "metallb.labels" . | nindent 4 }} + {{- if .Values.prometheus.prometheusRule.additionalLabels }} +{{ toYaml .Values.prometheus.prometheusRule.additionalLabels | indent 4 }} + {{- end }} + {{- if .Values.prometheus.prometheusRule.annotations }} + annotations: +{{ toYaml .Values.prometheus.prometheusRule.annotations | indent 4 }} + {{- end }} +spec: + groups: + - name: {{ template "metallb.fullname" . }}.rules + rules: + {{- if .Values.prometheus.prometheusRule.staleConfig.enabled }} + - alert: MetalLBStaleConfig + annotations: + message: {{`'{{ $labels.job }} - MetalLB {{ $labels.container }} on {{ $labels.pod + }} has a stale config for > 1 minute'`}} + expr: metallb_k8s_client_config_stale_bool{job="{{ include "metallb.name" . }}"} == 1 + for: 1m + {{- with .Values.prometheus.prometheusRule.staleConfig.labels }} + labels: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- end }} + {{- if .Values.prometheus.prometheusRule.configNotLoaded.enabled }} + - alert: MetalLBConfigNotLoaded + annotations: + message: {{`'{{ $labels.job }} - MetalLB {{ $labels.container }} on {{ $labels.pod + }} has not loaded for > 1 minute'`}} + expr: metallb_k8s_client_config_loaded_bool{job="{{ include "metallb.name" . }}"} == 0 + for: 1m + {{- with .Values.prometheus.prometheusRule.configNotLoaded.labels }} + labels: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- end }} + {{- if .Values.prometheus.prometheusRule.addressPoolExhausted.enabled }} + - alert: MetalLBAddressPoolExhausted + annotations: + message: {{`'{{ $labels.job }} - MetalLB {{ $labels.container }} on {{ $labels.pod + }} has exhausted address pool {{ $labels.pool }} for > 1 minute'`}} + expr: metallb_allocator_addresses_in_use_total >= on(pool) metallb_allocator_addresses_total + for: 1m + {{- with .Values.prometheus.prometheusRule.addressPoolExhausted.labels }} + labels: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- end }} + + {{- if .Values.prometheus.prometheusRule.addressPoolUsage.enabled }} + {{- range .Values.prometheus.prometheusRule.addressPoolUsage.thresholds }} + - alert: MetalLBAddressPoolUsage{{ .percent }}Percent + annotations: + message: {{`'{{ $labels.job }} - MetalLB {{ $labels.container }} on {{ $labels.pod + }} has address pool {{ $labels.pool }} past `}}{{ .percent }}{{`% usage for > 1 minute'`}} + expr: ( metallb_allocator_addresses_in_use_total / on(pool) metallb_allocator_addresses_total ) * 100 > {{ .percent }} + {{- with .labels }} + labels: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- end }} + {{- end }} + {{- if .Values.prometheus.prometheusRule.bgpSessionDown.enabled }} + - alert: MetalLBBGPSessionDown + annotations: + message: {{`'{{ $labels.job }} - MetalLB {{ $labels.container }} on {{ $labels.pod + }} has BGP session {{ $labels.peer }} down for > 1 minute'`}} + expr: metallb_bgp_session_up{job="{{ include "metallb.name" . }}"} == 0 + for: 1m + {{- with .Values.prometheus.prometheusRule.bgpSessionDown.labels }} + labels: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- end }} + {{- with .Values.prometheus.prometheusRule.extraAlerts }} + {{- toYaml . | nindent 4 }} + {{- end}} +{{- end }} diff --git a/packages/system/metallb/charts/metallb/templates/rbac.yaml b/packages/system/metallb/charts/metallb/templates/rbac.yaml new file mode 100644 index 00000000..6a38304b --- /dev/null +++ b/packages/system/metallb/charts/metallb/templates/rbac.yaml @@ -0,0 +1,206 @@ +{{- if .Values.rbac.create -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ template "metallb.fullname" . }}:controller + labels: + {{- include "metallb.labels" . | nindent 4 }} +rules: +- apiGroups: [""] + resources: ["services", "namespaces"] + verbs: ["get", "list", "watch"] +- apiGroups: [""] + resources: ["nodes"] + verbs: ["list"] +- apiGroups: [""] + resources: ["services/status"] + verbs: ["update"] +- apiGroups: [""] + resources: ["events"] + verbs: ["create", "patch"] +- apiGroups: ["admissionregistration.k8s.io"] + resources: ["validatingwebhookconfigurations", "mutatingwebhookconfigurations"] + resourceNames: ["metallb-webhook-configuration"] + verbs: ["create", "delete", "get", "list", "patch", "update", "watch"] +- apiGroups: ["admissionregistration.k8s.io"] + resources: ["validatingwebhookconfigurations", "mutatingwebhookconfigurations"] + verbs: ["list", "watch"] +- apiGroups: ["apiextensions.k8s.io"] + resources: ["customresourcedefinitions"] + resourceNames: ["addresspools.metallb.io","bfdprofiles.metallb.io","bgpadvertisements.metallb.io", + "bgppeers.metallb.io","ipaddresspools.metallb.io","l2advertisements.metallb.io","communities.metallb.io"] + verbs: ["create", "delete", "get", "list", "patch", "update", "watch"] +- apiGroups: ["apiextensions.k8s.io"] + resources: ["customresourcedefinitions"] + verbs: ["list", "watch"] +{{- if .Values.prometheus.secureMetricsPort }} +- apiGroups: ["authentication.k8s.io"] + resources: ["tokenreviews"] + verbs: ["create"] +- apiGroups: ["authorization.k8s.io"] + resources: ["subjectaccessreviews"] + verbs: ["create"] +{{- end }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ template "metallb.fullname" . }}:speaker + labels: + {{- include "metallb.labels" . | nindent 4 }} +rules: +- apiGroups: [""] + resources: ["services", "endpoints", "nodes", "namespaces"] + verbs: ["get", "list", "watch"] +- apiGroups: ["discovery.k8s.io"] + resources: ["endpointslices"] + verbs: ["get", "list", "watch"] +- apiGroups: [""] + resources: ["events"] + verbs: ["create", "patch"] +{{- if .Values.prometheus.secureMetricsPort }} +- apiGroups: ["authentication.k8s.io"] + resources: ["tokenreviews"] + verbs: ["create"] +- apiGroups: ["authorization.k8s.io"] + resources: ["subjectaccessreviews"] + verbs: ["create"] +{{- end }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ include "metallb.fullname" . }}-pod-lister + labels: {{- include "metallb.labels" . | nindent 4 }} +rules: +- apiGroups: [""] + resources: ["pods"] + verbs: ["list"] +- apiGroups: [""] + resources: ["secrets"] + verbs: ["get", "list", "watch"] +- apiGroups: [""] + resources: ["configmaps"] + verbs: ["get", "list", "watch"] +- apiGroups: ["metallb.io"] + resources: ["addresspools"] + verbs: ["get", "list", "watch"] +- apiGroups: ["metallb.io"] + resources: ["bfdprofiles"] + verbs: ["get", "list", "watch"] +- apiGroups: ["metallb.io"] + resources: ["bgppeers"] + verbs: ["get", "list", "watch"] +- apiGroups: ["metallb.io"] + resources: ["l2advertisements"] + verbs: ["get", "list", "watch"] +- apiGroups: ["metallb.io"] + resources: ["bgpadvertisements"] + verbs: ["get", "list", "watch"] +- apiGroups: ["metallb.io"] + resources: ["ipaddresspools"] + verbs: ["get", "list", "watch"] +- apiGroups: ["metallb.io"] + resources: ["communities"] + verbs: ["get", "list", "watch"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ include "metallb.fullname" . }}-controller + labels: {{- include "metallb.labels" . | nindent 4 }} +rules: +{{- if .Values.speaker.memberlist.enabled }} +- apiGroups: [""] + resources: ["secrets"] + verbs: ["create", "get", "list", "watch"] +- apiGroups: [""] + resources: ["secrets"] + resourceNames: [{{ include "metallb.secretName" . | quote }}] + verbs: ["list"] +- apiGroups: ["apps"] + resources: ["deployments"] + resourceNames: ["{{ template "metallb.fullname" . }}-controller"] + verbs: ["get"] +{{- end }} +- apiGroups: [""] + resources: ["secrets"] + verbs: ["create", "delete", "get", "list", "patch", "update", "watch"] +- apiGroups: ["metallb.io"] + resources: ["addresspools"] + verbs: ["get", "list", "watch"] +- apiGroups: ["metallb.io"] + resources: ["ipaddresspools"] + verbs: ["get", "list", "watch"] +- apiGroups: ["metallb.io"] + resources: ["bgppeers"] + verbs: ["get", "list"] +- apiGroups: ["metallb.io"] + resources: ["bgpadvertisements"] + verbs: ["get", "list"] +- apiGroups: ["metallb.io"] + resources: ["l2advertisements"] + verbs: ["get", "list"] +- apiGroups: ["metallb.io"] + resources: ["communities"] + verbs: ["get", "list","watch"] +- apiGroups: ["metallb.io"] + resources: ["bfdprofiles"] + verbs: ["get", "list","watch"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ template "metallb.fullname" . }}:controller + labels: + {{- include "metallb.labels" . | nindent 4 }} +subjects: +- kind: ServiceAccount + name: {{ template "metallb.controller.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ template "metallb.fullname" . }}:controller +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ template "metallb.fullname" . }}:speaker + labels: + {{- include "metallb.labels" . | nindent 4 }} +subjects: +- kind: ServiceAccount + name: {{ template "metallb.speaker.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ template "metallb.fullname" . }}:speaker +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ include "metallb.fullname" . }}-pod-lister + labels: {{- include "metallb.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ include "metallb.fullname" . }}-pod-lister +subjects: +- kind: ServiceAccount + name: {{ include "metallb.speaker.serviceAccountName" . }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ include "metallb.fullname" . }}-controller + labels: {{- include "metallb.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ include "metallb.fullname" . }}-controller +subjects: +- kind: ServiceAccount + name: {{ include "metallb.controller.serviceAccountName" . }} +{{- end -}} diff --git a/packages/system/metallb/charts/metallb/templates/service-accounts.yaml b/packages/system/metallb/charts/metallb/templates/service-accounts.yaml new file mode 100644 index 00000000..95609e5e --- /dev/null +++ b/packages/system/metallb/charts/metallb/templates/service-accounts.yaml @@ -0,0 +1,28 @@ +{{- if .Values.controller.serviceAccount.create }} +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ template "metallb.controller.serviceAccountName" . }} + labels: + {{- include "metallb.labels" . | nindent 4 }} + app.kubernetes.io/component: controller + {{- with .Values.controller.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} +{{- if .Values.speaker.serviceAccount.create }} +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ template "metallb.speaker.serviceAccountName" . }} + labels: + {{- include "metallb.labels" . | nindent 4 }} + app.kubernetes.io/component: speaker + {{- with .Values.speaker.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/packages/system/metallb/charts/metallb/templates/servicemonitor.yaml b/packages/system/metallb/charts/metallb/templates/servicemonitor.yaml new file mode 100644 index 00000000..1d8563d2 --- /dev/null +++ b/packages/system/metallb/charts/metallb/templates/servicemonitor.yaml @@ -0,0 +1,188 @@ +{{- if .Values.prometheus.serviceMonitor.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ template "metallb.fullname" . }}-speaker-monitor + labels: + {{- include "metallb.labels" . | nindent 4 }} + app.kubernetes.io/component: speaker + {{- if .Values.prometheus.serviceMonitor.speaker.additionalLabels }} +{{ toYaml .Values.prometheus.serviceMonitor.speaker.additionalLabels | indent 4 }} + {{- end }} + {{- if .Values.prometheus.serviceMonitor.speaker.annotations }} + annotations: +{{ toYaml .Values.prometheus.serviceMonitor.speaker.annotations | indent 4 }} + {{- end }} +spec: + endpoints: + - port: {{ template "metrics.exposedportname" . }} + honorLabels: true + {{- if .Values.prometheus.serviceMonitor.metricRelabelings }} + metricRelabelings: + {{- toYaml .Values.prometheus.serviceMonitor.metricRelabelings | nindent 8 }} + {{- end -}} + {{- if .Values.prometheus.serviceMonitor.relabelings }} + relabelings: + {{- toYaml .Values.prometheus.serviceMonitor.relabelings | nindent 8 }} + {{- end }} + {{- if .Values.prometheus.serviceMonitor.interval }} + interval: {{ .Values.prometheus.serviceMonitor.interval }} + {{- end -}} +{{ if .Values.prometheus.secureMetricsPort }} + bearerTokenFile: "/var/run/secrets/kubernetes.io/serviceaccount/token" + scheme: "https" +{{- if .Values.prometheus.serviceMonitor.speaker.tlsConfig }} + tlsConfig: +{{ toYaml .Values.prometheus.serviceMonitor.speaker.tlsConfig | indent 8 }} +{{- end }} +{{ end }} +{{- if .Values.speaker.frr.enabled }} + - port: {{ template "metrics.exposedfrrportname" . }} + honorLabels: true +{{ if .Values.speaker.frr.secureMetricsPort }} + {{- if .Values.prometheus.serviceMonitor.interval }} + interval: {{ .Values.prometheus.serviceMonitor.interval }} + {{- end }} + bearerTokenFile: "/var/run/secrets/kubernetes.io/serviceaccount/token" + scheme: "https" +{{- if .Values.prometheus.serviceMonitor.speaker.tlsConfig }} + tlsConfig: +{{ toYaml .Values.prometheus.serviceMonitor.speaker.tlsConfig | indent 8 }} +{{- end }} +{{- end }} +{{- end }} + jobLabel: {{ .Values.prometheus.serviceMonitor.jobLabel | quote }} + namespaceSelector: + matchNames: + - {{ .Release.Namespace }} + selector: + matchLabels: + name: {{ template "metallb.fullname" . }}-speaker-monitor-service +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/scrape: "true" + {{- if .Values.prometheus.serviceMonitor.speaker.annotations }} +{{ toYaml .Values.prometheus.serviceMonitor.speaker.annotations | indent 4 }} + {{- end }} + labels: + name: {{ template "metallb.fullname" . }}-speaker-monitor-service + name: {{ template "metallb.fullname" . }}-speaker-monitor-service +spec: + selector: + {{- include "metallb.selectorLabels" . | nindent 4 }} + app.kubernetes.io/component: speaker + clusterIP: None + ports: + - name: {{ template "metrics.exposedportname" . }} + port: {{ template "metrics.exposedport" . }} + targetPort: {{ template "metrics.exposedport" . }} +{{- if .Values.speaker.frr.enabled }} + - name: {{ template "metrics.exposedfrrportname" . }} + port: {{ template "metrics.exposedfrrport" . }} + targetPort: {{ template "metrics.exposedfrrport" . }} +{{- end }} + sessionAffinity: None + type: ClusterIP +--- +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ template "metallb.fullname" . }}-controller-monitor + labels: + {{- include "metallb.labels" . | nindent 4 }} + app.kubernetes.io/component: speaker + {{- if .Values.prometheus.serviceMonitor.controller.additionalLabels }} +{{ toYaml .Values.prometheus.serviceMonitor.controller.additionalLabels | indent 4 }} + {{- end }} + {{- if .Values.prometheus.serviceMonitor.controller.annotations }} + annotations: +{{ toYaml .Values.prometheus.serviceMonitor.controller.annotations | indent 4 }} + {{- end }} +spec: + endpoints: + - port: {{ template "metrics.exposedportname" . }} + {{- if .Values.prometheus.serviceMonitor.metricRelabelings }} + metricRelabelings: + {{- toYaml .Values.prometheus.serviceMonitor.metricRelabelings | nindent 8 }} + {{- end -}} + {{- if .Values.prometheus.serviceMonitor.relabelings }} + relabelings: + {{- toYaml .Values.prometheus.serviceMonitor.relabelings | nindent 8 }} + {{- end }} + {{- if .Values.prometheus.serviceMonitor.interval }} + interval: {{ .Values.prometheus.serviceMonitor.interval }} + {{- end }} + honorLabels: true +{{- if .Values.prometheus.secureMetricsPort }} + bearerTokenFile: "/var/run/secrets/kubernetes.io/serviceaccount/token" + scheme: "https" +{{- if .Values.prometheus.serviceMonitor.controller.tlsConfig }} + tlsConfig: +{{ toYaml .Values.prometheus.serviceMonitor.controller.tlsConfig | indent 8 }} +{{- end }} +{{- end }} + jobLabel: {{ .Values.prometheus.serviceMonitor.jobLabel | quote }} + namespaceSelector: + matchNames: + - {{ .Release.Namespace }} + selector: + matchLabels: + name: {{ template "metallb.fullname" . }}-controller-monitor-service +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/scrape: "true" + {{- if .Values.prometheus.serviceMonitor.controller.annotations }} +{{ toYaml .Values.prometheus.serviceMonitor.controller.annotations | indent 4 }} + {{- end }} + labels: + name: {{ template "metallb.fullname" . }}-controller-monitor-service + name: {{ template "metallb.fullname" . }}-controller-monitor-service +spec: + selector: + {{- include "metallb.selectorLabels" . | nindent 4 }} + app.kubernetes.io/component: controller + clusterIP: None + ports: + - name: {{ template "metrics.exposedportname" . }} + port: {{ template "metrics.exposedport" . }} + targetPort: {{ template "metrics.exposedport" . }} + sessionAffinity: None + type: ClusterIP +--- +{{- if .Values.prometheus.rbacPrometheus }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ template "metallb.fullname" . }}-prometheus +rules: + - apiGroups: + - "" + resources: + - pods + - services + - endpoints + verbs: + - get + - list + - watch +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ template "metallb.fullname" . }}-prometheus +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ template "metallb.fullname" . }}-prometheus +subjects: + - kind: ServiceAccount + name: {{ required ".Values.prometheus.serviceAccount must be defined when .Values.prometheus.serviceMonitor.enabled == true" .Values.prometheus.serviceAccount }} + namespace: {{ required ".Values.prometheus.namespace must be defined when .Values.prometheus.serviceMonitor.enabled == true" .Values.prometheus.namespace }} +{{- end }} +{{- end }} diff --git a/packages/system/metallb/charts/metallb/templates/speaker.yaml b/packages/system/metallb/charts/metallb/templates/speaker.yaml new file mode 100644 index 00000000..4bbbfb1d --- /dev/null +++ b/packages/system/metallb/charts/metallb/templates/speaker.yaml @@ -0,0 +1,505 @@ +{{- if .Values.speaker.frr.enabled }} +# FRR expects to have these files owned by frr:frr on startup. +# Having them in a ConfigMap allows us to modify behaviors: for example enabling more daemons on startup. +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ template "metallb.fullname" . }}-frr-startup + labels: + {{- include "metallb.labels" . | nindent 4 }} + app.kubernetes.io/component: speaker +data: + daemons: | + # This file tells the frr package which daemons to start. + # + # Sample configurations for these daemons can be found in + # /usr/share/doc/frr/examples/. + # + # ATTENTION: + # + # When activating a daemon for the first time, a config file, even if it is + # empty, has to be present *and* be owned by the user and group "frr", else + # the daemon will not be started by /etc/init.d/frr. The permissions should + # be u=rw,g=r,o=. + # When using "vtysh" such a config file is also needed. It should be owned by + # group "frrvty" and set to ug=rw,o= though. Check /etc/pam.d/frr, too. + # + # The watchfrr and zebra daemons are always started. + # + bgpd=yes + ospfd=no + ospf6d=no + ripd=no + ripngd=no + isisd=no + pimd=no + ldpd=no + nhrpd=no + eigrpd=no + babeld=no + sharpd=no + pbrd=no + bfdd=yes + fabricd=no + vrrpd=no + + # + # If this option is set the /etc/init.d/frr script automatically loads + # the config via "vtysh -b" when the servers are started. + # Check /etc/pam.d/frr if you intend to use "vtysh"! + # + vtysh_enable=yes + zebra_options=" -A 127.0.0.1 -s 90000000" + bgpd_options=" -A 127.0.0.1 -p 0" + ospfd_options=" -A 127.0.0.1" + ospf6d_options=" -A ::1" + ripd_options=" -A 127.0.0.1" + ripngd_options=" -A ::1" + isisd_options=" -A 127.0.0.1" + pimd_options=" -A 127.0.0.1" + ldpd_options=" -A 127.0.0.1" + nhrpd_options=" -A 127.0.0.1" + eigrpd_options=" -A 127.0.0.1" + babeld_options=" -A 127.0.0.1" + sharpd_options=" -A 127.0.0.1" + pbrd_options=" -A 127.0.0.1" + staticd_options="-A 127.0.0.1" + bfdd_options=" -A 127.0.0.1" + fabricd_options="-A 127.0.0.1" + vrrpd_options=" -A 127.0.0.1" + + # configuration profile + # + #frr_profile="traditional" + #frr_profile="datacenter" + + # + # This is the maximum number of FD's that will be available. + # Upon startup this is read by the control files and ulimit + # is called. Uncomment and use a reasonable value for your + # setup if you are expecting a large number of peers in + # say BGP. + #MAX_FDS=1024 + + # The list of daemons to watch is automatically generated by the init script. + #watchfrr_options="" + + # for debugging purposes, you can specify a "wrap" command to start instead + # of starting the daemon directly, e.g. to use valgrind on ospfd: + # ospfd_wrap="/usr/bin/valgrind" + # or you can use "all_wrap" for all daemons, e.g. to use perf record: + # all_wrap="/usr/bin/perf record --call-graph -" + # the normal daemon command is added to this at the end. + vtysh.conf: |+ + service integrated-vtysh-config + frr.conf: |+ + ! This file gets overriden the first time the speaker renders a config. + ! So anything configured here is only temporary. + frr version 7.5.1 + frr defaults traditional + hostname Router + line vty + log file /etc/frr/frr.log informational +{{- end }} +--- +{{- if .Values.speaker.enabled }} +apiVersion: apps/v1 +kind: DaemonSet +metadata: + name: {{ template "metallb.fullname" . }}-speaker + labels: + {{- include "metallb.labels" . | nindent 4 }} + app.kubernetes.io/component: speaker + {{- range $key, $value := .Values.speaker.labels }} + {{ $key }}: {{ $value | quote }} + {{- end }} +spec: + {{- if .Values.speaker.updateStrategy }} + updateStrategy: {{- toYaml .Values.speaker.updateStrategy | nindent 4 }} + {{- end }} + selector: + matchLabels: + {{- include "metallb.selectorLabels" . | nindent 6 }} + app.kubernetes.io/component: speaker + template: + metadata: + {{- if or .Values.prometheus.scrapeAnnotations .Values.speaker.podAnnotations }} + annotations: + {{- if .Values.prometheus.scrapeAnnotations }} + prometheus.io/scrape: "true" + {{- if not .Values.speaker.frr.enabled }} + prometheus.io/port: "{{ .Values.prometheus.metricsPort }}" + {{- end }} + {{- end }} + {{- with .Values.speaker.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- end }} + labels: + {{- include "metallb.selectorLabels" . | nindent 8 }} + app.kubernetes.io/component: speaker + {{- range $key, $value := .Values.speaker.labels }} + {{ $key }}: {{ $value | quote }} + {{- end }} + spec: + {{- if .Values.speaker.runtimeClassName }} + runtimeClassName: {{ .Values.speaker.runtimeClassName }} + {{- end }} + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ template "metallb.speaker.serviceAccountName" . }} + terminationGracePeriodSeconds: 0 + hostNetwork: true + volumes: + {{- if .Values.speaker.memberlist.enabled }} + - name: memberlist + secret: + secretName: {{ include "metallb.secretName" . }} + defaultMode: 420 + {{- end }} + {{- if .Values.speaker.excludeInterfaces.enabled }} + - name: metallb-excludel2 + configMap: + defaultMode: 256 + name: metallb-excludel2 + {{- end }} + {{- if .Values.speaker.frr.enabled }} + - name: frr-sockets + emptyDir: {} + - name: frr-startup + configMap: + name: {{ template "metallb.fullname" . }}-frr-startup + - name: frr-conf + emptyDir: {} + - name: reloader + emptyDir: {} + - name: metrics + emptyDir: {} + {{- if .Values.prometheus.speakerMetricsTLSSecret }} + - name: metrics-certs + secret: + secretName: {{ .Values.prometheus.speakerMetricsTLSSecret }} + {{- end }} + initContainers: + # Copies the initial config files with the right permissions to the shared volume. + - name: cp-frr-files + image: {{ .Values.speaker.frr.image.repository }}:{{ .Values.speaker.frr.image.tag | default .Chart.AppVersion }} + securityContext: + runAsUser: 100 + runAsGroup: 101 + command: ["/bin/sh", "-c", "cp -rLf /tmp/frr/* /etc/frr/"] + volumeMounts: + - name: frr-startup + mountPath: /tmp/frr + - name: frr-conf + mountPath: /etc/frr + # Copies the reloader to the shared volume between the speaker and reloader. + - name: cp-reloader + image: {{ .Values.speaker.image.repository }}:{{ .Values.speaker.image.tag | default .Chart.AppVersion }} + command: ["/bin/sh", "-c", "cp -f /frr-reloader.sh /etc/frr_reloader/"] + volumeMounts: + - name: reloader + mountPath: /etc/frr_reloader + # Copies the metrics exporter + - name: cp-metrics + image: {{ .Values.speaker.image.repository }}:{{ .Values.speaker.image.tag | default .Chart.AppVersion }} + command: ["/bin/sh", "-c", "cp -f /frr-metrics /etc/frr_metrics/"] + volumeMounts: + - name: metrics + mountPath: /etc/frr_metrics + shareProcessNamespace: true + {{- end }} + containers: + - name: speaker + image: {{ .Values.speaker.image.repository }}:{{ .Values.speaker.image.tag | default .Chart.AppVersion }} + {{- if .Values.speaker.image.pullPolicy }} + imagePullPolicy: {{ .Values.speaker.image.pullPolicy }} + {{- end }} + {{- if .Values.speaker.command }} + command: + - {{ .Values.speaker.command }} + {{- end }} + args: + - --port={{ .Values.prometheus.metricsPort }} + {{- with .Values.speaker.logLevel }} + - --log-level={{ . }} + {{- end }} + {{- if .Values.loadBalancerClass }} + - --lb-class={{ .Values.loadBalancerClass }} + {{- end }} + env: + - name: METALLB_NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + - name: METALLB_HOST + valueFrom: + fieldRef: + fieldPath: status.hostIP + {{- if .Values.speaker.memberlist.enabled }} + - name: METALLB_ML_BIND_ADDR + valueFrom: + fieldRef: + fieldPath: status.podIP + - name: METALLB_ML_LABELS + value: "app.kubernetes.io/name={{ include "metallb.name" . }},app.kubernetes.io/component=speaker" + - name: METALLB_ML_BIND_PORT + value: "{{ .Values.speaker.memberlist.mlBindPort }}" + - name: METALLB_ML_SECRET_KEY_PATH + value: "{{ .Values.speaker.memberlist.mlSecretKeyPath }}" + {{- end }} + {{- if .Values.speaker.frr.enabled }} + - name: FRR_CONFIG_FILE + value: /etc/frr_reloader/frr.conf + - name: FRR_RELOADER_PID_FILE + value: /etc/frr_reloader/reloader.pid + - name: METALLB_BGP_TYPE + value: frr + {{- end }} + ports: + - name: monitoring + containerPort: {{ .Values.prometheus.metricsPort }} + {{- if .Values.speaker.memberlist.enabled }} + - name: memberlist-tcp + containerPort: {{ .Values.speaker.memberlist.mlBindPort }} + protocol: TCP + - name: memberlist-udp + containerPort: {{ .Values.speaker.memberlist.mlBindPort }} + protocol: UDP + {{- end }} + {{- if .Values.speaker.livenessProbe.enabled }} + livenessProbe: + httpGet: + path: /metrics + port: monitoring + initialDelaySeconds: {{ .Values.speaker.livenessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.speaker.livenessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.speaker.livenessProbe.timeoutSeconds }} + successThreshold: {{ .Values.speaker.livenessProbe.successThreshold }} + failureThreshold: {{ .Values.speaker.livenessProbe.failureThreshold }} + {{- end }} + {{- if .Values.speaker.readinessProbe.enabled }} + readinessProbe: + httpGet: + path: /metrics + port: monitoring + initialDelaySeconds: {{ .Values.speaker.readinessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.speaker.readinessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.speaker.readinessProbe.timeoutSeconds }} + successThreshold: {{ .Values.speaker.readinessProbe.successThreshold }} + failureThreshold: {{ .Values.speaker.readinessProbe.failureThreshold }} + {{- end }} + {{- with .Values.speaker.resources }} + resources: + {{- toYaml . | nindent 10 }} + {{- end }} + securityContext: + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + capabilities: + drop: + - ALL + add: + - NET_RAW + {{- if or .Values.speaker.frr.enabled .Values.speaker.memberlist.enabled .Values.speaker.excludeInterfaces.enabled }} + volumeMounts: + {{- if .Values.speaker.memberlist.enabled }} + - name: memberlist + mountPath: {{ .Values.speaker.memberlist.mlSecretKeyPath }} + {{- end }} + {{- if .Values.speaker.frr.enabled }} + - name: reloader + mountPath: /etc/frr_reloader + {{- end }} + {{- if .Values.speaker.excludeInterfaces.enabled }} + - name: metallb-excludel2 + mountPath: /etc/metallb + {{- end }} + {{- end }} + {{- if .Values.speaker.frr.enabled }} + - name: frr + securityContext: + capabilities: + add: + - NET_ADMIN + - NET_RAW + - SYS_ADMIN + - NET_BIND_SERVICE + image: {{ .Values.speaker.frr.image.repository }}:{{ .Values.speaker.frr.image.tag | default .Chart.AppVersion }} + {{- if .Values.speaker.frr.image.pullPolicy }} + imagePullPolicy: {{ .Values.speaker.frr.image.pullPolicy }} + {{- end }} + env: + - name: TINI_SUBREAPER + value: "true" + volumeMounts: + - name: frr-sockets + mountPath: /var/run/frr + - name: frr-conf + mountPath: /etc/frr + # The command is FRR's default entrypoint & waiting for the log file to appear and tailing it. + # If the log file isn't created in 60 seconds the tail fails and the container is restarted. + # This workaround is needed to have the frr logs as part of kubectl logs -c frr < speaker_pod_name >. + command: + - /bin/sh + - -c + - | + /sbin/tini -- /usr/lib/frr/docker-start & + attempts=0 + until [[ -f /etc/frr/frr.log || $attempts -eq 60 ]]; do + sleep 1 + attempts=$(( $attempts + 1 )) + done + tail -f /etc/frr/frr.log + {{- with .Values.speaker.frr.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- if .Values.speaker.livenessProbe.enabled }} + livenessProbe: + httpGet: + path: /livez + port: {{ .Values.speaker.frr.metricsPort }} + periodSeconds: {{ .Values.speaker.livenessProbe.periodSeconds }} + failureThreshold: {{ .Values.speaker.livenessProbe.failureThreshold }} + {{- end }} + {{- if .Values.speaker.startupProbe.enabled }} + startupProbe: + httpGet: + path: /livez + port: {{ .Values.speaker.frr.metricsPort }} + failureThreshold: {{ .Values.speaker.startupProbe.failureThreshold }} + periodSeconds: {{ .Values.speaker.startupProbe.periodSeconds }} + {{- end }} + - name: reloader + image: {{ .Values.speaker.frr.image.repository }}:{{ .Values.speaker.frr.image.tag | default .Chart.AppVersion }} + {{- if .Values.speaker.frr.image.pullPolicy }} + imagePullPolicy: {{ .Values.speaker.frr.image.pullPolicy }} + {{- end }} + command: ["/etc/frr_reloader/frr-reloader.sh"] + volumeMounts: + - name: frr-sockets + mountPath: /var/run/frr + - name: frr-conf + mountPath: /etc/frr + - name: reloader + mountPath: /etc/frr_reloader + {{- with .Values.speaker.reloader.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + - name: frr-metrics + image: {{ .Values.speaker.frr.image.repository }}:{{ .Values.speaker.frr.image.tag | default .Chart.AppVersion }} + command: ["/etc/frr_metrics/frr-metrics"] + args: + - --metrics-port={{ .Values.speaker.frr.metricsPort }} + ports: + - containerPort: {{ .Values.speaker.frr.metricsPort }} + name: monitoring + volumeMounts: + - name: frr-sockets + mountPath: /var/run/frr + - name: frr-conf + mountPath: /etc/frr + - name: metrics + mountPath: /etc/frr_metrics + {{- with .Values.speaker.frrMetrics.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- end }} + {{- if .Values.prometheus.secureMetricsPort }} + - name: kube-rbac-proxy + image: {{ .Values.prometheus.rbacProxy.repository }}:{{ .Values.prometheus.rbacProxy.tag }} + imagePullPolicy: {{ .Values.prometheus.rbacProxy.pullPolicy }} + args: + - --logtostderr + - --secure-listen-address=:{{ .Values.prometheus.secureMetricsPort }} + - --upstream=http://$(METALLB_HOST):{{ .Values.prometheus.metricsPort }}/ + - --tls-cipher-suites=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_RSA_WITH_AES_128_CBC_SHA256,TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 + {{- if .Values.prometheus.speakerMetricsTLSSecret }} + - --tls-private-key-file=/etc/metrics/tls.key + - --tls-cert-file=/etc/metrics/tls.crt + {{- end }} + ports: + - containerPort: {{ .Values.prometheus.secureMetricsPort }} + name: metricshttps + env: + - name: METALLB_HOST + valueFrom: + fieldRef: + fieldPath: status.hostIP + resources: + requests: + cpu: 10m + memory: 20Mi + terminationMessagePolicy: FallbackToLogsOnError + {{- if .Values.prometheus.speakerMetricsTLSSecret }} + volumeMounts: + - name: metrics-certs + mountPath: /etc/metrics + readOnly: true + {{- end }} + {{ end }} + {{- if .Values.speaker.frr.secureMetricsPort }} + - name: kube-rbac-proxy-frr + image: {{ .Values.prometheus.rbacProxy.repository }}:{{ .Values.prometheus.rbacProxy.tag | default .Chart.AppVersion }} + imagePullPolicy: {{ .Values.prometheus.rbacProxy.pullPolicy }} + args: + - --logtostderr + - --secure-listen-address=:{{ .Values.speaker.frr.secureMetricsPort }} + - --tls-cipher-suites=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_RSA_WITH_AES_128_CBC_SHA256,TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 + - --upstream=http://$(METALLB_HOST):{{ .Values.speaker.frr.metricsPort }}/ + {{- if .Values.prometheus.speakerMetricsTLSSecret }} + - --tls-private-key-file=/etc/metrics/tls.key + - --tls-cert-file=/etc/metrics/tls.crt + {{- end }} + ports: + - containerPort: {{ .Values.speaker.frr.secureMetricsPort }} + name: metricshttps + env: + - name: METALLB_HOST + valueFrom: + fieldRef: + fieldPath: status.hostIP + resources: + requests: + cpu: 10m + memory: 20Mi + terminationMessagePolicy: FallbackToLogsOnError + {{- if .Values.prometheus.speakerMetricsTLSSecret }} + volumeMounts: + - name: metrics-certs + mountPath: /etc/metrics + readOnly: true + {{- end }} + {{ end }} + nodeSelector: + "kubernetes.io/os": linux + {{- with .Values.speaker.nodeSelector }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.speaker.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if or .Values.speaker.tolerateMaster .Values.speaker.tolerations }} + tolerations: + {{- if .Values.speaker.tolerateMaster }} + - key: node-role.kubernetes.io/master + effect: NoSchedule + operator: Exists + - key: node-role.kubernetes.io/control-plane + effect: NoSchedule + operator: Exists + {{- end }} + {{- with .Values.speaker.tolerations }} + {{- toYaml . | nindent 6 }} + {{- end }} + {{- end }} + {{- with .Values.speaker.priorityClassName }} + priorityClassName: {{ . | quote }} + {{- end }} +{{- end }} diff --git a/packages/system/metallb/charts/metallb/templates/webhooks.yaml b/packages/system/metallb/charts/metallb/templates/webhooks.yaml new file mode 100644 index 00000000..3f3d5ed7 --- /dev/null +++ b/packages/system/metallb/charts/metallb/templates/webhooks.yaml @@ -0,0 +1,168 @@ +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingWebhookConfiguration +metadata: + name: metallb-webhook-configuration + labels: + {{- include "metallb.labels" . | nindent 4 }} +webhooks: +- admissionReviewVersions: + - v1 + clientConfig: + service: + name: metallb-webhook-service + namespace: {{ .Release.Namespace }} + path: /validate-metallb-io-v1beta1-addresspool + failurePolicy: {{ .Values.crds.validationFailurePolicy }} + name: addresspoolvalidationwebhook.metallb.io + rules: + - apiGroups: + - metallb.io + apiVersions: + - v1beta1 + operations: + - CREATE + - UPDATE + resources: + - addresspools + sideEffects: None +- admissionReviewVersions: + - v1 + clientConfig: + service: + name: metallb-webhook-service + namespace: {{ .Release.Namespace }} + path: /validate-metallb-io-v1beta2-bgppeer + failurePolicy: {{ .Values.crds.validationFailurePolicy }} + name: bgppeervalidationwebhook.metallb.io + rules: + - apiGroups: + - metallb.io + apiVersions: + - v1beta2 + operations: + - CREATE + - UPDATE + resources: + - bgppeers + sideEffects: None +- admissionReviewVersions: + - v1 + clientConfig: + service: + name: metallb-webhook-service + namespace: {{ .Release.Namespace }} + path: /validate-metallb-io-v1beta1-ipaddresspool + failurePolicy: {{ .Values.crds.validationFailurePolicy }} + name: ipaddresspoolvalidationwebhook.metallb.io + rules: + - apiGroups: + - metallb.io + apiVersions: + - v1beta1 + operations: + - CREATE + - UPDATE + resources: + - ipaddresspools + sideEffects: None +- admissionReviewVersions: + - v1 + clientConfig: + service: + name: metallb-webhook-service + namespace: {{ .Release.Namespace }} + path: /validate-metallb-io-v1beta1-bgpadvertisement + failurePolicy: {{ .Values.crds.validationFailurePolicy }} + name: bgpadvertisementvalidationwebhook.metallb.io + rules: + - apiGroups: + - metallb.io + apiVersions: + - v1beta1 + operations: + - CREATE + - UPDATE + resources: + - bgpadvertisements + sideEffects: None +- admissionReviewVersions: + - v1 + clientConfig: + service: + name: metallb-webhook-service + namespace: {{ .Release.Namespace }} + path: /validate-metallb-io-v1beta1-community + failurePolicy: {{ .Values.crds.validationFailurePolicy }} + name: communityvalidationwebhook.metallb.io + rules: + - apiGroups: + - metallb.io + apiVersions: + - v1beta1 + operations: + - CREATE + - UPDATE + resources: + - communities + sideEffects: None +- admissionReviewVersions: + - v1 + clientConfig: + service: + name: metallb-webhook-service + namespace: {{ .Release.Namespace }} + path: /validate-metallb-io-v1beta1-bfdprofile + failurePolicy: {{ .Values.crds.validationFailurePolicy }} + name: bfdprofilevalidationwebhook.metallb.io + rules: + - apiGroups: + - metallb.io + apiVersions: + - v1beta1 + operations: + - CREATE + - DELETE + resources: + - bfdprofiles + sideEffects: None +- admissionReviewVersions: + - v1 + clientConfig: + service: + name: metallb-webhook-service + namespace: {{ .Release.Namespace }} + path: /validate-metallb-io-v1beta1-l2advertisement + failurePolicy: {{ .Values.crds.validationFailurePolicy }} + name: l2advertisementvalidationwebhook.metallb.io + rules: + - apiGroups: + - metallb.io + apiVersions: + - v1beta1 + operations: + - CREATE + - UPDATE + resources: + - l2advertisements + sideEffects: None +--- +apiVersion: v1 +kind: Service +metadata: + name: metallb-webhook-service + labels: + {{- include "metallb.labels" . | nindent 4 }} +spec: + ports: + - port: 443 + targetPort: 9443 + selector: + {{- include "metallb.selectorLabels" . | nindent 4 }} + app.kubernetes.io/component: controller +--- +apiVersion: v1 +kind: Secret +metadata: + name: webhook-server-cert + labels: + {{- include "metallb.labels" . | nindent 4 }} diff --git a/packages/system/metallb/charts/metallb/values.schema.json b/packages/system/metallb/charts/metallb/values.schema.json new file mode 100644 index 00000000..5a92e56a --- /dev/null +++ b/packages/system/metallb/charts/metallb/values.schema.json @@ -0,0 +1,427 @@ +{ + "$schema": "https://json-schema.org/draft-07/schema#", + "title": "Values", + "type": "object", + "definitions": { + "prometheusAlert": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + }, + "labels": { + "type": "object", + "additionalProperties": { "type": "string" } + } + }, + "required": [ "enabled" ] + }, + "probe": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + }, + "failureThreshold": { + "type": "integer" + }, + "initialDelaySeconds": { + "type": "integer" + }, + "periodSeconds": { + "type": "integer" + }, + "successThreshold": { + "type": "integer" + }, + "timeoutSeconds": { + "type": "integer" + } + }, + "required": [ + "failureThreshold", + "initialDelaySeconds", + "periodSeconds", + "successThreshold", + "timeoutSeconds" + ] + }, + "component": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + }, + "logLevel": { + "type": "string", + "enum": [ "all", "debug", "info", "warn", "error", "none" ] + }, + "image": { + "type": "object", + "properties": { + "repository": { + "type": "string" + }, + "tag": { + "anyOf": [ + { "type": "string" }, + { "type": "null" } + ] + }, + "pullPolicy": { + "anyOf": [ + { + "type": "null" + }, + { + "type": "string", + "enum": [ "Always", "IfNotPresent", "Never" ] + } + ] + } + } + }, + "serviceAccount": { + "type": "object", + "properties": { + "create": { + "type": "boolean" + }, + "name": { + "type": "string" + }, + "annotations": { + "type": "object" + } + } + }, + "resources": { + "type": "object" + }, + "nodeSelector": { + "type": "object" + }, + "tolerations": { + "type": "array", + "items": { + "type": "object" + } + }, + "priorityClassName": { + "type":"string" + }, + "runtimeClassName": { + "type":"string" + }, + "affinity": { + "type": "object" + }, + "podAnnotations": { + "type": "object" + }, + "livenessProbe": { + "$ref": "#/definitions/probe" + }, + "readinessProbe": { + "$ref": "#/definitions/probe" + } + }, + "required": [ + "image", + "serviceAccount" + ] + } + }, + "properties": { + "imagePullSecrets": { + "description": "Secrets used for pulling images", + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + }, + "required": [ "name" ], + "additionalProperties": false + } + }, + "nameOverride": { + "description": "Override chart name", + "type": "string" + }, + "fullNameOverride": { + "description": "Override fully qualified app name", + "type": "string" + }, + "configInLine": { + "description": "MetalLB configuration", + "type": "object" + }, + "loadBalancerClass": { + "type":"string" + }, + "rbac": { + "description": "RBAC configuration", + "type": "object", + "properties": { + "create": { + "description": "Enable RBAC", + "type": "boolean" + } + } + }, + "prometheus": { + "description": "Prometheus monitoring config", + "type": "object", + "properties": { + "scrapeAnnotations": { "type": "boolean" }, + "metricsPort": { "type": "integer" }, + "secureMetricsPort": { "type": "integer" }, + "rbacPrometheus": { "type": "boolean" }, + "serviceAccount": { "type": "string" }, + "namespace": { "type": "string" }, + "rbacProxy": { + "description": "kube-rbac-proxy configuration", + "type": "object", + "properties": { + "repository": { "type": "string" }, + "tag": { "type": "string" } + } + }, + "podMonitor": { + "description": "Prometheus Operator PodMonitors", + "type": "object", + "properties": { + "enabled": { "type": "boolean" }, + "additionalMonitors": { "type": "object" }, + "jobLabel": { "type": "string" }, + "interval": { + "anyOf": [ + { "type": "integer" }, + { "type": "null" } + ] + }, + "metricRelabelings": { + "type": "array", + "items": { + "type": "object" + } + }, + "relabelings": { + "type": "array", + "items": { + "type": "object" + } + } + } + }, + "serviceMonitor": { + "description": "Prometheus Operator ServiceMonitors", + "type": "object", + "properties": { + "enabled": { "type": "boolean" }, + "jobLabel": { "type": "string" }, + "interval": { + "anyOf": [ + { "type": "integer" }, + { "type": "null" } + ] + }, + "metricRelabelings": { + "type": "array", + "items": { + "type": "object" + } + }, + "relabelings": { + "type": "array", + "items": { + "type": "object" + } + } + } + }, + "prometheusRule": { + "description": "Prometheus Operator alertmanager alerts", + "type": "object", + "properties": { + "enabled": { "type": "boolean" }, + "additionalMonitors": { "type": "object" }, + "staleConfig": { "$ref": "#/definitions/prometheusAlert" }, + "configNotLoaded": { "$ref": "#/definitions/prometheusAlert" }, + "addressPoolExhausted": { "$ref": "#/definitions/prometheusAlert" }, + "addressPoolUsage": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + }, + "thresholds": { + "type": "array", + "items": { + "type": "object", + "properties": { + "percent": { + "type": "integer", + "minimum": 0, + "maximum": 100 + }, + "labels": { + "type": "object", + "additionalProperties": { "type": "string" } + } + }, + "required": [ "percent" ] + } + } + }, + "required": [ "enabled" ] + }, + "bgpSessionDown": { "$ref": "#/definitions/prometheusAlert" }, + "extraAlerts": { + "type": "array", + "items": { + "type": "object" + } + } + }, + "required": [ + "enabled", + "staleConfig", + "configNotLoaded", + "addressPoolExhausted", + "addressPoolUsage", + "bgpSessionDown" + ] + } + }, + "required": [ "podMonitor", "prometheusRule" ] + }, + "speaker": { + "allOf": [ + { "$ref": "#/definitions/component" }, + { "description": "MetalLB Speaker", + "type": "object", + "properties": { + "tolerateMaster": { + "type": "boolean" + }, + "memberlist": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + }, + "mlBindPort": { + "type": "integer" + }, + "mlSecretKeyPath": { + "type": "string" + } + } + }, + "excludeInterfaces": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + } + } + }, + "updateStrategy": { + "type": "object", + "properties": { + "type": { + "type": "string" + } + }, + "required": [ "type" ] + }, + "runtimeClassName": { + "type": "string" + }, + "secretName": { + "type": "string" + }, + "frr": { + "description": "Install FRR container in speaker deployment", + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + }, + "image": { "$ref": "#/definitions/component/properties/image" }, + "metricsPort": { "type": "integer" }, + "secureMetricsPort": { "type": "integer" }, + "resources:": { "type": "object" } + }, + "required": [ "enabled" ] + }, + "command" : { + "type": "string" + }, + "reloader": { + "type": "object", + "properties": { + "resources": { "type": "object" } + } + }, + "frrMetrics": { + "type": "object", + "properties": { + "resources": { "type": "object" } + } + } + }, + "required": [ "tolerateMaster" ] + } + ] + }, + "crds": { + "description": "CRD configuration", + "type": "object", + "properties": { + "enabled": { + "description": "Enable CRDs", + "type": "boolean" + }, + "validationFailurePolicy": { + "description": "Failure policy to use with validating webhooks", + "type": "string", + "enum": [ "Ignore", "Fail" ] + } + } + } + }, + "controller": { + "allOf": [ + { "$ref": "#/definitions/component" }, + { "description": "MetalLB Controller", + "type": "object", + "properties": { + "strategy": { + "type": "object", + "properties": { + "type": { + "type": "string" + } + }, + "required": [ "type" ] + }, + "command" : { + "type": "string" + }, + "webhookMode" : { + "type": "string" + } + } + } + ] + }, + "required": [ + "controller", + "speaker" + ] +} diff --git a/packages/system/metallb/charts/metallb/values.yaml b/packages/system/metallb/charts/metallb/values.yaml new file mode 100644 index 00000000..a0b15818 --- /dev/null +++ b/packages/system/metallb/charts/metallb/values.yaml @@ -0,0 +1,342 @@ +# Default values for metallb. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +imagePullSecrets: [] +nameOverride: "" +fullnameOverride: "" +loadBalancerClass: "" + +# To configure MetalLB, you must specify ONE of the following two +# options. + +rbac: + # create specifies whether to install and use RBAC rules. + create: true + +prometheus: + # scrape annotations specifies whether to add Prometheus metric + # auto-collection annotations to pods. See + # https://github.com/prometheus/prometheus/blob/release-2.1/documentation/examples/prometheus-kubernetes.yml + # for a corresponding Prometheus configuration. Alternatively, you + # may want to use the Prometheus Operator + # (https://github.com/coreos/prometheus-operator) for more powerful + # monitoring configuration. If you use the Prometheus operator, this + # can be left at false. + scrapeAnnotations: false + + # port both controller and speaker will listen on for metrics + metricsPort: 7472 + + # if set, enables rbac proxy on the controller and speaker to expose + # the metrics via tls. + # secureMetricsPort: 9120 + + # the name of the secret to be mounted in the speaker pod + # to expose the metrics securely. If not present, a self signed + # certificate to be used. + speakerMetricsTLSSecret: "" + + # the name of the secret to be mounted in the controller pod + # to expose the metrics securely. If not present, a self signed + # certificate to be used. + controllerMetricsTLSSecret: "" + + # prometheus doens't have the permission to scrape all namespaces so we give it permission to scrape metallb's one + rbacPrometheus: true + + # the service account used by prometheus + # required when " .Values.prometheus.rbacPrometheus == true " and " .Values.prometheus.podMonitor.enabled=true or prometheus.serviceMonitor.enabled=true " + serviceAccount: "" + + # the namespace where prometheus is deployed + # required when " .Values.prometheus.rbacPrometheus == true " and " .Values.prometheus.podMonitor.enabled=true or prometheus.serviceMonitor.enabled=true " + namespace: "" + + # the image to be used for the kuberbacproxy container + rbacProxy: + repository: gcr.io/kubebuilder/kube-rbac-proxy + tag: v0.12.0 + pullPolicy: + + # Prometheus Operator PodMonitors + podMonitor: + # enable support for Prometheus Operator + enabled: false + + # optional additionnal labels for podMonitors + additionalLabels: {} + + # optional annotations for podMonitors + annotations: {} + + # Job label for scrape target + jobLabel: "app.kubernetes.io/name" + + # Scrape interval. If not set, the Prometheus default scrape interval is used. + interval: + + # metric relabel configs to apply to samples before ingestion. + metricRelabelings: [] + # - action: keep + # regex: 'kube_(daemonset|deployment|pod|namespace|node|statefulset).+' + # sourceLabels: [__name__] + + # relabel configs to apply to samples before ingestion. + relabelings: [] + # - sourceLabels: [__meta_kubernetes_pod_node_name] + # separator: ; + # regex: ^(.*)$ + # target_label: nodename + # replacement: $1 + # action: replace + + # Prometheus Operator ServiceMonitors. To be used as an alternative + # to podMonitor, supports secure metrics. + serviceMonitor: + # enable support for Prometheus Operator + enabled: false + + speaker: + # optional additional labels for the speaker serviceMonitor + additionalLabels: {} + # optional additional annotations for the speaker serviceMonitor + annotations: {} + # optional tls configuration for the speaker serviceMonitor, in case + # secure metrics are enabled. + tlsConfig: + insecureSkipVerify: true + + controller: + # optional additional labels for the controller serviceMonitor + additionalLabels: {} + # optional additional annotations for the controller serviceMonitor + annotations: {} + # optional tls configuration for the controller serviceMonitor, in case + # secure metrics are enabled. + tlsConfig: + insecureSkipVerify: true + + # Job label for scrape target + jobLabel: "app.kubernetes.io/name" + + # Scrape interval. If not set, the Prometheus default scrape interval is used. + interval: + + # metric relabel configs to apply to samples before ingestion. + metricRelabelings: [] + # - action: keep + # regex: 'kube_(daemonset|deployment|pod|namespace|node|statefulset).+' + # sourceLabels: [__name__] + + # relabel configs to apply to samples before ingestion. + relabelings: [] + # - sourceLabels: [__meta_kubernetes_pod_node_name] + # separator: ; + # regex: ^(.*)$ + # target_label: nodename + # replacement: $1 + # action: replace + + # Prometheus Operator alertmanager alerts + prometheusRule: + # enable alertmanager alerts + enabled: false + + # optional additionnal labels for prometheusRules + additionalLabels: {} + + # optional annotations for prometheusRules + annotations: {} + + # MetalLBStaleConfig + staleConfig: + enabled: true + labels: + severity: warning + + # MetalLBConfigNotLoaded + configNotLoaded: + enabled: true + labels: + severity: warning + + # MetalLBAddressPoolExhausted + addressPoolExhausted: + enabled: true + labels: + severity: alert + + addressPoolUsage: + enabled: true + thresholds: + - percent: 75 + labels: + severity: warning + - percent: 85 + labels: + severity: warning + - percent: 95 + labels: + severity: alert + + # MetalLBBGPSessionDown + bgpSessionDown: + enabled: true + labels: + severity: alert + + extraAlerts: [] + +# controller contains configuration specific to the MetalLB cluster +# controller. +controller: + enabled: true + # -- Controller log level. Must be one of: `all`, `debug`, `info`, `warn`, `error` or `none` + logLevel: info + # command: /controller + # webhookMode: enabled + image: + repository: quay.io/metallb/controller + tag: + pullPolicy: + ## @param controller.updateStrategy.type Metallb controller deployment strategy type. + ## ref: https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#strategy + ## e.g: + ## strategy: + ## type: RollingUpdate + ## rollingUpdate: + ## maxSurge: 25% + ## maxUnavailable: 25% + ## + strategy: + type: RollingUpdate + serviceAccount: + # Specifies whether a ServiceAccount should be created + create: true + # The name of the ServiceAccount to use. If not set and create is + # true, a name is generated using the fullname template + name: "" + annotations: {} + securityContext: + runAsNonRoot: true + # nobody + runAsUser: 65534 + fsGroup: 65534 + resources: {} + # limits: + # cpu: 100m + # memory: 100Mi + nodeSelector: {} + tolerations: [] + priorityClassName: "" + runtimeClassName: "" + affinity: {} + podAnnotations: {} + labels: {} + livenessProbe: + enabled: true + failureThreshold: 3 + initialDelaySeconds: 10 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 + readinessProbe: + enabled: true + failureThreshold: 3 + initialDelaySeconds: 10 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 + +# speaker contains configuration specific to the MetalLB speaker +# daemonset. +speaker: + enabled: true + # command: /speaker + # -- Speaker log level. Must be one of: `all`, `debug`, `info`, `warn`, `error` or `none` + logLevel: info + tolerateMaster: true + memberlist: + enabled: true + mlBindPort: 7946 + mlSecretKeyPath: "/etc/ml_secret_key" + excludeInterfaces: + enabled: true + image: + repository: quay.io/metallb/speaker + tag: + pullPolicy: + ## @param speaker.updateStrategy.type Speaker daemonset strategy type + ## ref: https://kubernetes.io/docs/tasks/manage-daemon/update-daemon-set/ + ## + updateStrategy: + ## StrategyType + ## Can be set to RollingUpdate or OnDelete + ## + type: RollingUpdate + serviceAccount: + # Specifies whether a ServiceAccount should be created + create: true + # The name of the ServiceAccount to use. If not set and create is + # true, a name is generated using the fullname template + name: "" + annotations: {} + ## Defines a secret name for the controller to generate a memberlist encryption secret + ## By default secretName: {{ "metallb.fullname" }}-memberlist + ## + # secretName: + resources: {} + # limits: + # cpu: 100m + # memory: 100Mi + nodeSelector: {} + tolerations: [] + priorityClassName: "" + affinity: {} + ## Selects which runtime class will be used by the pod. + runtimeClassName: "" + podAnnotations: {} + labels: {} + livenessProbe: + enabled: true + failureThreshold: 3 + initialDelaySeconds: 10 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 + readinessProbe: + enabled: true + failureThreshold: 3 + initialDelaySeconds: 10 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 + startupProbe: + enabled: true + failureThreshold: 30 + periodSeconds: 5 + # frr contains configuration specific to the MetalLB FRR container, + # for speaker running alongside FRR. + frr: + enabled: true + image: + repository: quay.io/frrouting/frr + tag: 8.4.2 + pullPolicy: + metricsPort: 7473 + resources: {} + + # if set, enables a rbac proxy sidecar container on the speaker to + # expose the frr metrics via tls. + # secureMetricsPort: 9121 + + reloader: + resources: {} + + frrMetrics: + resources: {} + +crds: + enabled: true + validationFailurePolicy: Fail diff --git a/packages/system/metallb/values.yaml b/packages/system/metallb/values.yaml new file mode 100644 index 00000000..737f17cf --- /dev/null +++ b/packages/system/metallb/values.yaml @@ -0,0 +1,6 @@ +metallb: + crds: + enabled: true + + #speaker: + # tolerateMaster: false diff --git a/packages/system/monitoring/.helmignore b/packages/system/monitoring/.helmignore new file mode 100644 index 00000000..70528e63 --- /dev/null +++ b/packages/system/monitoring/.helmignore @@ -0,0 +1 @@ +grafana-dashboards diff --git a/packages/system/monitoring/Chart.yaml b/packages/system/monitoring/Chart.yaml new file mode 100644 index 00000000..4cff6296 --- /dev/null +++ b/packages/system/monitoring/Chart.yaml @@ -0,0 +1,2 @@ +name: cozy-monitoring +version: 1.0.0 diff --git a/packages/system/monitoring/Makefile b/packages/system/monitoring/Makefile new file mode 100644 index 00000000..52020e87 --- /dev/null +++ b/packages/system/monitoring/Makefile @@ -0,0 +1,24 @@ +NAME=monitoring +NAMESPACE=cozy-monitoring + +show: + helm template --dry-run=server -n $(NAMESPACE) $(NAME) . + +apply: + helm upgrade -i -n $(NAMESPACE) $(NAME) . + +diff: + helm diff upgrade --allow-unreleased --normalize-manifests -n $(NAMESPACE) $(NAME) . + +update: + rm -rf charts + helm repo add prometheus-community https://prometheus-community.github.io/helm-charts + helm repo update prometheus-community + # Kube-state-metrics + helm pull prometheus-community/kube-state-metrics --untar --untardir charts + # Node-exporter + helm pull prometheus-community/prometheus-node-exporter --untar --untardir charts + # Metrics-server + helm repo add metrics-server https://kubernetes-sigs.github.io/metrics-server/ + helm repo update metrics-server + helm pull metrics-server/metrics-server --untar --untardir charts diff --git a/packages/system/monitoring/alerts/general.yaml b/packages/system/monitoring/alerts/general.yaml new file mode 100644 index 00000000..adf82635 --- /dev/null +++ b/packages/system/monitoring/alerts/general.yaml @@ -0,0 +1,57 @@ +apiVersion: operator.victoriametrics.com/v1beta1 +kind: VMRule +metadata: + name: alerts-general + namespace: cozy-monitoring +spec: + groups: + - name: coreos.general + labels: + alertname: foo + rules: + - alert: DeadMansSwitch + expr: vector(1) + labels: + severity_level: "4" + annotations: + description: This is a DeadMansSwitch meant to ensure that the entire Alerting + pipeline is functional. + summary: Alerting DeadMansSwitch + - record: fd_utilization + expr: process_open_fds / process_max_fds + - alert: FdExhaustionClose + expr: max(predict_linear(fd_utilization{pod!=""}[1h], 3600 * 4)) BY (job, namespace, pod) > 1 + for: 10m + labels: + severity_level: "4" + annotations: + description: '{{ $labels.job }}: {{ $labels.namespace }}/{{ $labels.pod }} instance + will exhaust in file/socket descriptors within the next 4 hours' + summary: file descriptors soon exhausted + - alert: FdExhaustionClose + expr: max(predict_linear(fd_utilization{pod=""}[1h], 3600 * 4)) BY (job, instance) > 1 + for: 10m + labels: + severity_level: "4" + annotations: + description: '{{ $labels.job }}: {{ $labels.instance }} instance + will exhaust in file/socket descriptors within the next 4 hours' + summary: file descriptors soon exhausted + - alert: FdExhaustionClose + expr: max(predict_linear(fd_utilization{pod!=""}[10m], 3600)) BY (job, namespace, pod) > 1 + for: 10m + labels: + severity_level: "3" + annotations: + description: '{{ $labels.job }}: {{ $labels.namespace }}/{{ $labels.pod }} instance + will exhaust in file/socket descriptors within the next hour' + summary: file descriptors soon exhausted + - alert: FdExhaustionClose + expr: max(predict_linear(fd_utilization{pod=""}[10m], 3600)) BY (job, instance) > 1 + for: 10m + labels: + severity_level: "3" + annotations: + description: '{{ $labels.job }}: {{ $labels.instance }} instance + will exhaust in file/socket descriptors within the next hour' + summary: file descriptors soon exhausted diff --git a/packages/system/monitoring/alerts/kube-dns.yaml b/packages/system/monitoring/alerts/kube-dns.yaml new file mode 100644 index 00000000..4310707b --- /dev/null +++ b/packages/system/monitoring/alerts/kube-dns.yaml @@ -0,0 +1,25 @@ +apiVersion: operator.victoriametrics.com/v1beta1 +kind: VMRule +metadata: + name: alerts-node + namespace: cozy-monitoring +spec: + groups: + - name: kubernetes.dns + rules: + - alert: KubernetesDnsTargetDown + expr: absent(up{job="kube-dns"} == 1) + for: 5m + labels: + severity_level: "5" + tier: cluster + annotations: + plk_protocol_version: "1" + plk_markup_format: "markdown" + description: |- + Prometheus is unable to collect metrics from kube-dns. Thus its status is unknown. + + To debug the problem, use the following commands: + 1. `kubectl -n kube-system describe deployment -l k8s-app=kube-dns` + 2. `kubectl -n kube-system describe pod -l k8s-app=kube-dns` + summary: Kube-dns or CoreDNS are not under monitoring. diff --git a/packages/system/monitoring/alerts/kube-state-metrics.yaml b/packages/system/monitoring/alerts/kube-state-metrics.yaml new file mode 100644 index 00000000..a671283f --- /dev/null +++ b/packages/system/monitoring/alerts/kube-state-metrics.yaml @@ -0,0 +1,50 @@ +apiVersion: operator.victoriametrics.com/v1beta1 +kind: VMRule +metadata: + name: alerts-kube-state-metrics + namespace: cozy-monitoring +spec: + groups: + - name: kube-state-metrics + rules: + - alert: DeploymentGenerationMismatch + expr: max(kube_deployment_status_observed_generation != kube_deployment_metadata_generation) by (namespace, deployment) + for: 15m + labels: + severity_level: "4" + annotations: + plk_protocol_version: "1" + description: Observed deployment generation does not match expected one for + deployment {{$labels.namespace}}/{{$labels.deployment}} + summary: Deployment is outdated + - alert: KubeStateMetricsDown + expr: absent(up{job="kube-state-metrics"} == 1) + for: 5m + labels: + severity_level: "3" + annotations: + plk_protocol_version: "1" + plk_markup_format: markdown + description: |- + There are no metrics about cluster resources for 5 minutes. + + Most alerts an monitroing panels aren't working. + + To debug the problem: + 1. Check kube-state-metrics pods: `kubectl -n d8-monitoring describe pod -l app=kube-state-metrics` + 2. Check its logs: `kubectl -n d8-monitoring describe deploy kube-state-metrics` + summary: > + Kube-state-metrics is not working in the cluster. + - name: kubernetes.rules + rules: + - alert: KubePodCrashLooping + expr: | + max_over_time(kube_pod_container_status_waiting_reason{reason="CrashLoopBackOff", job="kube-state-metrics"}[5m]) >= 1 + annotations: + description: 'Pod {{ $labels.namespace }}/{{ $labels.pod }} ({{ $labels.container + }}) is in waiting state (reason: "CrashLoopBackOff").' + runbook_url: https://github.com/kubernetes-monitoring/kubernetes-mixin/tree/master/runbook.md#alert-name-kubepodcrashlooping + summary: Pod is crash looping. + for: 15m + labels: + severity: warning diff --git a/packages/system/monitoring/alerts/kubelet.yaml b/packages/system/monitoring/alerts/kubelet.yaml new file mode 100644 index 00000000..d0719f2d --- /dev/null +++ b/packages/system/monitoring/alerts/kubelet.yaml @@ -0,0 +1,63 @@ +apiVersion: operator.victoriametrics.com/v1beta1 +kind: VMRule +metadata: + name: alerts-kubelet + namespace: cozy-monitoring +spec: + groups: + - name: coreos.kubelet + rules: + - alert: K8SNodeNotReady + expr: min(kube_node_status_condition{condition="Ready",status="true"}) BY (node) == 0 and + min(kube_node_spec_unschedulable == 0) by (node) + for: 1m + labels: + severity_level: "3" + annotations: + plk_protocol_version: "1" + description: The Kubelet on {{ $labels.node }} has not checked in with the API, + or has set itself to NotReady, for more than 10 minutes + summary: Node status is NotReady + - alert: K8SManyNodesNotReady + expr: count(kube_node_status_condition{condition="Ready",status="true"} == 0 and on (node) kube_node_spec_unschedulable == 0) > 1 + and (count(kube_node_status_condition{condition="Ready",status="true"} == 0 and on (node) kube_node_spec_unschedulable == 0) / + count(kube_node_status_condition{condition="Ready",status="true"} and on (node) kube_node_spec_unschedulable == 0)) > 0.2 + for: 1m + labels: + severity_level: "3" + annotations: + plk_protocol_version: "1" + description: '{{ $value }}% of Kubernetes nodes are not ready' + summary: Too many nodes are not ready + - alert: K8SKubeletDown + expr: (count(up{job="kubelet"} == 0) or absent(up{job="kubelet"} == 1)) / count(up{job="kubelet"}) * 100 > 3 + for: 10m + labels: + severity_level: "4" + tier: "cluster" + annotations: + plk_protocol_version: "1" + plk_group_for__target_down: "TargetDown,prometheus=deckhouse,job=kubelet,kubernetes=~kubernetes" + description: Prometheus failed to scrape {{ $value }}% of kubelets. + summary: A few kubelets cannot be scraped + - alert: K8SKubeletDown + expr: (count(up{job="kubelet"} == 0) or absent(up{job="kubelet"} == 1)) / count(up{job="kubelet"}) * 100 > 10 + for: 30m + labels: + severity_level: "3" + tier: "cluster" + annotations: + plk_protocol_version: "1" + plk_group_for__target_down: "TargetDown,prometheus=deckhouse,job=kubelet,kubernetes=~kubernetes" + description: Prometheus failed to scrape {{ $value }}% of kubelets. + summary: Many kubelets cannot be scraped + - alert: K8SKubeletTooManyPods + expr: kubelet_running_pods > on(node) (kube_node_status_capacity{resource="pods",unit="integer"}) * 0.9 + for: 10m + labels: + severity_level: "7" + annotations: + plk_protocol_version: "1" + description: Kubelet {{ $labels.node }} is running {{ $value }} pods, close + to the limit of {{ printf "kube_node_status_capacity{resource=\"pods\",unit=\"integer\",node=\"%s\"}" $labels.node | query | first | value }} + summary: Kubelet is close to pod limit diff --git a/packages/system/monitoring/alerts/node-disk-usage.yaml b/packages/system/monitoring/alerts/node-disk-usage.yaml new file mode 100644 index 00000000..e7ceff1f --- /dev/null +++ b/packages/system/monitoring/alerts/node-disk-usage.yaml @@ -0,0 +1,357 @@ +apiVersion: operator.victoriametrics.com/v1beta1 +kind: VMRule +metadata: + name: alerts-node + namespace: cozy-monitoring +spec: + groups: + - name: kubernetes.node.disk_inodes_usage + rules: + - alert: KubeletNodeFSInodesUsage + expr: | + ( + max by (node, mountpoint) (node_filesystem_files_free / node_filesystem_files) * 100 < + max by (node, mountpoint) (kubelet_eviction_nodefs_inodes{type="soft"}) + ) + for: 10m + labels: + severity_level: "9" + tier: cluster + annotations: + plk_protocol_version: "1" + plk_markup_format: markdown + plk_create_group_if_not_exists__node_disk_usage: "NodeDiskUsage,tier=cluster,prometheus=deckhouse,node={{ $labels.node }},kubernetes=~kubernetes" + plk_grouped_by__node_disk_usage: "NodeDiskUsage,tier=cluster,prometheus=deckhouse,node={{ $labels.node }},kubernetes=~kubernetes" + description: | + Soft eviction of nodefs on the {{$labels.node}} Node at the {{$labels.mountpoint}} mountpoint is in progress. + + Threshold at: {{ printf "kubelet_eviction_nodefs_inodes{type=\"soft\", node=\"%s\", mountpoint=\"%s\"}" $labels.node $labels.mountpoint | query | first | value }}% + + Currently at: {{ .Value }}% + summary: Soft eviction of nodefs on the {{$labels.node}} Node at the {{$labels.mountpoint}} mountpoint is in progress. + + - alert: KubeletNodeFSInodesUsage + expr: | + ( + max by (node, mountpoint) (node_filesystem_files_free / node_filesystem_files) * 100 < + max by (node, mountpoint) (kubelet_eviction_nodefs_inodes{type="hard"} + 5) + ) + for: 5m + labels: + severity_level: "7" + tier: cluster + annotations: + plk_protocol_version: "1" + plk_markup_format: markdown + plk_create_group_if_not_exists__node_disk_usage: "NodeDiskUsage,tier=cluster,prometheus=deckhouse,node={{ $labels.node }},kubernetes=~kubernetes" + plk_grouped_by__node_disk_usage: "NodeDiskUsage,tier=cluster,prometheus=deckhouse,node={{ $labels.node }},kubernetes=~kubernetes" + description: | + Close to hard eviction threshold of nodefs on the {{$labels.node}} Node at the {{$labels.mountpoint}} mountpoint. + + Threshold at: {{ printf "kubelet_eviction_nodefs_inodes{type=\"hard\", node=\"%s\", mountpoint=\"%s\"}" $labels.node $labels.mountpoint | query | first | value }}% + + Currently at: {{ .Value }}% + summary: > + Close to hard eviction threshold of nodefs on the {{$labels.node}} Node at the {{$labels.mountpoint}} mountpoint. + + - alert: KubeletNodeFSInodesUsage + expr: | + ( + max by (node, mountpoint) (node_filesystem_files_free / node_filesystem_files) * 100 < + max by (node, mountpoint) (kubelet_eviction_nodefs_inodes{type="hard"}) + ) + labels: + severity_level: "6" + tier: cluster + annotations: + plk_protocol_version: "1" + plk_markup_format: markdown + plk_create_group_if_not_exists__node_disk_usage: "NodeDiskUsage,tier=cluster,prometheus=deckhouse,node={{ $labels.node }},kubernetes=~kubernetes" + plk_grouped_by__node_disk_usage: "NodeDiskUsage,tier=cluster,prometheus=deckhouse,node={{ $labels.node }},kubernetes=~kubernetes" + description: | + Hard eviction of nodefs on the {{$labels.node}} Node at the {{$labels.mountpoint}} mountpoint is in progress. + + Threshold at: {{ printf "kubelet_eviction_nodefs_inodes{type=\"hard\", node=\"%s\", mountpoint=\"%s\"}" $labels.node $labels.mountpoint | query | first | value }}% + + Currently at: {{ .Value }}% + summary: Hard eviction of nodefs on the {{$labels.node}} Node at the {{$labels.mountpoint}} mountpoint is in progress. + + - alert: KubeletNodeFSInodesUsage + expr: | + ( + ( + max by (node, mountpoint) (node_filesystem_files_free) + ) == 0 + ) + * (max by (node, mountpoint) ({__name__=~"kubelet_eviction_nodefs_inodes"})) + labels: + severity_level: "5" + tier: cluster + annotations: + plk_protocol_version: "1" + plk_markup_format: markdown + plk_create_group_if_not_exists__node_disk_usage: "NodeDiskUsage,tier=cluster,prometheus=deckhouse,node={{ $labels.node }},kubernetes=~kubernetes" + plk_grouped_by__node_disk_usage: "NodeDiskUsage,tier=cluster,prometheus=deckhouse,node={{ $labels.node }},kubernetes=~kubernetes" + summary: No more free inodes on nodefs on the {{$labels.node}} Node at the {{$labels.mountpoint}} mountpoint. + + - alert: KubeletImageFSInodesUsage + expr: | + ( + max by (node, mountpoint) (node_filesystem_files_free / node_filesystem_files) * 100 < + max by (node, mountpoint) (kubelet_eviction_imagefs_inodes{type="soft"}) + ) + for: 10m + labels: + severity_level: "9" + tier: cluster + annotations: + plk_protocol_version: "1" + plk_markup_format: markdown + plk_create_group_if_not_exists__node_disk_usage: "NodeDiskUsage,tier=cluster,prometheus=deckhouse,node={{ $labels.node }},kubernetes=~kubernetes" + plk_grouped_by__node_disk_usage: "NodeDiskUsage,tier=cluster,prometheus=deckhouse,node={{ $labels.node }},kubernetes=~kubernetes" + description: | + Soft eviction of imagefs on the {{$labels.node}} Node at the {{$labels.mountpoint}} mountpoint is in progress. + + Threshold at: {{ printf "kubelet_eviction_imagefs_inodes{type=\"soft\", node=\"%s\", mountpoint=\"%s\"}" $labels.node $labels.mountpoint | query | first | value }}% + + Currently at: {{ .Value }}% + summary: Soft eviction of imagefs on the {{$labels.node}} Node at the {{$labels.mountpoint}} mountpoint is in progress. + + - alert: KubeletImageFSInodesUsage + expr: | + ( + max by (node, mountpoint) (node_filesystem_files_free / node_filesystem_files) * 100 < + max by (node, mountpoint) (kubelet_eviction_imagefs_inodes{type="hard"} + 5) + ) + for: 5m + labels: + severity_level: "7" + tier: cluster + annotations: + plk_protocol_version: "1" + plk_markup_format: markdown + plk_create_group_if_not_exists__node_disk_usage: "NodeDiskUsage,tier=cluster,prometheus=deckhouse,node={{ $labels.node }},kubernetes=~kubernetes" + plk_grouped_by__node_disk_usage: "NodeDiskUsage,tier=cluster,prometheus=deckhouse,node={{ $labels.node }},kubernetes=~kubernetes" + description: | + Close to hard eviction threshold of imagefs on the {{$labels.node}} Node at the {{$labels.mountpoint}} mountpoint. + + Threshold at: {{ printf "kubelet_eviction_imagefs_inodes{type=\"hard\", node=\"%s\", mountpoint=\"%s\"}" $labels.node $labels.mountpoint | query | first | value }}% + + Currently at: {{ .Value }}% + summary: Close to hard eviction threshold of imagefs on the {{$labels.node}} Node at the {{$labels.mountpoint}} mountpoint. + + - alert: KubeletImageFSInodesUsage + expr: | + ( + max by (node, mountpoint) (node_filesystem_files_free / node_filesystem_files) * 100 < + max by (node, mountpoint) (kubelet_eviction_imagefs_inodes{type="hard"}) + ) + labels: + severity_level: "6" + tier: cluster + annotations: + plk_protocol_version: "1" + plk_markup_format: markdown + plk_create_group_if_not_exists__node_disk_usage: "NodeDiskUsage,tier=cluster,prometheus=deckhouse,node={{ $labels.node }},kubernetes=~kubernetes" + plk_grouped_by__node_disk_usage: "NodeDiskUsage,tier=cluster,prometheus=deckhouse,node={{ $labels.node }},kubernetes=~kubernetes" + description: | + Hard eviction of imagefs on the {{$labels.node}} Node at the {{$labels.mountpoint}} mountpoint is in progress. + + Threshold at: {{ printf "kubelet_eviction_imagefs_inodes{type=\"hard\", node=\"%s\", mountpoint=\"%s\"}" $labels.node $labels.mountpoint | query | first | value }}% + + Currently at: {{ .Value }}% + summary: Hard eviction of imagefs on the {{$labels.node}} Node at the {{$labels.mountpoint}} mountpoint is in progress. + + - alert: KubeletImageFSInodesUsage + expr: | + ( + ( + max by (node, mountpoint) (node_filesystem_files_free) + ) == 0 + ) + * (max by (node, mountpoint) ({__name__=~"kubelet_eviction_imagefs_inodes"})) + labels: + severity_level: "5" + tier: cluster + annotations: + plk_protocol_version: "1" + plk_markup_format: markdown + plk_create_group_if_not_exists__node_disk_usage: "NodeDiskUsage,tier=cluster,prometheus=deckhouse,node={{ $labels.node }},kubernetes=~kubernetes" + plk_grouped_by__node_disk_usage: "NodeDiskUsage,tier=cluster,prometheus=deckhouse,node={{ $labels.node }},kubernetes=~kubernetes" + summary: No more free inodes on imagefs on the {{$labels.node}} Node at the {{$labels.mountpoint}} mountpoint. + + - name: kubernetes.node.disk_bytes_usage + rules: + - alert: KubeletNodeFSBytesUsage + expr: | + ( + max by (node, mountpoint) (node_filesystem_avail_bytes / node_filesystem_size_bytes) * 100 < + max by (node, mountpoint) (kubelet_eviction_nodefs_bytes{type="soft"}) + ) + for: 10m + labels: + severity_level: "9" + tier: cluster + annotations: + plk_protocol_version: "1" + plk_markup_format: markdown + plk_create_group_if_not_exists__node_disk_usage: "NodeDiskUsage,tier=cluster,prometheus=deckhouse,node={{ $labels.node }},kubernetes=~kubernetes" + plk_grouped_by__node_disk_usage: "NodeDiskUsage,tier=cluster,prometheus=deckhouse,node={{ $labels.node }},kubernetes=~kubernetes" + description: | + Soft eviction of nodefs on the {{$labels.node}} Node at the {{$labels.mountpoint}} mountpoint is in progress. + + Threshold at: {{ printf "kubelet_eviction_nodefs_bytes{type=\"soft\", node=\"%s\", mountpoint=\"%s\"}" $labels.node $labels.mountpoint | query | first | value }}% + + Currently at: {{ .Value }}% + summary: Soft eviction of nodefs on the {{$labels.node}} Node at the {{$labels.mountpoint}} mountpoint is in progress. + + - alert: KubeletNodeFSBytesUsage + expr: | + ( + max by (node, mountpoint) (node_filesystem_avail_bytes / node_filesystem_size_bytes) * 100 < + max by (node, mountpoint) (kubelet_eviction_nodefs_bytes{type="hard"} + 5) + ) + for: 5m + labels: + severity_level: "7" + tier: cluster + annotations: + plk_protocol_version: "1" + plk_markup_format: markdown + plk_create_group_if_not_exists__node_disk_usage: "NodeDiskUsage,tier=cluster,prometheus=deckhouse,node={{ $labels.node }},kubernetes=~kubernetes" + plk_grouped_by__node_disk_usage: "NodeDiskUsage,tier=cluster,prometheus=deckhouse,node={{ $labels.node }},kubernetes=~kubernetes" + description: | + Close to hard eviction threshold of nodefs on the {{$labels.node}} Node at the {{$labels.mountpoint}} mountpoint. + + Threshold at: {{ printf "kubelet_eviction_nodefs_bytes{type=\"hard\", node=\"%s\", mountpoint=\"%s\"}" $labels.node $labels.mountpoint | query | first | value }}% + + Currently at: {{ .Value }}% + summary: Close to hard eviction threshold of nodefs on the {{$labels.node}} Node at the {{$labels.mountpoint}} mountpoint. + + - alert: KubeletNodeFSBytesUsage + expr: | + ( + max by (node, mountpoint) (node_filesystem_avail_bytes / node_filesystem_size_bytes) * 100 < + max by (node, mountpoint) (kubelet_eviction_nodefs_bytes{type="hard"}) + ) + labels: + severity_level: "6" + tier: cluster + annotations: + plk_protocol_version: "1" + plk_markup_format: markdown + plk_create_group_if_not_exists__node_disk_usage: "NodeDiskUsage,tier=cluster,prometheus=deckhouse,node={{ $labels.node }},kubernetes=~kubernetes" + plk_grouped_by__node_disk_usage: "NodeDiskUsage,tier=cluster,prometheus=deckhouse,node={{ $labels.node }},kubernetes=~kubernetes" + description: | + Hard eviction of nodefs on the {{$labels.node}} Node at the {{$labels.mountpoint}} mountpoint is in progress. + + Threshold at: {{ printf "kubelet_eviction_nodefs_bytes{type=\"hard\", node=\"%s\", mountpoint=\"%s\"}" $labels.node $labels.mountpoint | query | first | value }}% + + Currently at: {{ .Value }}% + summary: Hard eviction of nodefs on the {{$labels.node}} Node at the {{$labels.mountpoint}} mountpoint is in progress. + + - alert: KubeletNodeFSBytesUsage + expr: | + ( + ( + max by (node, mountpoint) (node_filesystem_avail_bytes) + ) == 0 + ) + * (max by (node, mountpoint) ({__name__=~"kubelet_eviction_nodefs_bytes"})) + labels: + severity_level: "5" + tier: cluster + annotations: + plk_protocol_version: "1" + plk_markup_format: markdown + plk_create_group_if_not_exists__node_disk_usage: "NodeDiskUsage,tier=cluster,prometheus=deckhouse,node={{ $labels.node }},kubernetes=~kubernetes" + plk_grouped_by__node_disk_usage: "NodeDiskUsage,tier=cluster,prometheus=deckhouse,node={{ $labels.node }},kubernetes=~kubernetes" + summary: No more free space on nodefs on the {{$labels.node}} Node at the {{$labels.mountpoint}} mountpoint. + + - alert: KubeletImageFSBytesUsage + expr: | + ( + max by (node, mountpoint) (node_filesystem_avail_bytes / node_filesystem_size_bytes) * 100 < + max by (node, mountpoint) (kubelet_eviction_imagefs_bytes{type="soft"}) + ) + for: 10m + labels: + severity_level: "9" + tier: cluster + annotations: + plk_protocol_version: "1" + plk_markup_format: markdown + plk_create_group_if_not_exists__node_disk_usage: "NodeDiskUsage,tier=cluster,prometheus=deckhouse,node={{ $labels.node }},kubernetes=~kubernetes" + plk_grouped_by__node_disk_usage: "NodeDiskUsage,tier=cluster,prometheus=deckhouse,node={{ $labels.node }},kubernetes=~kubernetes" + description: | + Soft eviction of imagefs (filesystem that the container runtime uses for storing images and container writable layers) on the {{$labels.node}} Node at the {{$labels.mountpoint}} mountpoint is in progress. + + Threshold at: {{ printf "kubelet_eviction_imagefs_bytes{type=\"soft\", node=\"%s\", mountpoint=\"%s\"}" $labels.node $labels.mountpoint | query | first | value }}% + + Currently at: {{ .Value }}% + summary: Soft eviction of imagefs on the {{$labels.node}} Node at the {{$labels.mountpoint}} mountpoint is in progress. + + - alert: KubeletImageFSBytesUsage + expr: | + ( + max by (node, mountpoint) (node_filesystem_avail_bytes / node_filesystem_size_bytes) * 100 < + max by (node, mountpoint) (kubelet_eviction_imagefs_bytes{type="hard"} + 5) + ) + for: 5m + labels: + severity_level: "7" + tier: cluster + annotations: + plk_protocol_version: "1" + plk_markup_format: markdown + plk_create_group_if_not_exists__node_disk_usage: "NodeDiskUsage,tier=cluster,prometheus=deckhouse,node={{ $labels.node }},kubernetes=~kubernetes" + plk_grouped_by__node_disk_usage: "NodeDiskUsage,tier=cluster,prometheus=deckhouse,node={{ $labels.node }},kubernetes=~kubernetes" + description: | + Close to hard eviction threshold of imagefs (filesystem that the container runtime uses for storing images and container writable layers) on node {{$labels.node}} mountpoint {{$labels.mountpoint}}. + + Threshold at: {{ printf "kubelet_eviction_imagefs_bytes{type=\"hard\", node=\"%s\", mountpoint=\"%s\"}" $labels.node $labels.mountpoint | query | first | value }}% + + Currently at: {{ .Value }}% + summary: Close to hard eviction threshold of imagefs on the {{$labels.node}} Node at the {{$labels.mountpoint}} mountpoint. + + - alert: KubeletImageFSBytesUsage + expr: | + ( + max by (node, mountpoint) (node_filesystem_avail_bytes / node_filesystem_size_bytes) * 100 < + max by (node, mountpoint) (kubelet_eviction_imagefs_bytes{type="hard"}) + ) + labels: + severity_level: "6" + tier: cluster + annotations: + plk_protocol_version: "1" + plk_markup_format: markdown + plk_create_group_if_not_exists__node_disk_usage: "NodeDiskUsage,tier=cluster,prometheus=deckhouse,node={{ $labels.node }},kubernetes=~kubernetes" + plk_grouped_by__node_disk_usage: "NodeDiskUsage,tier=cluster,prometheus=deckhouse,node={{ $labels.node }},kubernetes=~kubernetes" + description: | + Hard eviction of imagefs (filesystem that the container runtime uses for storing images and container writable layers) on the {{$labels.node}} Node at the {{$labels.mountpoint}} mountpoint is in progress. + + Threshold at: {{ printf "kubelet_eviction_imagefs_bytes{type=\"hard\", node=\"%s\", mountpoint=\"%s\"}" $labels.node $labels.mountpoint | query | first | value }}% + + Currently at: {{ .Value }}% + summary: Hard eviction of imagefs on the {{$labels.node}} Node at the {{$labels.mountpoint}} mountpoint is in progress. + + - alert: KubeletImageFSBytesUsage + expr: | + ( + ( + max by (node, mountpoint) (node_filesystem_avail_bytes) + ) == 0 + ) + * (max by (node, mountpoint) ({__name__=~"kubelet_eviction_imagefs_bytes"})) + labels: + severity_level: "5" + tier: cluster + annotations: + plk_protocol_version: "1" + plk_markup_format: markdown + plk_create_group_if_not_exists__node_disk_usage: "NodeDiskUsage,tier=cluster,prometheus=deckhouse,node={{ $labels.node }},kubernetes=~kubernetes" + plk_grouped_by__node_disk_usage: "NodeDiskUsage,tier=cluster,prometheus=deckhouse,node={{ $labels.node }},kubernetes=~kubernetes" + description: | + No more free bytes on imagefs (filesystem that the container runtime uses for storing images and container writable layers) on node {{$labels.node}} mountpoint {{$labels.mountpoint}}. + summary: No more free bytes on imagefs on the {{$labels.node}} Node at the {{$labels.mountpoint}} mountpoint. diff --git a/packages/system/monitoring/alerts/node.yaml b/packages/system/monitoring/alerts/node.yaml new file mode 100644 index 00000000..88b6f72b --- /dev/null +++ b/packages/system/monitoring/alerts/node.yaml @@ -0,0 +1,36 @@ +apiVersion: operator.victoriametrics.com/v1beta1 +kind: VMRule +metadata: + name: alerts-node + namespace: cozy-monitoring +spec: + groups: + - name: coreos.node + rules: + - record: node:node_cpu:rate:sum + expr: sum(rate(node_cpu{mode!="idle",mode!="iowait"}[3m])) + BY (node) + - record: node:node_filesystem_usage:sum + expr: sum((node_filesystem_size{mountpoint="/"} - node_filesystem_free{mountpoint="/"})) + BY (node) + - record: node:node_network_receive_bytes:rate:sum + expr: sum(rate(node_network_receive_bytes[3m])) BY (node) + - record: node:node_network_transmit_bytes:rate:sum + expr: sum(rate(node_network_transmit_bytes[3m])) BY (node) + - record: node:node_cpu:ratio + expr: sum(rate(node_cpu{mode!="idle",mode!="iowait"}[5m])) WITHOUT (cpu, mode) / ON(node) + GROUP_LEFT() count(sum(node_cpu) BY (node, cpu)) BY (node) + - record: cluster:node_cpu:sum_rate5m + expr: sum(rate(node_cpu{mode!="idle",mode!="iowait"}[5m])) + - record: cluster:node_cpu:ratio + expr: cluster:node_cpu:rate5m / count(sum(node_cpu) BY (node, cpu)) + - alert: NodeExporterDown + expr: absent(up{job="node-exporter"} == 1) + for: 10m + labels: + severity_level: "3" + annotations: + plk_protocol_version: "1" + description: Prometheus could not scrape a node-exporter for more than 10m, + or node-exporters have disappeared from discovery + summary: Prometheus could not scrape a node-exporter diff --git a/packages/system/monitoring/alerts/pod-status.yaml b/packages/system/monitoring/alerts/pod-status.yaml new file mode 100644 index 00000000..9070d2e8 --- /dev/null +++ b/packages/system/monitoring/alerts/pod-status.yaml @@ -0,0 +1,34 @@ +apiVersion: operator.victoriametrics.com/v1beta1 +kind: VMRule +metadata: + name: alerts-node + namespace: cozy-monitoring +spec: + groups: + - name: kubernetes.pod_status_incorrect + rules: + - alert: PodStatusIsIncorrect + expr: > + (count by (node, namespace, pod) (kube_pod_status_ready{condition="true"} == 0) * on (namespace, pod) group_left(node) (max by (namespace, node, pod) (kube_pod_info))) + and + ( + (count by (namespace, pod) (kube_pod_container_status_ready==1) * on (namespace, pod) group_left(node) (max by (namespace, node, pod) (kube_pod_info))) + unless + (count by (namespace, pod) (kube_pod_container_status_ready==0) * on (namespace, pod) group_left(node) (max by (namespace, node, pod) (kube_pod_info))) + ) + for: 10m + annotations: + plk_markup_format: markdown + plk_protocol_version: "1" + plk_create_group_if_not_exists__node_have_pods_with_incorrect_status: "NodeHavePodsWithIncorrectStatus,prometheus=deckhouse,node={{ $labels.node }},kubernetes=~kubernetes" + plk_grouped_by__node_have_pods_with_incorrect_status: "NodeHavePodsWithIncorrectStatus,prometheus=deckhouse,node={{ $labels.node }},kubernetes=~kubernetes" + description: | + There is a {{ $labels.namespace }}/{{ $labels.pod }} Pod in the cluster that runs on the {{ $labels.node }} and listed as NotReady while all the Pod's containers are Ready. + + This could be due to the [Kubernetes bug](https://github.com/kubernetes/kubernetes/issues/80968). + + The recommended course of action: + 1. Find all the Pods having this state: `kubectl get pod -o json --all-namespaces | jq '.items[] | select(.status.phase == "Running") | select(.status.conditions[] | select(.type == "ContainersReady" and .status == "True")) | select(.status.conditions[] | select(.type == "Ready" and .status == "False")) | "\(.spec.nodeName)/\(.metadata.namespace)/\(.metadata.name)"'`; + 2. Find all the Nodes affected: `kubectl get pod -o json --all-namespaces | jq '.items[] | select(.status.phase == "Running") | select(.status.conditions[] | select(.type == "ContainersReady" and .status == "True")) | select(.status.conditions[] | select(.type == "Ready" and .status == "False")) | .spec.nodeName' -r | sort | uniq -c`; + 3. Restart `kubelet` on each Node: `systemctl restart kubelet`. + summary: The state of the {{ $labels.namespace }}/{{ $labels.pod }} Pod running on the {{ $labels.node }} Node is incorrect. You need to restart `kubelet`. diff --git a/packages/system/monitoring/charts/kube-state-metrics/.helmignore b/packages/system/monitoring/charts/kube-state-metrics/.helmignore new file mode 100644 index 00000000..f0c13194 --- /dev/null +++ b/packages/system/monitoring/charts/kube-state-metrics/.helmignore @@ -0,0 +1,21 @@ +# 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 +*~ +# Various IDEs +.project +.idea/ +*.tmproj diff --git a/packages/system/monitoring/charts/kube-state-metrics/Chart.yaml b/packages/system/monitoring/charts/kube-state-metrics/Chart.yaml new file mode 100644 index 00000000..4342ac86 --- /dev/null +++ b/packages/system/monitoring/charts/kube-state-metrics/Chart.yaml @@ -0,0 +1,26 @@ +annotations: + artifacthub.io/license: Apache-2.0 + artifacthub.io/links: | + - name: Chart Source + url: https://github.com/prometheus-community/helm-charts +apiVersion: v2 +appVersion: 2.10.1 +description: Install kube-state-metrics to generate and expose cluster-level metrics +home: https://github.com/kubernetes/kube-state-metrics/ +keywords: +- metric +- monitoring +- prometheus +- kubernetes +maintainers: +- email: tariq.ibrahim@mulesoft.com + name: tariq1890 +- email: manuel@rueg.eu + name: mrueg +- email: david@0xdc.me + name: dotdc +name: kube-state-metrics +sources: +- https://github.com/kubernetes/kube-state-metrics/ +type: application +version: 5.15.2 diff --git a/packages/system/monitoring/charts/kube-state-metrics/README.md b/packages/system/monitoring/charts/kube-state-metrics/README.md new file mode 100644 index 00000000..843be89e --- /dev/null +++ b/packages/system/monitoring/charts/kube-state-metrics/README.md @@ -0,0 +1,85 @@ +# kube-state-metrics Helm Chart + +Installs the [kube-state-metrics agent](https://github.com/kubernetes/kube-state-metrics). + +## Get Repository Info + +```console +helm repo add prometheus-community https://prometheus-community.github.io/helm-charts +helm repo update +``` + +_See [helm repo](https://helm.sh/docs/helm/helm_repo/) for command documentation._ + + +## Install Chart + +```console +helm install [RELEASE_NAME] prometheus-community/kube-state-metrics [flags] +``` + +_See [configuration](#configuration) below._ + +_See [helm install](https://helm.sh/docs/helm/helm_install/) for command documentation._ + +## Uninstall Chart + +```console +helm uninstall [RELEASE_NAME] +``` + +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._ + +## Upgrading Chart + +```console +helm upgrade [RELEASE_NAME] prometheus-community/kube-state-metrics [flags] +``` + +_See [helm upgrade](https://helm.sh/docs/helm/helm_upgrade/) for command documentation._ + +### Migrating from stable/kube-state-metrics and kubernetes/kube-state-metrics + +You can upgrade in-place: + +1. [get repository info](#get-repository-info) +1. [upgrade](#upgrading-chart) your existing release name using the new chart repository + +## Upgrading to v3.0.0 + +v3.0.0 includes kube-state-metrics v2.0, see the [changelog](https://github.com/kubernetes/kube-state-metrics/blob/release-2.0/CHANGELOG.md) for major changes on the application-side. + +The upgraded chart now the following changes: + +* Dropped support for helm v2 (helm v3 or later is required) +* collectors key was renamed to resources +* namespace key was renamed to namespaces + +## Configuration + +See [Customizing the Chart Before Installing](https://helm.sh/docs/intro/using_helm/#customizing-the-chart-before-installing). To see all configurable options with detailed comments: + +```console +helm show values prometheus-community/kube-state-metrics +``` + +### kube-rbac-proxy + +You can enable `kube-state-metrics` endpoint protection using `kube-rbac-proxy`. By setting `kubeRBACProxy.enabled: true`, this chart will deploy one RBAC proxy container per endpoint (metrics & telemetry). +To authorize access, authenticate your requests (via a `ServiceAccount` for example) with a `ClusterRole` attached such as: + +```yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: kube-state-metrics-read +rules: + - apiGroups: [ "" ] + resources: ["services/kube-state-metrics"] + verbs: + - get +``` + +See [kube-rbac-proxy examples](https://github.com/brancz/kube-rbac-proxy/tree/master/examples/resource-attributes) for more details. diff --git a/packages/system/monitoring/charts/kube-state-metrics/templates/NOTES.txt b/packages/system/monitoring/charts/kube-state-metrics/templates/NOTES.txt new file mode 100644 index 00000000..3589c24e --- /dev/null +++ b/packages/system/monitoring/charts/kube-state-metrics/templates/NOTES.txt @@ -0,0 +1,23 @@ +kube-state-metrics is a simple service that listens to the Kubernetes API server and generates metrics about the state of the objects. +The exposed metrics can be found here: +https://github.com/kubernetes/kube-state-metrics/blob/master/docs/README.md#exposed-metrics + +The metrics are exported on the HTTP endpoint /metrics on the listening port. +In your case, {{ template "kube-state-metrics.fullname" . }}.{{ template "kube-state-metrics.namespace" . }}.svc.cluster.local:{{ .Values.service.port }}/metrics + +They are served either as plaintext or protobuf depending on the Accept header. +They are designed to be consumed either by Prometheus itself or by a scraper that is compatible with scraping a Prometheus client endpoint. + +{{- if .Values.kubeRBACProxy.enabled}} + +kube-rbac-proxy endpoint protections is enabled: +- Metrics endpoints are now HTTPS +- Ensure that the client authenticates the requests (e.g. via service account) with the following role permissions: +``` +rules: + - apiGroups: [ "" ] + resources: ["services/{{ template "kube-state-metrics.fullname" . }}"] + verbs: + - get +``` +{{- end }} diff --git a/packages/system/monitoring/charts/kube-state-metrics/templates/_helpers.tpl b/packages/system/monitoring/charts/kube-state-metrics/templates/_helpers.tpl new file mode 100644 index 00000000..a4358c87 --- /dev/null +++ b/packages/system/monitoring/charts/kube-state-metrics/templates/_helpers.tpl @@ -0,0 +1,156 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "kube-state-metrics.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | 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 "kube-state-metrics.fullname" -}} +{{- if .Values.fullnameOverride -}} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- if contains $name .Release.Name -}} +{{- .Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Create the name of the service account to use +*/}} +{{- define "kube-state-metrics.serviceAccountName" -}} +{{- if .Values.serviceAccount.create -}} + {{ default (include "kube-state-metrics.fullname" .) .Values.serviceAccount.name }} +{{- else -}} + {{ default "default" .Values.serviceAccount.name }} +{{- end -}} +{{- end -}} + +{{/* +Allow the release namespace to be overridden for multi-namespace deployments in combined charts +*/}} +{{- define "kube-state-metrics.namespace" -}} + {{- if .Values.namespaceOverride -}} + {{- .Values.namespaceOverride -}} + {{- else -}} + {{- .Release.Namespace -}} + {{- end -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "kube-state-metrics.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Generate basic labels +*/}} +{{- define "kube-state-metrics.labels" }} +helm.sh/chart: {{ template "kube-state-metrics.chart" . }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +app.kubernetes.io/component: metrics +app.kubernetes.io/part-of: {{ template "kube-state-metrics.name" . }} +{{- include "kube-state-metrics.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +{{- if .Values.customLabels }} +{{ toYaml .Values.customLabels }} +{{- end }} +{{- if .Values.releaseLabel }} +release: {{ .Release.Name }} +{{- end }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "kube-state-metrics.selectorLabels" }} +{{- if .Values.selectorOverride }} +{{ toYaml .Values.selectorOverride }} +{{- else }} +app.kubernetes.io/name: {{ include "kube-state-metrics.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} +{{- end }} + +{{/* Sets default scrape limits for servicemonitor */}} +{{- define "servicemonitor.scrapeLimits" -}} +{{- with .sampleLimit }} +sampleLimit: {{ . }} +{{- end }} +{{- with .targetLimit }} +targetLimit: {{ . }} +{{- end }} +{{- with .labelLimit }} +labelLimit: {{ . }} +{{- end }} +{{- with .labelNameLengthLimit }} +labelNameLengthLimit: {{ . }} +{{- end }} +{{- with .labelValueLengthLimit }} +labelValueLengthLimit: {{ . }} +{{- end }} +{{- end -}} + +{{/* +Formats imagePullSecrets. Input is (dict "Values" .Values "imagePullSecrets" .{specific imagePullSecrets}) +*/}} +{{- define "kube-state-metrics.imagePullSecrets" -}} +{{- range (concat .Values.global.imagePullSecrets .imagePullSecrets) }} + {{- if eq (typeOf .) "map[string]interface {}" }} +- {{ toYaml . | trim }} + {{- else }} +- name: {{ . }} + {{- end }} +{{- end }} +{{- end -}} + +{{/* +The image to use for kube-state-metrics +*/}} +{{- define "kube-state-metrics.image" -}} +{{- if .Values.image.sha }} +{{- if .Values.global.imageRegistry }} +{{- printf "%s/%s:%s@%s" .Values.global.imageRegistry .Values.image.repository (default (printf "v%s" .Chart.AppVersion) .Values.image.tag) .Values.image.sha }} +{{- else }} +{{- printf "%s/%s:%s@%s" .Values.image.registry .Values.image.repository (default (printf "v%s" .Chart.AppVersion) .Values.image.tag) .Values.image.sha }} +{{- end }} +{{- else }} +{{- if .Values.global.imageRegistry }} +{{- printf "%s/%s:%s" .Values.global.imageRegistry .Values.image.repository (default (printf "v%s" .Chart.AppVersion) .Values.image.tag) }} +{{- else }} +{{- printf "%s/%s:%s" .Values.image.registry .Values.image.repository (default (printf "v%s" .Chart.AppVersion) .Values.image.tag) }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +The image to use for kubeRBACProxy +*/}} +{{- define "kubeRBACProxy.image" -}} +{{- if .Values.kubeRBACProxy.image.sha }} +{{- if .Values.global.imageRegistry }} +{{- printf "%s/%s:%s@%s" .Values.global.imageRegistry .Values.kubeRBACProxy.image.repository (default (printf "v%s" .Chart.AppVersion) .Values.kubeRBACProxy.image.tag) .Values.kubeRBACProxy.image.sha }} +{{- else }} +{{- printf "%s/%s:%s@%s" .Values.kubeRBACProxy.image.registry .Values.kubeRBACProxy.image.repository (default (printf "v%s" .Chart.AppVersion) .Values.kubeRBACProxy.image.tag) .Values.kubeRBACProxy.image.sha }} +{{- end }} +{{- else }} +{{- if .Values.global.imageRegistry }} +{{- printf "%s/%s:%s" .Values.global.imageRegistry .Values.kubeRBACProxy.image.repository (default (printf "v%s" .Chart.AppVersion) .Values.kubeRBACProxy.image.tag) }} +{{- else }} +{{- printf "%s/%s:%s" .Values.kubeRBACProxy.image.registry .Values.kubeRBACProxy.image.repository (default (printf "v%s" .Chart.AppVersion) .Values.kubeRBACProxy.image.tag) }} +{{- end }} +{{- end }} +{{- end }} diff --git a/packages/system/monitoring/charts/kube-state-metrics/templates/ciliumnetworkpolicy.yaml b/packages/system/monitoring/charts/kube-state-metrics/templates/ciliumnetworkpolicy.yaml new file mode 100644 index 00000000..025cd47a --- /dev/null +++ b/packages/system/monitoring/charts/kube-state-metrics/templates/ciliumnetworkpolicy.yaml @@ -0,0 +1,33 @@ +{{- if and .Values.networkPolicy.enabled (eq .Values.networkPolicy.flavor "cilium") }} +apiVersion: cilium.io/v2 +kind: CiliumNetworkPolicy +metadata: + {{- if .Values.annotations }} + annotations: + {{ toYaml .Values.annotations | nindent 4 }} + {{- end }} + labels: + {{- include "kube-state-metrics.labels" . | indent 4 }} + name: {{ template "kube-state-metrics.fullname" . }} + namespace: {{ template "kube-state-metrics.namespace" . }} +spec: + endpointSelector: + matchLabels: + {{- include "kube-state-metrics.selectorLabels" . | indent 6 }} + egress: + {{- if and .Values.networkPolicy.cilium .Values.networkPolicy.cilium.kubeApiServerSelector }} + {{ toYaml .Values.networkPolicy.cilium.kubeApiServerSelector | nindent 6 }} + {{- else }} + - toEntities: + - kube-apiserver + {{- end }} + ingress: + - toPorts: + - ports: + - port: {{ .Values.service.port | quote }} + protocol: TCP + {{- if .Values.selfMonitor.enabled }} + - port: {{ .Values.selfMonitor.telemetryPort | default 8081 | quote }} + protocol: TCP + {{ end }} +{{ end }} diff --git a/packages/system/monitoring/charts/kube-state-metrics/templates/clusterrolebinding.yaml b/packages/system/monitoring/charts/kube-state-metrics/templates/clusterrolebinding.yaml new file mode 100644 index 00000000..cf9f628d --- /dev/null +++ b/packages/system/monitoring/charts/kube-state-metrics/templates/clusterrolebinding.yaml @@ -0,0 +1,20 @@ +{{- if and .Values.rbac.create .Values.rbac.useClusterRole -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + labels: + {{- include "kube-state-metrics.labels" . | indent 4 }} + name: {{ template "kube-state-metrics.fullname" . }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole +{{- if .Values.rbac.useExistingRole }} + name: {{ .Values.rbac.useExistingRole }} +{{- else }} + name: {{ template "kube-state-metrics.fullname" . }} +{{- end }} +subjects: +- kind: ServiceAccount + name: {{ template "kube-state-metrics.serviceAccountName" . }} + namespace: {{ template "kube-state-metrics.namespace" . }} +{{- end -}} diff --git a/packages/system/monitoring/charts/kube-state-metrics/templates/crs-configmap.yaml b/packages/system/monitoring/charts/kube-state-metrics/templates/crs-configmap.yaml new file mode 100644 index 00000000..d38a75a5 --- /dev/null +++ b/packages/system/monitoring/charts/kube-state-metrics/templates/crs-configmap.yaml @@ -0,0 +1,16 @@ +{{- if .Values.customResourceState.enabled}} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ template "kube-state-metrics.fullname" . }}-customresourcestate-config + namespace: {{ template "kube-state-metrics.namespace" . }} + labels: + {{- include "kube-state-metrics.labels" . | indent 4 }} + {{- if .Values.annotations }} + annotations: + {{ toYaml .Values.annotations | nindent 4 }} + {{- end }} +data: + config.yaml: | + {{- toYaml .Values.customResourceState.config | nindent 4 }} +{{- end }} diff --git a/packages/system/monitoring/charts/kube-state-metrics/templates/deployment.yaml b/packages/system/monitoring/charts/kube-state-metrics/templates/deployment.yaml new file mode 100644 index 00000000..2aedc920 --- /dev/null +++ b/packages/system/monitoring/charts/kube-state-metrics/templates/deployment.yaml @@ -0,0 +1,290 @@ +apiVersion: apps/v1 +{{- if .Values.autosharding.enabled }} +kind: StatefulSet +{{- else }} +kind: Deployment +{{- end }} +metadata: + name: {{ template "kube-state-metrics.fullname" . }} + namespace: {{ template "kube-state-metrics.namespace" . }} + labels: + {{- include "kube-state-metrics.labels" . | indent 4 }} + {{- if .Values.annotations }} + annotations: +{{ toYaml .Values.annotations | indent 4 }} + {{- end }} +spec: + selector: + matchLabels: + {{- include "kube-state-metrics.selectorLabels" . | indent 6 }} + replicas: {{ .Values.replicas }} + {{- if not .Values.autosharding.enabled }} + strategy: + type: {{ .Values.updateStrategy | default "RollingUpdate" }} + {{- end }} + revisionHistoryLimit: {{ .Values.revisionHistoryLimit }} + {{- if .Values.autosharding.enabled }} + serviceName: {{ template "kube-state-metrics.fullname" . }} + volumeClaimTemplates: [] + {{- end }} + template: + metadata: + labels: + {{- include "kube-state-metrics.labels" . | indent 8 }} + {{- if .Values.podAnnotations }} + annotations: +{{ toYaml .Values.podAnnotations | indent 8 }} + {{- end }} + spec: + hostNetwork: {{ .Values.hostNetwork }} + serviceAccountName: {{ template "kube-state-metrics.serviceAccountName" . }} + {{- if .Values.securityContext.enabled }} + securityContext: {{- omit .Values.securityContext "enabled" | toYaml | nindent 8 }} + {{- end }} + {{- if .Values.priorityClassName }} + priorityClassName: {{ .Values.priorityClassName }} + {{- end }} + {{- with .Values.initContainers }} + initContainers: + {{- toYaml . | nindent 6 }} + {{- end }} + containers: + {{- $httpPort := ternary 9090 (.Values.service.port | default 8080) .Values.kubeRBACProxy.enabled}} + {{- $telemetryPort := ternary 9091 (.Values.selfMonitor.telemetryPort | default 8081) .Values.kubeRBACProxy.enabled}} + - name: {{ template "kube-state-metrics.name" . }} + {{- if .Values.autosharding.enabled }} + env: + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + {{- end }} + args: + {{- if .Values.extraArgs }} + {{- .Values.extraArgs | toYaml | nindent 8 }} + {{- end }} + - --port={{ $httpPort }} + {{- if .Values.collectors }} + - --resources={{ .Values.collectors | join "," }} + {{- end }} + {{- if .Values.metricLabelsAllowlist }} + - --metric-labels-allowlist={{ .Values.metricLabelsAllowlist | join "," }} + {{- end }} + {{- if .Values.metricAnnotationsAllowList }} + - --metric-annotations-allowlist={{ .Values.metricAnnotationsAllowList | join "," }} + {{- end }} + {{- if .Values.metricAllowlist }} + - --metric-allowlist={{ .Values.metricAllowlist | join "," }} + {{- end }} + {{- if .Values.metricDenylist }} + - --metric-denylist={{ .Values.metricDenylist | join "," }} + {{- end }} + {{- $namespaces := list }} + {{- if .Values.namespaces }} + {{- range $ns := join "," .Values.namespaces | split "," }} + {{- $namespaces = append $namespaces (tpl $ns $) }} + {{- end }} + {{- end }} + {{- if .Values.releaseNamespace }} + {{- $namespaces = append $namespaces ( include "kube-state-metrics.namespace" . ) }} + {{- end }} + {{- if $namespaces }} + - --namespaces={{ $namespaces | mustUniq | join "," }} + {{- end }} + {{- if .Values.namespacesDenylist }} + - --namespaces-denylist={{ tpl (.Values.namespacesDenylist | join ",") $ }} + {{- end }} + {{- if .Values.autosharding.enabled }} + - --pod=$(POD_NAME) + - --pod-namespace=$(POD_NAMESPACE) + {{- end }} + {{- if .Values.kubeconfig.enabled }} + - --kubeconfig=/opt/k8s/.kube/config + {{- end }} + {{- if .Values.kubeRBACProxy.enabled }} + - --telemetry-host=127.0.0.1 + - --telemetry-port={{ $telemetryPort }} + {{- else }} + {{- if .Values.selfMonitor.telemetryHost }} + - --telemetry-host={{ .Values.selfMonitor.telemetryHost }} + {{- end }} + {{- if .Values.selfMonitor.telemetryPort }} + - --telemetry-port={{ $telemetryPort }} + {{- end }} + {{- if .Values.customResourceState.enabled }} + - --custom-resource-state-config-file=/etc/customresourcestate/config.yaml + {{- end }} + {{- end }} + {{- if or (.Values.kubeconfig.enabled) (.Values.customResourceState.enabled) (.Values.volumeMounts) }} + volumeMounts: + {{- if .Values.kubeconfig.enabled }} + - name: kubeconfig + mountPath: /opt/k8s/.kube/ + readOnly: true + {{- end }} + {{- if .Values.customResourceState.enabled }} + - name: customresourcestate-config + mountPath: /etc/customresourcestate + readOnly: true + {{- end }} + {{- if .Values.volumeMounts }} +{{ toYaml .Values.volumeMounts | indent 8 }} + {{- end }} + {{- end }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + image: {{ include "kube-state-metrics.image" . }} + {{- if eq .Values.kubeRBACProxy.enabled false }} + ports: + - containerPort: {{ .Values.service.port | default 8080}} + name: "http" + {{- if .Values.selfMonitor.enabled }} + - containerPort: {{ $telemetryPort }} + name: "metrics" + {{- end }} + {{- end }} + livenessProbe: + httpGet: + path: /healthz + port: {{ $httpPort }} + initialDelaySeconds: 5 + timeoutSeconds: 5 + readinessProbe: + httpGet: + path: / + port: {{ $httpPort }} + initialDelaySeconds: 5 + timeoutSeconds: 5 + {{- if .Values.resources }} + resources: +{{ toYaml .Values.resources | indent 10 }} +{{- end }} +{{- if .Values.containerSecurityContext }} + securityContext: +{{ toYaml .Values.containerSecurityContext | indent 10 }} +{{- end }} + {{- if .Values.kubeRBACProxy.enabled }} + - name: kube-rbac-proxy-http + args: + {{- if .Values.kubeRBACProxy.extraArgs }} + {{- .Values.kubeRBACProxy.extraArgs | toYaml | nindent 8 }} + {{- end }} + - --secure-listen-address=:{{ .Values.service.port | default 8080}} + - --upstream=http://127.0.0.1:{{ $httpPort }}/ + - --proxy-endpoints-port=8888 + - --config-file=/etc/kube-rbac-proxy-config/config-file.yaml + volumeMounts: + - name: kube-rbac-proxy-config + mountPath: /etc/kube-rbac-proxy-config + {{- with .Values.kubeRBACProxy.volumeMounts }} + {{- toYaml . | nindent 10 }} + {{- end }} + imagePullPolicy: {{ .Values.kubeRBACProxy.image.pullPolicy }} + image: {{ include "kubeRBACProxy.image" . }} + ports: + - containerPort: {{ .Values.service.port | default 8080}} + name: "http" + - containerPort: 8888 + name: "http-healthz" + readinessProbe: + httpGet: + scheme: HTTPS + port: 8888 + path: healthz + initialDelaySeconds: 5 + timeoutSeconds: 5 + {{- if .Values.kubeRBACProxy.resources }} + resources: +{{ toYaml .Values.kubeRBACProxy.resources | indent 10 }} +{{- end }} +{{- if .Values.kubeRBACProxy.containerSecurityContext }} + securityContext: +{{ toYaml .Values.kubeRBACProxy.containerSecurityContext | indent 10 }} +{{- end }} + {{- if .Values.selfMonitor.enabled }} + - name: kube-rbac-proxy-telemetry + args: + {{- if .Values.kubeRBACProxy.extraArgs }} + {{- .Values.kubeRBACProxy.extraArgs | toYaml | nindent 8 }} + {{- end }} + - --secure-listen-address=:{{ .Values.selfMonitor.telemetryPort | default 8081 }} + - --upstream=http://127.0.0.1:{{ $telemetryPort }}/ + - --proxy-endpoints-port=8889 + - --config-file=/etc/kube-rbac-proxy-config/config-file.yaml + volumeMounts: + - name: kube-rbac-proxy-config + mountPath: /etc/kube-rbac-proxy-config + {{- with .Values.kubeRBACProxy.volumeMounts }} + {{- toYaml . | nindent 10 }} + {{- end }} + imagePullPolicy: {{ .Values.kubeRBACProxy.image.pullPolicy }} + image: {{ include "kubeRBACProxy.image" . }} + ports: + - containerPort: {{ .Values.selfMonitor.telemetryPort | default 8081 }} + name: "metrics" + - containerPort: 8889 + name: "metrics-healthz" + readinessProbe: + httpGet: + scheme: HTTPS + port: 8889 + path: healthz + initialDelaySeconds: 5 + timeoutSeconds: 5 + {{- if .Values.kubeRBACProxy.resources }} + resources: +{{ toYaml .Values.kubeRBACProxy.resources | indent 10 }} +{{- end }} +{{- if .Values.kubeRBACProxy.containerSecurityContext }} + securityContext: +{{ toYaml .Values.kubeRBACProxy.containerSecurityContext | indent 10 }} +{{- end }} + {{- end }} + {{- end }} + {{- with .Values.containers }} + {{- toYaml . | nindent 6 }} + {{- end }} +{{- if or .Values.imagePullSecrets .Values.global.imagePullSecrets }} + imagePullSecrets: + {{- include "kube-state-metrics.imagePullSecrets" (dict "Values" .Values "imagePullSecrets" .Values.imagePullSecrets) | indent 8 }} + {{- end }} + {{- if .Values.affinity }} + affinity: +{{ toYaml .Values.affinity | indent 8 }} + {{- end }} + {{- if .Values.nodeSelector }} + nodeSelector: +{{ toYaml .Values.nodeSelector | indent 8 }} + {{- end }} + {{- if .Values.tolerations }} + tolerations: +{{ toYaml .Values.tolerations | indent 8 }} + {{- end }} + {{- if .Values.topologySpreadConstraints }} + topologySpreadConstraints: +{{ toYaml .Values.topologySpreadConstraints | indent 8 }} + {{- end }} + {{- if or (.Values.kubeconfig.enabled) (.Values.customResourceState.enabled) (.Values.volumes) (.Values.kubeRBACProxy.enabled) }} + volumes: + {{- if .Values.kubeconfig.enabled}} + - name: kubeconfig + secret: + secretName: {{ template "kube-state-metrics.fullname" . }}-kubeconfig + {{- end }} + {{- if .Values.kubeRBACProxy.enabled}} + - name: kube-rbac-proxy-config + configMap: + name: {{ template "kube-state-metrics.fullname" . }}-rbac-config + {{- end }} + {{- if .Values.customResourceState.enabled}} + - name: customresourcestate-config + configMap: + name: {{ template "kube-state-metrics.fullname" . }}-customresourcestate-config + {{- end }} + {{- if .Values.volumes }} +{{ toYaml .Values.volumes | indent 8 }} + {{- end }} + {{- end }} diff --git a/packages/system/monitoring/charts/kube-state-metrics/templates/extra-manifests.yaml b/packages/system/monitoring/charts/kube-state-metrics/templates/extra-manifests.yaml new file mode 100644 index 00000000..567f7bf3 --- /dev/null +++ b/packages/system/monitoring/charts/kube-state-metrics/templates/extra-manifests.yaml @@ -0,0 +1,4 @@ +{{ range .Values.extraManifests }} +--- +{{ tpl (toYaml .) $ }} +{{ end }} diff --git a/packages/system/monitoring/charts/kube-state-metrics/templates/kubeconfig-secret.yaml b/packages/system/monitoring/charts/kube-state-metrics/templates/kubeconfig-secret.yaml new file mode 100644 index 00000000..6af00845 --- /dev/null +++ b/packages/system/monitoring/charts/kube-state-metrics/templates/kubeconfig-secret.yaml @@ -0,0 +1,12 @@ +{{- if .Values.kubeconfig.enabled -}} +apiVersion: v1 +kind: Secret +metadata: + name: {{ template "kube-state-metrics.fullname" . }}-kubeconfig + namespace: {{ template "kube-state-metrics.namespace" . }} + labels: + {{- include "kube-state-metrics.labels" . | indent 4 }} +type: Opaque +data: + config: '{{ .Values.kubeconfig.secret }}' +{{- end -}} diff --git a/packages/system/monitoring/charts/kube-state-metrics/templates/networkpolicy.yaml b/packages/system/monitoring/charts/kube-state-metrics/templates/networkpolicy.yaml new file mode 100644 index 00000000..309b38ec --- /dev/null +++ b/packages/system/monitoring/charts/kube-state-metrics/templates/networkpolicy.yaml @@ -0,0 +1,43 @@ +{{- if and .Values.networkPolicy.enabled (eq .Values.networkPolicy.flavor "kubernetes") }} +kind: NetworkPolicy +apiVersion: networking.k8s.io/v1 +metadata: + {{- if .Values.annotations }} + annotations: + {{ toYaml .Values.annotations | nindent 4 }} + {{- end }} + labels: + {{- include "kube-state-metrics.labels" . | indent 4 }} + name: {{ template "kube-state-metrics.fullname" . }} + namespace: {{ template "kube-state-metrics.namespace" . }} +spec: + {{- if .Values.networkPolicy.egress }} + ## Deny all egress by default + egress: + {{- toYaml .Values.networkPolicy.egress | nindent 4 }} + {{- end }} + ingress: + {{- if .Values.networkPolicy.ingress }} + {{- toYaml .Values.networkPolicy.ingress | nindent 4 }} + {{- else }} + ## Allow ingress on default ports by default + - ports: + - port: {{ .Values.service.port | default 8080 }} + protocol: TCP + {{- if .Values.selfMonitor.enabled }} + {{- $telemetryPort := ternary 9091 (.Values.selfMonitor.telemetryPort | default 8081) .Values.kubeRBACProxy.enabled}} + - port: {{ $telemetryPort }} + protocol: TCP + {{- end }} + {{- end }} + podSelector: + {{- if .Values.networkPolicy.podSelector }} + {{- toYaml .Values.networkPolicy.podSelector | nindent 4 }} + {{- else }} + matchLabels: + {{- include "kube-state-metrics.selectorLabels" . | indent 6 }} + {{- end }} + policyTypes: + - Ingress + - Egress +{{- end }} diff --git a/packages/system/monitoring/charts/kube-state-metrics/templates/pdb.yaml b/packages/system/monitoring/charts/kube-state-metrics/templates/pdb.yaml new file mode 100644 index 00000000..3771b511 --- /dev/null +++ b/packages/system/monitoring/charts/kube-state-metrics/templates/pdb.yaml @@ -0,0 +1,18 @@ +{{- if .Values.podDisruptionBudget -}} +{{ if $.Capabilities.APIVersions.Has "policy/v1/PodDisruptionBudget" -}} +apiVersion: policy/v1 +{{- else -}} +apiVersion: policy/v1beta1 +{{- end }} +kind: PodDisruptionBudget +metadata: + name: {{ template "kube-state-metrics.fullname" . }} + namespace: {{ template "kube-state-metrics.namespace" . }} + labels: + {{- include "kube-state-metrics.labels" . | indent 4 }} +spec: + selector: + matchLabels: + app.kubernetes.io/name: {{ template "kube-state-metrics.name" . }} +{{ toYaml .Values.podDisruptionBudget | indent 2 }} +{{- end -}} diff --git a/packages/system/monitoring/charts/kube-state-metrics/templates/podsecuritypolicy.yaml b/packages/system/monitoring/charts/kube-state-metrics/templates/podsecuritypolicy.yaml new file mode 100644 index 00000000..8905e113 --- /dev/null +++ b/packages/system/monitoring/charts/kube-state-metrics/templates/podsecuritypolicy.yaml @@ -0,0 +1,39 @@ +{{- if and .Values.podSecurityPolicy.enabled (.Capabilities.APIVersions.Has "policy/v1beta1/PodSecurityPolicy") }} +apiVersion: policy/v1beta1 +kind: PodSecurityPolicy +metadata: + name: {{ template "kube-state-metrics.fullname" . }} + labels: + {{- include "kube-state-metrics.labels" . | indent 4 }} +{{- if .Values.podSecurityPolicy.annotations }} + annotations: +{{ toYaml .Values.podSecurityPolicy.annotations | indent 4 }} +{{- end }} +spec: + privileged: false + volumes: + - 'secret' +{{- if .Values.podSecurityPolicy.additionalVolumes }} +{{ toYaml .Values.podSecurityPolicy.additionalVolumes | indent 4 }} +{{- end }} + hostNetwork: false + hostIPC: false + hostPID: false + runAsUser: + rule: 'MustRunAsNonRoot' + seLinux: + rule: 'RunAsAny' + supplementalGroups: + rule: 'MustRunAs' + ranges: + # Forbid adding the root group. + - min: 1 + max: 65535 + fsGroup: + rule: 'MustRunAs' + ranges: + # Forbid adding the root group. + - min: 1 + max: 65535 + readOnlyRootFilesystem: false +{{- end }} diff --git a/packages/system/monitoring/charts/kube-state-metrics/templates/psp-clusterrole.yaml b/packages/system/monitoring/charts/kube-state-metrics/templates/psp-clusterrole.yaml new file mode 100644 index 00000000..654e4a3d --- /dev/null +++ b/packages/system/monitoring/charts/kube-state-metrics/templates/psp-clusterrole.yaml @@ -0,0 +1,19 @@ +{{- if and .Values.podSecurityPolicy.enabled (.Capabilities.APIVersions.Has "policy/v1beta1/PodSecurityPolicy") }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + {{- include "kube-state-metrics.labels" . | indent 4 }} + name: psp-{{ template "kube-state-metrics.fullname" . }} +rules: +{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} +{{- if semverCompare "> 1.15.0-0" $kubeTargetVersion }} +- apiGroups: ['policy'] +{{- else }} +- apiGroups: ['extensions'] +{{- end }} + resources: ['podsecuritypolicies'] + verbs: ['use'] + resourceNames: + - {{ template "kube-state-metrics.fullname" . }} +{{- end }} diff --git a/packages/system/monitoring/charts/kube-state-metrics/templates/psp-clusterrolebinding.yaml b/packages/system/monitoring/charts/kube-state-metrics/templates/psp-clusterrolebinding.yaml new file mode 100644 index 00000000..5b62a18b --- /dev/null +++ b/packages/system/monitoring/charts/kube-state-metrics/templates/psp-clusterrolebinding.yaml @@ -0,0 +1,16 @@ +{{- if and .Values.podSecurityPolicy.enabled (.Capabilities.APIVersions.Has "policy/v1beta1/PodSecurityPolicy") }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + labels: + {{- include "kube-state-metrics.labels" . | indent 4 }} + name: psp-{{ template "kube-state-metrics.fullname" . }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: psp-{{ template "kube-state-metrics.fullname" . }} +subjects: + - kind: ServiceAccount + name: {{ template "kube-state-metrics.serviceAccountName" . }} + namespace: {{ template "kube-state-metrics.namespace" . }} +{{- end }} diff --git a/packages/system/monitoring/charts/kube-state-metrics/templates/rbac-configmap.yaml b/packages/system/monitoring/charts/kube-state-metrics/templates/rbac-configmap.yaml new file mode 100644 index 00000000..671dc9d6 --- /dev/null +++ b/packages/system/monitoring/charts/kube-state-metrics/templates/rbac-configmap.yaml @@ -0,0 +1,22 @@ +{{- if .Values.kubeRBACProxy.enabled}} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ template "kube-state-metrics.fullname" . }}-rbac-config + namespace: {{ template "kube-state-metrics.namespace" . }} + labels: + {{- include "kube-state-metrics.labels" . | indent 4 }} + {{- if .Values.annotations }} + annotations: + {{ toYaml .Values.annotations | nindent 4 }} + {{- end }} +data: + config-file.yaml: |+ + authorization: + resourceAttributes: + namespace: {{ template "kube-state-metrics.namespace" . }} + apiVersion: v1 + resource: services + subresource: {{ template "kube-state-metrics.fullname" . }} + name: {{ template "kube-state-metrics.fullname" . }} +{{- end }} diff --git a/packages/system/monitoring/charts/kube-state-metrics/templates/role.yaml b/packages/system/monitoring/charts/kube-state-metrics/templates/role.yaml new file mode 100644 index 00000000..d33687f2 --- /dev/null +++ b/packages/system/monitoring/charts/kube-state-metrics/templates/role.yaml @@ -0,0 +1,212 @@ +{{- if and (eq .Values.rbac.create true) (not .Values.rbac.useExistingRole) -}} +{{- range (ternary (join "," .Values.namespaces | split "," ) (list "") (eq $.Values.rbac.useClusterRole false)) }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +{{- if eq $.Values.rbac.useClusterRole false }} +kind: Role +{{- else }} +kind: ClusterRole +{{- end }} +metadata: + labels: + {{- include "kube-state-metrics.labels" $ | indent 4 }} + name: {{ template "kube-state-metrics.fullname" $ }} +{{- if eq $.Values.rbac.useClusterRole false }} + namespace: {{ . }} +{{- end }} +rules: +{{ if has "certificatesigningrequests" $.Values.collectors }} +- apiGroups: ["certificates.k8s.io"] + resources: + - certificatesigningrequests + verbs: ["list", "watch"] +{{ end -}} +{{ if has "configmaps" $.Values.collectors }} +- apiGroups: [""] + resources: + - configmaps + verbs: ["list", "watch"] +{{ end -}} +{{ if has "cronjobs" $.Values.collectors }} +- apiGroups: ["batch"] + resources: + - cronjobs + verbs: ["list", "watch"] +{{ end -}} +{{ if has "daemonsets" $.Values.collectors }} +- apiGroups: ["extensions", "apps"] + resources: + - daemonsets + verbs: ["list", "watch"] +{{ end -}} +{{ if has "deployments" $.Values.collectors }} +- apiGroups: ["extensions", "apps"] + resources: + - deployments + verbs: ["list", "watch"] +{{ end -}} +{{ if has "endpoints" $.Values.collectors }} +- apiGroups: [""] + resources: + - endpoints + verbs: ["list", "watch"] +{{ end -}} +{{ if has "endpointslices" $.Values.collectors }} +- apiGroups: ["discovery.k8s.io"] + resources: + - endpointslices + verbs: ["list", "watch"] +{{ end -}} +{{ if has "horizontalpodautoscalers" $.Values.collectors }} +- apiGroups: ["autoscaling"] + resources: + - horizontalpodautoscalers + verbs: ["list", "watch"] +{{ end -}} +{{ if has "ingresses" $.Values.collectors }} +- apiGroups: ["extensions", "networking.k8s.io"] + resources: + - ingresses + verbs: ["list", "watch"] +{{ end -}} +{{ if has "jobs" $.Values.collectors }} +- apiGroups: ["batch"] + resources: + - jobs + verbs: ["list", "watch"] +{{ end -}} +{{ if has "leases" $.Values.collectors }} +- apiGroups: ["coordination.k8s.io"] + resources: + - leases + verbs: ["list", "watch"] +{{ end -}} +{{ if has "limitranges" $.Values.collectors }} +- apiGroups: [""] + resources: + - limitranges + verbs: ["list", "watch"] +{{ end -}} +{{ if has "mutatingwebhookconfigurations" $.Values.collectors }} +- apiGroups: ["admissionregistration.k8s.io"] + resources: + - mutatingwebhookconfigurations + verbs: ["list", "watch"] +{{ end -}} +{{ if has "namespaces" $.Values.collectors }} +- apiGroups: [""] + resources: + - namespaces + verbs: ["list", "watch"] +{{ end -}} +{{ if has "networkpolicies" $.Values.collectors }} +- apiGroups: ["networking.k8s.io"] + resources: + - networkpolicies + verbs: ["list", "watch"] +{{ end -}} +{{ if has "nodes" $.Values.collectors }} +- apiGroups: [""] + resources: + - nodes + verbs: ["list", "watch"] +{{ end -}} +{{ if has "persistentvolumeclaims" $.Values.collectors }} +- apiGroups: [""] + resources: + - persistentvolumeclaims + verbs: ["list", "watch"] +{{ end -}} +{{ if has "persistentvolumes" $.Values.collectors }} +- apiGroups: [""] + resources: + - persistentvolumes + verbs: ["list", "watch"] +{{ end -}} +{{ if has "poddisruptionbudgets" $.Values.collectors }} +- apiGroups: ["policy"] + resources: + - poddisruptionbudgets + verbs: ["list", "watch"] +{{ end -}} +{{ if has "pods" $.Values.collectors }} +- apiGroups: [""] + resources: + - pods + verbs: ["list", "watch"] +{{ end -}} +{{ if has "replicasets" $.Values.collectors }} +- apiGroups: ["extensions", "apps"] + resources: + - replicasets + verbs: ["list", "watch"] +{{ end -}} +{{ if has "replicationcontrollers" $.Values.collectors }} +- apiGroups: [""] + resources: + - replicationcontrollers + verbs: ["list", "watch"] +{{ end -}} +{{ if has "resourcequotas" $.Values.collectors }} +- apiGroups: [""] + resources: + - resourcequotas + verbs: ["list", "watch"] +{{ end -}} +{{ if has "secrets" $.Values.collectors }} +- apiGroups: [""] + resources: + - secrets + verbs: ["list", "watch"] +{{ end -}} +{{ if has "services" $.Values.collectors }} +- apiGroups: [""] + resources: + - services + verbs: ["list", "watch"] +{{ end -}} +{{ if has "statefulsets" $.Values.collectors }} +- apiGroups: ["apps"] + resources: + - statefulsets + verbs: ["list", "watch"] +{{ end -}} +{{ if has "storageclasses" $.Values.collectors }} +- apiGroups: ["storage.k8s.io"] + resources: + - storageclasses + verbs: ["list", "watch"] +{{ end -}} +{{ if has "validatingwebhookconfigurations" $.Values.collectors }} +- apiGroups: ["admissionregistration.k8s.io"] + resources: + - validatingwebhookconfigurations + verbs: ["list", "watch"] +{{ end -}} +{{ if has "volumeattachments" $.Values.collectors }} +- apiGroups: ["storage.k8s.io"] + resources: + - volumeattachments + verbs: ["list", "watch"] +{{ end -}} +{{- if $.Values.kubeRBACProxy.enabled }} +- apiGroups: ["authentication.k8s.io"] + resources: + - tokenreviews + verbs: ["create"] +- apiGroups: ["authorization.k8s.io"] + resources: + - subjectaccessreviews + verbs: ["create"] +{{- end }} +{{- if $.Values.customResourceState.enabled }} +- apiGroups: ["apiextensions.k8s.io"] + resources: + - customresourcedefinitions + verbs: ["list", "watch"] +{{- end }} +{{ if $.Values.rbac.extraRules }} +{{ toYaml $.Values.rbac.extraRules }} +{{ end }} +{{- end -}} +{{- end -}} diff --git a/packages/system/monitoring/charts/kube-state-metrics/templates/rolebinding.yaml b/packages/system/monitoring/charts/kube-state-metrics/templates/rolebinding.yaml new file mode 100644 index 00000000..330651b7 --- /dev/null +++ b/packages/system/monitoring/charts/kube-state-metrics/templates/rolebinding.yaml @@ -0,0 +1,24 @@ +{{- if and (eq .Values.rbac.create true) (eq .Values.rbac.useClusterRole false) -}} +{{- range (join "," $.Values.namespaces) | split "," }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + labels: + {{- include "kube-state-metrics.labels" $ | indent 4 }} + name: {{ template "kube-state-metrics.fullname" $ }} + namespace: {{ . }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role +{{- if (not $.Values.rbac.useExistingRole) }} + name: {{ template "kube-state-metrics.fullname" $ }} +{{- else }} + name: {{ $.Values.rbac.useExistingRole }} +{{- end }} +subjects: +- kind: ServiceAccount + name: {{ template "kube-state-metrics.serviceAccountName" $ }} + namespace: {{ template "kube-state-metrics.namespace" $ }} +{{- end -}} +{{- end -}} diff --git a/packages/system/monitoring/charts/kube-state-metrics/templates/service.yaml b/packages/system/monitoring/charts/kube-state-metrics/templates/service.yaml new file mode 100644 index 00000000..6c486a66 --- /dev/null +++ b/packages/system/monitoring/charts/kube-state-metrics/templates/service.yaml @@ -0,0 +1,49 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ template "kube-state-metrics.fullname" . }} + namespace: {{ template "kube-state-metrics.namespace" . }} + labels: + {{- include "kube-state-metrics.labels" . | indent 4 }} + annotations: + {{- if .Values.prometheusScrape }} + prometheus.io/scrape: '{{ .Values.prometheusScrape }}' + {{- end }} + {{- if .Values.service.annotations }} + {{- toYaml .Values.service.annotations | nindent 4 }} + {{- end }} +spec: + type: "{{ .Values.service.type }}" + ports: + - name: "http" + protocol: TCP + port: {{ .Values.service.port | default 8080}} + {{- if .Values.service.nodePort }} + nodePort: {{ .Values.service.nodePort }} + {{- end }} + targetPort: {{ .Values.service.port | default 8080}} + {{ if .Values.selfMonitor.enabled }} + - name: "metrics" + protocol: TCP + port: {{ .Values.selfMonitor.telemetryPort | default 8081 }} + targetPort: {{ .Values.selfMonitor.telemetryPort | default 8081 }} + {{- if .Values.selfMonitor.telemetryNodePort }} + nodePort: {{ .Values.selfMonitor.telemetryNodePort }} + {{- end }} + {{ end }} +{{- if .Values.service.loadBalancerIP }} + loadBalancerIP: "{{ .Values.service.loadBalancerIP }}" +{{- end }} +{{- if .Values.service.loadBalancerSourceRanges }} + loadBalancerSourceRanges: + {{- range $cidr := .Values.service.loadBalancerSourceRanges }} + - {{ $cidr }} + {{- end }} +{{- end }} +{{- if .Values.autosharding.enabled }} + clusterIP: None +{{- else if .Values.service.clusterIP }} + clusterIP: "{{ .Values.service.clusterIP }}" +{{- end }} + selector: + {{- include "kube-state-metrics.selectorLabels" . | indent 4 }} diff --git a/packages/system/monitoring/charts/kube-state-metrics/templates/serviceaccount.yaml b/packages/system/monitoring/charts/kube-state-metrics/templates/serviceaccount.yaml new file mode 100644 index 00000000..a7ff4dd3 --- /dev/null +++ b/packages/system/monitoring/charts/kube-state-metrics/templates/serviceaccount.yaml @@ -0,0 +1,15 @@ +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + labels: + {{- include "kube-state-metrics.labels" . | indent 4 }} + name: {{ template "kube-state-metrics.serviceAccountName" . }} + namespace: {{ template "kube-state-metrics.namespace" . }} +{{- if .Values.serviceAccount.annotations }} + annotations: +{{ toYaml .Values.serviceAccount.annotations | indent 4 }} +{{- end }} +imagePullSecrets: + {{- include "kube-state-metrics.imagePullSecrets" (dict "Values" .Values "imagePullSecrets" .Values.serviceAccount.imagePullSecrets) | indent 2 }} +{{- end -}} diff --git a/packages/system/monitoring/charts/kube-state-metrics/templates/servicemonitor.yaml b/packages/system/monitoring/charts/kube-state-metrics/templates/servicemonitor.yaml new file mode 100644 index 00000000..e2cde649 --- /dev/null +++ b/packages/system/monitoring/charts/kube-state-metrics/templates/servicemonitor.yaml @@ -0,0 +1,120 @@ +{{- if .Values.prometheus.monitor.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ template "kube-state-metrics.fullname" . }} + namespace: {{ template "kube-state-metrics.namespace" . }} + labels: + {{- include "kube-state-metrics.labels" . | indent 4 }} + {{- with .Values.prometheus.monitor.additionalLabels }} + {{- tpl (toYaml . | nindent 4) $ }} + {{- end }} + {{- with .Values.prometheus.monitor.annotations }} + annotations: + {{- tpl (toYaml . | nindent 4) $ }} + {{- end }} +spec: + jobLabel: {{ default "app.kubernetes.io/name" .Values.prometheus.monitor.jobLabel }} + {{- with .Values.prometheus.monitor.targetLabels }} + targetLabels: + {{- toYaml . | trim | nindent 4 }} + {{- end }} + {{- with .Values.prometheus.monitor.podTargetLabels }} + podTargetLabels: + {{- toYaml . | trim | nindent 4 }} + {{- end }} + {{- include "servicemonitor.scrapeLimits" .Values.prometheus.monitor | indent 2 }} + {{- if .Values.prometheus.monitor.namespaceSelector }} + namespaceSelector: + matchNames: + {{- with .Values.prometheus.monitor.namespaceSelector }} + {{- toYaml . | nindent 6 }} + {{- end }} + {{- end }} + selector: + matchLabels: + {{- with .Values.prometheus.monitor.selectorOverride }} + {{- toYaml . | nindent 6 }} + {{- else }} + {{- include "kube-state-metrics.selectorLabels" . | indent 6 }} + {{- end }} + endpoints: + - port: http + {{- if .Values.prometheus.monitor.interval }} + interval: {{ .Values.prometheus.monitor.interval }} + {{- end }} + {{- if .Values.prometheus.monitor.scrapeTimeout }} + scrapeTimeout: {{ .Values.prometheus.monitor.scrapeTimeout }} + {{- end }} + {{- if .Values.prometheus.monitor.proxyUrl }} + proxyUrl: {{ .Values.prometheus.monitor.proxyUrl}} + {{- end }} + {{- if .Values.prometheus.monitor.enableHttp2 }} + enableHttp2: {{ .Values.prometheus.monitor.enableHttp2}} + {{- end }} + {{- if .Values.prometheus.monitor.honorLabels }} + honorLabels: true + {{- end }} + {{- if .Values.prometheus.monitor.metricRelabelings }} + metricRelabelings: + {{- toYaml .Values.prometheus.monitor.metricRelabelings | nindent 8 }} + {{- end }} + {{- if .Values.prometheus.monitor.relabelings }} + relabelings: + {{- toYaml .Values.prometheus.monitor.relabelings | nindent 8 }} + {{- end }} + {{- if .Values.prometheus.monitor.scheme }} + scheme: {{ .Values.prometheus.monitor.scheme }} + {{- end }} + {{- if .Values.prometheus.monitor.tlsConfig }} + tlsConfig: + {{- toYaml .Values.prometheus.monitor.tlsConfig | nindent 8 }} + {{- end }} + {{- if .Values.prometheus.monitor.bearerTokenFile }} + bearerTokenFile: {{ .Values.prometheus.monitor.bearerTokenFile }} + {{- end }} + {{- with .Values.prometheus.monitor.bearerTokenSecret }} + bearerTokenSecret: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if .Values.selfMonitor.enabled }} + - port: metrics + {{- if .Values.prometheus.monitor.interval }} + interval: {{ .Values.prometheus.monitor.interval }} + {{- end }} + {{- if .Values.prometheus.monitor.scrapeTimeout }} + scrapeTimeout: {{ .Values.prometheus.monitor.scrapeTimeout }} + {{- end }} + {{- if .Values.prometheus.monitor.proxyUrl }} + proxyUrl: {{ .Values.prometheus.monitor.proxyUrl}} + {{- end }} + {{- if .Values.prometheus.monitor.enableHttp2 }} + enableHttp2: {{ .Values.prometheus.monitor.enableHttp2}} + {{- end }} + {{- if .Values.prometheus.monitor.honorLabels }} + honorLabels: true + {{- end }} + {{- if .Values.prometheus.monitor.metricRelabelings }} + metricRelabelings: + {{- toYaml .Values.prometheus.monitor.metricRelabelings | nindent 8 }} + {{- end }} + {{- if .Values.prometheus.monitor.relabelings }} + relabelings: + {{- toYaml .Values.prometheus.monitor.relabelings | nindent 8 }} + {{- end }} + {{- if .Values.prometheus.monitor.scheme }} + scheme: {{ .Values.prometheus.monitor.scheme }} + {{- end }} + {{- if .Values.prometheus.monitor.tlsConfig }} + tlsConfig: + {{- toYaml .Values.prometheus.monitor.tlsConfig | nindent 8 }} + {{- end }} + {{- if .Values.prometheus.monitor.bearerTokenFile }} + bearerTokenFile: {{ .Values.prometheus.monitor.bearerTokenFile }} + {{- end }} + {{- with .Values.prometheus.monitor.bearerTokenSecret }} + bearerTokenSecret: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- end }} +{{- end }} diff --git a/packages/system/monitoring/charts/kube-state-metrics/templates/stsdiscovery-role.yaml b/packages/system/monitoring/charts/kube-state-metrics/templates/stsdiscovery-role.yaml new file mode 100644 index 00000000..489de147 --- /dev/null +++ b/packages/system/monitoring/charts/kube-state-metrics/templates/stsdiscovery-role.yaml @@ -0,0 +1,26 @@ +{{- if and .Values.autosharding.enabled .Values.rbac.create -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: stsdiscovery-{{ template "kube-state-metrics.fullname" . }} + namespace: {{ template "kube-state-metrics.namespace" . }} + labels: + {{- include "kube-state-metrics.labels" . | indent 4 }} +rules: +- apiGroups: + - "" + resources: + - pods + verbs: + - get +- apiGroups: + - apps + resourceNames: + - {{ template "kube-state-metrics.fullname" . }} + resources: + - statefulsets + verbs: + - get + - list + - watch +{{- end }} diff --git a/packages/system/monitoring/charts/kube-state-metrics/templates/stsdiscovery-rolebinding.yaml b/packages/system/monitoring/charts/kube-state-metrics/templates/stsdiscovery-rolebinding.yaml new file mode 100644 index 00000000..73b37a4f --- /dev/null +++ b/packages/system/monitoring/charts/kube-state-metrics/templates/stsdiscovery-rolebinding.yaml @@ -0,0 +1,17 @@ +{{- if and .Values.autosharding.enabled .Values.rbac.create -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: stsdiscovery-{{ template "kube-state-metrics.fullname" . }} + namespace: {{ template "kube-state-metrics.namespace" . }} + labels: + {{- include "kube-state-metrics.labels" . | indent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: stsdiscovery-{{ template "kube-state-metrics.fullname" . }} +subjects: + - kind: ServiceAccount + name: {{ template "kube-state-metrics.serviceAccountName" . }} + namespace: {{ template "kube-state-metrics.namespace" . }} +{{- end }} diff --git a/packages/system/monitoring/charts/kube-state-metrics/templates/verticalpodautoscaler.yaml b/packages/system/monitoring/charts/kube-state-metrics/templates/verticalpodautoscaler.yaml new file mode 100644 index 00000000..f46305b5 --- /dev/null +++ b/packages/system/monitoring/charts/kube-state-metrics/templates/verticalpodautoscaler.yaml @@ -0,0 +1,44 @@ +{{- if and (.Capabilities.APIVersions.Has "autoscaling.k8s.io/v1") (.Values.verticalPodAutoscaler.enabled) }} +apiVersion: autoscaling.k8s.io/v1 +kind: VerticalPodAutoscaler +metadata: + name: {{ template "kube-state-metrics.fullname" . }} + namespace: {{ template "kube-state-metrics.namespace" . }} + labels: + {{- include "kube-state-metrics.labels" . | indent 4 }} +spec: + {{- with .Values.verticalPodAutoscaler.recommenders }} + recommenders: + {{- toYaml . | nindent 4 }} + {{- end }} + resourcePolicy: + containerPolicies: + - containerName: {{ template "kube-state-metrics.name" . }} + {{- with .Values.verticalPodAutoscaler.controlledResources }} + controlledResources: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if .Values.verticalPodAutoscaler.controlledValues }} + controlledValues: {{ .Values.verticalPodAutoscaler.controlledValues }} + {{- end }} + {{- if .Values.verticalPodAutoscaler.maxAllowed }} + maxAllowed: + {{ toYaml .Values.verticalPodAutoscaler.maxAllowed | nindent 8 }} + {{- end }} + {{- if .Values.verticalPodAutoscaler.minAllowed }} + minAllowed: + {{ toYaml .Values.verticalPodAutoscaler.minAllowed | nindent 8 }} + {{- end }} + targetRef: + apiVersion: apps/v1 + {{- if .Values.autosharding.enabled }} + kind: StatefulSet + {{- else }} + kind: Deployment + {{- end }} + name: {{ template "kube-state-metrics.fullname" . }} + {{- with .Values.verticalPodAutoscaler.updatePolicy }} + updatePolicy: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/packages/system/monitoring/charts/kube-state-metrics/values.yaml b/packages/system/monitoring/charts/kube-state-metrics/values.yaml new file mode 100644 index 00000000..ee6e1a9f --- /dev/null +++ b/packages/system/monitoring/charts/kube-state-metrics/values.yaml @@ -0,0 +1,456 @@ +# Default values for kube-state-metrics. +prometheusScrape: true +image: + registry: registry.k8s.io + repository: kube-state-metrics/kube-state-metrics + # If unset use v + .Charts.appVersion + tag: "" + sha: "" + pullPolicy: IfNotPresent + +imagePullSecrets: [] +# - name: "image-pull-secret" + +global: + # To help compatibility with other charts which use global.imagePullSecrets. + # Allow either an array of {name: pullSecret} maps (k8s-style), or an array of strings (more common helm-style). + # global: + # imagePullSecrets: + # - name: pullSecret1 + # - name: pullSecret2 + # or + # global: + # imagePullSecrets: + # - pullSecret1 + # - pullSecret2 + imagePullSecrets: [] + # + # Allow parent charts to override registry hostname + imageRegistry: "" + +# If set to true, this will deploy kube-state-metrics as a StatefulSet and the data +# will be automatically sharded across <.Values.replicas> pods using the built-in +# autodiscovery feature: https://github.com/kubernetes/kube-state-metrics#automated-sharding +# This is an experimental feature and there are no stability guarantees. +autosharding: + enabled: false + +replicas: 1 + +# Change the deployment strategy when autosharding is disabled +# updateStrategy: Recreate + +# Number of old history to retain to allow rollback +# Default Kubernetes value is set to 10 +revisionHistoryLimit: 10 + +# List of additional cli arguments to configure kube-state-metrics +# for example: --enable-gzip-encoding, --log-file, etc. +# all the possible args can be found here: https://github.com/kubernetes/kube-state-metrics/blob/master/docs/cli-arguments.md +extraArgs: [] + +service: + port: 8080 + # Default to clusterIP for backward compatibility + type: ClusterIP + nodePort: 0 + loadBalancerIP: "" + # Only allow access to the loadBalancerIP from these IPs + loadBalancerSourceRanges: [] + clusterIP: "" + annotations: {} + +## Additional labels to add to all resources +customLabels: {} + # app: kube-state-metrics + +## Override selector labels +selectorOverride: {} + +## set to true to add the release label so scraping of the servicemonitor with kube-prometheus-stack works out of the box +releaseLabel: false + +hostNetwork: false + +rbac: + # If true, create & use RBAC resources + create: true + + # Set to a rolename to use existing role - skipping role creating - but still doing serviceaccount and rolebinding to it, rolename set here. + # useExistingRole: your-existing-role + + # If set to false - Run without Cluteradmin privs needed - ONLY works if namespace is also set (if useExistingRole is set this name is used as ClusterRole or Role to bind to) + useClusterRole: true + + # Add permissions for CustomResources' apiGroups in Role/ClusterRole. Should be used in conjunction with Custom Resource State Metrics configuration + # Example: + # - apiGroups: ["monitoring.coreos.com"] + # resources: ["prometheuses"] + # verbs: ["list", "watch"] + extraRules: [] + +# Configure kube-rbac-proxy. When enabled, creates one kube-rbac-proxy container per exposed HTTP endpoint (metrics and telemetry if enabled). +# The requests are served through the same service but requests are then HTTPS. +kubeRBACProxy: + enabled: false + image: + registry: quay.io + repository: brancz/kube-rbac-proxy + tag: v0.14.0 + sha: "" + pullPolicy: IfNotPresent + + # List of additional cli arguments to configure kube-rbac-prxy + # for example: --tls-cipher-suites, --log-file, etc. + # all the possible args can be found here: https://github.com/brancz/kube-rbac-proxy#usage + extraArgs: [] + + ## Specify security settings for a Container + ## Allows overrides and additional options compared to (Pod) securityContext + ## Ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container + containerSecurityContext: {} + + resources: {} + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 100m + # memory: 64Mi + # requests: + # cpu: 10m + # memory: 32Mi + + ## volumeMounts enables mounting custom volumes in rbac-proxy containers + ## Useful for TLS certificates and keys + volumeMounts: [] + # - mountPath: /etc/tls + # name: kube-rbac-proxy-tls + # readOnly: true + +serviceAccount: + # Specifies whether a ServiceAccount should be created, require rbac true + create: true + # The name of the ServiceAccount to use. + # If not set and create is true, a name is generated using the fullname template + name: + # Reference to one or more secrets to be used when pulling images + # ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ + imagePullSecrets: [] + # ServiceAccount annotations. + # Use case: AWS EKS IAM roles for service accounts + # ref: https://docs.aws.amazon.com/eks/latest/userguide/specify-service-account-role.html + annotations: {} + +prometheus: + monitor: + enabled: false + annotations: {} + additionalLabels: {} + namespace: "" + namespaceSelector: [] + jobLabel: "" + targetLabels: [] + podTargetLabels: [] + interval: "" + ## SampleLimit defines per-scrape limit on number of scraped samples that will be accepted. + ## + sampleLimit: 0 + + ## TargetLimit defines a limit on the number of scraped targets that will be accepted. + ## + targetLimit: 0 + + ## Per-scrape limit on number of labels that will be accepted for a sample. Only valid in Prometheus versions 2.27.0 and newer. + ## + labelLimit: 0 + + ## Per-scrape limit on length of labels name that will be accepted for a sample. Only valid in Prometheus versions 2.27.0 and newer. + ## + labelNameLengthLimit: 0 + + ## Per-scrape limit on length of labels value that will be accepted for a sample. Only valid in Prometheus versions 2.27.0 and newer. + ## + labelValueLengthLimit: 0 + scrapeTimeout: "" + proxyUrl: "" + ## Whether to enable HTTP2 for servicemonitor + # enableHttp2: false + selectorOverride: {} + honorLabels: false + metricRelabelings: [] + relabelings: [] + scheme: "" + ## File to read bearer token for scraping targets + bearerTokenFile: "" + ## Secret to mount to read bearer token for scraping targets. The secret needs + ## to be in the same namespace as the service monitor and accessible by the + ## Prometheus Operator + bearerTokenSecret: {} + # name: secret-name + # key: key-name + tlsConfig: {} + +## Specify if a Pod Security Policy for kube-state-metrics must be created +## Ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/ +## +podSecurityPolicy: + enabled: false + annotations: {} + ## Specify pod annotations + ## Ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/#apparmor + ## Ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/#seccomp + ## Ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/#sysctl + ## + # seccomp.security.alpha.kubernetes.io/allowedProfileNames: '*' + # seccomp.security.alpha.kubernetes.io/defaultProfileName: 'docker/default' + # apparmor.security.beta.kubernetes.io/defaultProfileName: 'runtime/default' + + additionalVolumes: [] + +## Configure network policy for kube-state-metrics +networkPolicy: + enabled: false + # networkPolicy.flavor -- Flavor of the network policy to use. + # Can be: + # * kubernetes for networking.k8s.io/v1/NetworkPolicy + # * cilium for cilium.io/v2/CiliumNetworkPolicy + flavor: kubernetes + + ## Configure the cilium network policy kube-apiserver selector + # cilium: + # kubeApiServerSelector: + # - toEntities: + # - kube-apiserver + + # egress: + # - {} + # ingress: + # - {} + # podSelector: + # matchLabels: + # app.kubernetes.io/name: kube-state-metrics + +securityContext: + enabled: true + runAsGroup: 65534 + runAsUser: 65534 + fsGroup: 65534 + runAsNonRoot: true + seccompProfile: + type: RuntimeDefault + +## Specify security settings for a Container +## Allows overrides and additional options compared to (Pod) securityContext +## Ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container +containerSecurityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + +## Node labels for pod assignment +## Ref: https://kubernetes.io/docs/user-guide/node-selection/ +nodeSelector: {} + +## Affinity settings for pod assignment +## Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ +affinity: {} + +## Tolerations for pod assignment +## Ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ +tolerations: [] + +## Topology spread constraints for pod assignment +## Ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/ +topologySpreadConstraints: [] + +# Annotations to be added to the deployment/statefulset +annotations: {} + +# Annotations to be added to the pod +podAnnotations: {} + +## Assign a PriorityClassName to pods if set +# priorityClassName: "" + +# Ref: https://kubernetes.io/docs/tasks/run-application/configure-pdb/ +podDisruptionBudget: {} + +# Comma-separated list of metrics to be exposed. +# This list comprises of exact metric names and/or regex patterns. +# The allowlist and denylist are mutually exclusive. +metricAllowlist: [] + +# Comma-separated list of metrics not to be enabled. +# This list comprises of exact metric names and/or regex patterns. +# The allowlist and denylist are mutually exclusive. +metricDenylist: [] + +# Comma-separated list of additional Kubernetes label keys that will be used in the resource's +# labels metric. By default the metric contains only name and namespace labels. +# To include additional labels, provide a list of resource names in their plural form and Kubernetes +# label keys you would like to allow for them (Example: '=namespaces=[k8s-label-1,k8s-label-n,...],pods=[app],...)'. +# A single '*' can be provided per resource instead to allow any labels, but that has +# severe performance implications (Example: '=pods=[*]'). +metricLabelsAllowlist: [] + # - namespaces=[k8s-label-1,k8s-label-n] + +# Comma-separated list of Kubernetes annotations keys that will be used in the resource' +# labels metric. By default the metric contains only name and namespace labels. +# To include additional annotations provide a list of resource names in their plural form and Kubernetes +# annotation keys you would like to allow for them (Example: '=namespaces=[kubernetes.io/team,...],pods=[kubernetes.io/team],...)'. +# A single '*' can be provided per resource instead to allow any annotations, but that has +# severe performance implications (Example: '=pods=[*]'). +metricAnnotationsAllowList: [] + # - pods=[k8s-annotation-1,k8s-annotation-n] + +# Available collectors for kube-state-metrics. +# By default, all available resources are enabled, comment out to disable. +collectors: + - certificatesigningrequests + - configmaps + - cronjobs + - daemonsets + - deployments + - endpoints + - horizontalpodautoscalers + - ingresses + - jobs + - leases + - limitranges + - mutatingwebhookconfigurations + - namespaces + - networkpolicies + - nodes + - persistentvolumeclaims + - persistentvolumes + - poddisruptionbudgets + - pods + - replicasets + - replicationcontrollers + - resourcequotas + - secrets + - services + - statefulsets + - storageclasses + - validatingwebhookconfigurations + - volumeattachments + +# Enabling kubeconfig will pass the --kubeconfig argument to the container +kubeconfig: + enabled: false + # base64 encoded kube-config file + secret: + +# Enabling support for customResourceState, will create a configMap including your config that will be read from kube-state-metrics +customResourceState: + enabled: false + # Add (Cluster)Role permissions to list/watch the customResources defined in the config to rbac.extraRules + config: {} + +# Enable only the release namespace for collecting resources. By default all namespaces are collected. +# If releaseNamespace and namespaces are both set a merged list will be collected. +releaseNamespace: false + +# Comma-separated list(string) or yaml list of namespaces to be enabled for collecting resources. By default all namespaces are collected. +namespaces: "" + +# Comma-separated list of namespaces not to be enabled. If namespaces and namespaces-denylist are both set, +# only namespaces that are excluded in namespaces-denylist will be used. +namespacesDenylist: "" + +## Override the deployment namespace +## +namespaceOverride: "" + +resources: {} + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 100m + # memory: 64Mi + # requests: + # cpu: 10m + # memory: 32Mi + +## Provide a k8s version to define apiGroups for podSecurityPolicy Cluster Role. +## For example: kubeTargetVersionOverride: 1.14.9 +## +kubeTargetVersionOverride: "" + +# Enable self metrics configuration for service and Service Monitor +# Default values for telemetry configuration can be overridden +# If you set telemetryNodePort, you must also set service.type to NodePort +selfMonitor: + enabled: false + # telemetryHost: 0.0.0.0 + # telemetryPort: 8081 + # telemetryNodePort: 0 + +# Enable vertical pod autoscaler support for kube-state-metrics +verticalPodAutoscaler: + enabled: false + + # Recommender responsible for generating recommendation for the object. + # List should be empty (then the default recommender will generate the recommendation) + # or contain exactly one recommender. + # recommenders: [] + # - name: custom-recommender-performance + + # List of resources that the vertical pod autoscaler can control. Defaults to cpu and memory + controlledResources: [] + # Specifies which resource values should be controlled: RequestsOnly or RequestsAndLimits. + # controlledValues: RequestsAndLimits + + # Define the max allowed resources for the pod + maxAllowed: {} + # cpu: 200m + # memory: 100Mi + # Define the min allowed resources for the pod + minAllowed: {} + # cpu: 200m + # memory: 100Mi + + # updatePolicy: + # Specifies minimal number of replicas which need to be alive for VPA Updater to attempt pod eviction + # minReplicas: 1 + # Specifies whether recommended updates are applied when a Pod is started and whether recommended updates + # are applied during the life of a Pod. Possible values are "Off", "Initial", "Recreate", and "Auto". + # updateMode: Auto + +# volumeMounts are used to add custom volume mounts to deployment. +# See example below +volumeMounts: [] +# - mountPath: /etc/config +# name: config-volume + +# volumes are used to add custom volumes to deployment +# See example below +volumes: [] +# - configMap: +# name: cm-for-volume +# name: config-volume + +# Extra manifests to deploy as an array +extraManifests: [] + # - apiVersion: v1 + # kind: ConfigMap + # metadata: + # labels: + # name: prometheus-extra + # data: + # extra-data: "value" + +## Containers allows injecting additional containers. +containers: [] + # - name: crd-init + # image: kiwigrid/k8s-sidecar:latest + +## InitContainers allows injecting additional initContainers. +initContainers: [] + # - name: crd-sidecar + # image: kiwigrid/k8s-sidecar:latest diff --git a/packages/system/monitoring/charts/metrics-server/.helmignore b/packages/system/monitoring/charts/metrics-server/.helmignore new file mode 100644 index 00000000..0e8a0eb3 --- /dev/null +++ b/packages/system/monitoring/charts/metrics-server/.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/packages/system/monitoring/charts/metrics-server/Chart.yaml b/packages/system/monitoring/charts/metrics-server/Chart.yaml new file mode 100644 index 00000000..7c0f77a5 --- /dev/null +++ b/packages/system/monitoring/charts/metrics-server/Chart.yaml @@ -0,0 +1,32 @@ +annotations: + artifacthub.io/changes: | + - kind: added + description: "Added default Metrics Server resource requests." + - kind: changed + description: "Updated the Metrics Server OCI image to v0.6.3." + - kind: changed + description: "Updated the addon resizer OCI image to v1.8.19." + - kind: changed + description: "Changed the default addon resizer nanny resource configuration to match the documented Metrics Server autoscaling values." +apiVersion: v2 +appVersion: 0.6.4 +description: Metrics Server is a scalable, efficient source of container resource + metrics for Kubernetes built-in autoscaling pipelines. +home: https://github.com/kubernetes-sigs/metrics-server +icon: https://avatars.githubusercontent.com/u/36015203?s=400&v=4 +keywords: +- kubernetes +- metrics-server +- metrics +maintainers: +- name: stevehipwell + url: https://github.com/stevehipwell +- name: krmichel + url: https://github.com/krmichel +- name: endrec + url: https://github.com/endrec +name: metrics-server +sources: +- https://github.com/kubernetes-sigs/metrics-server +type: application +version: 3.11.0 diff --git a/packages/system/monitoring/charts/metrics-server/README.md b/packages/system/monitoring/charts/metrics-server/README.md new file mode 100644 index 00000000..50956b9a --- /dev/null +++ b/packages/system/monitoring/charts/metrics-server/README.md @@ -0,0 +1,90 @@ +# Kubernetes Metrics Server + +[Metrics Server](https://github.com/kubernetes-sigs/metrics-server/) is a scalable, efficient source of container resource metrics for Kubernetes built-in autoscaling pipelines. + + + +## Installing the Chart + +Before you can install the chart you will need to add the `metrics-server` repo to [Helm](https://helm.sh/). + +```shell +helm repo add metrics-server https://kubernetes-sigs.github.io/metrics-server/ +``` + +After you've installed the repo you can install the chart. + +```shell +helm upgrade --install metrics-server metrics-server/metrics-server +``` + +## Configuration + +The following table lists the configurable parameters of the _Metrics Server_ chart and their default values. + +| Parameter | Description | Default | +| ------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------ | +| `image.repository` | Image repository. | `registry.k8s.io/metrics-server/metrics-server` | +| `image.tag` | Image tag, will override the default tag derived from the chart app version. | `""` | +| `image.pullPolicy` | Image pull policy. | `IfNotPresent` | +| `imagePullSecrets` | Image pull secrets. | `[]` | +| `nameOverride` | Override the `name` of the chart. | `nil` | +| `fullnameOverride` | Override the `fullname` of the chart. | `nil` | +| `serviceAccount.create` | If `true`, create a new service account. | `true` | +| `serviceAccount.annotations` | Annotations to add to the service account. | `{}` | +| `serviceAccount.name` | Service account to be used. If not set and `serviceAccount.create` is `true`, a name is generated using the full name template. | `nil` | +| `serviceAccount.secrets` | The list of secrets mountable by this service account. See https://kubernetes.io/docs/reference/labels-annotations-taints/#enforce-mountable-secrets | `[]` | +| `rbac.create` | If `true`, create the RBAC resources. | `true` | +| `rbac.pspEnabled` | If `true`, create a pod security policy resource. | `false` | +| `apiService.create` | If `true`, create the `v1beta1.metrics.k8s.io` API service. You typically want this enabled! If you disable API service creation you have to manage it outside of this chart for e.g horizontal pod autoscaling to work with this release. | `true` | +| `apiService.annotations` | Annotations to add to the API service | `{}` | +| `apiService.insecureSkipTLSVerify` | Specifies whether to skip TLS verification | `true` | +| `apiService.caBundle` | The PEM encoded CA bundle for TLS verification | `""` | +| `commonLabels` | Labels to add to each object of the chart. | `{}` | +| `podLabels` | Labels to add to the pod. | `{}` | +| `podAnnotations` | Annotations to add to the pod. | `{}` | +| `podSecurityContext` | Security context for the pod. | `{}` | +| `securityContext` | Security context for the _metrics-server_ container. | _See values.yaml_ | +| `priorityClassName` | Priority class name to use. | `system-cluster-critical` | +| `containerPort` | port for the _metrics-server_ container. | `10250` | +| `hostNetwork.enabled` | If `true`, start _metric-server_ in hostNetwork mode. You would require this enabled if you use alternate overlay networking for pods and API server unable to communicate with metrics-server. As an example, this is required if you use Weave network on EKS. | `false` | +| `replicas` | Number of replicas to run. | `1` | +| `updateStrategy` | Customise the default update strategy. | `{}` | +| `podDisruptionBudget.enabled` | If `true`, create `PodDisruptionBudget` resource. | `{}` | +| `podDisruptionBudget.minAvailable` | Set the `PodDisruptionBugdet` minimum available pods. | `nil` | +| `podDisruptionBudget.maxUnavailable` | Set the `PodDisruptionBugdet` maximum unavailable pods. | `nil` | +| `defaultArgs` | Default arguments to pass to the _metrics-server_ command. | See _values.yaml_ | +| `args` | Additional arguments to pass to the _metrics-server_ command. | `[]` | +| `livenessProbe` | Liveness probe. | See _values.yaml_ | +| `readinessProbe` | Readiness probe. | See _values.yaml_ | +| `service.type` | Service type. | `ClusterIP` | +| `service.port` | Service port. | `443` | +| `service.annotations` | Annotations to add to the service. | `{}` | +| `service.labels` | Labels to add to the service. | `{}` | +| `addonResizer.enabled` | If `true`, run the addon-resizer as a sidecar to automatically scale resource requests with cluster size. | `false` | +| `addonResizer.image.repository` | addon-resizer image repository | `registry.k8s.io/autoscaling/addon-resizer` | +| `addonResizer.image.tag` | addon-resizer image tag | `1.8.19` | +| `addonResizer.resources` | Resource requests and limits for the _nanny_ container. | `{ requests: { cpu: 40m, memory: 25Mi }, limits: { cpu: 40m, memory: 25Mi } }` | +| `addonResizer.nanny.cpu` | The base CPU requirement. | `0m` | +| `addonResizer.nanny.extraCPU` | The amount of CPU to add per node. | `1m` | +| `addonResizer.nanny.memory` | The base memory requirement. | `0Mi` | +| `addonResizer.nanny.extraMemory` | The amount of memory to add per node. | `2Mi` | +| `addonResizer.nanny.minClusterSize` | Specifies the smallest number of nodes resources will be scaled to. | `100` | +| `addonResizer.nanny.pollPeriod` | The time, in milliseconds, to poll the dependent container. | `300000` | +| `addonResizer.nanny.threshold` | A number between 0-100. The dependent's resources are rewritten when they deviate from expected by more than threshold. | `5` | +| `metrics.enabled` | If `true`, allow unauthenticated access to `/metrics`. | `false` | +| `serviceMonitor.enabled` | If `true`, create a _Prometheus_ service monitor. This needs `metrics.enabled` to be `true`. | `false` | +| `serviceMonitor.additionalLabels` | Additional labels to be set on the ServiceMonitor. | `{}` | +| `serviceMonitor.metricRelabelings` | _Prometheus_ metric relabeling. | `[]` | +| `serviceMonitor.relabelings` | _Prometheus_ relabeling. | `[]` | +| `serviceMonitor.interval` | _Prometheus_ scrape frequency. | `1m` | +| `serviceMonitor.scrapeTimeout` | _Prometheus_ scrape timeout. | `10s` | +| `resources` | Resource requests and limits for the _metrics-server_ container. See https://github.com/kubernetes-sigs/metrics-server#scaling | `{ requests: { cpu: 100m, memory: 200Mi }}` | +| `extraVolumeMounts` | Additional volume mounts for the _metrics-server_ container. | `[]` | +| `extraVolumes` | Additional volumes for the pod. | `[]` | +| `nodeSelector` | Node labels for pod assignment. | `{}` | +| `tolerations` | Tolerations for pod assignment. | `[]` | +| `affinity` | Affinity for pod assignment. | `{}` | +| `topologySpreadConstraints` | Pod Topology Spread Constraints. | `[]` | +| `deploymentAnnotations` | Annotations to add to the deployment. | `{}` | +| `schedulerName` | scheduler to set to the deployment. | `""` | diff --git a/packages/system/monitoring/charts/metrics-server/ci/ci-values.yaml b/packages/system/monitoring/charts/metrics-server/ci/ci-values.yaml new file mode 100644 index 00000000..b9e9ef73 --- /dev/null +++ b/packages/system/monitoring/charts/metrics-server/ci/ci-values.yaml @@ -0,0 +1,2 @@ +args: + - --kubelet-insecure-tls diff --git a/packages/system/monitoring/charts/metrics-server/templates/NOTES.txt b/packages/system/monitoring/charts/metrics-server/templates/NOTES.txt new file mode 100644 index 00000000..0ad6bb07 --- /dev/null +++ b/packages/system/monitoring/charts/metrics-server/templates/NOTES.txt @@ -0,0 +1,7 @@ +*********************************************************************** +* Metrics Server * +*********************************************************************** + Chart version: {{ .Chart.Version }} + App version: {{ .Chart.AppVersion }} + Image tag: {{ include "metrics-server.image" . }} +*********************************************************************** diff --git a/packages/system/monitoring/charts/metrics-server/templates/_helpers.tpl b/packages/system/monitoring/charts/metrics-server/templates/_helpers.tpl new file mode 100644 index 00000000..9b87f118 --- /dev/null +++ b/packages/system/monitoring/charts/metrics-server/templates/_helpers.tpl @@ -0,0 +1,102 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "metrics-server.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | 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 "metrics-server.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "metrics-server.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "metrics-server.labels" -}} +helm.sh/chart: {{ include "metrics-server.chart" . }} +{{ include "metrics-server.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- if .Values.commonLabels }} +{{ toYaml .Values.commonLabels }} +{{- end }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "metrics-server.selectorLabels" -}} +app.kubernetes.io/name: {{ include "metrics-server.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "metrics-server.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "metrics-server.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} + +{{/* +The image to use +*/}} +{{- define "metrics-server.image" -}} +{{- printf "%s:%s" .Values.image.repository (default (printf "v%s" .Chart.AppVersion) .Values.image.tag) }} +{{- end }} + +{{/* +The image to use for the addon resizer +*/}} +{{- define "metrics-server.addonResizer.image" -}} +{{- printf "%s:%s" .Values.addonResizer.image.repository .Values.addonResizer.image.tag }} +{{- end }} + +{{/* +ConfigMap name of addon resizer +*/}} +{{- define "metrics-server.addonResizer.configMap" -}} +{{- printf "%s-%s" (include "metrics-server.fullname" .) "nanny-config" }} +{{- end }} + +{{/* +Role name of addon resizer +*/}} +{{- define "metrics-server.addonResizer.role" -}} +{{ printf "system:%s-nanny" (include "metrics-server.fullname" .) }} +{{- end }} + +{{/* Get PodDisruptionBudget API Version */}} +{{- define "metrics-server.pdb.apiVersion" -}} + {{- if and (.Capabilities.APIVersions.Has "policy/v1") (semverCompare ">= 1.21-0" .Capabilities.KubeVersion.Version) -}} + {{- print "policy/v1" -}} + {{- else -}} + {{- print "policy/v1beta1" -}} + {{- end -}} +{{- end -}} diff --git a/packages/system/monitoring/charts/metrics-server/templates/apiservice.yaml b/packages/system/monitoring/charts/metrics-server/templates/apiservice.yaml new file mode 100644 index 00000000..f58931d9 --- /dev/null +++ b/packages/system/monitoring/charts/metrics-server/templates/apiservice.yaml @@ -0,0 +1,25 @@ +{{- if .Values.apiService.create -}} +apiVersion: apiregistration.k8s.io/v1 +kind: APIService +metadata: + name: v1beta1.metrics.k8s.io + labels: + {{- include "metrics-server.labels" . | nindent 4 }} + {{- with .Values.apiService.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- with .Values.apiService.caBundle }} + caBundle: {{ b64enc . }} + {{- end }} + group: metrics.k8s.io + groupPriorityMinimum: 100 + insecureSkipTLSVerify: {{ .Values.apiService.insecureSkipTLSVerify }} + service: + name: {{ include "metrics-server.fullname" . }} + namespace: {{ .Release.Namespace }} + port: {{ .Values.service.port }} + version: v1beta1 + versionPriority: 100 +{{- end -}} diff --git a/packages/system/monitoring/charts/metrics-server/templates/clusterrole-aggregated-reader.yaml b/packages/system/monitoring/charts/metrics-server/templates/clusterrole-aggregated-reader.yaml new file mode 100644 index 00000000..d5e8fe1b --- /dev/null +++ b/packages/system/monitoring/charts/metrics-server/templates/clusterrole-aggregated-reader.yaml @@ -0,0 +1,21 @@ +{{- if .Values.rbac.create -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ printf "system:%s-aggregated-reader" (include "metrics-server.name" .) }} + labels: + {{- include "metrics-server.labels" . | nindent 4 }} + rbac.authorization.k8s.io/aggregate-to-admin: "true" + rbac.authorization.k8s.io/aggregate-to-edit: "true" + rbac.authorization.k8s.io/aggregate-to-view: "true" +rules: + - apiGroups: + - metrics.k8s.io + resources: + - pods + - nodes + verbs: + - get + - list + - watch +{{- end -}} diff --git a/packages/system/monitoring/charts/metrics-server/templates/clusterrole-nanny.yaml b/packages/system/monitoring/charts/metrics-server/templates/clusterrole-nanny.yaml new file mode 100644 index 00000000..24edd81c --- /dev/null +++ b/packages/system/monitoring/charts/metrics-server/templates/clusterrole-nanny.yaml @@ -0,0 +1,13 @@ +{{- if and .Values.rbac.create .Values.addonResizer.enabled -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ printf "system:%s-nanny" (include "metrics-server.fullname" .) }} + labels: + {{- include "metrics-server.labels" . | nindent 4 }} +rules: + - nonResourceURLs: + - /metrics + verbs: + - get +{{- end -}} diff --git a/packages/system/monitoring/charts/metrics-server/templates/clusterrole.yaml b/packages/system/monitoring/charts/metrics-server/templates/clusterrole.yaml new file mode 100644 index 00000000..5d25c1e8 --- /dev/null +++ b/packages/system/monitoring/charts/metrics-server/templates/clusterrole.yaml @@ -0,0 +1,37 @@ +{{- if .Values.rbac.create -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ printf "system:%s" (include "metrics-server.fullname" .) }} + labels: + {{- include "metrics-server.labels" . | nindent 4 }} +rules: + - apiGroups: + - "" + resources: + - nodes/metrics + verbs: + - get + - apiGroups: + - "" + resources: + - pods + - nodes + - namespaces + - configmaps + verbs: + - get + - list + - watch + {{- if .Values.rbac.pspEnabled }} + - apiGroups: + - extensions + - policy + resources: + - podsecuritypolicies + resourceNames: + - {{ printf "privileged-%s" (include "metrics-server.fullname" .) }} + verbs: + - use + {{- end -}} +{{- end -}} diff --git a/packages/system/monitoring/charts/metrics-server/templates/clusterrolebinding-auth-delegator.yaml b/packages/system/monitoring/charts/metrics-server/templates/clusterrolebinding-auth-delegator.yaml new file mode 100644 index 00000000..826c3b7b --- /dev/null +++ b/packages/system/monitoring/charts/metrics-server/templates/clusterrolebinding-auth-delegator.yaml @@ -0,0 +1,16 @@ +{{- if .Values.rbac.create -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ printf "%s:system:auth-delegator" (include "metrics-server.fullname" .) }} + labels: + {{- include "metrics-server.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: system:auth-delegator +subjects: + - kind: ServiceAccount + name: {{ include "metrics-server.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} +{{- end -}} diff --git a/packages/system/monitoring/charts/metrics-server/templates/clusterrolebinding-nanny.yaml b/packages/system/monitoring/charts/metrics-server/templates/clusterrolebinding-nanny.yaml new file mode 100644 index 00000000..43738ccb --- /dev/null +++ b/packages/system/monitoring/charts/metrics-server/templates/clusterrolebinding-nanny.yaml @@ -0,0 +1,18 @@ +{{- if .Values.rbac.create -}} +{{- if .Values.addonResizer.enabled -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ printf "system:%s-nanny" (include "metrics-server.fullname" .) }} + labels: + {{- include "metrics-server.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: system:{{ template "metrics-server.fullname" . }}-nanny +subjects: + - kind: ServiceAccount + name: {{ include "metrics-server.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} +{{- end -}} +{{- end -}} diff --git a/packages/system/monitoring/charts/metrics-server/templates/clusterrolebinding.yaml b/packages/system/monitoring/charts/metrics-server/templates/clusterrolebinding.yaml new file mode 100644 index 00000000..512cb651 --- /dev/null +++ b/packages/system/monitoring/charts/metrics-server/templates/clusterrolebinding.yaml @@ -0,0 +1,16 @@ +{{- if .Values.rbac.create -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ printf "system:%s" (include "metrics-server.fullname" .) }} + labels: + {{- include "metrics-server.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: system:{{ template "metrics-server.fullname" . }} +subjects: + - kind: ServiceAccount + name: {{ include "metrics-server.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} +{{- end -}} diff --git a/packages/system/monitoring/charts/metrics-server/templates/configmaps-nanny.yaml b/packages/system/monitoring/charts/metrics-server/templates/configmaps-nanny.yaml new file mode 100644 index 00000000..c25005ec --- /dev/null +++ b/packages/system/monitoring/charts/metrics-server/templates/configmaps-nanny.yaml @@ -0,0 +1,17 @@ +{{- if .Values.addonResizer.enabled -}} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "metrics-server.addonResizer.configMap" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "metrics-server.labels" . | nindent 4 }} +data: + NannyConfiguration: |- + apiVersion: nannyconfig/v1alpha1 + kind: NannyConfiguration + baseCPU: {{ .Values.addonResizer.nanny.cpu }} + cpuPerNode: {{ .Values.addonResizer.nanny.extraCpu }} + baseMemory: {{ .Values.addonResizer.nanny.memory }} + memoryPerNode: {{ .Values.addonResizer.nanny.extraMemory }} +{{- end -}} diff --git a/packages/system/monitoring/charts/metrics-server/templates/deployment.yaml b/packages/system/monitoring/charts/metrics-server/templates/deployment.yaml new file mode 100644 index 00000000..1d656fcc --- /dev/null +++ b/packages/system/monitoring/charts/metrics-server/templates/deployment.yaml @@ -0,0 +1,146 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "metrics-server.fullname" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "metrics-server.labels" . | nindent 4 }} + {{- with .Values.deploymentAnnotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + replicas: {{ .Values.replicas }} + {{- with .Values.updateStrategy }} + strategy: + {{- toYaml . | nindent 4 }} + {{- end }} + selector: + matchLabels: + {{- include "metrics-server.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + {{- include "metrics-server.selectorLabels" . | nindent 8 }} + {{- with .Values.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + schedulerName: {{ .Values.schedulerName }} + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "metrics-server.serviceAccountName" . }} + {{- with .Values.podSecurityContext }} + securityContext: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.priorityClassName }} + priorityClassName: {{ . | quote }} + {{- end }} + {{- if .Values.hostNetwork.enabled }} + hostNetwork: true + {{- end }} + containers: + - name: metrics-server + {{- with .Values.securityContext }} + securityContext: + {{- toYaml . | nindent 12 }} + {{- end }} + image: {{ include "metrics-server.image" . }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + args: + - {{ printf "--secure-port=%d" (int .Values.containerPort) }} + {{- range .Values.defaultArgs }} + - {{ . }} + {{- end }} + {{- if .Values.metrics.enabled }} + - --authorization-always-allow-paths=/metrics + {{- end }} + {{- range .Values.args }} + - {{ . }} + {{- end }} + ports: + - name: https + protocol: TCP + containerPort: {{ .Values.containerPort }} + {{- with .Values.livenessProbe }} + livenessProbe: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.readinessProbe }} + readinessProbe: + {{- toYaml . | nindent 12 }} + {{- end }} + volumeMounts: + - name: tmp + mountPath: /tmp + {{- with .Values.extraVolumeMounts }} + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- if .Values.addonResizer.enabled }} + - name: metrics-server-nanny + image: {{ include "metrics-server.addonResizer.image" . }} + env: + - name: MY_POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: MY_POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + command: + - /pod_nanny + - --config-dir=/etc/config + - --deployment={{ include "metrics-server.fullname" . }} + - --container=metrics-server + - --threshold={{ .Values.addonResizer.nanny.threshold }} + - --poll-period={{ .Values.addonResizer.nanny.pollPeriod }} + - --estimator=exponential + - --minClusterSize={{ .Values.addonResizer.nanny.minClusterSize }} + - --use-metrics=true + volumeMounts: + - name: nanny-config-volume + mountPath: /etc/config + {{- with .Values.addonResizer.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- end }} + volumes: + - name: tmp + emptyDir: {} + {{- if .Values.addonResizer.enabled }} + - name: nanny-config-volume + configMap: + name: {{ include "metrics-server.addonResizer.configMap" . }} + {{- end }} + {{- with .Values.extraVolumes }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.topologySpreadConstraints }} + topologySpreadConstraints: + {{- toYaml . | nindent 8 }} + {{- end }} diff --git a/packages/system/monitoring/charts/metrics-server/templates/pdb.yaml b/packages/system/monitoring/charts/metrics-server/templates/pdb.yaml new file mode 100644 index 00000000..1f5eddf8 --- /dev/null +++ b/packages/system/monitoring/charts/metrics-server/templates/pdb.yaml @@ -0,0 +1,19 @@ +{{- if .Values.podDisruptionBudget.enabled -}} +apiVersion: {{ include "metrics-server.pdb.apiVersion" . }} +kind: PodDisruptionBudget +metadata: + name: {{ include "metrics-server.fullname" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "metrics-server.labels" . | nindent 4 }} +spec: + {{- if .Values.podDisruptionBudget.minAvailable }} + minAvailable: {{ .Values.podDisruptionBudget.minAvailable }} + {{- end }} + {{- if .Values.podDisruptionBudget.maxUnavailable }} + maxUnavailable: {{ .Values.podDisruptionBudget.maxUnavailable }} + {{- end }} + selector: + matchLabels: + {{- include "metrics-server.selectorLabels" . | nindent 6 }} +{{- end -}} diff --git a/packages/system/monitoring/charts/metrics-server/templates/psp.yaml b/packages/system/monitoring/charts/metrics-server/templates/psp.yaml new file mode 100644 index 00000000..bf8ace1a --- /dev/null +++ b/packages/system/monitoring/charts/metrics-server/templates/psp.yaml @@ -0,0 +1,28 @@ +{{- if .Values.rbac.pspEnabled }} +apiVersion: policy/v1beta1 +kind: PodSecurityPolicy +metadata: + name: {{ printf "privileged-%s" (include "metrics-server.fullname" .) }} + labels: + {{- include "metrics-server.labels" . | nindent 4 }} +spec: + allowedCapabilities: + - '*' + fsGroup: + rule: RunAsAny + privileged: true + runAsUser: + rule: RunAsAny + seLinux: + rule: RunAsAny + supplementalGroups: + rule: RunAsAny + volumes: + - '*' + hostPID: true + hostIPC: true + hostNetwork: true + hostPorts: + - min: 1 + max: 65536 +{{- end }} diff --git a/packages/system/monitoring/charts/metrics-server/templates/role-nanny.yaml b/packages/system/monitoring/charts/metrics-server/templates/role-nanny.yaml new file mode 100644 index 00000000..f0bf8fce --- /dev/null +++ b/packages/system/monitoring/charts/metrics-server/templates/role-nanny.yaml @@ -0,0 +1,27 @@ +{{- if .Values.rbac.create -}} +{{- if .Values.addonResizer.enabled -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ include "metrics-server.addonResizer.role" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "metrics-server.labels" . | nindent 4 }} +rules: +- apiGroups: + - "" + resources: + - pods + verbs: + - get +- apiGroups: + - apps + resources: + - deployments + resourceNames: + - {{ include "metrics-server.fullname" . }} + verbs: + - get + - patch +{{- end -}} +{{- end -}} diff --git a/packages/system/monitoring/charts/metrics-server/templates/rolebinding-nanny.yaml b/packages/system/monitoring/charts/metrics-server/templates/rolebinding-nanny.yaml new file mode 100644 index 00000000..73bfaaff --- /dev/null +++ b/packages/system/monitoring/charts/metrics-server/templates/rolebinding-nanny.yaml @@ -0,0 +1,19 @@ +{{- if .Values.rbac.create -}} +{{- if .Values.addonResizer.enabled -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ printf "%s-nanny" (include "metrics-server.fullname" .) }} + namespace: kube-system + labels: + {{- include "metrics-server.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ include "metrics-server.addonResizer.role" . }} +subjects: + - kind: ServiceAccount + name: {{ include "metrics-server.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} +{{- end -}} +{{- end -}} diff --git a/packages/system/monitoring/charts/metrics-server/templates/rolebinding.yaml b/packages/system/monitoring/charts/metrics-server/templates/rolebinding.yaml new file mode 100644 index 00000000..3fda7433 --- /dev/null +++ b/packages/system/monitoring/charts/metrics-server/templates/rolebinding.yaml @@ -0,0 +1,17 @@ +{{- if .Values.rbac.create -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ printf "%s-auth-reader" (include "metrics-server.fullname" .) }} + namespace: kube-system + labels: + {{- include "metrics-server.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: extension-apiserver-authentication-reader +subjects: + - kind: ServiceAccount + name: {{ include "metrics-server.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} +{{- end -}} diff --git a/packages/system/monitoring/charts/metrics-server/templates/service.yaml b/packages/system/monitoring/charts/metrics-server/templates/service.yaml new file mode 100644 index 00000000..d45bcf36 --- /dev/null +++ b/packages/system/monitoring/charts/metrics-server/templates/service.yaml @@ -0,0 +1,23 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "metrics-server.fullname" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "metrics-server.labels" . | nindent 4 }} + {{- with .Values.service.labels -}} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.service.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + type: {{ .Values.service.type }} + ports: + - name: https + port: {{ .Values.service.port }} + protocol: TCP + targetPort: https + selector: + {{- include "metrics-server.selectorLabels" . | nindent 4 }} diff --git a/packages/system/monitoring/charts/metrics-server/templates/serviceaccount.yaml b/packages/system/monitoring/charts/metrics-server/templates/serviceaccount.yaml new file mode 100644 index 00000000..80ef6996 --- /dev/null +++ b/packages/system/monitoring/charts/metrics-server/templates/serviceaccount.yaml @@ -0,0 +1,17 @@ +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ template "metrics-server.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "metrics-server.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- with .Values.serviceAccount.secrets }} +secrets: + {{- toYaml . | nindent 2 }} +{{- end }} +{{- end -}} diff --git a/packages/system/monitoring/charts/metrics-server/templates/servicemonitor.yaml b/packages/system/monitoring/charts/metrics-server/templates/servicemonitor.yaml new file mode 100644 index 00000000..5c1c5b77 --- /dev/null +++ b/packages/system/monitoring/charts/metrics-server/templates/servicemonitor.yaml @@ -0,0 +1,40 @@ +{{- if and .Values.serviceMonitor.enabled .Values.metrics.enabled -}} +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ include "metrics-server.fullname" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "metrics-server.labels" . | nindent 4 }} + {{- with .Values.serviceMonitor.additionalLabels }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + jobLabel: {{ .Release.Name }} + namespaceSelector: + matchNames: + - {{ .Release.Namespace }} + selector: + matchLabels: + {{- include "metrics-server.selectorLabels" . | nindent 6 }} + endpoints: + - port: https + path: /metrics + scheme: https + tlsConfig: + insecureSkipVerify: true + {{- with .Values.serviceMonitor.interval }} + interval: {{ . }} + {{- end }} + {{- with .Values.serviceMonitor.scrapeTimeout }} + scrapeTimeout: {{ . }} + {{- end }} + {{- with .Values.serviceMonitor.metricRelabelings }} + metricRelabelings: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.serviceMonitor.relabelings }} + relabelings: + {{- toYaml . | nindent 8 }} + {{- end }} +{{- end -}} diff --git a/packages/system/monitoring/charts/metrics-server/values.yaml b/packages/system/monitoring/charts/metrics-server/values.yaml new file mode 100644 index 00000000..fba10aaf --- /dev/null +++ b/packages/system/monitoring/charts/metrics-server/values.yaml @@ -0,0 +1,182 @@ +# Default values for metrics-server. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +image: + repository: registry.k8s.io/metrics-server/metrics-server + # Overrides the image tag whose default is v{{ .Chart.AppVersion }} + tag: "" + pullPolicy: IfNotPresent + +imagePullSecrets: [] +# - name: registrySecretName + +nameOverride: "" +fullnameOverride: "" + +serviceAccount: + # Specifies whether a service account should be created + create: true + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" + # The list of secrets mountable by this service account. + # See https://kubernetes.io/docs/reference/labels-annotations-taints/#enforce-mountable-secrets + secrets: [] + +rbac: + # Specifies whether RBAC resources should be created + create: true + pspEnabled: false + +apiService: + # Specifies if the v1beta1.metrics.k8s.io API service should be created. + # + # You typically want this enabled! If you disable API service creation you have to + # manage it outside of this chart for e.g horizontal pod autoscaling to + # work with this release. + create: true + # Annotations to add to the API service + annotations: {} + # Specifies whether to skip TLS verification + insecureSkipTLSVerify: true + # The PEM encoded CA bundle for TLS verification + caBundle: "" + +commonLabels: {} +podLabels: {} +podAnnotations: {} + +podSecurityContext: {} + +securityContext: + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + runAsNonRoot: true + runAsUser: 1000 + seccompProfile: + type: RuntimeDefault + capabilities: + drop: + - ALL + +priorityClassName: system-cluster-critical + +containerPort: 10250 + +hostNetwork: + # Specifies if metrics-server should be started in hostNetwork mode. + # + # You would require this enabled if you use alternate overlay networking for pods and + # API server unable to communicate with metrics-server. As an example, this is required + # if you use Weave network on EKS + enabled: false + +replicas: 1 + +updateStrategy: {} +# type: RollingUpdate +# rollingUpdate: +# maxSurge: 0 +# maxUnavailable: 1 + +podDisruptionBudget: + # https://kubernetes.io/docs/tasks/run-application/configure-pdb/ + enabled: false + minAvailable: + maxUnavailable: + +defaultArgs: + - --cert-dir=/tmp + - --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname + - --kubelet-use-node-status-port + - --metric-resolution=15s + +args: [] + +livenessProbe: + httpGet: + path: /livez + port: https + scheme: HTTPS + initialDelaySeconds: 0 + periodSeconds: 10 + failureThreshold: 3 + +readinessProbe: + httpGet: + path: /readyz + port: https + scheme: HTTPS + initialDelaySeconds: 20 + periodSeconds: 10 + failureThreshold: 3 + +service: + type: ClusterIP + port: 443 + annotations: {} + labels: {} + # Add these labels to have metrics-server show up in `kubectl cluster-info` + # kubernetes.io/cluster-service: "true" + # kubernetes.io/name: "Metrics-server" + +addonResizer: + enabled: false + image: + repository: registry.k8s.io/autoscaling/addon-resizer + tag: 1.8.19 + resources: + requests: + cpu: 40m + memory: 25Mi + limits: + cpu: 40m + memory: 25Mi + nanny: + cpu: 0m + extraCpu: 1m + memory: 0Mi + extraMemory: 2Mi + minClusterSize: 100 + pollPeriod: 300000 + threshold: 5 + +metrics: + enabled: false + +serviceMonitor: + enabled: false + additionalLabels: {} + interval: 1m + scrapeTimeout: 10s + metricRelabelings: [] + relabelings: [] + +# See https://github.com/kubernetes-sigs/metrics-server#scaling +resources: + requests: + cpu: 100m + memory: 200Mi + # limits: + # cpu: + # memory: + +extraVolumeMounts: [] + +extraVolumes: [] + +nodeSelector: {} + +tolerations: [] + +affinity: {} + +topologySpreadConstraints: [] + +# Annotations to add to the deployment +deploymentAnnotations: {} + +schedulerName: "" diff --git a/packages/system/monitoring/charts/prometheus-node-exporter/.helmignore b/packages/system/monitoring/charts/prometheus-node-exporter/.helmignore new file mode 100644 index 00000000..f0c13194 --- /dev/null +++ b/packages/system/monitoring/charts/prometheus-node-exporter/.helmignore @@ -0,0 +1,21 @@ +# 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 +*~ +# Various IDEs +.project +.idea/ +*.tmproj diff --git a/packages/system/monitoring/charts/prometheus-node-exporter/Chart.yaml b/packages/system/monitoring/charts/prometheus-node-exporter/Chart.yaml new file mode 100644 index 00000000..ae934c9f --- /dev/null +++ b/packages/system/monitoring/charts/prometheus-node-exporter/Chart.yaml @@ -0,0 +1,25 @@ +annotations: + artifacthub.io/license: Apache-2.0 + artifacthub.io/links: | + - name: Chart Source + url: https://github.com/prometheus-community/helm-charts +apiVersion: v2 +appVersion: 1.7.0 +description: A Helm chart for prometheus node-exporter +home: https://github.com/prometheus/node_exporter/ +keywords: +- node-exporter +- prometheus +- exporter +maintainers: +- email: gianrubio@gmail.com + name: gianrubio +- email: zanhsieh@gmail.com + name: zanhsieh +- email: rootsandtrees@posteo.de + name: zeritti +name: prometheus-node-exporter +sources: +- https://github.com/prometheus/node_exporter/ +type: application +version: 4.24.0 diff --git a/packages/system/monitoring/charts/prometheus-node-exporter/README.md b/packages/system/monitoring/charts/prometheus-node-exporter/README.md new file mode 100644 index 00000000..ef838441 --- /dev/null +++ b/packages/system/monitoring/charts/prometheus-node-exporter/README.md @@ -0,0 +1,96 @@ +# Prometheus Node Exporter + +Prometheus exporter for hardware and OS metrics exposed by *NIX kernels, written in Go with pluggable metric collectors. + +This chart bootstraps a Prometheus [Node Exporter](http://github.com/prometheus/node_exporter) daemonset on a [Kubernetes](http://kubernetes.io) cluster using the [Helm](https://helm.sh) package manager. + +## Get Repository Info + +```console +helm repo add prometheus-community https://prometheus-community.github.io/helm-charts +helm repo update +``` + +_See [helm repo](https://helm.sh/docs/helm/helm_repo/) for command documentation._ + +## Install Chart + +```console +helm install [RELEASE_NAME] prometheus-community/prometheus-node-exporter +``` + +_See [configuration](#configuring) below._ + +_See [helm install](https://helm.sh/docs/helm/helm_install/) for command documentation._ + +## Uninstall Chart + +```console +helm uninstall [RELEASE_NAME] +``` + +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._ + +## Upgrading Chart + +```console +helm upgrade [RELEASE_NAME] prometheus-community/prometheus-node-exporter --install +``` + +_See [helm upgrade](https://helm.sh/docs/helm/helm_upgrade/) for command documentation._ + +### 3.x to 4.x + +Starting from version 4.0.0, the `node exporter` chart is using the [Kubernetes recommended labels](https://kubernetes.io/docs/concepts/overview/working-with-objects/common-labels/). Therefore you have to delete the daemonset before you upgrade. + +```console +kubectl delete daemonset -l app=prometheus-node-exporter +helm upgrade -i prometheus-node-exporter prometheus-community/prometheus-node-exporter +``` + +If you use your own custom [ServiceMonitor](https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api.md#servicemonitor) or [PodMonitor](https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api.md#podmonitor), please ensure to upgrade their `selector` fields accordingly to the new labels. + +### From 2.x to 3.x + +Change the following: + +```yaml +hostRootFsMount: true +``` + +to: + +```yaml +hostRootFsMount: + enabled: true + mountPropagation: HostToContainer +``` + +## Configuring + +See [Customizing the Chart Before Installing](https://helm.sh/docs/intro/using_helm/#customizing-the-chart-before-installing). To see all configurable options with detailed comments, visit the chart's [values.yaml](./values.yaml), or run these configuration commands: + +```console +helm show values prometheus-community/prometheus-node-exporter +``` + +### kube-rbac-proxy + +You can enable `prometheus-node-exporter` endpoint protection using `kube-rbac-proxy`. By setting `kubeRBACProxy.enabled: true`, this chart will deploy a RBAC proxy container protecting the node-exporter endpoint. +To authorize access, authenticate your requests (via a `ServiceAccount` for example) with a `ClusterRole` attached such as: + +```yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: prometheus-node-exporter-read +rules: + - apiGroups: [ "" ] + resources: ["services/node-exporter-prometheus-node-exporter"] + verbs: + - get +``` + +See [kube-rbac-proxy examples](https://github.com/brancz/kube-rbac-proxy/tree/master/examples/resource-attributes) for more details. diff --git a/packages/system/monitoring/charts/prometheus-node-exporter/ci/port-values.yaml b/packages/system/monitoring/charts/prometheus-node-exporter/ci/port-values.yaml new file mode 100644 index 00000000..dbfb4b67 --- /dev/null +++ b/packages/system/monitoring/charts/prometheus-node-exporter/ci/port-values.yaml @@ -0,0 +1,3 @@ +service: + targetPort: 9102 + port: 9102 diff --git a/packages/system/monitoring/charts/prometheus-node-exporter/templates/NOTES.txt b/packages/system/monitoring/charts/prometheus-node-exporter/templates/NOTES.txt new file mode 100644 index 00000000..db8584de --- /dev/null +++ b/packages/system/monitoring/charts/prometheus-node-exporter/templates/NOTES.txt @@ -0,0 +1,29 @@ +1. Get the application URL by running these commands: +{{- if contains "NodePort" .Values.service.type }} + export NODE_PORT=$(kubectl get --namespace {{ template "prometheus-node-exporter.namespace" . }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ template "prometheus-node-exporter.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ template "prometheus-node-exporter.namespace" . }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT +{{- else if contains "LoadBalancer" .Values.service.type }} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get svc -w {{ template "prometheus-node-exporter.fullname" . }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ template "prometheus-node-exporter.namespace" . }} {{ template "prometheus-node-exporter.fullname" . }} -o jsonpath='{.status.loadBalancer.ingress[0].ip}') + echo http://$SERVICE_IP:{{ .Values.service.port }} +{{- else if contains "ClusterIP" .Values.service.type }} + export POD_NAME=$(kubectl get pods --namespace {{ template "prometheus-node-exporter.namespace" . }} -l "app.kubernetes.io/name={{ template "prometheus-node-exporter.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + echo "Visit http://127.0.0.1:9100 to use your application" + kubectl port-forward --namespace {{ template "prometheus-node-exporter.namespace" . }} $POD_NAME 9100 +{{- end }} + +{{- if .Values.kubeRBACProxy.enabled}} + +kube-rbac-proxy endpoint protections is enabled: +- Metrics endpoints is now HTTPS +- Ensure that the client authenticates the requests (e.g. via service account) with the following role permissions: +``` +rules: + - apiGroups: [ "" ] + resources: ["services/{{ template "prometheus-node-exporter.fullname" . }}"] + verbs: + - get +``` +{{- end }} \ No newline at end of file diff --git a/packages/system/monitoring/charts/prometheus-node-exporter/templates/_helpers.tpl b/packages/system/monitoring/charts/prometheus-node-exporter/templates/_helpers.tpl new file mode 100644 index 00000000..84552fe4 --- /dev/null +++ b/packages/system/monitoring/charts/prometheus-node-exporter/templates/_helpers.tpl @@ -0,0 +1,185 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "prometheus-node-exporter.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | 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 "prometheus-node-exporter.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "prometheus-node-exporter.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "prometheus-node-exporter.labels" -}} +helm.sh/chart: {{ include "prometheus-node-exporter.chart" . }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +app.kubernetes.io/component: metrics +app.kubernetes.io/part-of: {{ include "prometheus-node-exporter.name" . }} +{{ include "prometheus-node-exporter.selectorLabels" . }} +{{- with .Chart.AppVersion }} +app.kubernetes.io/version: {{ . | quote }} +{{- end }} +{{- with .Values.podLabels }} +{{ toYaml . }} +{{- end }} +{{- if .Values.releaseLabel }} +release: {{ .Release.Name }} +{{- end }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "prometheus-node-exporter.selectorLabels" -}} +app.kubernetes.io/name: {{ include "prometheus-node-exporter.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + + +{{/* +Create the name of the service account to use +*/}} +{{- define "prometheus-node-exporter.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "prometheus-node-exporter.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} + +{{/* +The image to use +*/}} +{{- define "prometheus-node-exporter.image" -}} +{{- if .Values.image.sha }} +{{- fail "image.sha forbidden. Use image.digest instead" }} +{{- else if .Values.image.digest }} +{{- if .Values.global.imageRegistry }} +{{- printf "%s/%s:%s@%s" .Values.global.imageRegistry .Values.image.repository (default (printf "v%s" .Chart.AppVersion) .Values.image.tag) .Values.image.digest }} +{{- else }} +{{- printf "%s/%s:%s@%s" .Values.image.registry .Values.image.repository (default (printf "v%s" .Chart.AppVersion) .Values.image.tag) .Values.image.digest }} +{{- end }} +{{- else }} +{{- if .Values.global.imageRegistry }} +{{- printf "%s/%s:%s" .Values.global.imageRegistry .Values.image.repository (default (printf "v%s" .Chart.AppVersion) .Values.image.tag) }} +{{- else }} +{{- printf "%s/%s:%s" .Values.image.registry .Values.image.repository (default (printf "v%s" .Chart.AppVersion) .Values.image.tag) }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Allow the release namespace to be overridden for multi-namespace deployments in combined charts +*/}} +{{- define "prometheus-node-exporter.namespace" -}} +{{- if .Values.namespaceOverride }} +{{- .Values.namespaceOverride }} +{{- else }} +{{- .Release.Namespace }} +{{- end }} +{{- end }} + +{{/* +Create the namespace name of the service monitor +*/}} +{{- define "prometheus-node-exporter.monitor-namespace" -}} +{{- if .Values.namespaceOverride }} +{{- .Values.namespaceOverride }} +{{- else }} +{{- if .Values.prometheus.monitor.namespace }} +{{- .Values.prometheus.monitor.namespace }} +{{- else }} +{{- .Release.Namespace }} +{{- end }} +{{- end }} +{{- end }} + +{{/* Sets default scrape limits for servicemonitor */}} +{{- define "servicemonitor.scrapeLimits" -}} +{{- with .sampleLimit }} +sampleLimit: {{ . }} +{{- end }} +{{- with .targetLimit }} +targetLimit: {{ . }} +{{- end }} +{{- with .labelLimit }} +labelLimit: {{ . }} +{{- end }} +{{- with .labelNameLengthLimit }} +labelNameLengthLimit: {{ . }} +{{- end }} +{{- with .labelValueLengthLimit }} +labelValueLengthLimit: {{ . }} +{{- end }} +{{- end }} + +{{/* +Formats imagePullSecrets. Input is (dict "Values" .Values "imagePullSecrets" .{specific imagePullSecrets}) +*/}} +{{- define "prometheus-node-exporter.imagePullSecrets" -}} +{{- range (concat .Values.global.imagePullSecrets .imagePullSecrets) }} + {{- if eq (typeOf .) "map[string]interface {}" }} +- {{ toYaml . | trim }} + {{- else }} +- name: {{ . }} + {{- end }} +{{- end }} +{{- end -}} + +{{/* +Create the namespace name of the pod monitor +*/}} +{{- define "prometheus-node-exporter.podmonitor-namespace" -}} +{{- if .Values.namespaceOverride }} +{{- .Values.namespaceOverride }} +{{- else }} +{{- if .Values.prometheus.podMonitor.namespace }} +{{- .Values.prometheus.podMonitor.namespace }} +{{- else }} +{{- .Release.Namespace }} +{{- end }} +{{- end }} +{{- end }} + +{{/* Sets default scrape limits for podmonitor */}} +{{- define "podmonitor.scrapeLimits" -}} +{{- with .sampleLimit }} +sampleLimit: {{ . }} +{{- end }} +{{- with .targetLimit }} +targetLimit: {{ . }} +{{- end }} +{{- with .labelLimit }} +labelLimit: {{ . }} +{{- end }} +{{- with .labelNameLengthLimit }} +labelNameLengthLimit: {{ . }} +{{- end }} +{{- with .labelValueLengthLimit }} +labelValueLengthLimit: {{ . }} +{{- end }} +{{- end }} diff --git a/packages/system/monitoring/charts/prometheus-node-exporter/templates/clusterrole.yaml b/packages/system/monitoring/charts/prometheus-node-exporter/templates/clusterrole.yaml new file mode 100644 index 00000000..c256dba7 --- /dev/null +++ b/packages/system/monitoring/charts/prometheus-node-exporter/templates/clusterrole.yaml @@ -0,0 +1,19 @@ +{{- if and (eq .Values.rbac.create true) (eq .Values.kubeRBACProxy.enabled true) -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ include "prometheus-node-exporter.fullname" . }} + labels: + {{- include "prometheus-node-exporter.labels" . | nindent 4 }} +rules: + {{- if $.Values.kubeRBACProxy.enabled }} + - apiGroups: [ "authentication.k8s.io" ] + resources: + - tokenreviews + verbs: [ "create" ] + - apiGroups: [ "authorization.k8s.io" ] + resources: + - subjectaccessreviews + verbs: [ "create" ] + {{- end }} +{{- end -}} diff --git a/packages/system/monitoring/charts/prometheus-node-exporter/templates/clusterrolebinding.yaml b/packages/system/monitoring/charts/prometheus-node-exporter/templates/clusterrolebinding.yaml new file mode 100644 index 00000000..653305ad --- /dev/null +++ b/packages/system/monitoring/charts/prometheus-node-exporter/templates/clusterrolebinding.yaml @@ -0,0 +1,20 @@ +{{- if and (eq .Values.rbac.create true) (eq .Values.kubeRBACProxy.enabled true) -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + labels: + {{- include "prometheus-node-exporter.labels" . | nindent 4 }} + name: {{ template "prometheus-node-exporter.fullname" . }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole +{{- if .Values.rbac.useExistingRole }} + name: {{ .Values.rbac.useExistingRole }} +{{- else }} + name: {{ template "prometheus-node-exporter.fullname" . }} +{{- end }} +subjects: +- kind: ServiceAccount + name: {{ template "prometheus-node-exporter.serviceAccountName" . }} + namespace: {{ template "prometheus-node-exporter.namespace" . }} +{{- end -}} diff --git a/packages/system/monitoring/charts/prometheus-node-exporter/templates/daemonset.yaml b/packages/system/monitoring/charts/prometheus-node-exporter/templates/daemonset.yaml new file mode 100644 index 00000000..a5116a89 --- /dev/null +++ b/packages/system/monitoring/charts/prometheus-node-exporter/templates/daemonset.yaml @@ -0,0 +1,285 @@ +apiVersion: apps/v1 +kind: DaemonSet +metadata: + name: {{ include "prometheus-node-exporter.fullname" . }} + namespace: {{ include "prometheus-node-exporter.namespace" . }} + labels: + {{- include "prometheus-node-exporter.labels" . | nindent 4 }} + {{- with .Values.daemonsetAnnotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + selector: + matchLabels: + {{- include "prometheus-node-exporter.selectorLabels" . | nindent 6 }} + revisionHistoryLimit: {{ .Values.revisionHistoryLimit }} + {{- with .Values.updateStrategy }} + updateStrategy: + {{- toYaml . | nindent 4 }} + {{- end }} + template: + metadata: + {{- with .Values.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "prometheus-node-exporter.labels" . | nindent 8 }} + spec: + automountServiceAccountToken: {{ ternary true false (or .Values.serviceAccount.automountServiceAccountToken .Values.kubeRBACProxy.enabled) }} + {{- with .Values.securityContext }} + securityContext: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.priorityClassName }} + priorityClassName: {{ . }} + {{- end }} + {{- with .Values.extraInitContainers }} + initContainers: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "prometheus-node-exporter.serviceAccountName" . }} + containers: + {{- $servicePort := ternary 8100 .Values.service.port .Values.kubeRBACProxy.enabled }} + - name: node-exporter + image: {{ include "prometheus-node-exporter.image" . }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + args: + - --path.procfs=/host/proc + - --path.sysfs=/host/sys + {{- if .Values.hostRootFsMount.enabled }} + - --path.rootfs=/host/root + {{- if semverCompare ">=1.4.0" (default .Chart.AppVersion .Values.image.tag) }} + - --path.udev.data=/host/root/run/udev/data + {{- end }} + {{- end }} + - --web.listen-address=[$(HOST_IP)]:{{ $servicePort }} + {{- with .Values.extraArgs }} + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.containerSecurityContext }} + securityContext: + {{- toYaml . | nindent 12 }} + {{- end }} + env: + - name: HOST_IP + {{- if .Values.kubeRBACProxy.enabled }} + value: 127.0.0.1 + {{- else if .Values.service.listenOnAllInterfaces }} + value: 0.0.0.0 + {{- else }} + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: status.hostIP + {{- end }} + {{- range $key, $value := .Values.env }} + - name: {{ $key }} + value: {{ $value | quote }} + {{- end }} + {{- if eq .Values.kubeRBACProxy.enabled false }} + ports: + - name: {{ .Values.service.portName }} + containerPort: {{ .Values.service.port }} + protocol: TCP + {{- end }} + livenessProbe: + failureThreshold: {{ .Values.livenessProbe.failureThreshold }} + httpGet: + {{- if .Values.kubeRBACProxy.enabled }} + host: 127.0.0.1 + {{- end }} + httpHeaders: + {{- range $_, $header := .Values.livenessProbe.httpGet.httpHeaders }} + - name: {{ $header.name }} + value: {{ $header.value }} + {{- end }} + path: / + port: {{ $servicePort }} + scheme: {{ upper .Values.livenessProbe.httpGet.scheme }} + initialDelaySeconds: {{ .Values.livenessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.livenessProbe.periodSeconds }} + successThreshold: {{ .Values.livenessProbe.successThreshold }} + timeoutSeconds: {{ .Values.livenessProbe.timeoutSeconds }} + readinessProbe: + failureThreshold: {{ .Values.readinessProbe.failureThreshold }} + httpGet: + {{- if .Values.kubeRBACProxy.enabled }} + host: 127.0.0.1 + {{- end }} + httpHeaders: + {{- range $_, $header := .Values.readinessProbe.httpGet.httpHeaders }} + - name: {{ $header.name }} + value: {{ $header.value }} + {{- end }} + path: / + port: {{ $servicePort }} + scheme: {{ upper .Values.readinessProbe.httpGet.scheme }} + initialDelaySeconds: {{ .Values.readinessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.readinessProbe.periodSeconds }} + successThreshold: {{ .Values.readinessProbe.successThreshold }} + timeoutSeconds: {{ .Values.readinessProbe.timeoutSeconds }} + {{- with .Values.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + volumeMounts: + - name: proc + mountPath: /host/proc + readOnly: true + - name: sys + mountPath: /host/sys + readOnly: true + {{- if .Values.hostRootFsMount.enabled }} + - name: root + mountPath: /host/root + {{- with .Values.hostRootFsMount.mountPropagation }} + mountPropagation: {{ . }} + {{- end }} + readOnly: true + {{- end }} + {{- range $_, $mount := .Values.extraHostVolumeMounts }} + - name: {{ $mount.name }} + mountPath: {{ $mount.mountPath }} + readOnly: {{ $mount.readOnly }} + {{- with $mount.mountPropagation }} + mountPropagation: {{ . }} + {{- end }} + {{- end }} + {{- range $_, $mount := .Values.sidecarVolumeMount }} + - name: {{ $mount.name }} + mountPath: {{ $mount.mountPath }} + readOnly: true + {{- end }} + {{- range $_, $mount := .Values.configmaps }} + - name: {{ $mount.name }} + mountPath: {{ $mount.mountPath }} + {{- end }} + {{- range $_, $mount := .Values.secrets }} + - name: {{ .name }} + mountPath: {{ .mountPath }} + {{- end }} + {{- with .Values.sidecars }} + {{- toYaml . | nindent 8 }} + {{- if or $.Values.sidecarVolumeMount $.Values.sidecarHostVolumeMounts }} + volumeMounts: + {{- range $_, $mount := $.Values.sidecarVolumeMount }} + - name: {{ $mount.name }} + mountPath: {{ $mount.mountPath }} + readOnly: {{ $mount.readOnly }} + {{- end }} + {{- range $_, $mount := $.Values.sidecarHostVolumeMounts }} + - name: {{ $mount.name }} + mountPath: {{ $mount.mountPath }} + readOnly: {{ $mount.readOnly }} + {{- if $mount.mountPropagation }} + mountPropagation: {{ $mount.mountPropagation }} + {{- end }} + {{- end }} + {{- end }} + {{- end }} + {{- if .Values.kubeRBACProxy.enabled }} + - name: kube-rbac-proxy + args: + {{- if .Values.kubeRBACProxy.extraArgs }} + {{- .Values.kubeRBACProxy.extraArgs | toYaml | nindent 12 }} + {{- end }} + - --secure-listen-address=:{{ .Values.service.port}} + - --upstream=http://127.0.0.1:{{ $servicePort }}/ + - --proxy-endpoints-port=8888 + - --config-file=/etc/kube-rbac-proxy-config/config-file.yaml + volumeMounts: + - name: kube-rbac-proxy-config + mountPath: /etc/kube-rbac-proxy-config + imagePullPolicy: {{ .Values.kubeRBACProxy.image.pullPolicy }} + {{- if .Values.kubeRBACProxy.image.sha }} + image: "{{ .Values.global.imageRegistry | default .Values.kubeRBACProxy.image.registry}}/{{ .Values.kubeRBACProxy.image.repository }}:{{ .Values.kubeRBACProxy.image.tag }}@sha256:{{ .Values.kubeRBACProxy.image.sha }}" + {{- else }} + image: "{{ .Values.global.imageRegistry | default .Values.kubeRBACProxy.image.registry}}/{{ .Values.kubeRBACProxy.image.repository }}:{{ .Values.kubeRBACProxy.image.tag }}" + {{- end }} + ports: + - containerPort: {{ .Values.service.port}} + name: "http" + - containerPort: 8888 + name: "http-healthz" + readinessProbe: + httpGet: + scheme: HTTPS + port: 8888 + path: healthz + initialDelaySeconds: 5 + timeoutSeconds: 5 + {{- if .Values.kubeRBACProxy.resources }} + resources: + {{ toYaml .Values.kubeRBACProxy.resources | nindent 12 }} + {{- end }} + {{- if .Values.kubeRBACProxy.containerSecurityContext }} + securityContext: + {{ toYaml .Values.kubeRBACProxy.containerSecurityContext | nindent 12 }} + {{- end }} + {{- end }} + {{- if or .Values.imagePullSecrets .Values.global.imagePullSecrets }} + imagePullSecrets: + {{- include "prometheus-node-exporter.imagePullSecrets" (dict "Values" .Values "imagePullSecrets" .Values.imagePullSecrets) | indent 8 }} + {{- end }} + hostNetwork: {{ .Values.hostNetwork }} + hostPID: {{ .Values.hostPID }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.dnsConfig }} + dnsConfig: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + volumes: + - name: proc + hostPath: + path: /proc + - name: sys + hostPath: + path: /sys + {{- if .Values.hostRootFsMount.enabled }} + - name: root + hostPath: + path: / + {{- end }} + {{- range $_, $mount := .Values.extraHostVolumeMounts }} + - name: {{ $mount.name }} + hostPath: + path: {{ $mount.hostPath }} + {{- end }} + {{- range $_, $mount := .Values.sidecarVolumeMount }} + - name: {{ $mount.name }} + emptyDir: + medium: Memory + {{- end }} + {{- range $_, $mount := .Values.sidecarHostVolumeMounts }} + - name: {{ $mount.name }} + hostPath: + path: {{ $mount.hostPath }} + {{- end }} + {{- range $_, $mount := .Values.configmaps }} + - name: {{ $mount.name }} + configMap: + name: {{ $mount.name }} + {{- end }} + {{- range $_, $mount := .Values.secrets }} + - name: {{ $mount.name }} + secret: + secretName: {{ $mount.name }} + {{- end }} + {{- if .Values.kubeRBACProxy.enabled }} + - name: kube-rbac-proxy-config + configMap: + name: {{ template "prometheus-node-exporter.fullname" . }}-rbac-config + {{- end }} diff --git a/packages/system/monitoring/charts/prometheus-node-exporter/templates/endpoints.yaml b/packages/system/monitoring/charts/prometheus-node-exporter/templates/endpoints.yaml new file mode 100644 index 00000000..45eeb8d9 --- /dev/null +++ b/packages/system/monitoring/charts/prometheus-node-exporter/templates/endpoints.yaml @@ -0,0 +1,18 @@ +{{- if .Values.endpoints }} +apiVersion: v1 +kind: Endpoints +metadata: + name: {{ include "prometheus-node-exporter.fullname" . }} + namespace: {{ include "prometheus-node-exporter.namespace" . }} + labels: + {{- include "prometheus-node-exporter.labels" . | nindent 4 }} +subsets: + - addresses: + {{- range .Values.endpoints }} + - ip: {{ . }} + {{- end }} + ports: + - name: {{ .Values.service.portName }} + port: 9100 + protocol: TCP +{{- end }} diff --git a/packages/system/monitoring/charts/prometheus-node-exporter/templates/extra-manifests.yaml b/packages/system/monitoring/charts/prometheus-node-exporter/templates/extra-manifests.yaml new file mode 100644 index 00000000..2b21b710 --- /dev/null +++ b/packages/system/monitoring/charts/prometheus-node-exporter/templates/extra-manifests.yaml @@ -0,0 +1,4 @@ +{{ range .Values.extraManifests }} +--- +{{ tpl . $ }} +{{ end }} diff --git a/packages/system/monitoring/charts/prometheus-node-exporter/templates/networkpolicy.yaml b/packages/system/monitoring/charts/prometheus-node-exporter/templates/networkpolicy.yaml new file mode 100644 index 00000000..82572272 --- /dev/null +++ b/packages/system/monitoring/charts/prometheus-node-exporter/templates/networkpolicy.yaml @@ -0,0 +1,23 @@ +{{- if .Values.networkPolicy.enabled }} +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: {{ include "prometheus-node-exporter.fullname" . }} + namespace: {{ include "prometheus-node-exporter.namespace" . }} + labels: + {{- include "prometheus-node-exporter.labels" $ | nindent 4 }} + {{- with .Values.service.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + ingress: + - ports: + - port: {{ .Values.service.port }} + policyTypes: + - Egress + - Ingress + podSelector: + matchLabels: + {{- include "prometheus-node-exporter.selectorLabels" . | nindent 6 }} +{{- end }} diff --git a/packages/system/monitoring/charts/prometheus-node-exporter/templates/podmonitor.yaml b/packages/system/monitoring/charts/prometheus-node-exporter/templates/podmonitor.yaml new file mode 100644 index 00000000..f88da6a3 --- /dev/null +++ b/packages/system/monitoring/charts/prometheus-node-exporter/templates/podmonitor.yaml @@ -0,0 +1,91 @@ +{{- if .Values.prometheus.podMonitor.enabled }} +apiVersion: {{ .Values.prometheus.podMonitor.apiVersion | default "monitoring.coreos.com/v1" }} +kind: PodMonitor +metadata: + name: {{ include "prometheus-node-exporter.fullname" . }} + namespace: {{ include "prometheus-node-exporter.podmonitor-namespace" . }} + labels: + {{- include "prometheus-node-exporter.labels" . | nindent 4 }} + {{- with .Values.prometheus.podMonitor.additionalLabels }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + jobLabel: {{ default "app.kubernetes.io/name" .Values.prometheus.podMonitor.jobLabel }} + {{- include "podmonitor.scrapeLimits" .Values.prometheus.podMonitor | nindent 2 }} + selector: + matchLabels: + {{- with .Values.prometheus.podMonitor.selectorOverride }} + {{- toYaml . | nindent 6 }} + {{- else }} + {{- include "prometheus-node-exporter.selectorLabels" . | nindent 6 }} + {{- end }} + namespaceSelector: + matchNames: + - {{ include "prometheus-node-exporter.namespace" . }} + {{- with .Values.prometheus.podMonitor.attachMetadata }} + attachMetadata: + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.prometheus.podMonitor.podTargetLabels }} + podTargetLabels: + {{- toYaml . | nindent 4 }} + {{- end }} + podMetricsEndpoints: + - port: {{ .Values.service.portName }} + {{- with .Values.prometheus.podMonitor.scheme }} + scheme: {{ . }} + {{- end }} + {{- with .Values.prometheus.podMonitor.path }} + path: {{ . }} + {{- end }} + {{- with .Values.prometheus.podMonitor.basicAuth }} + basicAuth: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.prometheus.podMonitor.bearerTokenSecret }} + bearerTokenSecret: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.prometheus.podMonitor.tlsConfig }} + tlsConfig: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.prometheus.podMonitor.authorization }} + authorization: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.prometheus.podMonitor.oauth2 }} + oauth2: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.prometheus.podMonitor.proxyUrl }} + proxyUrl: {{ . }} + {{- end }} + {{- with .Values.prometheus.podMonitor.interval }} + interval: {{ . }} + {{- end }} + {{- with .Values.prometheus.podMonitor.honorTimestamps }} + honorTimestamps: {{ . }} + {{- end }} + {{- with .Values.prometheus.podMonitor.honorLabels }} + honorLabels: {{ . }} + {{- end }} + {{- with .Values.prometheus.podMonitor.scrapeTimeout }} + scrapeTimeout: {{ . }} + {{- end }} + {{- with .Values.prometheus.podMonitor.relabelings }} + relabelings: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.prometheus.podMonitor.metricRelabelings }} + metricRelabelings: + {{- toYaml . | nindent 8 }} + {{- end }} + enableHttp2: {{ default false .Values.prometheus.podMonitor.enableHttp2 }} + filterRunning: {{ default true .Values.prometheus.podMonitor.filterRunning }} + followRedirects: {{ default false .Values.prometheus.podMonitor.followRedirects }} + {{- with .Values.prometheus.podMonitor.params }} + params: + {{- toYaml . | nindent 8 }} + {{- end }} +{{- end }} diff --git a/packages/system/monitoring/charts/prometheus-node-exporter/templates/psp-clusterrole.yaml b/packages/system/monitoring/charts/prometheus-node-exporter/templates/psp-clusterrole.yaml new file mode 100644 index 00000000..89573172 --- /dev/null +++ b/packages/system/monitoring/charts/prometheus-node-exporter/templates/psp-clusterrole.yaml @@ -0,0 +1,14 @@ +{{- if and .Values.rbac.create .Values.rbac.pspEnabled (.Capabilities.APIVersions.Has "policy/v1beta1/PodSecurityPolicy") }} +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: psp-{{ include "prometheus-node-exporter.fullname" . }} + labels: + {{- include "prometheus-node-exporter.labels" . | nindent 4 }} +rules: +- apiGroups: ['extensions'] + resources: ['podsecuritypolicies'] + verbs: ['use'] + resourceNames: + - {{ include "prometheus-node-exporter.fullname" . }} +{{- end }} diff --git a/packages/system/monitoring/charts/prometheus-node-exporter/templates/psp-clusterrolebinding.yaml b/packages/system/monitoring/charts/prometheus-node-exporter/templates/psp-clusterrolebinding.yaml new file mode 100644 index 00000000..33337017 --- /dev/null +++ b/packages/system/monitoring/charts/prometheus-node-exporter/templates/psp-clusterrolebinding.yaml @@ -0,0 +1,16 @@ +{{- if and .Values.rbac.create .Values.rbac.pspEnabled (.Capabilities.APIVersions.Has "policy/v1beta1/PodSecurityPolicy") }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: psp-{{ include "prometheus-node-exporter.fullname" . }} + labels: + {{- include "prometheus-node-exporter.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: psp-{{ include "prometheus-node-exporter.fullname" . }} +subjects: + - kind: ServiceAccount + name: {{ include "prometheus-node-exporter.fullname" . }} + namespace: {{ include "prometheus-node-exporter.namespace" . }} +{{- end }} diff --git a/packages/system/monitoring/charts/prometheus-node-exporter/templates/psp.yaml b/packages/system/monitoring/charts/prometheus-node-exporter/templates/psp.yaml new file mode 100644 index 00000000..4896c84d --- /dev/null +++ b/packages/system/monitoring/charts/prometheus-node-exporter/templates/psp.yaml @@ -0,0 +1,49 @@ +{{- if and .Values.rbac.create .Values.rbac.pspEnabled (.Capabilities.APIVersions.Has "policy/v1beta1/PodSecurityPolicy") }} +apiVersion: policy/v1beta1 +kind: PodSecurityPolicy +metadata: + name: {{ include "prometheus-node-exporter.fullname" . }} + namespace: {{ include "prometheus-node-exporter.namespace" . }} + labels: + {{- include "prometheus-node-exporter.labels" . | nindent 4 }} + {{- with .Values.rbac.pspAnnotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + privileged: false + # Allow core volume types. + volumes: + - 'configMap' + - 'emptyDir' + - 'projected' + - 'secret' + - 'downwardAPI' + - 'persistentVolumeClaim' + - 'hostPath' + hostNetwork: true + hostIPC: false + hostPID: true + hostPorts: + - min: 0 + max: 65535 + runAsUser: + # Permits the container to run with root privileges as well. + rule: 'RunAsAny' + seLinux: + # This policy assumes the nodes are using AppArmor rather than SELinux. + rule: 'RunAsAny' + supplementalGroups: + rule: 'MustRunAs' + ranges: + # Allow adding the root group. + - min: 0 + max: 65535 + fsGroup: + rule: 'MustRunAs' + ranges: + # Allow adding the root group. + - min: 0 + max: 65535 + readOnlyRootFilesystem: false +{{- end }} diff --git a/packages/system/monitoring/charts/prometheus-node-exporter/templates/rbac-configmap.yaml b/packages/system/monitoring/charts/prometheus-node-exporter/templates/rbac-configmap.yaml new file mode 100644 index 00000000..814e1103 --- /dev/null +++ b/packages/system/monitoring/charts/prometheus-node-exporter/templates/rbac-configmap.yaml @@ -0,0 +1,16 @@ +{{- if .Values.kubeRBACProxy.enabled}} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ template "prometheus-node-exporter.fullname" . }}-rbac-config + namespace: {{ include "prometheus-node-exporter.namespace" . }} +data: + config-file.yaml: |+ + authorization: + resourceAttributes: + namespace: {{ template "prometheus-node-exporter.namespace" . }} + apiVersion: v1 + resource: services + subresource: {{ template "prometheus-node-exporter.fullname" . }} + name: {{ template "prometheus-node-exporter.fullname" . }} +{{- end }} \ No newline at end of file diff --git a/packages/system/monitoring/charts/prometheus-node-exporter/templates/service.yaml b/packages/system/monitoring/charts/prometheus-node-exporter/templates/service.yaml new file mode 100644 index 00000000..a065e46e --- /dev/null +++ b/packages/system/monitoring/charts/prometheus-node-exporter/templates/service.yaml @@ -0,0 +1,29 @@ +{{- if .Values.service.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "prometheus-node-exporter.fullname" . }} + namespace: {{ include "prometheus-node-exporter.namespace" . }} + labels: + {{- include "prometheus-node-exporter.labels" $ | nindent 4 }} + {{- with .Values.service.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: +{{- if .Values.service.ipDualStack.enabled }} + ipFamilies: {{ toYaml .Values.service.ipDualStack.ipFamilies | nindent 4 }} + ipFamilyPolicy: {{ .Values.service.ipDualStack.ipFamilyPolicy }} +{{- end }} + type: {{ .Values.service.type }} + ports: + - port: {{ .Values.service.port }} + {{- if ( and (eq .Values.service.type "NodePort" ) (not (empty .Values.service.nodePort)) ) }} + nodePort: {{ .Values.service.nodePort }} + {{- end }} + targetPort: {{ .Values.service.targetPort }} + protocol: TCP + name: {{ .Values.service.portName }} + selector: + {{- include "prometheus-node-exporter.selectorLabels" . | nindent 4 }} +{{- end }} diff --git a/packages/system/monitoring/charts/prometheus-node-exporter/templates/serviceaccount.yaml b/packages/system/monitoring/charts/prometheus-node-exporter/templates/serviceaccount.yaml new file mode 100644 index 00000000..5c3348c0 --- /dev/null +++ b/packages/system/monitoring/charts/prometheus-node-exporter/templates/serviceaccount.yaml @@ -0,0 +1,17 @@ +{{- if and .Values.rbac.create .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "prometheus-node-exporter.serviceAccountName" . }} + namespace: {{ include "prometheus-node-exporter.namespace" . }} + labels: + {{- include "prometheus-node-exporter.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- if or .Values.serviceAccount.imagePullSecrets .Values.global.imagePullSecrets }} +imagePullSecrets: + {{- include "prometheus-node-exporter.imagePullSecrets" (dict "Values" .Values "imagePullSecrets" .Values.serviceAccount.imagePullSecrets) | indent 2 }} +{{- end }} +{{- end -}} diff --git a/packages/system/monitoring/charts/prometheus-node-exporter/templates/servicemonitor.yaml b/packages/system/monitoring/charts/prometheus-node-exporter/templates/servicemonitor.yaml new file mode 100644 index 00000000..0d7a42ea --- /dev/null +++ b/packages/system/monitoring/charts/prometheus-node-exporter/templates/servicemonitor.yaml @@ -0,0 +1,61 @@ +{{- if .Values.prometheus.monitor.enabled }} +apiVersion: {{ .Values.prometheus.monitor.apiVersion | default "monitoring.coreos.com/v1" }} +kind: ServiceMonitor +metadata: + name: {{ include "prometheus-node-exporter.fullname" . }} + namespace: {{ include "prometheus-node-exporter.monitor-namespace" . }} + labels: + {{- include "prometheus-node-exporter.labels" . | nindent 4 }} + {{- with .Values.prometheus.monitor.additionalLabels }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + jobLabel: {{ default "app.kubernetes.io/name" .Values.prometheus.monitor.jobLabel }} + {{- include "servicemonitor.scrapeLimits" .Values.prometheus.monitor | nindent 2 }} + {{- with .Values.prometheus.monitor.podTargetLabels }} + podTargetLabels: + {{- toYaml . | nindent 4 }} + {{- end }} + selector: + matchLabels: + {{- with .Values.prometheus.monitor.selectorOverride }} + {{- toYaml . | nindent 6 }} + {{- else }} + {{- include "prometheus-node-exporter.selectorLabels" . | nindent 6 }} + {{- end }} + {{- with .Values.prometheus.monitor.attachMetadata }} + attachMetadata: + {{- toYaml . | nindent 4 }} + {{- end }} + endpoints: + - port: {{ .Values.service.portName }} + scheme: {{ .Values.prometheus.monitor.scheme }} + {{- with .Values.prometheus.monitor.basicAuth }} + basicAuth: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.prometheus.monitor.bearerTokenFile }} + bearerTokenFile: {{ . }} + {{- end }} + {{- with .Values.prometheus.monitor.tlsConfig }} + tlsConfig: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.prometheus.monitor.proxyUrl }} + proxyUrl: {{ . }} + {{- end }} + {{- with .Values.prometheus.monitor.interval }} + interval: {{ . }} + {{- end }} + {{- with .Values.prometheus.monitor.scrapeTimeout }} + scrapeTimeout: {{ . }} + {{- end }} + {{- with .Values.prometheus.monitor.relabelings }} + relabelings: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.prometheus.monitor.metricRelabelings }} + metricRelabelings: + {{- toYaml . | nindent 8 }} + {{- end }} +{{- end }} diff --git a/packages/system/monitoring/charts/prometheus-node-exporter/templates/verticalpodautoscaler.yaml b/packages/system/monitoring/charts/prometheus-node-exporter/templates/verticalpodautoscaler.yaml new file mode 100644 index 00000000..2c2705f8 --- /dev/null +++ b/packages/system/monitoring/charts/prometheus-node-exporter/templates/verticalpodautoscaler.yaml @@ -0,0 +1,40 @@ +{{- if and (.Capabilities.APIVersions.Has "autoscaling.k8s.io/v1") (.Values.verticalPodAutoscaler.enabled) }} +apiVersion: autoscaling.k8s.io/v1 +kind: VerticalPodAutoscaler +metadata: + name: {{ include "prometheus-node-exporter.fullname" . }} + namespace: {{ include "prometheus-node-exporter.namespace" . }} + labels: + {{- include "prometheus-node-exporter.labels" . | nindent 4 }} +spec: + {{- with .Values.verticalPodAutoscaler.recommenders }} + recommenders: + {{- toYaml . | nindent 4 }} + {{- end }} + resourcePolicy: + containerPolicies: + - containerName: node-exporter + {{- with .Values.verticalPodAutoscaler.controlledResources }} + controlledResources: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.verticalPodAutoscaler.controlledValues }} + controlledValues: {{ . }} + {{- end }} + {{- with .Values.verticalPodAutoscaler.maxAllowed }} + maxAllowed: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.verticalPodAutoscaler.minAllowed }} + minAllowed: + {{- toYaml . | nindent 8 }} + {{- end }} + targetRef: + apiVersion: apps/v1 + kind: DaemonSet + name: {{ include "prometheus-node-exporter.fullname" . }} + {{- with .Values.verticalPodAutoscaler.updatePolicy }} + updatePolicy: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/packages/system/monitoring/charts/prometheus-node-exporter/values.yaml b/packages/system/monitoring/charts/prometheus-node-exporter/values.yaml new file mode 100644 index 00000000..6e4665c1 --- /dev/null +++ b/packages/system/monitoring/charts/prometheus-node-exporter/values.yaml @@ -0,0 +1,480 @@ +# Default values for prometheus-node-exporter. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. +image: + registry: quay.io + repository: prometheus/node-exporter + # Overrides the image tag whose default is {{ printf "v%s" .Chart.AppVersion }} + tag: "" + pullPolicy: IfNotPresent + digest: "" + +imagePullSecrets: [] +# - name: "image-pull-secret" +nameOverride: "" +fullnameOverride: "" + +# Number of old history to retain to allow rollback +# Default Kubernetes value is set to 10 +revisionHistoryLimit: 10 + +global: + # To help compatibility with other charts which use global.imagePullSecrets. + # Allow either an array of {name: pullSecret} maps (k8s-style), or an array of strings (more common helm-style). + # global: + # imagePullSecrets: + # - name: pullSecret1 + # - name: pullSecret2 + # or + # global: + # imagePullSecrets: + # - pullSecret1 + # - pullSecret2 + imagePullSecrets: [] + # + # Allow parent charts to override registry hostname + imageRegistry: "" + +# Configure kube-rbac-proxy. When enabled, creates a kube-rbac-proxy to protect the node-exporter http endpoint. +# The requests are served through the same service but requests are HTTPS. +kubeRBACProxy: + enabled: false + image: + registry: quay.io + repository: brancz/kube-rbac-proxy + tag: v0.15.0 + sha: "" + pullPolicy: IfNotPresent + + # List of additional cli arguments to configure kube-rbac-prxy + # for example: --tls-cipher-suites, --log-file, etc. + # all the possible args can be found here: https://github.com/brancz/kube-rbac-proxy#usage + extraArgs: [] + + ## Specify security settings for a Container + ## Allows overrides and additional options compared to (Pod) securityContext + ## Ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container + containerSecurityContext: {} + + resources: {} + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 100m + # memory: 64Mi + # requests: + # cpu: 10m + # memory: 32Mi + +service: + enabled: true + type: ClusterIP + port: 9100 + targetPort: 9100 + nodePort: + portName: metrics + listenOnAllInterfaces: true + annotations: + prometheus.io/scrape: "true" + ipDualStack: + enabled: false + ipFamilies: ["IPv6", "IPv4"] + ipFamilyPolicy: "PreferDualStack" + +# Set a NetworkPolicy with: +# ingress only on service.port +# no egress permitted +networkPolicy: + enabled: false + +# Additional environment variables that will be passed to the daemonset +env: {} +## env: +## VARIABLE: value + +prometheus: + monitor: + enabled: false + additionalLabels: {} + namespace: "" + + jobLabel: "" + + # List of pod labels to add to node exporter metrics + # https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api.md#servicemonitor + podTargetLabels: [] + + scheme: http + basicAuth: {} + bearerTokenFile: + tlsConfig: {} + + ## proxyUrl: URL of a proxy that should be used for scraping. + ## + proxyUrl: "" + + ## Override serviceMonitor selector + ## + selectorOverride: {} + + ## Attach node metadata to discovered targets. Requires Prometheus v2.35.0 and above. + ## + attachMetadata: + node: false + + relabelings: [] + metricRelabelings: [] + interval: "" + scrapeTimeout: 10s + ## prometheus.monitor.apiVersion ApiVersion for the serviceMonitor Resource(defaults to "monitoring.coreos.com/v1") + apiVersion: "" + + ## SampleLimit defines per-scrape limit on number of scraped samples that will be accepted. + ## + sampleLimit: 0 + + ## TargetLimit defines a limit on the number of scraped targets that will be accepted. + ## + targetLimit: 0 + + ## Per-scrape limit on number of labels that will be accepted for a sample. Only valid in Prometheus versions 2.27.0 and newer. + ## + labelLimit: 0 + + ## Per-scrape limit on length of labels name that will be accepted for a sample. Only valid in Prometheus versions 2.27.0 and newer. + ## + labelNameLengthLimit: 0 + + ## Per-scrape limit on length of labels value that will be accepted for a sample. Only valid in Prometheus versions 2.27.0 and newer. + ## + labelValueLengthLimit: 0 + + # PodMonitor defines monitoring for a set of pods. + # ref. https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api.md#monitoring.coreos.com/v1.PodMonitor + # Using a PodMonitor may be preferred in some environments where there is very large number + # of Node Exporter endpoints (1000+) behind a single service. + # The PodMonitor is disabled by default. When switching from ServiceMonitor to PodMonitor, + # the time series resulting from the configuration through PodMonitor may have different labels. + # For instance, there will not be the service label any longer which might + # affect PromQL queries selecting that label. + podMonitor: + enabled: false + # Namespace in which to deploy the pod monitor. Defaults to the release namespace. + namespace: "" + # Additional labels, e.g. setting a label for pod monitor selector as set in prometheus + additionalLabels: {} + # release: kube-prometheus-stack + # PodTargetLabels transfers labels of the Kubernetes Pod onto the target. + podTargetLabels: [] + # apiVersion defaults to monitoring.coreos.com/v1. + apiVersion: "" + # Override pod selector to select pod objects. + selectorOverride: {} + # Attach node metadata to discovered targets. Requires Prometheus v2.35.0 and above. + attachMetadata: + node: false + # The label to use to retrieve the job name from. Defaults to label app.kubernetes.io/name. + jobLabel: "" + + # Scheme/protocol to use for scraping. + scheme: "http" + # Path to scrape metrics at. + path: "/metrics" + + # BasicAuth allow an endpoint to authenticate over basic authentication. + # More info: https://prometheus.io/docs/operating/configuration/#endpoint + basicAuth: {} + # Secret to mount to read bearer token for scraping targets. + # The secret needs to be in the same namespace as the pod monitor and accessible by the Prometheus Operator. + # https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#secretkeyselector-v1-core + bearerTokenSecret: {} + # TLS configuration to use when scraping the endpoint. + tlsConfig: {} + # Authorization section for this endpoint. + # https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api.md#monitoring.coreos.com/v1.SafeAuthorization + authorization: {} + # OAuth2 for the URL. Only valid in Prometheus versions 2.27.0 and newer. + # https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api.md#monitoring.coreos.com/v1.OAuth2 + oauth2: {} + + # ProxyURL eg http://proxyserver:2195. Directs scrapes through proxy to this endpoint. + proxyUrl: "" + # Interval at which endpoints should be scraped. If not specified Prometheus’ global scrape interval is used. + interval: "" + # Timeout after which the scrape is ended. If not specified, the Prometheus global scrape interval is used. + scrapeTimeout: "" + # HonorTimestamps controls whether Prometheus respects the timestamps present in scraped data. + honorTimestamps: true + # HonorLabels chooses the metric’s labels on collisions with target labels. + honorLabels: true + # Whether to enable HTTP2. Default false. + enableHttp2: "" + # Drop pods that are not running. (Failed, Succeeded). + # Enabled by default. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#pod-phase + filterRunning: "" + # FollowRedirects configures whether scrape requests follow HTTP 3xx redirects. Default false. + followRedirects: "" + # Optional HTTP URL parameters + params: {} + + # RelabelConfigs to apply to samples before scraping. Prometheus Operator automatically adds + # relabelings for a few standard Kubernetes fields. The original scrape job’s name + # is available via the __tmp_prometheus_job_name label. + # More info: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#relabel_config + relabelings: [] + # MetricRelabelConfigs to apply to samples before ingestion. + metricRelabelings: [] + + # SampleLimit defines per-scrape limit on number of scraped samples that will be accepted. + sampleLimit: 0 + # TargetLimit defines a limit on the number of scraped targets that will be accepted. + targetLimit: 0 + # Per-scrape limit on number of labels that will be accepted for a sample. + # Only valid in Prometheus versions 2.27.0 and newer. + labelLimit: 0 + # Per-scrape limit on length of labels name that will be accepted for a sample. + # Only valid in Prometheus versions 2.27.0 and newer. + labelNameLengthLimit: 0 + # Per-scrape limit on length of labels value that will be accepted for a sample. + # Only valid in Prometheus versions 2.27.0 and newer. + labelValueLengthLimit: 0 + +## Customize the updateStrategy if set +updateStrategy: + type: RollingUpdate + rollingUpdate: + maxUnavailable: 1 + +resources: {} + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 200m + # memory: 50Mi + # requests: + # cpu: 100m + # memory: 30Mi + +serviceAccount: + # Specifies whether a ServiceAccount should be created + create: true + # The name of the ServiceAccount to use. + # If not set and create is true, a name is generated using the fullname template + name: + annotations: {} + imagePullSecrets: [] + automountServiceAccountToken: false + +securityContext: + fsGroup: 65534 + runAsGroup: 65534 + runAsNonRoot: true + runAsUser: 65534 + +containerSecurityContext: + readOnlyRootFilesystem: true + # capabilities: + # add: + # - SYS_TIME + +rbac: + ## If true, create & use RBAC resources + ## + create: true + ## If true, create & use Pod Security Policy resources + ## https://kubernetes.io/docs/concepts/policy/pod-security-policy/ + pspEnabled: true + pspAnnotations: {} + +# for deployments that have node_exporter deployed outside of the cluster, list +# their addresses here +endpoints: [] + +# Expose the service to the host network +hostNetwork: true + +# Share the host process ID namespace +hostPID: true + +# Mount the node's root file system (/) at /host/root in the container +hostRootFsMount: + enabled: true + # Defines how new mounts in existing mounts on the node or in the container + # are propagated to the container or node, respectively. Possible values are + # None, HostToContainer, and Bidirectional. If this field is omitted, then + # None is used. More information on: + # https://kubernetes.io/docs/concepts/storage/volumes/#mount-propagation + mountPropagation: HostToContainer + +## Assign a group of affinity scheduling rules +## +affinity: {} +# nodeAffinity: +# requiredDuringSchedulingIgnoredDuringExecution: +# nodeSelectorTerms: +# - matchFields: +# - key: metadata.name +# operator: In +# values: +# - target-host-name + +# Annotations to be added to node exporter pods +podAnnotations: + # Fix for very slow GKE cluster upgrades + cluster-autoscaler.kubernetes.io/safe-to-evict: "true" + +# Extra labels to be added to node exporter pods +podLabels: {} + +# Annotations to be added to node exporter daemonset +daemonsetAnnotations: {} + +## set to true to add the release label so scraping of the servicemonitor with kube-prometheus-stack works out of the box +releaseLabel: false + +# Custom DNS configuration to be added to prometheus-node-exporter pods +dnsConfig: {} +# nameservers: +# - 1.2.3.4 +# searches: +# - ns1.svc.cluster-domain.example +# - my.dns.search.suffix +# options: +# - name: ndots +# value: "2" +# - name: edns0 + +## Assign a nodeSelector if operating a hybrid cluster +## +nodeSelector: + kubernetes.io/os: linux + # kubernetes.io/arch: amd64 + +tolerations: + - effect: NoSchedule + operator: Exists + +## Assign a PriorityClassName to pods if set +# priorityClassName: "" + +## Additional container arguments +## +extraArgs: [] +# - --collector.diskstats.ignored-devices=^(ram|loop|fd|(h|s|v)d[a-z]|nvme\\d+n\\d+p)\\d+$ +# - --collector.textfile.directory=/run/prometheus + +## Additional mounts from the host to node-exporter container +## +extraHostVolumeMounts: [] +# - name: +# hostPath: +# mountPath: +# readOnly: true|false +# mountPropagation: None|HostToContainer|Bidirectional + +## Additional configmaps to be mounted. +## +configmaps: [] +# - name: +# mountPath: +secrets: [] +# - name: +# mountPath: +## Override the deployment namespace +## +namespaceOverride: "" + +## Additional containers for export metrics to text file +## +sidecars: [] +## - name: nvidia-dcgm-exporter +## image: nvidia/dcgm-exporter:1.4.3 + +## Volume for sidecar containers +## +sidecarVolumeMount: [] +## - name: collector-textfiles +## mountPath: /run/prometheus +## readOnly: false + +## Additional mounts from the host to sidecar containers +## +sidecarHostVolumeMounts: [] +# - name: +# hostPath: +# mountPath: +# readOnly: true|false +# mountPropagation: None|HostToContainer|Bidirectional + +## Additional InitContainers to initialize the pod +## +extraInitContainers: [] + +## Liveness probe +## +livenessProbe: + failureThreshold: 3 + httpGet: + httpHeaders: [] + scheme: http + initialDelaySeconds: 0 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 + +## Readiness probe +## +readinessProbe: + failureThreshold: 3 + httpGet: + httpHeaders: [] + scheme: http + initialDelaySeconds: 0 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 + +# Enable vertical pod autoscaler support for prometheus-node-exporter +verticalPodAutoscaler: + enabled: false + + # Recommender responsible for generating recommendation for the object. + # List should be empty (then the default recommender will generate the recommendation) + # or contain exactly one recommender. + # recommenders: + # - name: custom-recommender-performance + + # List of resources that the vertical pod autoscaler can control. Defaults to cpu and memory + controlledResources: [] + # Specifies which resource values should be controlled: RequestsOnly or RequestsAndLimits. + # controlledValues: RequestsAndLimits + + # Define the max allowed resources for the pod + maxAllowed: {} + # cpu: 200m + # memory: 100Mi + # Define the min allowed resources for the pod + minAllowed: {} + # cpu: 200m + # memory: 100Mi + + # updatePolicy: + # Specifies minimal number of replicas which need to be alive for VPA Updater to attempt pod eviction + # minReplicas: 1 + # Specifies whether recommended updates are applied when a Pod is started and whether recommended updates + # are applied during the life of a Pod. Possible values are "Off", "Initial", "Recreate", and "Auto". + # updateMode: Auto + +# Extra manifests to deploy as an array +extraManifests: [] + # - | + # apiVersion: v1 + # kind: ConfigMap + # metadata: + # name: prometheus-extra + # data: + # extra-data: "value" diff --git a/packages/system/monitoring/templates/additional-scrape-configs.yaml b/packages/system/monitoring/templates/additional-scrape-configs.yaml new file mode 100644 index 00000000..8936d661 --- /dev/null +++ b/packages/system/monitoring/templates/additional-scrape-configs.yaml @@ -0,0 +1,7 @@ +apiVersion: v1 +kind: Secret +metadata: + name: additional-scrape-configs +stringData: + prometheus-additional.yaml: | + {{- toYaml .Values.additionalScrapeConfigs | nindent 4 }} diff --git a/packages/system/monitoring/templates/apiserver-scrape.yaml b/packages/system/monitoring/templates/apiserver-scrape.yaml new file mode 100644 index 00000000..0661c993 --- /dev/null +++ b/packages/system/monitoring/templates/apiserver-scrape.yaml @@ -0,0 +1,31 @@ +--- +apiVersion: operator.victoriametrics.com/v1beta1 +kind: VMServiceScrape +metadata: + name: apiserver + namespace: cozy-monitoring +spec: + endpoints: + - bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token + port: https + scheme: https + relabelConfigs: + - action: labeldrop + regex: (endpoint|namespace|pod|container) + - replacement: kube-apiserver + targetLabel: job + - sourceLabels: [__meta_kubernetes_pod_node_name] + targetLabel: node + - targetLabel: tier + replacement: cluster + tlsConfig: + caFile: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt + serverName: kubernetes + jobLabel: component + namespaceSelector: + matchNames: + - default + selector: + matchLabels: + component: apiserver + provider: kubernetes diff --git a/packages/system/monitoring/templates/cadvisor-scrape.yaml b/packages/system/monitoring/templates/cadvisor-scrape.yaml new file mode 100644 index 00000000..4961b7b0 --- /dev/null +++ b/packages/system/monitoring/templates/cadvisor-scrape.yaml @@ -0,0 +1,32 @@ +--- +apiVersion: operator.victoriametrics.com/v1beta1 +kind: VMNodeScrape +metadata: + name: victoria-metrics-operator-cadvisor + namespace: cozy-monitoring +spec: + bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token + honorLabels: true + interval: 30s + metricRelabelConfigs: + - action: labeldrop + regex: (uid) + - action: labeldrop + regex: (id|name) + - action: drop + regex: (rest_client_request_duration_seconds_bucket|rest_client_request_duration_seconds_sum|rest_client_request_duration_seconds_count) + source_labels: + - __name__ + path: /metrics/cadvisor + relabelConfigs: + - action: labelmap + regex: __meta_kubernetes_node_label_(.+) + - sourceLabels: [__metrics_path__] + targetLabel: metrics_path + - replacement: cadvisor + targetLabel: job + scheme: https + scrapeTimeout: 5s + tlsConfig: + caFile: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt + insecureSkipVerify: true diff --git a/packages/system/monitoring/templates/coredns-scrape.yaml b/packages/system/monitoring/templates/coredns-scrape.yaml new file mode 100644 index 00000000..9c7253eb --- /dev/null +++ b/packages/system/monitoring/templates/coredns-scrape.yaml @@ -0,0 +1,42 @@ +--- +apiVersion: v1 +kind: Service +metadata: + name: coredns + namespace: kube-system + labels: + app: coredns +spec: + clusterIP: None + ports: + - name: http-metrics + port: 9153 + protocol: TCP + targetPort: 9153 + selector: + k8s-app: kube-dns +--- +apiVersion: operator.victoriametrics.com/v1beta1 +kind: VMServiceScrape +metadata: + name: coredns + namespace: cozy-monitoring +spec: + selector: + matchLabels: + app: coredns + namespaceSelector: + matchNames: + - "kube-system" + endpoints: + - bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token + port: http-metrics + relabelConfigs: + - action: labeldrop + regex: (endpoint|namespace|pod|container) + - replacement: kube-dns + targetLabel: job + - sourceLabels: [__meta_kubernetes_pod_node_name] + targetLabel: node + - targetLabel: tier + replacement: cluster diff --git a/packages/system/monitoring/templates/etcd-scrape.yaml b/packages/system/monitoring/templates/etcd-scrape.yaml new file mode 100644 index 00000000..eb5d5446 --- /dev/null +++ b/packages/system/monitoring/templates/etcd-scrape.yaml @@ -0,0 +1,34 @@ +#--- +#apiVersion: operator.victoriametrics.com/v1beta1 +#kind: VMNodeScrape +#metadata: +# name: kube-etcd +# namespace: cozy-monitoring +#spec: +# selector: +# node-role.kubernetes.io/control-plane: "" +# bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token +# honorLabels: true +# metricRelabelConfigs: +# - action: labeldrop +# regex: (uid) +# - action: labeldrop +# regex: (id|name) +# - action: drop +# regex: (rest_client_request_duration_seconds_bucket|rest_client_request_duration_seconds_sum|rest_client_request_duration_seconds_count) +# source_labels: +# - __name__ +# port: "2379" +# relabelConfigs: +# - action: labelmap +# regex: __meta_kubernetes_node_label_(.+) +# - sourceLabels: +# - __metrics_path__ +# targetLabel: metrics_path +# - replacement: etcd +# targetLabel: job +# scheme: https +# scrapeTimeout: 5s +# tlsConfig: +# caFile: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt +# insecureSkipVerify: true diff --git a/packages/system/monitoring/templates/kube-controller-manager-scrape.yaml b/packages/system/monitoring/templates/kube-controller-manager-scrape.yaml new file mode 100644 index 00000000..9c77cf75 --- /dev/null +++ b/packages/system/monitoring/templates/kube-controller-manager-scrape.yaml @@ -0,0 +1,49 @@ +--- +apiVersion: v1 +kind: Service +metadata: + name: kube-controller-manager + namespace: kube-system + labels: + app: kube-controller-manager +spec: + clusterIP: None + ports: + - name: http-metrics + port: 10257 + protocol: TCP + targetPort: 10257 + selector: + k8s-app: kube-controller-manager + type: ClusterIP +--- +apiVersion: operator.victoriametrics.com/v1beta1 +kind: VMServiceScrape +metadata: + name: kube-controller-manager + namespace: cozy-monitoring +spec: + selector: + matchLabels: + app: kube-controller-manager + namespaceSelector: + matchNames: + - "kube-system" + endpoints: + - bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token + port: http-metrics + scheme: https + relabelConfigs: + - action: labeldrop + regex: (endpoint|namespace|pod|container) + - replacement: kube-controller-manager + targetLabel: job + - sourceLabels: [__meta_kubernetes_pod_node_name] + targetLabel: node + - targetLabel: tier + replacement: cluster + tlsConfig: + caFile: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt + serverName: kubernetes + insecureSkipVerify: true + jobLabel: jobLabel diff --git a/packages/system/monitoring/templates/kube-scheduler-scrape.yaml b/packages/system/monitoring/templates/kube-scheduler-scrape.yaml new file mode 100644 index 00000000..af978942 --- /dev/null +++ b/packages/system/monitoring/templates/kube-scheduler-scrape.yaml @@ -0,0 +1,48 @@ +--- +apiVersion: v1 +kind: Service +metadata: + name: kube-scheduler + namespace: kube-system + labels: + app: kube-scheduler +spec: + clusterIP: None + ports: + - name: http-metrics + port: 10259 + protocol: TCP + targetPort: 10259 + selector: + k8s-app: kube-scheduler + type: ClusterIP +--- +apiVersion: operator.victoriametrics.com/v1beta1 +kind: VMServiceScrape +metadata: + name: kube-scheduler + namespace: cozy-monitoring +spec: + selector: + matchLabels: + app: kube-scheduler + namespaceSelector: + matchNames: + - "kube-system" + endpoints: + - bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token + port: http-metrics + scheme: https + relabelConfigs: + - action: labeldrop + regex: (endpoint|namespace|pod|container) + - replacement: kube-scheduler + targetLabel: job + - sourceLabels: [__meta_kubernetes_pod_node_name] + targetLabel: node + - targetLabel: tier + replacement: cluster + tlsConfig: + caFile: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt + insecureSkipVerify: true + jobLabel: jobLabel diff --git a/packages/system/monitoring/templates/kube-state-metrics-scrape.yaml b/packages/system/monitoring/templates/kube-state-metrics-scrape.yaml new file mode 100644 index 00000000..623492b5 --- /dev/null +++ b/packages/system/monitoring/templates/kube-state-metrics-scrape.yaml @@ -0,0 +1,28 @@ +--- +apiVersion: operator.victoriametrics.com/v1beta1 +kind: VMServiceScrape +metadata: + name: kube-state-metrics + namespace: cozy-monitoring +spec: + selector: + matchLabels: + app.kubernetes.io/name: kube-state-metrics + app.kubernetes.io/instance: "monitoring" + endpoints: + - port: http + honorLabels: true + metricRelabelConfigs: + - action: labeldrop + regex: (uid|container_id|image_id) + relabelConfigs: + #- action: labeldrop + # regex: (endpoint|namespace|pod|container) + - replacement: kube-state-metrics + targetLabel: job + - sourceLabels: + - __meta_kubernetes_pod_node_name + targetLabel: node + - targetLabel: tier + replacement: cluster + jobLabel: app.kubernetes.io/name diff --git a/packages/system/monitoring/templates/kubelet-scrape.yaml b/packages/system/monitoring/templates/kubelet-scrape.yaml new file mode 100644 index 00000000..33c5c6ed --- /dev/null +++ b/packages/system/monitoring/templates/kubelet-scrape.yaml @@ -0,0 +1,63 @@ +--- +apiVersion: operator.victoriametrics.com/v1beta1 +kind: VMNodeScrape +metadata: + name: victoria-metrics-operator-probes + namespace: cozy-monitoring +spec: + bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token + honorLabels: true + interval: 30s + metricRelabelConfigs: + - action: labeldrop + regex: (uid) + - action: labeldrop + regex: (id|name) + - action: drop + regex: (rest_client_request_duration_seconds_bucket|rest_client_request_duration_seconds_sum|rest_client_request_duration_seconds_count) + source_labels: + - __name__ + path: /metrics/probes + relabelConfigs: + - action: labelmap + regex: __meta_kubernetes_node_label_(.+) + - sourceLabels: [__metrics_path__] + targetLabel: metrics_path + - replacement: kubelet + targetLabel: job + scheme: https + scrapeTimeout: 5s + tlsConfig: + caFile: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt + insecureSkipVerify: true +--- +apiVersion: operator.victoriametrics.com/v1beta1 +kind: VMNodeScrape +metadata: + name: victoria-metrics-operator-kubelet + namespace: cozy-monitoring +spec: + bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token + honorLabels: true + interval: 30s + metricRelabelConfigs: + - action: labeldrop + regex: (uid) + - action: labeldrop + regex: (id|name) + - action: drop + regex: (rest_client_request_duration_seconds_bucket|rest_client_request_duration_seconds_sum|rest_client_request_duration_seconds_count) + source_labels: [__name__] + relabelConfigs: + - action: labelmap + regex: __meta_kubernetes_node_label_(.+) + - sourceLabels: + - __metrics_path__ + targetLabel: metrics_path + - replacement: kubelet + targetLabel: job + scheme: https + scrapeTimeout: 5s + tlsConfig: + caFile: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt + insecureSkipVerify: true diff --git a/packages/system/monitoring/templates/nginx-scrape.yaml b/packages/system/monitoring/templates/nginx-scrape.yaml new file mode 100644 index 00000000..d9de45a0 --- /dev/null +++ b/packages/system/monitoring/templates/nginx-scrape.yaml @@ -0,0 +1,54 @@ +--- +apiVersion: operator.victoriametrics.com/v1beta1 +kind: VMPodScrape +metadata: + name: nginx-ingress-controller + namespace: cozy-monitoring +spec: + jobLabel: jobLabel + namespaceSelector: + matchNames: + - cozy-ingress-nginx + podMetricsEndpoints: + - port: metrics + honorLabels: true + interval: 30s + relabelConfigs: + - replacement: nginx-ingress-controller + targetLabel: job + - sourceLabels: [__meta_kubernetes_pod_node_name] + targetLabel: node + - targetLabel: tier + replacement: cluster + selector: + matchLabels: + app.kubernetes.io/component: controller + app.kubernetes.io/name: ingress-nginx +--- +apiVersion: operator.victoriametrics.com/v1beta1 +kind: VMPodScrape +metadata: + name: nginx-ingress-controller-detailed + namespace: cozy-monitoring +spec: + jobLabel: jobLabel + namespaceSelector: + matchNames: + - cozy-ingress-nginx + podMetricsEndpoints: + - port: metrics2 + honorLabels: true + interval: 30s + relabelConfigs: + - replacement: nginx-ingress-controller + targetLabel: job + - sourceLabels: [__meta_kubernetes_pod_node_name] + targetLabel: node + - sourceLabels: [__meta_kubernetes_pod_label_app_kubernetes_io_name] + targetLabel: controller + - targetLabel: tier + replacement: cluster + selector: + matchLabels: + app.kubernetes.io/component: controller + app.kubernetes.io/name: ingress-nginx diff --git a/packages/system/monitoring/templates/node-exporter-scrape.yaml b/packages/system/monitoring/templates/node-exporter-scrape.yaml new file mode 100644 index 00000000..be0850da --- /dev/null +++ b/packages/system/monitoring/templates/node-exporter-scrape.yaml @@ -0,0 +1,24 @@ +--- +apiVersion: operator.victoriametrics.com/v1beta1 +kind: VMServiceScrape +metadata: + name: node-exporter + namespace: cozy-monitoring +spec: + selector: + matchLabels: + app.kubernetes.io/name: prometheus-node-exporter + endpoints: + - metricRelabelConfigs: + - action: drop + regex: /var/lib/kubelet/pods.+ + source_labels: [mountpoint] + relabelConfigs: + - regex: endpoint|namespace|pod|service + action: labeldrop + - sourceLabels: [__meta_kubernetes_pod_node_name] + targetLabel: node + - replacement: node-exporter + targetLabel: job + port: metrics + jobLabel: jobLabel diff --git a/packages/system/monitoring/templates/vmagent-scrape.yaml b/packages/system/monitoring/templates/vmagent-scrape.yaml new file mode 100644 index 00000000..310efeb0 --- /dev/null +++ b/packages/system/monitoring/templates/vmagent-scrape.yaml @@ -0,0 +1,18 @@ +--- +apiVersion: operator.victoriametrics.com/v1beta1 +kind: VMServiceScrape +metadata: + name: vmagent-vmagent + namespace: cozy-monitoring +spec: + endpoints: + - path: /metrics + port: http + relabelConfigs: + - sourceLabels: [__meta_kubernetes_pod_node_name] + targetLabel: node + selector: + matchLabels: + app.kubernetes.io/component: monitoring + app.kubernetes.io/instance: vmagent + app.kubernetes.io/name: vmagent diff --git a/packages/system/monitoring/templates/vmagent.yaml b/packages/system/monitoring/templates/vmagent.yaml new file mode 100644 index 00000000..1c686b28 --- /dev/null +++ b/packages/system/monitoring/templates/vmagent.yaml @@ -0,0 +1,25 @@ +apiVersion: operator.victoriametrics.com/v1beta1 +kind: VMAgent +metadata: + name: vmagent + namespace: cozy-monitoring +spec: + externalLabels: + cluster: cozystack + extraArgs: + promscrape.streamParse: "true" + remoteWrite: + - url: http://vminsert-shortterm.tenant-root.svc:8480/insert/0/prometheus/api/v1/write + - url: http://vminsert-longterm.tenant-root.svc:8480/insert/0/prometheus/api/v1/write + scrapeInterval: 30s + selectAllByDefault: true + additionalScrapeConfigs: + name: additional-scrape-configs + key: prometheus-additional.yaml + #statefulMode: true + #statefulStorage: + # volumeClaimTemplate: + # spec: + # resources: + # requests: + # storage: 20Gi diff --git a/packages/system/monitoring/templates/vmoperator-scrape.yaml b/packages/system/monitoring/templates/vmoperator-scrape.yaml new file mode 100644 index 00000000..b6846001 --- /dev/null +++ b/packages/system/monitoring/templates/vmoperator-scrape.yaml @@ -0,0 +1,17 @@ +--- +apiVersion: operator.victoriametrics.com/v1beta1 +kind: VMServiceScrape +metadata: + name: victoria-metrics-operator + namespace: cozy-victoria-metrics-operator +spec: + endpoints: + - path: /metrics + port: http + relabelConfigs: + - sourceLabels: [__meta_kubernetes_pod_node_name] + targetLabel: node + selector: + matchLabels: + app.kubernetes.io/name: victoria-metrics-operator + app.kubernetes.io/instance: victoria-metrics-operator diff --git a/packages/system/monitoring/templates/vmrules.yaml b/packages/system/monitoring/templates/vmrules.yaml new file mode 100644 index 00000000..8c5ec7b7 --- /dev/null +++ b/packages/system/monitoring/templates/vmrules.yaml @@ -0,0 +1,271 @@ +apiVersion: operator.victoriametrics.com/v1beta1 +kind: VMRule +metadata: + name: container-memory-kmem + namespace: cozy-monitoring +spec: + groups: + - name: container_memory_kmem + rules: + - record: container_memory:kmem + expr: | + container_memory_usage_bytes + - + ( + container_memory_swap + + + container_memory_rss + + + container_memory_cache + ) + - record: container_memory_working_set_bytes:without_kmem + expr: | + container_memory_working_set_bytes - container_memory:kmem +--- +apiVersion: operator.victoriametrics.com/v1beta1 +kind: VMRule +metadata: + name: kube-persistentvolume-is-local + namespace: cozy-monitoring +spec: + groups: + - name: kube_persistentvolume_is_local + rules: + # kube_persistentvolume_is_local migration. + # The patch was not generic enough, but it is used in many alerts/panels. + # This recording rule is aimed to avoid rewriting them. + # + # kube_persistentvolume_is_local {instance="", job="", persistentvolume="", scrape_endpoint="", storageclass=""} 0 + - expr: max by (instance, job, persistentvolume, scrape_endpoint, storageclass) (kube_persistentvolume_info{local_path!~".+"} - 1) + record: kube_persistentvolume_is_local + - expr: max by (instance, job, persistentvolume, scrape_endpoint, storageclass) (kube_persistentvolume_info{host_path!~".+"} - 1) + record: kube_persistentvolume_is_local + # kube_persistentvolume_is_local {instance="", job="", persistentvolume="", scrape_endpoint="", storageclass=""} 1 + - expr: max by (instance, job, persistentvolume, scrape_endpoint, storageclass) (kube_persistentvolume_info{local_path=~".+"}) + record: kube_persistentvolume_is_local + - expr: max by (instance, job, persistentvolume, scrape_endpoint, storageclass) (kube_persistentvolume_info{host_path=~".+"}) + record: kube_persistentvolume_is_local +--- +apiVersion: operator.victoriametrics.com/v1beta1 +kind: VMRule +metadata: + name: kube-controller-pod + namespace: cozy-monitoring +spec: + groups: + - name: kube_controller_pod + rules: + - record: kube_controller_pod + expr: |- + max by(job, node, namespace, controller, controller_name, controller_type, pod) + ( + label_replace ( + # lowercase ReplicaSet + label_replace ( + # lowercase Deployment + label_replace ( + # rename owner_kind to controller_type + label_replace ( + # rename owner_name to controller_name + label_replace ( + # rename owner_kind_name to controller + max by(job, namespace, replicaset, owner_kind_name, owner_kind, owner_name) ( + label_replace ( + # rename temp label to owner_kind_name + label_join ( + # generate owner_kind_name + label_join ( + # generate temp label for owner_kind_name + label_replace( + # rename ReplicaSet + kube_replicaset_owner{owner_kind=~"Deployment|"}, + "replica", "ReplicaSet", "owner_kind", ""), + "temp", "/", "replica", "replicaset"), + "owner_kind_name", "/", "owner_kind", "owner_name"), + "owner_kind_name", "$1", "temp", "(.+/.*)") + ) + * on(job, namespace, replicaset) group_right(owner_kind, owner_name, owner_kind_name) + label_replace( + # add label replicaset for multiplication + max by(job, namespace, owner_name, pod) ( + kube_pod_owner{owner_kind="ReplicaSet"}) + * on (namespace, pod) group_left(node) sum by (node, namespace, pod) (kube_pod_info), + "replicaset", "$1", "owner_name", "(.*)"), + "controller", "$1", "owner_kind_name", "(.*)"), + "controller_name", "$1", "owner_name", "(.*)"), + "controller_type", "$1", "owner_kind", "(.*)"), + "controller", "deploy/$1", "controller", "Deployment/(.*)"), + "controller", "rs/$1", "controller", "ReplicaSet/(.*)") + ) + - record: kube_controller_pod + expr: |- + sum by(job, node, namespace, controller, controller_type, controller_name, pod) + ( + # certificate controller + label_replace ( + # job controller + label_replace ( + # sts controller + label_replace ( + # ds controller + label_replace ( + # none controller + label_replace ( + # controller_type for static pods + label_replace ( + # controller + label_join ( + # controller_name + label_replace ( + # controller_type + label_replace ( + kube_pod_owner{owner_kind!="ReplicaSet"} + * on (namespace, pod) group_left(node) sum by (node, namespace, pod) (kube_pod_info), + "controller_type", "$1", "owner_kind", "(.*)"), + "controller_name", "$1", "owner_name", "(.*)"), + "controller", "/", "controller_type", "controller_name"), + "controller_type", "No controller", "controller_type", ""), + "controller", "No Controller", "controller", "/"), + "controller", "ds/$1", "controller", "DaemonSet/(.*)"), + "controller", "sts/$1", "controller", "StatefulSet/(.*)"), + "controller", "job/$1", "controller", "Job/(.*)"), + "controller", "certificate/$1", "controller", "Certificate/(.*)") + ) + - record: kube_controller_replicas + expr: |- + # get daemonset replicas + max by(job, namespace, controller_type, controller_name) + ( + label_replace ( + # set controller_name + label_replace ( + # set controller_type + kube_daemonset_status_desired_number_scheduled, + "controller_type", "DaemonSet", "", ""), + "controller_name", "$1", "daemonset", "(.*)") + ) + or ( + # get deployment available replicas + max by(job, namespace, controller_type, controller_name) + ( + label_replace ( + # set controller_name + label_replace ( + # set controller_type + kube_deployment_spec_replicas, + "controller_type", "Deployment", "", ""), + "controller_name", "$1", "deployment", "(.*)")) + ) + # get statefulset ready replicas + or ( + max by(job, namespace, controller_type, controller_name) + ( + label_replace ( + # set controller_name + label_replace ( + # set controller_type + kube_statefulset_replicas, + "controller_type", "StatefulSet", "", ""), + "controller_name", "$1", "statefulset", "(.*)")) + ) + # get replicaset ready replicas + or ( + max by(job, namespace, controller_type, controller_name) + ( + label_replace ( + # set controller_name + label_replace ( + # set controller_type + kube_replicaset_spec_replicas, + "controller_type", "ReplicaSet", "", ""), + "controller_name", "$1", "replicaset", "(.*)")) + ) + - record: kube_controller_replicas_ready + expr: |- + # get daemonset ready replicas + max by(job, namespace, controller_type, controller_name) + ( + label_replace ( + # set controller_name + label_replace ( + # set controller_type + kube_daemonset_status_number_ready, + "controller_type", "DaemonSet", "", ""), + "controller_name", "$1", "daemonset", "(.*)") + ) + or ( + # get deployment available replicas + max by(job, namespace, controller_type, controller_name) + ( + label_replace ( + # set controller_name + label_replace ( + # set controller_type + kube_deployment_status_replicas_available, + "controller_type", "Deployment", "", ""), + "controller_name", "$1", "deployment", "(.*)")) + ) + # get statefulset ready replicas + or ( + max by(job, namespace, controller_type, controller_name) + ( + label_replace ( + # set controller_name + label_replace ( + # set controller_type + kube_statefulset_status_replicas_ready, + "controller_type", "StatefulSet", "", ""), + "controller_name", "$1", "statefulset", "(.*)")) + ) + # get replicaset ready replicas + or ( + max by(job, namespace, controller_type, controller_name) + ( + label_replace ( + # set controller_name + label_replace ( + # set controller_type + kube_replicaset_status_ready_replicas, + "controller_type", "ReplicaSet", "", ""), + "controller_name", "$1", "replicaset", "(.*)")) + ) +--- +apiVersion: operator.victoriametrics.com/v1beta1 +kind: VMRule +metadata: + name: ingress-nginx-detailed + namespace: cozy-monitoring +spec: + groups: + - name: ingress_nginx + rules: + - record: ingress_nginx_overall_info + expr: count({__name__=~"ingress_nginx_overall_.*", __name__!="ingress_nginx_overall_info"}) by (job, controller, app, node, endpoint, content_kind, namespace, vhost) * 0 + 1 + - record: ingress_nginx_detail_info + expr: count({__name__=~"ingress_nginx_detail_.*", __name__!="ingress_nginx_detail_info", __name__!~"ingress_nginx_detail_backend_.*"}) by (job, controller, app, node, endpoint, content_kind, namespace, ingress, service, service_port, vhost, location) * 0 + 1 + - record: ingress_nginx_detail_backend_info + expr: count({__name__=~"ingress_nginx_detail_backend_.*", __name__!="ingress_nginx_detail_backend_info"}) by (job, controller, app, node, endpoint, namespace, ingress, service, service_port, vhost, location, pod_ip) * 0 + 1 +--- +apiVersion: operator.victoriametrics.com/v1beta1 +kind: VMRule +metadata: + name: wss + namespace: cozy-monitoring +spec: + groups: + - name: kubernetes.wss_bytes + rules: + - record: container_memory:kmem + expr: | + container_memory_usage_bytes + - + ( + container_memory_swap + + + container_memory_rss + + + container_memory_cache + ) + - record: container_memory_working_set_bytes:without_kmem + expr: | + container_memory_working_set_bytes - container_memory:kmem diff --git a/packages/system/monitoring/values.yaml b/packages/system/monitoring/values.yaml new file mode 100644 index 00000000..249ef7b3 --- /dev/null +++ b/packages/system/monitoring/values.yaml @@ -0,0 +1,13 @@ +metrics-server: + defaultArgs: + - --cert-dir=/tmp + - --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname + - --kubelet-use-node-status-port + - --metric-resolution=15s + - --kubelet-insecure-tls + + metrics: + enabled: true + + serviceMonitor: + enabled: true diff --git a/packages/system/piraeus-operator/.helmignore b/packages/system/piraeus-operator/.helmignore new file mode 100644 index 00000000..1e107f52 --- /dev/null +++ b/packages/system/piraeus-operator/.helmignore @@ -0,0 +1 @@ +examples diff --git a/packages/system/piraeus-operator/Chart.yaml b/packages/system/piraeus-operator/Chart.yaml new file mode 100644 index 00000000..1243393e --- /dev/null +++ b/packages/system/piraeus-operator/Chart.yaml @@ -0,0 +1,2 @@ +name: cozy-piraeus-operator +version: 1.0.0 diff --git a/packages/system/piraeus-operator/Makefile b/packages/system/piraeus-operator/Makefile new file mode 100644 index 00000000..1f23a118 --- /dev/null +++ b/packages/system/piraeus-operator/Makefile @@ -0,0 +1,17 @@ +NAME=piraeus-operator +NAMESPACE=cozy-linstor + +show: + helm template --dry-run=server -n $(NAMESPACE) $(NAME) . + +apply: + helm upgrade -i -n $(NAMESPACE) $(NAME) . + +diff: + helm diff upgrade --allow-unreleased --normalize-manifests -n $(NAMESPACE) $(NAME) . + +update: + rm -rf charts + tag=$$(git ls-remote --tags --sort="v:refname" https://github.com/piraeusdatastore/piraeus-operator | awk -F'[/^]' 'END{print $$3}') && \ + curl -sSL https://github.com/piraeusdatastore/piraeus-operator/archive/refs/tags/$${tag}.tar.gz | \ + tar xzvf - --strip 1 piraeus-operator-$${tag#*v}/charts diff --git a/packages/system/piraeus-operator/charts/piraeus/.helmignore b/packages/system/piraeus-operator/charts/piraeus/.helmignore new file mode 100644 index 00000000..0e8a0eb3 --- /dev/null +++ b/packages/system/piraeus-operator/charts/piraeus/.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/packages/system/piraeus-operator/charts/piraeus/Chart.yaml b/packages/system/piraeus-operator/charts/piraeus/Chart.yaml new file mode 100644 index 00000000..2afc4450 --- /dev/null +++ b/packages/system/piraeus-operator/charts/piraeus/Chart.yaml @@ -0,0 +1,18 @@ +apiVersion: v2 +name: piraeus +description: | + The Piraeus Operator manages software defined storage clusters using LINSTOR in Kubernetes. +type: application +version: 2.3.0 +appVersion: "v2.3.0" +maintainers: + - name: Piraeus Datastore + url: https://piraeus.io +home: https://piraeus.io +icon: https://raw.githubusercontent.com/piraeusdatastore/piraeus/master/artwork/sandbox-artwork/icon/color.svg +keywords: + - storage +sources: + - https://github.com/piraeusdatastore/piraeus-operator + - https://github.com/piraeusdatastore/linstor-csi + - https://github.com/LINBIT/linstor-server diff --git a/packages/system/piraeus-operator/charts/piraeus/README.md b/packages/system/piraeus-operator/charts/piraeus/README.md new file mode 100644 index 00000000..abda911d --- /dev/null +++ b/packages/system/piraeus-operator/charts/piraeus/README.md @@ -0,0 +1,35 @@ +# Piraeus Operator + +Deploys the [Piraeus Operator](https://github.com/piraeusdatastore/piraeus-operator) which deploys and manages a simple +and resilient storage solution for Kubernetes. + +The main deployment method for Piraeus Operator switched to [`kustomize`](../../docs/tutorial) +in release `v2.0.0`. This chart is intended for users who want to continue using Helm. + +This chart **only** configures the Operator, but does not create the `LinstorCluster` resource creating the actual +storage system. Refer to the existing [tutorials](../../docs/tutorial) +and [how-to guides](../../docs/how-to). + +## Deploying Piraeus Operator + +To deploy Piraeus Operator with Helm, clone this repository and deploy the chart: + +``` +$ git clone --branch v2 https://github.com/piraeusdatastore/piraeus-operator +$ cd piraeus-operator +$ helm install piraeus-operator charts/piraeus-operator --create-namespace -n piraeus-datastore +``` + +Follow the instructions printed by Helm to create your storage cluster: + +``` +$ kubectl apply -f - <']`, `metadata.annotations['']`. + minLength: 1 + type: string + type: object + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + storagePools: + description: StoragePools is a list of storage pools to configure + on the node. + items: + properties: + filePool: + description: Configures a file system based storage pool, allocating + a regular file per volume. + properties: + directory: + description: Directory is the path to the host directory + used to store volume data. + type: string + type: object + fileThinPool: + description: Configures a file system based storage pool, allocating + a sparse file per volume. + properties: + directory: + description: Directory is the path to the host directory + used to store volume data. + type: string + type: object + lvmPool: + description: Configures a LVM Volume Group as storage pool. + properties: + volumeGroup: + type: string + type: object + lvmThinPool: + description: Configures a LVM Thin Pool as storage pool. + properties: + thinPool: + description: ThinPool is the name of the thinpool LV (without + VG prefix). + type: string + volumeGroup: + type: string + type: object + name: + description: Name of the storage pool in linstor. + minLength: 3 + type: string + properties: + description: Properties to set on the storage pool. + items: + properties: + name: + description: Name of the property to set. + minLength: 1 + type: string + optional: + description: Optional values are only set if they have + a non-empty value + type: boolean + value: + description: Value to set the property to. + type: string + valueFrom: + description: ValueFrom sets the value from an existing + resource. + properties: + nodeFieldRef: + description: Select a field of the node. Supports + `metadata.name`, `metadata.labels['']`, `metadata.annotations['']`. + minLength: 1 + type: string + type: object + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + source: + properties: + hostDevices: + description: HostDevices is a list of device paths used + to configure the given pool. + items: + type: string + minItems: 1 + type: array + type: object + required: + - name + type: object + type: array + type: object + status: + description: LinstorSatelliteConfigurationStatus defines the observed + state of LinstorSatelliteConfiguration + properties: + conditions: + description: Current LINSTOR Satellite Config state + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + \n type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + 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 + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + 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.13.0 + name: linstorsatellites.piraeus.io +spec: + group: piraeus.io + names: + kind: LinstorSatellite + listKind: LinstorSatelliteList + plural: linstorsatellites + singular: linstorsatellite + scope: Cluster + versions: + - name: v1 + schema: + openAPIV3Schema: + description: LinstorSatellite is the Schema for the linstorsatellites 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: LinstorSatelliteSpec defines the desired state of LinstorSatellite + properties: + clusterRef: + description: ClusterRef references the LinstorCluster used to create + this LinstorSatellite. + properties: + clientSecretName: + description: ClientSecretName references the secret used by the + operator to validate the https endpoint. + type: string + externalController: + description: ExternalController references an external controller. + When set, the Operator uses the external cluster to register + satellites. + properties: + url: + description: URL of the external controller. + minLength: 3 + type: string + required: + - url + type: object + name: + description: Name of the LinstorCluster resource controlling this + satellite. + type: string + type: object + internalTLS: + description: "InternalTLS configures secure communication for the + LINSTOR Satellite. \n If set, the control traffic between LINSTOR + Controller and Satellite will be encrypted using mTLS. The Controller + will use the client key from `LinstorCluster.spec.internalTLS` when + connecting." + nullable: true + properties: + certManager: + description: CertManager references a cert-manager Issuer or ClusterIssuer. + If set, a Certificate resource will be created, provisioning + the secret references in SecretName using the issuer configured + here. + properties: + group: + description: Group of the resource being referred to. + type: string + kind: + description: Kind of the resource being referred to. + type: string + name: + description: Name of the resource being referred to. + type: string + required: + - name + type: object + secretName: + description: SecretName references a secret holding the TLS key + and certificates. + type: string + tlsHandshakeDaemon: + description: "TLSHandshakeDaemon enables tlshd for establishing + TLS sessions for use by DRBD. \n If enabled, adds a new sidecar + to the LINSTOR Satellite that runs the tlshd handshake daemon. + The daemon uses the TLS certificate and key to establish secure + connections on behalf of DRBD." + type: boolean + type: object + patches: + description: "Patches is a list of kustomize patches to apply. \n + See https://kubectl.docs.kubernetes.io/references/kustomize/kustomization/patches/ + for how to create patches." + items: + description: Patch represent either a Strategic Merge Patch or a + JSON patch and its targets. + properties: + options: + additionalProperties: + type: boolean + description: Options is a list of options for the patch + type: object + patch: + description: Patch is the content of a patch. + minLength: 1 + type: string + target: + description: Target points to the resources that the patch is + applied to + properties: + annotationSelector: + description: AnnotationSelector is a string that follows + the label selection expression https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#api + It matches against the resource annotations. + type: string + group: + type: string + kind: + type: string + labelSelector: + description: LabelSelector is a string that follows the + label selection expression https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#api + It matches against the resource labels. + type: string + name: + description: Name of the resource. + type: string + namespace: + description: Namespace the resource belongs to, if it can + belong to a namespace. + type: string + version: + type: string + type: object + type: object + type: array + properties: + description: Properties is a list of properties to set on the node. + items: + properties: + name: + description: Name of the property to set. + minLength: 1 + type: string + optional: + description: Optional values are only set if they have a non-empty + value + type: boolean + value: + description: Value to set the property to. + type: string + valueFrom: + description: ValueFrom sets the value from an existing resource. + properties: + nodeFieldRef: + description: Select a field of the node. Supports `metadata.name`, + `metadata.labels['']`, `metadata.annotations['']`. + minLength: 1 + type: string + type: object + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + repository: + description: Repository used to pull workload images. + type: string + storagePools: + description: StoragePools is a list of storage pools to configure + on the node. + items: + properties: + filePool: + description: Configures a file system based storage pool, allocating + a regular file per volume. + properties: + directory: + description: Directory is the path to the host directory + used to store volume data. + type: string + type: object + fileThinPool: + description: Configures a file system based storage pool, allocating + a sparse file per volume. + properties: + directory: + description: Directory is the path to the host directory + used to store volume data. + type: string + type: object + lvmPool: + description: Configures a LVM Volume Group as storage pool. + properties: + volumeGroup: + type: string + type: object + lvmThinPool: + description: Configures a LVM Thin Pool as storage pool. + properties: + thinPool: + description: ThinPool is the name of the thinpool LV (without + VG prefix). + type: string + volumeGroup: + type: string + type: object + name: + description: Name of the storage pool in linstor. + minLength: 3 + type: string + properties: + description: Properties to set on the storage pool. + items: + properties: + name: + description: Name of the property to set. + minLength: 1 + type: string + optional: + description: Optional values are only set if they have + a non-empty value + type: boolean + value: + description: Value to set the property to. + type: string + valueFrom: + description: ValueFrom sets the value from an existing + resource. + properties: + nodeFieldRef: + description: Select a field of the node. Supports + `metadata.name`, `metadata.labels['']`, `metadata.annotations['']`. + minLength: 1 + type: string + type: object + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + source: + properties: + hostDevices: + description: HostDevices is a list of device paths used + to configure the given pool. + items: + type: string + minItems: 1 + type: array + type: object + required: + - name + type: object + type: array + required: + - clusterRef + type: object + status: + description: LinstorSatelliteStatus defines the observed state of LinstorSatellite + properties: + conditions: + description: Current LINSTOR Satellite state + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + \n type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + 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 + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + type: object + type: object + served: true + storage: true + subresources: + status: {} +{{ end }} diff --git a/packages/system/piraeus-operator/charts/piraeus/templates/deployment.yaml b/packages/system/piraeus-operator/charts/piraeus/templates/deployment.yaml new file mode 100644 index 00000000..d10e931c --- /dev/null +++ b/packages/system/piraeus-operator/charts/piraeus/templates/deployment.yaml @@ -0,0 +1,101 @@ +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "piraeus-operator.fullname" . }}-controller-manager + labels: + {{- include "piraeus-operator.labels" . | nindent 4 }} +spec: + replicas: {{ .Values.replicaCount }} + selector: + matchLabels: + {{- include "piraeus-operator.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + {{- include "piraeus-operator.selectorLabels" . | nindent 8 }} + annotations: + kubectl.kubernetes.io/default-container: manager + spec: + containers: + - args: + - --health-probe-bind-address=:8081 + {{- if .Values.kubeRbacProxy.enabled }} + - --metrics-bind-address=127.0.0.1:8080 + {{- else }} + - --metrics-bind-address=0 + {{- end }} + {{- range $opt, $val := .Values.operator.options }} + - --{{ $opt | kebabcase }}={{ $val }} + {{- end }} + command: + - /manager + env: + - name: NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: IMAGE_CONFIG_MAP_NAME + value: {{ include "piraeus-operator.fullname" . }}-image-config + image: {{ .Values.operator.image.repository }}:{{ .Values.operator.image.tag | default .Chart.AppVersion }} + imagePullPolicy: {{ .Values.operator.image.pullPolicy }} + livenessProbe: + httpGet: + path: /healthz + port: 8081 + initialDelaySeconds: 15 + periodSeconds: 20 + name: manager + ports: + - containerPort: 9443 + name: webhook-server + protocol: TCP + readinessProbe: + httpGet: + path: /readyz + port: 8081 + initialDelaySeconds: 5 + periodSeconds: 10 + resources: + {{- toYaml .Values.operator.resources | nindent 12 }} + securityContext: + {{- toYaml .Values.operator.securityContext | nindent 12}} + volumeMounts: + - mountPath: /tmp/k8s-webhook-server/serving-certs + name: cert + readOnly: true + {{- if .Values.kubeRbacProxy.enabled }} + - args: + - --secure-listen-address=0.0.0.0:8443 + - --upstream=http://127.0.0.1:8080/ + - --tls-private-key-file=/etc/tls/tls.key + - --tls-cert-file=/etc/tls/tls.crt + {{- range $opt, $val := .Values.kubeRbacProxy.options }} + - --{{ $opt | kebabcase }}={{ $val }} + {{- end }} + image: {{ .Values.kubeRbacProxy.image.repository }}:{{ .Values.kubeRbacProxy.image.tag }} + imagePullPolicy: {{ .Values.kubeRbacProxy.image.pullPolicy }} + name: kube-rbac-proxy + ports: + - containerPort: 8443 + name: https + protocol: TCP + resources: + {{- toYaml .Values.kubeRbacProxy.resources | nindent 12 }} + securityContext: + {{- toYaml .Values.kubeRbacProxy.securityContext | nindent 12}} + volumeMounts: + - mountPath: /etc/tls + name: cert + {{- end }} + securityContext: + runAsNonRoot: true + serviceAccountName: {{ include "piraeus-operator.serviceAccountName" . }} + terminationGracePeriodSeconds: 10 + tolerations: + {{- toYaml .Values.tolerations | nindent 8 }} + volumes: + - name: cert + secret: + defaultMode: 420 + secretName: {{ include "piraeus-operator.certifcateName" . }} diff --git a/packages/system/piraeus-operator/charts/piraeus/templates/metrics-service.yaml b/packages/system/piraeus-operator/charts/piraeus/templates/metrics-service.yaml new file mode 100644 index 00000000..d1a24e3c --- /dev/null +++ b/packages/system/piraeus-operator/charts/piraeus/templates/metrics-service.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "piraeus-operator.fullname" . }}-controller-manager-metrics-service + labels: + {{- include "piraeus-operator.labels" . | nindent 4 }} +spec: + type: ClusterIP + selector: + {{- include "piraeus-operator.selectorLabels" . | nindent 4 }} + ports: + - name: metrics + port: 443 + targetPort: 8443 diff --git a/packages/system/piraeus-operator/charts/piraeus/templates/rbac.yaml b/packages/system/piraeus-operator/charts/piraeus/templates/rbac.yaml new file mode 100644 index 00000000..e487114c --- /dev/null +++ b/packages/system/piraeus-operator/charts/piraeus/templates/rbac.yaml @@ -0,0 +1,461 @@ +{{ if .Values.serviceAccount.create }} +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "piraeus-operator.serviceAccountName" . }} + labels: + {{- include "piraeus-operator.labels" . | nindent 4 }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ include "piraeus-operator.fullname" . }}-controller-manager + labels: + {{- include "piraeus-operator.labels" . | nindent 4 }} +rules: + - apiGroups: + - "" + resources: + - configmaps + - events + - persistentvolumes + - secrets + - serviceaccounts + - services + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: + - "" + resources: + - configmaps + - pods + - secrets + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: + - "" + resources: + - nodes + verbs: + - get + - list + - watch + - apiGroups: + - "" + resources: + - nodes + - persistentvolumeclaims + verbs: + - get + - list + - patch + - update + - watch + - apiGroups: + - "" + resources: + - persistentvolumeclaims/status + verbs: + - patch + - apiGroups: + - "" + resources: + - pods + verbs: + - delete + - list + - watch + - apiGroups: + - "" + resources: + - pods/eviction + verbs: + - create + - apiGroups: + - apiextensions.k8s.io + resources: + - customresourcedefinitions + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: + - apps + resources: + - daemonsets + - deployments + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: + - apps + resources: + - replicasets + verbs: + - get + - apiGroups: + - cert-manager.io + resources: + - certificates + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: + - events.k8s.io + resources: + - events + verbs: + - create + - get + - list + - patch + - update + - watch + - apiGroups: + - internal.linstor.linbit.com + resources: + - '*' + verbs: + - create + - delete + - deletecollection + - get + - list + - patch + - update + - watch + - apiGroups: + - piraeus.io + resources: + - linstorclusters + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: + - piraeus.io + resources: + - linstorclusters/finalizers + verbs: + - update + - apiGroups: + - piraeus.io + resources: + - linstorclusters/status + verbs: + - get + - patch + - update + - apiGroups: + - piraeus.io + resources: + - linstornodeconnections + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: + - piraeus.io + resources: + - linstornodeconnections/finalizers + verbs: + - update + - apiGroups: + - piraeus.io + resources: + - linstornodeconnections/status + verbs: + - get + - patch + - update + - apiGroups: + - piraeus.io + resources: + - linstorsatelliteconfigurations + verbs: + - get + - list + - watch + - apiGroups: + - piraeus.io + resources: + - linstorsatelliteconfigurations/status + verbs: + - get + - patch + - update + - apiGroups: + - piraeus.io + resources: + - linstorsatellites + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: + - piraeus.io + resources: + - linstorsatellites/finalizers + verbs: + - update + - apiGroups: + - piraeus.io + resources: + - linstorsatellites/status + verbs: + - get + - patch + - update + - apiGroups: + - rbac.authorization.k8s.io + resources: + - clusterrolebindings + - clusterroles + - rolebindings + - roles + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: + - security.openshift.io + resourceNames: + - privileged + resources: + - securitycontextconstraints + verbs: + - use + - apiGroups: + - snapshot.storage.k8s.io + resources: + - volumesnapshotclasses + - volumesnapshots + verbs: + - get + - list + - watch + - apiGroups: + - snapshot.storage.k8s.io + resources: + - volumesnapshotcontents + verbs: + - delete + - get + - list + - patch + - update + - watch + - apiGroups: + - snapshot.storage.k8s.io + resources: + - volumesnapshotcontents/status + verbs: + - patch + - update + - apiGroups: + - storage.k8s.io + resources: + - csidrivers + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: + - storage.k8s.io + resources: + - csinodes + verbs: + - get + - list + - patch + - watch + - apiGroups: + - storage.k8s.io + resources: + - csistoragecapacities + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: + - storage.k8s.io + resources: + - storageclasses + verbs: + - get + - list + - watch + - apiGroups: + - storage.k8s.io + resources: + - volumeattachments + verbs: + - delete + - get + - list + - patch + - watch + - apiGroups: + - storage.k8s.io + resources: + - volumeattachments/status + verbs: + - patch +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ include "piraeus-operator.fullname" . }}-manager-rolebinding + labels: + {{- include "piraeus-operator.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: '{{ include "piraeus-operator.fullname" . }}-controller-manager' +subjects: + - kind: ServiceAccount + name: '{{ include "piraeus-operator.serviceAccountName" . }}' + namespace: '{{ .Release.Namespace }}' +{{ end }} +{{ if.Values.rbac.create }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ include "piraeus-operator.fullname" . }}-proxy-role + labels: + {{- include "piraeus-operator.labels" . | nindent 4 }} +rules: + - apiGroups: + - authentication.k8s.io + resources: + - tokenreviews + verbs: + - create + - apiGroups: + - authorization.k8s.io + resources: + - subjectaccessreviews + verbs: + - create +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ include "piraeus-operator.fullname" . }}-proxy-rolebinding + labels: + {{- include "piraeus-operator.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: '{{ include "piraeus-operator.fullname" . }}-proxy-role' +subjects: + - kind: ServiceAccount + name: {{ include "piraeus-operator.serviceAccountName" . }} + namespace: '{{ .Release.Namespace }}' +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ include "piraeus-operator.fullname" . }}-leader-election-role + labels: + {{- include "piraeus-operator.labels" . | nindent 4 }} +rules: + - apiGroups: + - "" + resources: + - configmaps + verbs: + - get + - list + - watch + - create + - update + - patch + - delete + - apiGroups: + - coordination.k8s.io + resources: + - leases + verbs: + - get + - list + - watch + - create + - update + - patch + - delete + - apiGroups: + - "" + resources: + - events + verbs: + - create + - patch +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ include "piraeus-operator.fullname" . }}-leader-election-rolebinding + labels: + {{- include "piraeus-operator.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: '{{ include "piraeus-operator.fullname" . }}-leader-election-role' +subjects: + - kind: ServiceAccount + name: {{ include "piraeus-operator.serviceAccountName" . }} + namespace: '{{ .Release.Namespace }}' +{{ end }} diff --git a/packages/system/piraeus-operator/charts/piraeus/templates/validating-webhook-configuration.yaml b/packages/system/piraeus-operator/charts/piraeus/templates/validating-webhook-configuration.yaml new file mode 100644 index 00000000..ef22851b --- /dev/null +++ b/packages/system/piraeus-operator/charts/piraeus/templates/validating-webhook-configuration.yaml @@ -0,0 +1,154 @@ +# Check if the TLS secret already exists and initialize variables for later use at the top level +{{- $secret := lookup "v1" "Secret" .Release.Namespace (include "piraeus-operator.certifcateName" .) }} +{{ $ca := "" }} +{{ $key := "" }} +{{ $crt := "" }} +{{- if .Values.tls.certManagerIssuerRef }} +--- +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: {{ include "piraeus-operator.fullname" . }} + labels: + {{- include "piraeus-operator.labels" . | nindent 4 }} +spec: + secretName: {{ include "piraeus-operator.certifcateName" . }} + dnsNames: + - {{ include "piraeus-operator.fullname" . }}-webhook-service.{{ .Release.Namespace }}.svc + issuerRef: + {{- toYaml .Values.tls.certManagerIssuerRef | nindent 4 }} + privateKey: + rotationPolicy: Always +--- +{{- else if .Values.tls.autogenerate }} + {{- if and $secret (not .Values.tls.renew) }} + {{- $ca = get $secret.data "ca.crt" }} + {{- $key = get $secret.data "tls.key" }} + {{- $crt = get $secret.data "tls.crt" }} + {{- else }} + {{- $serviceName := (printf "%s-webhook-service.%s.svc" (include "piraeus-operator.fullname" .) .Release.Namespace)}} + {{- $cert := genSelfSignedCert $serviceName nil (list $serviceName) 3650 }} + {{- $ca = b64enc $cert.Cert }} + {{- $key = b64enc $cert.Key }} + {{- $crt = b64enc $cert.Cert }} + {{- end }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "piraeus-operator.certifcateName" . }} + labels: + {{- include "piraeus-operator.labels" . | nindent 4 }} +type: kubernetes.io/tls +data: + ca.crt: {{ $ca }} + tls.key: {{ $key }} + tls.crt: {{ $crt }} +{{- end }} +--- +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingWebhookConfiguration +metadata: + name: {{ include "piraeus-operator.fullname" . }}-validating-webhook-configuration + labels: + {{- include "piraeus-operator.labels" . | nindent 4 }} + {{- if .Values.tls.certManagerIssuerRef }} + annotations: + cert-manager.io/inject-ca-from: {{ .Release.Namespace }}/{{ include "piraeus-operator.fullname" . }} + {{- end }} +webhooks: +- admissionReviewVersions: + - v1 + clientConfig: + service: + name: '{{ include "piraeus-operator.fullname" . }}-webhook-service' + namespace: '{{ .Release.Namespace }}' + path: /validate-piraeus-io-v1-linstorcluster + {{- if not .Values.tls.certManagerIssuerRef }} + caBundle: {{ $ca }} + {{- end }} + failurePolicy: {{ .Values.webhook.failurePolicy }} + timeoutSeconds: {{ .Values.webhook.timeoutSeconds }} + name: vlinstorcluster.kb.io + rules: + - apiGroups: + - piraeus.io + apiVersions: + - v1 + operations: + - CREATE + - UPDATE + resources: + - linstorclusters + sideEffects: None +- admissionReviewVersions: + - v1 + clientConfig: + service: + name: '{{ include "piraeus-operator.fullname" . }}-webhook-service' + namespace: '{{ .Release.Namespace }}' + path: /validate-piraeus-io-v1-linstornodeconnection + {{- if not .Values.tls.certManagerIssuerRef }} + caBundle: {{ $ca }} + {{- end }} + failurePolicy: {{ .Values.webhook.failurePolicy }} + timeoutSeconds: {{ .Values.webhook.timeoutSeconds }} + name: vlinstornodeconnection.kb.io + rules: + - apiGroups: + - piraeus.io + apiVersions: + - v1 + operations: + - CREATE + - UPDATE + resources: + - linstornodeconnections + sideEffects: None +- admissionReviewVersions: + - v1 + clientConfig: + service: + name: '{{ include "piraeus-operator.fullname" . }}-webhook-service' + namespace: '{{ .Release.Namespace }}' + path: /validate-piraeus-io-v1-linstorsatellite + {{- if not .Values.tls.certManagerIssuerRef }} + caBundle: {{ $ca }} + {{- end }} + failurePolicy: {{ .Values.webhook.failurePolicy }} + timeoutSeconds: {{ .Values.webhook.timeoutSeconds }} + name: vlinstorsatellite.kb.io + rules: + - apiGroups: + - piraeus.io + apiVersions: + - v1 + operations: + - CREATE + - UPDATE + resources: + - linstorsatellites + sideEffects: None +- admissionReviewVersions: + - v1 + clientConfig: + service: + name: '{{ include "piraeus-operator.fullname" . }}-webhook-service' + namespace: '{{ .Release.Namespace }}' + path: /validate-piraeus-io-v1-linstorsatelliteconfiguration + {{- if not .Values.tls.certManagerIssuerRef }} + caBundle: {{ $ca }} + {{- end }} + failurePolicy: {{ .Values.webhook.failurePolicy }} + timeoutSeconds: {{ .Values.webhook.timeoutSeconds }} + name: vlinstorsatelliteconfiguration.kb.io + rules: + - apiGroups: + - piraeus.io + apiVersions: + - v1 + operations: + - CREATE + - UPDATE + resources: + - linstorsatelliteconfigurations + sideEffects: None diff --git a/packages/system/piraeus-operator/charts/piraeus/templates/webhook-service.yaml b/packages/system/piraeus-operator/charts/piraeus/templates/webhook-service.yaml new file mode 100644 index 00000000..d360269b --- /dev/null +++ b/packages/system/piraeus-operator/charts/piraeus/templates/webhook-service.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "piraeus-operator.fullname" . }}-webhook-service + labels: + {{- include "piraeus-operator.labels" . | nindent 4 }} +spec: + type: ClusterIP + selector: + {{- include "piraeus-operator.selectorLabels" . | nindent 4 }} + ports: + - name: https + port: 443 + targetPort: 9443 diff --git a/packages/system/piraeus-operator/charts/piraeus/values.yaml b/packages/system/piraeus-operator/charts/piraeus/values.yaml new file mode 100644 index 00000000..ada590fe --- /dev/null +++ b/packages/system/piraeus-operator/charts/piraeus/values.yaml @@ -0,0 +1,108 @@ +replicaCount: 1 + +installCRDs: false + +operator: + image: + repository: quay.io/piraeusdatastore/piraeus-operator + pullPolicy: IfNotPresent + # Overrides the image tag whose default is the chart appVersion. + tag: "" + securityContext: + capabilities: + drop: + - ALL + readOnlyRootFilesystem: true + runAsNonRoot: true + runAsUser: 1000 + + options: + leaderElect: true + + resources: { } + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + +kubeRbacProxy: + enabled: false + image: + repository: gcr.io/kubebuilder/kube-rbac-proxy + pullPolicy: IfNotPresent + tag: v0.13.1 + options: + logtostderr: "true" + v: 0 + securityContext: + capabilities: + drop: + - ALL + readOnlyRootFilesystem: true + runAsNonRoot: true + runAsUser: 1000 + + resources: { } + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + +webhook: + timeoutSeconds: 2 + failurePolicy: Fail + +tls: + certificateSecret: "" + autogenerate: true + renew: false + certManagerIssuerRef: {} + +imagePullSecrets: [ ] +nameOverride: "" +fullnameOverride: "" + +serviceAccount: + # Specifies whether a service account should be created + create: true + # Annotations to add to the service account + annotations: { } + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" + +rbac: + # Specifies whether RBAC resources should be created + create: true + +podAnnotations: { } + +podSecurityContext: {} + # fsGroup: 2000 + +nodeSelector: { } + +tolerations: + - key: drbd.linbit.com/lost-quorum + effect: NoSchedule + - key: drbd.linbit.com/force-io-error + effect: NoSchedule +affinity: { } + +podDisruptionBudget: + enabled: true + minAvailable: 1 + # maxUnavailable: 1 + +imageConfigOverride: [] + # - base: example.com/piraeus + # components: + # linstor-csi: + # image: linstor-csi + # tag: my-custom-tag + # Results in the image example.com/piraeus/linstor-csi:my-custom-tag being used. + # See templates/config.yaml for available components. diff --git a/packages/system/piraeus-operator/examples/1.yaml b/packages/system/piraeus-operator/examples/1.yaml new file mode 100644 index 00000000..e43081e8 --- /dev/null +++ b/packages/system/piraeus-operator/examples/1.yaml @@ -0,0 +1,28 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: myclaim +spec: + accessModes: + - ReadWriteOnce + volumeMode: Filesystem + resources: + requests: + storage: 8Gi + #storageClassName: linstor-lvm +--- +apiVersion: v1 +kind: Pod +metadata: + name: mypod +spec: + containers: + - name: myfrontend + image: nginx + volumeMounts: + - mountPath: "/var/www/html" + name: mypd + volumes: + - name: mypd + persistentVolumeClaim: + claimName: myclaim diff --git a/packages/system/piraeus-operator/hack/proxmox-install-module.sh b/packages/system/piraeus-operator/hack/proxmox-install-module.sh new file mode 100644 index 00000000..679a53ed --- /dev/null +++ b/packages/system/piraeus-operator/hack/proxmox-install-module.sh @@ -0,0 +1,9 @@ +wget -O /tmp/package-signing-pubkey.asc https://packages.linbit.com/package-signing-pubkey.asc +gpg --yes -o /etc/apt/trusted.gpg.d/linbit-keyring.gpg --dearmor /tmp/package-signing-pubkey.asc +PVERS=$(pveversion | awk -F'[/.]' '{print $2}') +echo "deb [signed-by=/etc/apt/trusted.gpg.d/linbit-keyring.gpg] http://packages.linbit.com/public/ proxmox-$PVERS drbd-9" > /etc/apt/sources.list +apt update && apt -y install drbd-dkms +echo "options drbd usermode_helper=disabled" > /etc/modprobe.d/drbd.conf +echo drbd > /etc/modules-load.d/drbd.conf +modprobe drbd +kubectl label node "${HOSTNAME}" node-role.kubernetes.io/linstor= --overwrite diff --git a/packages/system/piraeus-operator/templates/piraeus-tls.yaml b/packages/system/piraeus-operator/templates/piraeus-tls.yaml new file mode 100644 index 00000000..1d787ceb --- /dev/null +++ b/packages/system/piraeus-operator/templates/piraeus-tls.yaml @@ -0,0 +1,8 @@ +--- +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + name: ca-bootstrapper + namespace: {{ .Release.namespace }} +spec: + selfSigned: {} diff --git a/packages/system/piraeus-operator/values.yaml b/packages/system/piraeus-operator/values.yaml new file mode 100644 index 00000000..4cb448d1 --- /dev/null +++ b/packages/system/piraeus-operator/values.yaml @@ -0,0 +1,7 @@ +piraeus: + installCRDs: true + autogenerate: false + tls: + certManagerIssuerRef: + name: ca-bootstrapper + kind: Issuer diff --git a/packages/system/postgres-operator/.helmignore b/packages/system/postgres-operator/.helmignore new file mode 100644 index 00000000..d5c178e8 --- /dev/null +++ b/packages/system/postgres-operator/.helmignore @@ -0,0 +1,3 @@ +images +hack +.gitkeep diff --git a/packages/system/postgres-operator/Chart.yaml b/packages/system/postgres-operator/Chart.yaml new file mode 100644 index 00000000..38d0505f --- /dev/null +++ b/packages/system/postgres-operator/Chart.yaml @@ -0,0 +1,2 @@ +name: cozy-postgres-operator +version: 1.0.0 diff --git a/packages/system/postgres-operator/Makefile b/packages/system/postgres-operator/Makefile new file mode 100644 index 00000000..f46734d0 --- /dev/null +++ b/packages/system/postgres-operator/Makefile @@ -0,0 +1,17 @@ +NAME=postgres-operator +NAMESPACE=cozy-postgres-operator + +show: + helm template --dry-run=server -n $(NAMESPACE) $(NAME) . + +apply: + helm upgrade -i -n $(NAMESPACE) $(NAME) . + +diff: + helm diff upgrade --allow-unreleased --normalize-manifests -n $(NAMESPACE) $(NAME) . + +update: + rm -rf charts + helm repo add cnpg https://cloudnative-pg.github.io/charts + helm repo update cnpg + helm pull cnpg/cloudnative-pg --untar --untardir charts diff --git a/packages/system/postgres-operator/charts/cloudnative-pg/.helmignore b/packages/system/postgres-operator/charts/cloudnative-pg/.helmignore new file mode 100644 index 00000000..0e8a0eb3 --- /dev/null +++ b/packages/system/postgres-operator/charts/cloudnative-pg/.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/packages/system/postgres-operator/charts/cloudnative-pg/Chart.yaml b/packages/system/postgres-operator/charts/cloudnative-pg/Chart.yaml new file mode 100644 index 00000000..4a7db728 --- /dev/null +++ b/packages/system/postgres-operator/charts/cloudnative-pg/Chart.yaml @@ -0,0 +1,17 @@ +apiVersion: v2 +appVersion: 1.21.1 +description: CloudNativePG Helm Chart +home: https://cloudnative-pg.io +icon: https://raw.githubusercontent.com/cloudnative-pg/artwork/main/cloudnativepg-logo.svg +keywords: +- postgresql +- postgres +- database +maintainers: +- email: p.scorsolini@gmail.com + name: phisco +name: cloudnative-pg +sources: +- https://github.com/cloudnative-pg/charts +type: application +version: 0.19.1 diff --git a/packages/system/postgres-operator/charts/cloudnative-pg/LICENSE b/packages/system/postgres-operator/charts/cloudnative-pg/LICENSE new file mode 100644 index 00000000..d6456956 --- /dev/null +++ b/packages/system/postgres-operator/charts/cloudnative-pg/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/packages/system/postgres-operator/charts/cloudnative-pg/README.md b/packages/system/postgres-operator/charts/cloudnative-pg/README.md new file mode 100644 index 00000000..21bf54d8 --- /dev/null +++ b/packages/system/postgres-operator/charts/cloudnative-pg/README.md @@ -0,0 +1,58 @@ +# cloudnative-pg + +![Version: 0.19.1](https://img.shields.io/badge/Version-0.19.1-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 1.21.1](https://img.shields.io/badge/AppVersion-1.21.1-informational?style=flat-square) + +CloudNativePG Helm Chart + +**Homepage:** + +## Maintainers + +| Name | Email | Url | +| ---- | ------ | --- | +| phisco | | | + +## Source Code + +* + +## Values + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| additionalArgs | list | `[]` | Additinal arguments to be added to the operator's args list. | +| affinity | object | `{}` | Affinity for the operator to be installed. | +| commonAnnotations | object | `{}` | Annotations to be added to all other resources. | +| config | object | `{"create":true,"data":{},"name":"cnpg-controller-manager-config","secret":false}` | Operator configuration. | +| config.create | bool | `true` | Specifies whether the secret should be created. | +| config.data | object | `{}` | The content of the configmap/secret, see https://cloudnative-pg.io/documentation/current/operator_conf/#available-options for all the available options. | +| config.name | string | `"cnpg-controller-manager-config"` | The name of the configmap/secret to use. | +| config.secret | bool | `false` | Specifies whether it should be stored in a secret, instead of a configmap. | +| containerSecurityContext | object | `{"allowPrivilegeEscalation":false,"capabilities":{"drop":["ALL"]},"readOnlyRootFilesystem":true,"runAsGroup":10001,"runAsUser":10001,"seccompProfile":{"type":"RuntimeDefault"}}` | Container Security Context. | +| crds.create | bool | `true` | Specifies whether the CRDs should be created when installing the chart. | +| fullnameOverride | string | `""` | | +| image.pullPolicy | string | `"IfNotPresent"` | | +| image.repository | string | `"ghcr.io/cloudnative-pg/cloudnative-pg"` | | +| image.tag | string | `""` | Overrides the image tag whose default is the chart appVersion. | +| imagePullSecrets | list | `[]` | | +| monitoring.podMonitorEnabled | bool | `false` | Specifies whether the monitoring should be enabled. Requires Prometheus Operator CRDs. | +| monitoringQueriesConfigMap.name | string | `"cnpg-default-monitoring"` | The name of the default monitoring configmap. | +| monitoringQueriesConfigMap.queries | string | `"backends:\n query: |\n SELECT sa.datname\n , sa.usename\n , sa.application_name\n , states.state\n , COALESCE(sa.count, 0) AS total\n , COALESCE(sa.max_tx_secs, 0) AS max_tx_duration_seconds\n FROM ( VALUES ('active')\n , ('idle')\n , ('idle in transaction')\n , ('idle in transaction (aborted)')\n , ('fastpath function call')\n , ('disabled')\n ) AS states(state)\n LEFT JOIN (\n SELECT datname\n , state\n , usename\n , COALESCE(application_name, '') AS application_name\n , COUNT(*)\n , COALESCE(EXTRACT (EPOCH FROM (max(now() - xact_start))), 0) AS max_tx_secs\n FROM pg_catalog.pg_stat_activity\n GROUP BY datname, state, usename, application_name\n ) sa ON states.state = sa.state\n WHERE sa.usename IS NOT NULL\n metrics:\n - datname:\n usage: \"LABEL\"\n description: \"Name of the database\"\n - usename:\n usage: \"LABEL\"\n description: \"Name of the user\"\n - application_name:\n usage: \"LABEL\"\n description: \"Name of the application\"\n - state:\n usage: \"LABEL\"\n description: \"State of the backend\"\n - total:\n usage: \"GAUGE\"\n description: \"Number of backends\"\n - max_tx_duration_seconds:\n usage: \"GAUGE\"\n description: \"Maximum duration of a transaction in seconds\"\n\nbackends_waiting:\n query: |\n SELECT count(*) AS total\n FROM pg_catalog.pg_locks blocked_locks\n JOIN pg_catalog.pg_locks blocking_locks\n ON blocking_locks.locktype = blocked_locks.locktype\n AND blocking_locks.database IS NOT DISTINCT FROM blocked_locks.database\n AND blocking_locks.relation IS NOT DISTINCT FROM blocked_locks.relation\n AND blocking_locks.page IS NOT DISTINCT FROM blocked_locks.page\n AND blocking_locks.tuple IS NOT DISTINCT FROM blocked_locks.tuple\n AND blocking_locks.virtualxid IS NOT DISTINCT FROM blocked_locks.virtualxid\n AND blocking_locks.transactionid IS NOT DISTINCT FROM blocked_locks.transactionid\n AND blocking_locks.classid IS NOT DISTINCT FROM blocked_locks.classid\n AND blocking_locks.objid IS NOT DISTINCT FROM blocked_locks.objid\n AND blocking_locks.objsubid IS NOT DISTINCT FROM blocked_locks.objsubid\n AND blocking_locks.pid != blocked_locks.pid\n JOIN pg_catalog.pg_stat_activity blocking_activity ON blocking_activity.pid = blocking_locks.pid\n WHERE NOT blocked_locks.granted\n metrics:\n - total:\n usage: \"GAUGE\"\n description: \"Total number of backends that are currently waiting on other queries\"\n\npg_database:\n query: |\n SELECT datname\n , pg_catalog.pg_database_size(datname) AS size_bytes\n , pg_catalog.age(datfrozenxid) AS xid_age\n , pg_catalog.mxid_age(datminmxid) AS mxid_age\n FROM pg_catalog.pg_database\n metrics:\n - datname:\n usage: \"LABEL\"\n description: \"Name of the database\"\n - size_bytes:\n usage: \"GAUGE\"\n description: \"Disk space used by the database\"\n - xid_age:\n usage: \"GAUGE\"\n description: \"Number of transactions from the frozen XID to the current one\"\n - mxid_age:\n usage: \"GAUGE\"\n description: \"Number of multiple transactions (Multixact) from the frozen XID to the current one\"\n\npg_postmaster:\n query: |\n SELECT EXTRACT(EPOCH FROM pg_postmaster_start_time) AS start_time\n FROM pg_catalog.pg_postmaster_start_time()\n metrics:\n - start_time:\n usage: \"GAUGE\"\n description: \"Time at which postgres started (based on epoch)\"\n\npg_replication:\n query: \"SELECT CASE WHEN (\n NOT pg_catalog.pg_is_in_recovery()\n OR pg_catalog.pg_last_wal_receive_lsn() = pg_catalog.pg_last_wal_replay_lsn())\n THEN 0\n ELSE GREATEST (0,\n EXTRACT(EPOCH FROM (now() - pg_catalog.pg_last_xact_replay_timestamp())))\n END AS lag,\n pg_catalog.pg_is_in_recovery() AS in_recovery,\n EXISTS (TABLE pg_stat_wal_receiver) AS is_wal_receiver_up,\n (SELECT count(*) FROM pg_catalog.pg_stat_replication) AS streaming_replicas\"\n metrics:\n - lag:\n usage: \"GAUGE\"\n description: \"Replication lag behind primary in seconds\"\n - in_recovery:\n usage: \"GAUGE\"\n description: \"Whether the instance is in recovery\"\n - is_wal_receiver_up:\n usage: \"GAUGE\"\n description: \"Whether the instance wal_receiver is up\"\n - streaming_replicas:\n usage: \"GAUGE\"\n description: \"Number of streaming replicas connected to the instance\"\n\npg_replication_slots:\n query: |\n SELECT slot_name,\n slot_type,\n database,\n active,\n (CASE pg_catalog.pg_is_in_recovery()\n WHEN TRUE THEN pg_catalog.pg_wal_lsn_diff(pg_catalog.pg_last_wal_receive_lsn(), restart_lsn)\n ELSE pg_catalog.pg_wal_lsn_diff(pg_catalog.pg_current_wal_lsn(), restart_lsn)\n END) as pg_wal_lsn_diff\n FROM pg_catalog.pg_replication_slots\n WHERE NOT temporary\n metrics:\n - slot_name:\n usage: \"LABEL\"\n description: \"Name of the replication slot\"\n - slot_type:\n usage: \"LABEL\"\n description: \"Type of the replication slot\"\n - database:\n usage: \"LABEL\"\n description: \"Name of the database\"\n - active:\n usage: \"GAUGE\"\n description: \"Flag indicating whether the slot is active\"\n - pg_wal_lsn_diff:\n usage: \"GAUGE\"\n description: \"Replication lag in bytes\"\n\npg_stat_archiver:\n query: |\n SELECT archived_count\n , failed_count\n , COALESCE(EXTRACT(EPOCH FROM (now() - last_archived_time)), -1) AS seconds_since_last_archival\n , COALESCE(EXTRACT(EPOCH FROM (now() - last_failed_time)), -1) AS seconds_since_last_failure\n , COALESCE(EXTRACT(EPOCH FROM last_archived_time), -1) AS last_archived_time\n , COALESCE(EXTRACT(EPOCH FROM last_failed_time), -1) AS last_failed_time\n , COALESCE(CAST(CAST('x'||pg_catalog.right(pg_catalog.split_part(last_archived_wal, '.', 1), 16) AS pg_catalog.bit(64)) AS pg_catalog.int8), -1) AS last_archived_wal_start_lsn\n , COALESCE(CAST(CAST('x'||pg_catalog.right(pg_catalog.split_part(last_failed_wal, '.', 1), 16) AS pg_catalog.bit(64)) AS pg_catalog.int8), -1) AS last_failed_wal_start_lsn\n , EXTRACT(EPOCH FROM stats_reset) AS stats_reset_time\n FROM pg_catalog.pg_stat_archiver\n metrics:\n - archived_count:\n usage: \"COUNTER\"\n description: \"Number of WAL files that have been successfully archived\"\n - failed_count:\n usage: \"COUNTER\"\n description: \"Number of failed attempts for archiving WAL files\"\n - seconds_since_last_archival:\n usage: \"GAUGE\"\n description: \"Seconds since the last successful archival operation\"\n - seconds_since_last_failure:\n usage: \"GAUGE\"\n description: \"Seconds since the last failed archival operation\"\n - last_archived_time:\n usage: \"GAUGE\"\n description: \"Epoch of the last time WAL archiving succeeded\"\n - last_failed_time:\n usage: \"GAUGE\"\n description: \"Epoch of the last time WAL archiving failed\"\n - last_archived_wal_start_lsn:\n usage: \"GAUGE\"\n description: \"Archived WAL start LSN\"\n - last_failed_wal_start_lsn:\n usage: \"GAUGE\"\n description: \"Last failed WAL LSN\"\n - stats_reset_time:\n usage: \"GAUGE\"\n description: \"Time at which these statistics were last reset\"\n\npg_stat_bgwriter:\n query: |\n SELECT checkpoints_timed\n , checkpoints_req\n , checkpoint_write_time\n , checkpoint_sync_time\n , buffers_checkpoint\n , buffers_clean\n , maxwritten_clean\n , buffers_backend\n , buffers_backend_fsync\n , buffers_alloc\n FROM pg_catalog.pg_stat_bgwriter\n metrics:\n - checkpoints_timed:\n usage: \"COUNTER\"\n description: \"Number of scheduled checkpoints that have been performed\"\n - checkpoints_req:\n usage: \"COUNTER\"\n description: \"Number of requested checkpoints that have been performed\"\n - checkpoint_write_time:\n usage: \"COUNTER\"\n description: \"Total amount of time that has been spent in the portion of checkpoint processing where files are written to disk, in milliseconds\"\n - checkpoint_sync_time:\n usage: \"COUNTER\"\n description: \"Total amount of time that has been spent in the portion of checkpoint processing where files are synchronized to disk, in milliseconds\"\n - buffers_checkpoint:\n usage: \"COUNTER\"\n description: \"Number of buffers written during checkpoints\"\n - buffers_clean:\n usage: \"COUNTER\"\n description: \"Number of buffers written by the background writer\"\n - maxwritten_clean:\n usage: \"COUNTER\"\n description: \"Number of times the background writer stopped a cleaning scan because it had written too many buffers\"\n - buffers_backend:\n usage: \"COUNTER\"\n description: \"Number of buffers written directly by a backend\"\n - buffers_backend_fsync:\n usage: \"COUNTER\"\n description: \"Number of times a backend had to execute its own fsync call (normally the background writer handles those even when the backend does its own write)\"\n - buffers_alloc:\n usage: \"COUNTER\"\n description: \"Number of buffers allocated\"\n\npg_stat_database:\n query: |\n SELECT datname\n , xact_commit\n , xact_rollback\n , blks_read\n , blks_hit\n , tup_returned\n , tup_fetched\n , tup_inserted\n , tup_updated\n , tup_deleted\n , conflicts\n , temp_files\n , temp_bytes\n , deadlocks\n , blk_read_time\n , blk_write_time\n FROM pg_catalog.pg_stat_database\n metrics:\n - datname:\n usage: \"LABEL\"\n description: \"Name of this database\"\n - xact_commit:\n usage: \"COUNTER\"\n description: \"Number of transactions in this database that have been committed\"\n - xact_rollback:\n usage: \"COUNTER\"\n description: \"Number of transactions in this database that have been rolled back\"\n - blks_read:\n usage: \"COUNTER\"\n description: \"Number of disk blocks read in this database\"\n - blks_hit:\n usage: \"COUNTER\"\n description: \"Number of times disk blocks were found already in the buffer cache, so that a read was not necessary (this only includes hits in the PostgreSQL buffer cache, not the operating system's file system cache)\"\n - tup_returned:\n usage: \"COUNTER\"\n description: \"Number of rows returned by queries in this database\"\n - tup_fetched:\n usage: \"COUNTER\"\n description: \"Number of rows fetched by queries in this database\"\n - tup_inserted:\n usage: \"COUNTER\"\n description: \"Number of rows inserted by queries in this database\"\n - tup_updated:\n usage: \"COUNTER\"\n description: \"Number of rows updated by queries in this database\"\n - tup_deleted:\n usage: \"COUNTER\"\n description: \"Number of rows deleted by queries in this database\"\n - conflicts:\n usage: \"COUNTER\"\n description: \"Number of queries canceled due to conflicts with recovery in this database\"\n - temp_files:\n usage: \"COUNTER\"\n description: \"Number of temporary files created by queries in this database\"\n - temp_bytes:\n usage: \"COUNTER\"\n description: \"Total amount of data written to temporary files by queries in this database\"\n - deadlocks:\n usage: \"COUNTER\"\n description: \"Number of deadlocks detected in this database\"\n - blk_read_time:\n usage: \"COUNTER\"\n description: \"Time spent reading data file blocks by backends in this database, in milliseconds\"\n - blk_write_time:\n usage: \"COUNTER\"\n description: \"Time spent writing data file blocks by backends in this database, in milliseconds\"\n\npg_stat_replication:\n primary: true\n query: |\n SELECT usename\n , COALESCE(application_name, '') AS application_name\n , COALESCE(client_addr::text, '') AS client_addr\n , COALESCE(client_port::text, '') AS client_port\n , EXTRACT(EPOCH FROM backend_start) AS backend_start\n , COALESCE(pg_catalog.age(backend_xmin), 0) AS backend_xmin_age\n , pg_catalog.pg_wal_lsn_diff(pg_catalog.pg_current_wal_lsn(), sent_lsn) AS sent_diff_bytes\n , pg_catalog.pg_wal_lsn_diff(pg_catalog.pg_current_wal_lsn(), write_lsn) AS write_diff_bytes\n , pg_catalog.pg_wal_lsn_diff(pg_catalog.pg_current_wal_lsn(), flush_lsn) AS flush_diff_bytes\n , COALESCE(pg_catalog.pg_wal_lsn_diff(pg_catalog.pg_current_wal_lsn(), replay_lsn),0) AS replay_diff_bytes\n , COALESCE((EXTRACT(EPOCH FROM write_lag)),0)::float AS write_lag_seconds\n , COALESCE((EXTRACT(EPOCH FROM flush_lag)),0)::float AS flush_lag_seconds\n , COALESCE((EXTRACT(EPOCH FROM replay_lag)),0)::float AS replay_lag_seconds\n FROM pg_catalog.pg_stat_replication\n metrics:\n - usename:\n usage: \"LABEL\"\n description: \"Name of the replication user\"\n - application_name:\n usage: \"LABEL\"\n description: \"Name of the application\"\n - client_addr:\n usage: \"LABEL\"\n description: \"Client IP address\"\n - client_port:\n usage: \"LABEL\"\n description: \"Client TCP port\"\n - backend_start:\n usage: \"COUNTER\"\n description: \"Time when this process was started\"\n - backend_xmin_age:\n usage: \"COUNTER\"\n description: \"The age of this standby's xmin horizon\"\n - sent_diff_bytes:\n usage: \"GAUGE\"\n description: \"Difference in bytes from the last write-ahead log location sent on this connection\"\n - write_diff_bytes:\n usage: \"GAUGE\"\n description: \"Difference in bytes from the last write-ahead log location written to disk by this standby server\"\n - flush_diff_bytes:\n usage: \"GAUGE\"\n description: \"Difference in bytes from the last write-ahead log location flushed to disk by this standby server\"\n - replay_diff_bytes:\n usage: \"GAUGE\"\n description: \"Difference in bytes from the last write-ahead log location replayed into the database on this standby server\"\n - write_lag_seconds:\n usage: \"GAUGE\"\n description: \"Time elapsed between flushing recent WAL locally and receiving notification that this standby server has written it\"\n - flush_lag_seconds:\n usage: \"GAUGE\"\n description: \"Time elapsed between flushing recent WAL locally and receiving notification that this standby server has written and flushed it\"\n - replay_lag_seconds:\n usage: \"GAUGE\"\n description: \"Time elapsed between flushing recent WAL locally and receiving notification that this standby server has written, flushed and applied it\"\n\npg_settings:\n query: |\n SELECT name,\n CASE setting WHEN 'on' THEN '1' WHEN 'off' THEN '0' ELSE setting END AS setting\n FROM pg_catalog.pg_settings\n WHERE vartype IN ('integer', 'real', 'bool')\n ORDER BY 1\n metrics:\n - name:\n usage: \"LABEL\"\n description: \"Name of the setting\"\n - setting:\n usage: \"GAUGE\"\n description: \"Setting value\"\n"` | A string representation of a YAML defining monitoring queries. | +| nameOverride | string | `""` | | +| nodeSelector | object | `{}` | Nodeselector for the operator to be installed. | +| podAnnotations | object | `{}` | Annotations to be added to the pod. | +| podLabels | object | `{}` | Labels to be added to the pod. | +| podSecurityContext | object | `{"runAsNonRoot":true,"seccompProfile":{"type":"RuntimeDefault"}}` | Security Context for the whole pod. | +| priorityClassName | string | `""` | Priority indicates the importance of a Pod relative to other Pods. | +| rbac.aggregateClusterRoles | bool | `false` | Aggregate ClusterRoles to Kubernetes default user-facing roles. Ref: https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles | +| rbac.create | bool | `true` | Specifies whether ClusterRole and ClusterRoleBinding should be created. | +| replicaCount | int | `1` | | +| resources | object | `{}` | | +| service.name | string | `"cnpg-webhook-service"` | DO NOT CHANGE THE SERVICE NAME as it is currently used to generate the certificate and can not be configured | +| service.port | int | `443` | | +| service.type | string | `"ClusterIP"` | | +| serviceAccount.create | bool | `true` | Specifies whether the service account should be created. | +| serviceAccount.name | string | `""` | The name of the service account to use. If not set and create is true, a name is generated using the fullname template. | +| tolerations | list | `[]` | Tolerations for the operator to be installed. | +| webhook | object | `{"livenessProbe":{"initialDelaySeconds":3},"mutating":{"create":true,"failurePolicy":"Fail"},"port":9443,"readinessProbe":{"initialDelaySeconds":3},"validating":{"create":true,"failurePolicy":"Fail"}}` | The webhook configuration. | + diff --git a/packages/system/postgres-operator/charts/cloudnative-pg/templates/NOTES.txt b/packages/system/postgres-operator/charts/cloudnative-pg/templates/NOTES.txt new file mode 100644 index 00000000..0f79fe0d --- /dev/null +++ b/packages/system/postgres-operator/charts/cloudnative-pg/templates/NOTES.txt @@ -0,0 +1,18 @@ + +CloudNativePG operator should be installed in namespace "{{ .Release.Namespace }}". +You can now create a PostgreSQL cluster with 3 nodes in the current namespace as follows: + +cat < + matches that of any node on which a pod of the set of + pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied to the + union of the namespaces selected by this field and + the ones listed in the namespaces field. null selector + and null or empty namespaces list means "this pod's + namespace". An empty selector ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list of namespace + names that the term applies to. The term is applied + to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. null or + empty namespaces list and null namespaceSelector means + "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where + co-located is defined as running on a node whose value + of the label with key topologyKey matches that of + any node on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + additionalPodAntiAffinity: + description: AdditionalPodAntiAffinity allows to specify pod anti-affinity + terms to be added to the ones generated by the operator if EnablePodAntiAffinity + is set to true (default) or to be used exclusively if set to + false. + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods to + nodes that satisfy the anti-affinity expressions specified + by this field, but it may choose a node that violates one + or more of the expressions. The node that is most preferred + is the one with the greatest sum of weights, i.e. for each + node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling anti-affinity expressions, + etc.), compute a sum by iterating through the elements of + this field and adding "weight" to the sum if the node has + pods which matches the corresponding podAffinityTerm; the + node(s) with the highest sum are the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by this + field and the ones listed in the namespaces field. + null selector and null or empty namespaces list + means "this pod's namespace". An empty selector + ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. The + term is applied to the union of the namespaces + listed in this field and the ones selected by + namespaceSelector. null or empty namespaces list + and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods + matching the labelSelector in the specified namespaces, + where co-located is defined as running on a node + whose value of the label with key topologyKey + matches that of any node on which any of the selected + pods is running. Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching the corresponding + podAffinityTerm, in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the anti-affinity requirements specified by + this field are not met at scheduling time, the pod will + not be scheduled onto the node. If the anti-affinity requirements + specified by this field cease to be met at some point during + pod execution (e.g. due to a pod label update), the system + may or may not try to eventually evict the pod from its + node. When there are multiple elements, the lists of nodes + corresponding to each podAffinityTerm are intersected, i.e. + all terms must be satisfied. + items: + description: Defines a set of pods (namely those matching + the labelSelector relative to the given namespace(s)) + that this pod should be co-located (affinity) or not co-located + (anti-affinity) with, where co-located is defined as running + on a node whose value of the label with key + matches that of any node on which a pod of the set of + pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied to the + union of the namespaces selected by this field and + the ones listed in the namespaces field. null selector + and null or empty namespaces list means "this pod's + namespace". An empty selector ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list of namespace + names that the term applies to. The term is applied + to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. null or + empty namespaces list and null namespaceSelector means + "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where + co-located is defined as running on a node whose value + of the label with key topologyKey matches that of + any node on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + enablePodAntiAffinity: + description: Activates anti-affinity for the pods. The operator + will define pods anti-affinity unless this field is explicitly + set to false + type: boolean + nodeAffinity: + description: 'NodeAffinity describes node affinity scheduling + rules for the pod. More info: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#node-affinity' + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods to + nodes that satisfy the affinity expressions specified by + this field, but it may choose a node that violates one or + more of the expressions. The node that is most preferred + is the one with the greatest sum of weights, i.e. for each + node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, + etc.), compute a sum by iterating through the elements of + this field and adding "weight" to the sum if the node matches + the corresponding matchExpressions; the node(s) with the + highest sum are the most preferred. + items: + description: An empty preferred scheduling term matches + all objects with implicit weight 0 (i.e. it's a no-op). + A null preferred scheduling term matches no objects (i.e. + is also a no-op). + properties: + preference: + description: A node selector term, associated with the + corresponding weight. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists, DoesNotExist. Gt, and + Lt. + type: string + values: + description: 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. If the operator is Gt or + Lt, the values array must have a single + element, which will be interpreted as an + integer. This array is replaced during a + strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists, DoesNotExist. Gt, and + Lt. + type: string + values: + description: 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. If the operator is Gt or + Lt, the values array must have a single + element, which will be interpreted as an + integer. This array is replaced during a + strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + x-kubernetes-map-type: atomic + weight: + description: Weight associated with matching the corresponding + nodeSelectorTerm, in the range 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by this + field are not met at scheduling time, the pod will not be + scheduled onto the node. If the affinity requirements specified + by this field cease to be met at some point during pod execution + (e.g. due to an update), the system may or may not try to + eventually evict the pod from its node. + properties: + nodeSelectorTerms: + description: Required. A list of node selector terms. + The terms are ORed. + items: + description: A null or empty node selector term matches + no objects. The requirements of them are ANDed. The + TopologySelectorTerm type implements a subset of the + NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists, DoesNotExist. Gt, and + Lt. + type: string + values: + description: 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. If the operator is Gt or + Lt, the values array must have a single + element, which will be interpreted as an + integer. This array is replaced during a + strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists, DoesNotExist. Gt, and + Lt. + type: string + values: + description: 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. If the operator is Gt or + Lt, the values array must have a single + element, which will be interpreted as an + integer. This array is replaced during a + strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + x-kubernetes-map-type: atomic + type: array + required: + - nodeSelectorTerms + type: object + x-kubernetes-map-type: atomic + type: object + nodeSelector: + additionalProperties: + type: string + description: 'NodeSelector is map of key-value pairs used to define + the nodes on which the pods can run. More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/' + type: object + podAntiAffinityType: + description: 'PodAntiAffinityType allows the user to decide whether + pod anti-affinity between cluster instance has to be considered + a strong requirement during scheduling or not. Allowed values + are: "preferred" (default if empty) or "required". Setting it + to "required", could lead to instances remaining pending until + new kubernetes nodes are added if all the existing nodes don''t + match the required pod anti-affinity rule. More info: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity' + type: string + tolerations: + description: 'Tolerations is a list of Tolerations that should + be set for all the pods, in order to allow them to run on tainted + nodes. More info: 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 + topologyKey: + description: TopologyKey to use for anti-affinity configuration. + See k8s documentation for more info on that + type: string + type: object + backup: + description: The configuration to be used for backups + properties: + barmanObjectStore: + description: The configuration for the barman-cloud tool suite + properties: + azureCredentials: + description: The credentials to use to upload data to Azure + Blob Storage + properties: + connectionString: + description: The connection string to be used + properties: + key: + description: The key to select + type: string + name: + description: Name of the referent. + type: string + required: + - key + - name + type: object + inheritFromAzureAD: + description: Use the Azure AD based authentication without + providing explicitly the keys. + type: boolean + storageAccount: + description: The storage account where to upload data + properties: + key: + description: The key to select + type: string + name: + description: Name of the referent. + type: string + required: + - key + - name + type: object + storageKey: + description: The storage account key to be used in conjunction + with the storage account name + properties: + key: + description: The key to select + type: string + name: + description: Name of the referent. + type: string + required: + - key + - name + type: object + storageSasToken: + description: A shared-access-signature to be used in conjunction + with the storage account name + properties: + key: + description: The key to select + type: string + name: + description: Name of the referent. + type: string + required: + - key + - name + type: object + type: object + data: + description: The configuration to be used to backup the data + files When not defined, base backups files will be stored + uncompressed and may be unencrypted in the object store, + according to the bucket default policy. + properties: + compression: + description: Compress a backup file (a tar file per tablespace) + while streaming it to the object store. Available options + are empty string (no compression, default), `gzip`, + `bzip2` or `snappy`. + enum: + - gzip + - bzip2 + - snappy + type: string + encryption: + description: Whenever to force the encryption of files + (if the bucket is not already configured for that). + Allowed options are empty string (use the bucket policy, + default), `AES256` and `aws:kms` + enum: + - AES256 + - aws:kms + type: string + immediateCheckpoint: + description: Control whether the I/O workload for the + backup initial checkpoint will be limited, according + to the `checkpoint_completion_target` setting on the + PostgreSQL server. If set to true, an immediate checkpoint + will be used, meaning PostgreSQL will complete the checkpoint + as soon as possible. `false` by default. + type: boolean + jobs: + description: The number of parallel jobs to be used to + upload the backup, defaults to 2 + format: int32 + minimum: 1 + type: integer + type: object + destinationPath: + description: The path where to store the backup (i.e. s3://bucket/path/to/folder) + this path, with different destination folders, will be used + for WALs and for data + minLength: 1 + type: string + endpointCA: + description: EndpointCA store the CA bundle of the barman + endpoint. Useful when using self-signed certificates to + avoid errors with certificate issuer and barman-cloud-wal-archive + properties: + key: + description: The key to select + type: string + name: + description: Name of the referent. + type: string + required: + - key + - name + type: object + endpointURL: + description: Endpoint to be used to upload data to the cloud, + overriding the automatic endpoint discovery + type: string + googleCredentials: + description: The credentials to use to upload data to Google + Cloud Storage + properties: + applicationCredentials: + description: The secret containing the Google Cloud Storage + JSON file with the credentials + properties: + key: + description: The key to select + type: string + name: + description: Name of the referent. + type: string + required: + - key + - name + type: object + gkeEnvironment: + description: If set to true, will presume that it's running + inside a GKE environment, default to false. + type: boolean + type: object + historyTags: + additionalProperties: + type: string + description: HistoryTags is a list of key value pairs that + will be passed to the Barman --history-tags option. + type: object + s3Credentials: + description: The credentials to use to upload data to S3 + properties: + accessKeyId: + description: The reference to the access key id + properties: + key: + description: The key to select + type: string + name: + description: Name of the referent. + type: string + required: + - key + - name + type: object + inheritFromIAMRole: + description: Use the role based authentication without + providing explicitly the keys. + type: boolean + region: + description: The reference to the secret containing the + region name + properties: + key: + description: The key to select + type: string + name: + description: Name of the referent. + type: string + required: + - key + - name + type: object + secretAccessKey: + description: The reference to the secret access key + properties: + key: + description: The key to select + type: string + name: + description: Name of the referent. + type: string + required: + - key + - name + type: object + sessionToken: + description: The references to the session key + properties: + key: + description: The key to select + type: string + name: + description: Name of the referent. + type: string + required: + - key + - name + type: object + type: object + serverName: + description: The server name on S3, the cluster name is used + if this parameter is omitted + type: string + tags: + additionalProperties: + type: string + description: Tags is a list of key value pairs that will be + passed to the Barman --tags option. + type: object + wal: + description: The configuration for the backup of the WAL stream. + When not defined, WAL files will be stored uncompressed + and may be unencrypted in the object store, according to + the bucket default policy. + properties: + compression: + description: Compress a WAL file before sending it to + the object store. Available options are empty string + (no compression, default), `gzip`, `bzip2` or `snappy`. + enum: + - gzip + - bzip2 + - snappy + type: string + encryption: + description: Whenever to force the encryption of files + (if the bucket is not already configured for that). + Allowed options are empty string (use the bucket policy, + default), `AES256` and `aws:kms` + enum: + - AES256 + - aws:kms + type: string + maxParallel: + description: Number of WAL files to be either archived + in parallel (when the PostgreSQL instance is archiving + to a backup object store) or restored in parallel (when + a PostgreSQL standby is fetching WAL files from a recovery + object store). If not specified, WAL files will be processed + one at a time. It accepts a positive integer as a value + - with 1 being the minimum accepted value. + minimum: 1 + type: integer + type: object + required: + - destinationPath + type: object + retentionPolicy: + description: RetentionPolicy is the retention policy to be used + for backups and WALs (i.e. '60d'). The retention policy is expressed + in the form of `XXu` where `XX` is a positive integer and `u` + is in `[dwm]` - days, weeks, months. It's currently only applicable + when using the BarmanObjectStore method. + pattern: ^[1-9][0-9]*[dwm]$ + type: string + target: + default: prefer-standby + description: The policy to decide which instance should perform + backups. Available options are empty string, which will default + to `prefer-standby` policy, `primary` to have backups run always + on primary instances, `prefer-standby` to have backups run preferably + on the most updated standby, if available. + enum: + - primary + - prefer-standby + type: string + volumeSnapshot: + description: VolumeSnapshot provides the configuration for the + execution of volume snapshot backups. + properties: + annotations: + additionalProperties: + type: string + description: Annotations key-value pairs that will be added + to .metadata.annotations snapshot resources. + type: object + className: + description: ClassName specifies the Snapshot Class to be + used for PG_DATA PersistentVolumeClaim. It is the default + class for the other types if no specific class is present + type: string + labels: + additionalProperties: + type: string + description: Labels are key-value pairs that will be added + to .metadata.labels snapshot resources. + type: object + online: + default: true + description: Whether the default type of backup with volume + snapshots is online/hot (`true`, default) or offline/cold + (`false`) + type: boolean + onlineConfiguration: + default: + immediateCheckpoint: false + waitForArchive: true + description: Configuration parameters to control the online/hot + backup with volume snapshots + properties: + immediateCheckpoint: + description: Control whether the I/O workload for the + backup initial checkpoint will be limited, according + to the `checkpoint_completion_target` setting on the + PostgreSQL server. If set to true, an immediate checkpoint + will be used, meaning PostgreSQL will complete the checkpoint + as soon as possible. `false` by default. + type: boolean + waitForArchive: + default: true + description: If false, the function will return immediately + after the backup is completed, without waiting for WAL + to be archived. This behavior is only useful with backup + software that independently monitors WAL archiving. + Otherwise, WAL required to make the backup consistent + might be missing and make the backup useless. By default, + or when this parameter is true, pg_backup_stop will + wait for WAL to be archived when archiving is enabled. + On a standby, this means that it will wait only when + archive_mode = always. If write activity on the primary + is low, it may be useful to run pg_switch_wal on the + primary in order to trigger an immediate segment switch. + type: boolean + type: object + snapshotOwnerReference: + default: none + description: SnapshotOwnerReference indicates the type of + owner reference the snapshot should have + enum: + - none + - cluster + - backup + type: string + walClassName: + description: WalClassName specifies the Snapshot Class to + be used for the PG_WAL PersistentVolumeClaim. + type: string + type: object + type: object + bootstrap: + description: Instructions to bootstrap this cluster + properties: + initdb: + description: Bootstrap the cluster via initdb + properties: + dataChecksums: + description: 'Whether the `-k` option should be passed to + initdb, enabling checksums on data pages (default: `false`)' + type: boolean + database: + description: 'Name of the database used by the application. + Default: `app`.' + type: string + encoding: + description: The value to be passed as option `--encoding` + for initdb (default:`UTF8`) + type: string + import: + description: Bootstraps the new cluster by importing data + from an existing PostgreSQL instance using logical backup + (`pg_dump` and `pg_restore`) + properties: + databases: + description: The databases to import + items: + type: string + type: array + postImportApplicationSQL: + description: List of SQL queries to be executed as a superuser + in the application database right after is imported + - to be used with extreme care (by default empty). Only + available in microservice type. + items: + type: string + type: array + roles: + description: The roles to import + items: + type: string + type: array + schemaOnly: + description: 'When set to true, only the `pre-data` and + `post-data` sections of `pg_restore` are invoked, avoiding + data import. Default: `false`.' + type: boolean + source: + description: The source of the import + properties: + externalCluster: + description: The name of the externalCluster used + for import + type: string + required: + - externalCluster + type: object + type: + description: The import type. Can be `microservice` or + `monolith`. + enum: + - microservice + - monolith + type: string + required: + - databases + - source + - type + type: object + localeCType: + description: The value to be passed as option `--lc-ctype` + for initdb (default:`C`) + type: string + localeCollate: + description: The value to be passed as option `--lc-collate` + for initdb (default:`C`) + type: string + options: + description: 'The list of options that must be passed to initdb + when creating the cluster. Deprecated: This could lead to + inconsistent configurations, please use the explicit provided + parameters instead. If defined, explicit values will be + ignored.' + items: + type: string + type: array + owner: + description: Name of the owner of the database in the instance + to be used by applications. Defaults to the value of the + `database` key. + type: string + postInitApplicationSQL: + description: List of SQL queries to be executed as a superuser + in the application database right after is created - to + be used with extreme care (by default empty) + items: + type: string + type: array + postInitApplicationSQLRefs: + description: PostInitApplicationSQLRefs points references + to ConfigMaps or Secrets which contain SQL files, the general + implementation order to these references is from all Secrets + to all ConfigMaps, and inside Secrets or ConfigMaps, the + implementation order is same as the order of each array + (by default empty) + properties: + configMapRefs: + description: ConfigMapRefs holds a list of references + to ConfigMaps + items: + description: ConfigMapKeySelector contains enough information + to let you locate the key of a ConfigMap + properties: + key: + description: The key to select + type: string + name: + description: Name of the referent. + type: string + required: + - key + - name + type: object + type: array + secretRefs: + description: SecretRefs holds a list of references to + Secrets + items: + description: SecretKeySelector contains enough information + to let you locate the key of a Secret + properties: + key: + description: The key to select + type: string + name: + description: Name of the referent. + type: string + required: + - key + - name + type: object + type: array + type: object + postInitSQL: + description: List of SQL queries to be executed as a superuser + immediately after the cluster has been created - to be used + with extreme care (by default empty) + items: + type: string + type: array + postInitTemplateSQL: + description: List of SQL queries to be executed as a superuser + in the `template1` after the cluster has been created - + to be used with extreme care (by default empty) + items: + type: string + type: array + secret: + description: Name of the secret containing the initial credentials + for the owner of the user database. If empty a new secret + will be created from scratch + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + walSegmentSize: + description: 'The value in megabytes (1 to 1024) to be passed + to the `--wal-segsize` option for initdb (default: empty, + resulting in PostgreSQL default: 16MB)' + maximum: 1024 + minimum: 1 + type: integer + type: object + pg_basebackup: + description: Bootstrap the cluster taking a physical backup of + another compatible PostgreSQL instance + properties: + database: + description: 'Name of the database used by the application. + Default: `app`.' + type: string + owner: + description: Name of the owner of the database in the instance + to be used by applications. Defaults to the value of the + `database` key. + type: string + secret: + description: Name of the secret containing the initial credentials + for the owner of the user database. If empty a new secret + will be created from scratch + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + source: + description: The name of the server of which we need to take + a physical backup + minLength: 1 + type: string + required: + - source + type: object + recovery: + description: Bootstrap the cluster from a backup + properties: + backup: + description: The backup object containing the physical base + backup from which to initiate the recovery procedure. Mutually + exclusive with `source` and `volumeSnapshots`. + properties: + endpointCA: + description: EndpointCA store the CA bundle of the barman + endpoint. Useful when using self-signed certificates + to avoid errors with certificate issuer and barman-cloud-wal-archive. + properties: + key: + description: The key to select + type: string + name: + description: Name of the referent. + type: string + required: + - key + - name + type: object + name: + description: Name of the referent. + type: string + required: + - name + type: object + database: + description: 'Name of the database used by the application. + Default: `app`.' + type: string + owner: + description: Name of the owner of the database in the instance + to be used by applications. Defaults to the value of the + `database` key. + type: string + recoveryTarget: + description: 'By default, the recovery process applies all + the available WAL files in the archive (full recovery). + However, you can also end the recovery as soon as a consistent + state is reached or recover to a point-in-time (PITR) by + specifying a `RecoveryTarget` object, as expected by PostgreSQL + (i.e., timestamp, transaction Id, LSN, ...). More info: + https://www.postgresql.org/docs/current/runtime-config-wal.html#RUNTIME-CONFIG-WAL-RECOVERY-TARGET' + properties: + backupID: + description: The ID of the backup from which to start + the recovery process. If empty (default) the operator + will automatically detect the backup based on targetTime + or targetLSN if specified. Otherwise use the latest + available backup in chronological order. + type: string + exclusive: + description: Set the target to be exclusive. If omitted, + defaults to false, so that in Postgres, `recovery_target_inclusive` + will be true + type: boolean + targetImmediate: + description: End recovery as soon as a consistent state + is reached + type: boolean + targetLSN: + description: The target LSN (Log Sequence Number) + type: string + targetName: + description: The target name (to be previously created + with `pg_create_restore_point`) + type: string + targetTLI: + description: The target timeline ("latest" or a positive + integer) + type: string + targetTime: + description: The target time as a timestamp in the RFC3339 + standard + type: string + targetXID: + description: The target transaction ID + type: string + type: object + secret: + description: Name of the secret containing the initial credentials + for the owner of the user database. If empty a new secret + will be created from scratch + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + source: + description: The external cluster whose backup we will restore. + This is also used as the name of the folder under which + the backup is stored, so it must be set to the name of the + source cluster Mutually exclusive with `backup`. + type: string + volumeSnapshots: + description: The static PVC data source(s) from which to initiate + the recovery procedure. Currently supporting `VolumeSnapshot` + and `PersistentVolumeClaim` resources that map an existing + PVC group, compatible with CloudNativePG, and taken with + a cold backup copy on a fenced Postgres instance (limitation + which will be removed in the future when online backup will + be implemented). Mutually exclusive with `backup`. + properties: + storage: + description: Configuration of the storage of the instances + properties: + apiGroup: + description: APIGroup is the group for the resource + being referenced. If APIGroup is not specified, + the specified Kind must be in the core API group. + For any other third-party types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource being referenced + type: string + name: + description: Name is the name of resource being referenced + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + walStorage: + description: Configuration of the storage for PostgreSQL + WAL (Write-Ahead Log) + properties: + apiGroup: + description: APIGroup is the group for the resource + being referenced. If APIGroup is not specified, + the specified Kind must be in the core API group. + For any other third-party types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource being referenced + type: string + name: + description: Name is the name of resource being referenced + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + required: + - storage + type: object + type: object + type: object + certificates: + description: The configuration for the CA and related certificates + properties: + clientCASecret: + description: 'The secret containing the Client CA certificate. + If not defined, a new secret will be created with a self-signed + CA and will be used to generate all the client certificates.

    Contains:

    - `ca.crt`: CA that should + be used to validate the client certificates, used as `ssl_ca_file` + of all the instances.
    - `ca.key`: key used to generate + client certificates, if ReplicationTLSSecret is provided, this + can be omitted.
    ' + type: string + replicationTLSSecret: + description: The secret of type kubernetes.io/tls containing the + client certificate to authenticate as the `streaming_replica` + user. If not defined, ClientCASecret must provide also `ca.key`, + and a new secret will be created using the provided CA. + type: string + serverAltDNSNames: + description: The list of the server alternative DNS names to be + added to the generated server TLS certificates, when required. + items: + type: string + type: array + serverCASecret: + description: 'The secret containing the Server CA certificate. + If not defined, a new secret will be created with a self-signed + CA and will be used to generate the TLS certificate ServerTLSSecret.

    Contains:

    - `ca.crt`: CA that should + be used to validate the server certificate, used as `sslrootcert` + in client connection strings.
    - `ca.key`: key used to + generate Server SSL certs, if ServerTLSSecret is provided, this + can be omitted.
    ' + type: string + serverTLSSecret: + description: The secret of type kubernetes.io/tls containing the + server TLS certificate and key that will be set as `ssl_cert_file` + and `ssl_key_file` so that clients can connect to postgres securely. + If not defined, ServerCASecret must provide also `ca.key` and + a new secret will be created using the provided CA. + type: string + type: object + description: + description: Description of this PostgreSQL cluster + type: string + enableSuperuserAccess: + default: false + description: When this option is enabled, the operator will use the + `SuperuserSecret` to update the `postgres` user password (if the + secret is not present, the operator will automatically create one). + When this option is disabled, the operator will ignore the `SuperuserSecret` + content, delete it when automatically created, and then blank the + password of the `postgres` user by setting it to `NULL`. Disabled + by default. + type: boolean + env: + description: Env follows the Env format to pass environment variables + to the pods created in the cluster + 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: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + envFrom: + description: EnvFrom follows the EnvFrom format to pass environment + variables sources to the pods to be used by Env + items: + description: EnvFromSource represents the source of a set of ConfigMaps + properties: + configMapRef: + description: The ConfigMap to select from + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + optional: + description: Specify whether the ConfigMap must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + description: An optional identifier to prepend to each key in + the ConfigMap. Must be a C_IDENTIFIER. + type: string + secretRef: + description: The Secret to select from + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + optional: + description: Specify whether the Secret must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + ephemeralVolumesSizeLimit: + description: EphemeralVolumesSizeLimit allows the user to set the + limits for the ephemeral volumes + properties: + shm: + anyOf: + - type: integer + - type: string + description: Shm is the size limit of the shared memory volume + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + temporaryData: + anyOf: + - type: integer + - type: string + description: TemporaryData is the size limit of the temporary + data volume + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + externalClusters: + description: The list of external clusters which are used in the configuration + items: + description: ExternalCluster represents the connection parameters + to an external cluster which is used in the other sections of + the configuration + properties: + barmanObjectStore: + description: The configuration for the barman-cloud tool suite + properties: + azureCredentials: + description: The credentials to use to upload data to Azure + Blob Storage + properties: + connectionString: + description: The connection string to be used + properties: + key: + description: The key to select + type: string + name: + description: Name of the referent. + type: string + required: + - key + - name + type: object + inheritFromAzureAD: + description: Use the Azure AD based authentication without + providing explicitly the keys. + type: boolean + storageAccount: + description: The storage account where to upload data + properties: + key: + description: The key to select + type: string + name: + description: Name of the referent. + type: string + required: + - key + - name + type: object + storageKey: + description: The storage account key to be used in conjunction + with the storage account name + properties: + key: + description: The key to select + type: string + name: + description: Name of the referent. + type: string + required: + - key + - name + type: object + storageSasToken: + description: A shared-access-signature to be used in + conjunction with the storage account name + properties: + key: + description: The key to select + type: string + name: + description: Name of the referent. + type: string + required: + - key + - name + type: object + type: object + data: + description: The configuration to be used to backup the + data files When not defined, base backups files will be + stored uncompressed and may be unencrypted in the object + store, according to the bucket default policy. + properties: + compression: + description: Compress a backup file (a tar file per + tablespace) while streaming it to the object store. + Available options are empty string (no compression, + default), `gzip`, `bzip2` or `snappy`. + enum: + - gzip + - bzip2 + - snappy + type: string + encryption: + description: Whenever to force the encryption of files + (if the bucket is not already configured for that). + Allowed options are empty string (use the bucket policy, + default), `AES256` and `aws:kms` + enum: + - AES256 + - aws:kms + type: string + immediateCheckpoint: + description: Control whether the I/O workload for the + backup initial checkpoint will be limited, according + to the `checkpoint_completion_target` setting on the + PostgreSQL server. If set to true, an immediate checkpoint + will be used, meaning PostgreSQL will complete the + checkpoint as soon as possible. `false` by default. + type: boolean + jobs: + description: The number of parallel jobs to be used + to upload the backup, defaults to 2 + format: int32 + minimum: 1 + type: integer + type: object + destinationPath: + description: The path where to store the backup (i.e. s3://bucket/path/to/folder) + this path, with different destination folders, will be + used for WALs and for data + minLength: 1 + type: string + endpointCA: + description: EndpointCA store the CA bundle of the barman + endpoint. Useful when using self-signed certificates to + avoid errors with certificate issuer and barman-cloud-wal-archive + properties: + key: + description: The key to select + type: string + name: + description: Name of the referent. + type: string + required: + - key + - name + type: object + endpointURL: + description: Endpoint to be used to upload data to the cloud, + overriding the automatic endpoint discovery + type: string + googleCredentials: + description: The credentials to use to upload data to Google + Cloud Storage + properties: + applicationCredentials: + description: The secret containing the Google Cloud + Storage JSON file with the credentials + properties: + key: + description: The key to select + type: string + name: + description: Name of the referent. + type: string + required: + - key + - name + type: object + gkeEnvironment: + description: If set to true, will presume that it's + running inside a GKE environment, default to false. + type: boolean + type: object + historyTags: + additionalProperties: + type: string + description: HistoryTags is a list of key value pairs that + will be passed to the Barman --history-tags option. + type: object + s3Credentials: + description: The credentials to use to upload data to S3 + properties: + accessKeyId: + description: The reference to the access key id + properties: + key: + description: The key to select + type: string + name: + description: Name of the referent. + type: string + required: + - key + - name + type: object + inheritFromIAMRole: + description: Use the role based authentication without + providing explicitly the keys. + type: boolean + region: + description: The reference to the secret containing + the region name + properties: + key: + description: The key to select + type: string + name: + description: Name of the referent. + type: string + required: + - key + - name + type: object + secretAccessKey: + description: The reference to the secret access key + properties: + key: + description: The key to select + type: string + name: + description: Name of the referent. + type: string + required: + - key + - name + type: object + sessionToken: + description: The references to the session key + properties: + key: + description: The key to select + type: string + name: + description: Name of the referent. + type: string + required: + - key + - name + type: object + type: object + serverName: + description: The server name on S3, the cluster name is + used if this parameter is omitted + type: string + tags: + additionalProperties: + type: string + description: Tags is a list of key value pairs that will + be passed to the Barman --tags option. + type: object + wal: + description: The configuration for the backup of the WAL + stream. When not defined, WAL files will be stored uncompressed + and may be unencrypted in the object store, according + to the bucket default policy. + properties: + compression: + description: Compress a WAL file before sending it to + the object store. Available options are empty string + (no compression, default), `gzip`, `bzip2` or `snappy`. + enum: + - gzip + - bzip2 + - snappy + type: string + encryption: + description: Whenever to force the encryption of files + (if the bucket is not already configured for that). + Allowed options are empty string (use the bucket policy, + default), `AES256` and `aws:kms` + enum: + - AES256 + - aws:kms + type: string + maxParallel: + description: Number of WAL files to be either archived + in parallel (when the PostgreSQL instance is archiving + to a backup object store) or restored in parallel + (when a PostgreSQL standby is fetching WAL files from + a recovery object store). If not specified, WAL files + will be processed one at a time. It accepts a positive + integer as a value - with 1 being the minimum accepted + value. + minimum: 1 + type: integer + type: object + required: + - destinationPath + type: object + connectionParameters: + additionalProperties: + type: string + description: The list of connection parameters, such as dbname, + host, username, etc + type: object + name: + description: The server name, required + type: string + password: + description: The reference to the password to be used to connect + to the server + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + sslCert: + description: The reference to an SSL certificate to be used + to connect to this instance + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + sslKey: + description: The reference to an SSL private key to be used + to connect to this instance + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + sslRootCert: + description: The reference to an SSL CA public key to be used + to connect to this instance + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + required: + - name + type: object + type: array + failoverDelay: + default: 0 + description: The amount of time (in seconds) to wait before triggering + a failover after the primary PostgreSQL instance in the cluster + was detected to be unhealthy + format: int32 + type: integer + imageName: + description: Name of the container image, supporting both tags (`:`) + and digests for deterministic and repeatable deployments (`:@sha256:`) + type: string + imagePullPolicy: + description: 'Image pull policy. One of `Always`, `Never` or `IfNotPresent`. + If not defined, it defaults to `IfNotPresent`. Cannot be updated. + More info: https://kubernetes.io/docs/concepts/containers/images#updating-images' + type: string + imagePullSecrets: + description: The list of pull secrets to be used to pull the images + items: + description: LocalObjectReference contains enough information to + let you locate a local object with a known type inside the same + namespace + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + type: array + inheritedMetadata: + description: Metadata that will be inherited by all objects related + to the Cluster + properties: + annotations: + additionalProperties: + type: string + type: object + labels: + additionalProperties: + type: string + type: object + type: object + instances: + default: 1 + description: Number of instances required in the cluster + minimum: 1 + type: integer + logLevel: + default: info + description: 'The instances'' log level, one of the following values: + error, warning, info (default), debug, trace' + enum: + - error + - warning + - info + - debug + - trace + type: string + managed: + description: The configuration that is used by the portions of PostgreSQL + that are managed by the instance manager + properties: + roles: + description: Database roles managed by the `Cluster` + items: + description: "RoleConfiguration is the representation, in Kubernetes, + of a PostgreSQL role with the additional field Ensure specifying + whether to ensure the presence or absence of the role in the + database \n The defaults of the CREATE ROLE command are applied + Reference: https://www.postgresql.org/docs/current/sql-createrole.html" + properties: + bypassrls: + description: Whether a role bypasses every row-level security + (RLS) policy. Default is `false`. + type: boolean + comment: + description: Description of the role + type: string + connectionLimit: + default: -1 + description: If the role can log in, this specifies how + many concurrent connections the role can make. `-1` (the + default) means no limit. + format: int64 + type: integer + createdb: + description: When set to `true`, the role being defined + will be allowed to create new databases. Specifying `false` + (default) will deny a role the ability to create databases. + type: boolean + createrole: + description: Whether the role will be permitted to create, + alter, drop, comment on, change the security label for, + and grant or revoke membership in other roles. Default + is `false`. + type: boolean + disablePassword: + description: DisablePassword indicates that a role's password + should be set to NULL in Postgres + type: boolean + ensure: + default: present + description: Ensure the role is `present` or `absent` - + defaults to "present" + enum: + - present + - absent + type: string + inRoles: + description: List of one or more existing roles to which + this role will be immediately added as a new member. Default + empty. + items: + type: string + type: array + inherit: + default: true + description: Whether a role "inherits" the privileges of + roles it is a member of. Defaults is `true`. + type: boolean + login: + description: Whether the role is allowed to log in. A role + having the `login` attribute can be thought of as a user. + Roles without this attribute are useful for managing database + privileges, but are not users in the usual sense of the + word. Default is `false`. + type: boolean + name: + description: Name of the role + type: string + passwordSecret: + description: Secret containing the password of the role + (if present) If null, the password will be ignored unless + DisablePassword is set + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + replication: + description: Whether a role is a replication role. A role + must have this attribute (or be a superuser) in order + to be able to connect to the server in replication mode + (physical or logical replication) and in order to be able + to create or drop replication slots. A role having the + `replication` attribute is a very highly privileged role, + and should only be used on roles actually used for replication. + Default is `false`. + type: boolean + superuser: + description: Whether the role is a `superuser` who can override + all access restrictions within the database - superuser + status is dangerous and should be used only when really + needed. You must yourself be a superuser to create a new + superuser. Defaults is `false`. + type: boolean + validUntil: + description: Date and time after which the role's password + is no longer valid. When omitted, the password will never + expire (default). + format: date-time + type: string + required: + - name + type: object + type: array + type: object + maxSyncReplicas: + default: 0 + description: The target value for the synchronous replication quorum, + that can be decreased if the number of ready standbys is lower than + this. Undefined or 0 disable synchronous replication. + minimum: 0 + type: integer + minSyncReplicas: + default: 0 + description: Minimum number of instances required in synchronous replication + with the primary. Undefined or 0 allow writes to complete when no + standby is available. + minimum: 0 + type: integer + monitoring: + description: The configuration of the monitoring infrastructure of + this cluster + properties: + customQueriesConfigMap: + description: The list of config maps containing the custom queries + items: + description: ConfigMapKeySelector contains enough information + to let you locate the key of a ConfigMap + properties: + key: + description: The key to select + type: string + name: + description: Name of the referent. + type: string + required: + - key + - name + type: object + type: array + customQueriesSecret: + description: The list of secrets containing the custom queries + items: + description: SecretKeySelector contains enough information to + let you locate the key of a Secret + properties: + key: + description: The key to select + type: string + name: + description: Name of the referent. + type: string + required: + - key + - name + type: object + type: array + disableDefaultQueries: + default: false + description: 'Whether the default queries should be injected. + Set it to `true` if you don''t want to inject default queries + into the cluster. Default: false.' + type: boolean + enablePodMonitor: + default: false + description: Enable or disable the `PodMonitor` + type: boolean + type: object + nodeMaintenanceWindow: + description: Define a maintenance window for the Kubernetes nodes + properties: + inProgress: + default: false + description: Is there a node maintenance activity in progress? + type: boolean + reusePVC: + default: true + description: Reuse the existing PVC (wait for the node to come + up again) or not (recreate it elsewhere - when `instances` >1) + type: boolean + type: object + postgresGID: + default: 26 + description: The GID of the `postgres` user inside the image, defaults + to `26` + format: int64 + type: integer + postgresUID: + default: 26 + description: The UID of the `postgres` user inside the image, defaults + to `26` + format: int64 + type: integer + postgresql: + description: Configuration of the PostgreSQL server + properties: + ldap: + description: Options to specify LDAP configuration + properties: + bindAsAuth: + description: Bind as authentication configuration + properties: + prefix: + description: Prefix for the bind authentication option + type: string + suffix: + description: Suffix for the bind authentication option + type: string + type: object + bindSearchAuth: + description: Bind+Search authentication configuration + properties: + baseDN: + description: Root DN to begin the user search + type: string + bindDN: + description: DN of the user to bind to the directory + type: string + bindPassword: + description: Secret with the password for the user to + bind to the directory + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + 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 + searchAttribute: + description: Attribute to match against the username + type: string + searchFilter: + description: Search filter to use when doing the search+bind + authentication + type: string + type: object + port: + description: LDAP server port + type: integer + scheme: + description: LDAP schema to be used, possible options are + `ldap` and `ldaps` + enum: + - ldap + - ldaps + type: string + server: + description: LDAP hostname or IP address + type: string + tls: + description: Set to 'true' to enable LDAP over TLS. 'false' + is default + type: boolean + type: object + parameters: + additionalProperties: + type: string + description: PostgreSQL configuration options (postgresql.conf) + type: object + pg_hba: + description: PostgreSQL Host Based Authentication rules (lines + to be appended to the pg_hba.conf file) + items: + type: string + type: array + promotionTimeout: + description: Specifies the maximum number of seconds to wait when + promoting an instance to primary. Default value is 40000000, + greater than one year in seconds, big enough to simulate an + infinite timeout + format: int32 + type: integer + shared_preload_libraries: + description: Lists of shared preload libraries to add to the default + ones + items: + type: string + type: array + syncReplicaElectionConstraint: + description: Requirements to be met by sync replicas. This will + affect how the "synchronous_standby_names" parameter will be + set up. + properties: + enabled: + description: This flag enables the constraints for sync replicas + type: boolean + nodeLabelsAntiAffinity: + description: A list of node labels values to extract and compare + to evaluate if the pods reside in the same topology or not + items: + type: string + type: array + required: + - enabled + type: object + type: object + primaryUpdateMethod: + default: restart + description: 'Method to follow to upgrade the primary server during + a rolling update procedure, after all replicas have been successfully + updated: it can be with a switchover (`switchover`) or in-place + (`restart` - default)' + enum: + - switchover + - restart + type: string + primaryUpdateStrategy: + default: unsupervised + description: 'Deployment strategy to follow to upgrade the primary + server during a rolling update procedure, after all replicas have + been successfully updated: it can be automated (`unsupervised` - + default) or manual (`supervised`)' + enum: + - unsupervised + - supervised + type: string + priorityClassName: + description: Name of the priority class which will be used in every + generated Pod, if the PriorityClass specified does not exist, the + pod will not be able to schedule. Please refer to https://kubernetes.io/docs/concepts/scheduling-eviction/pod-priority-preemption/#priorityclass + for more information + type: string + projectedVolumeTemplate: + description: Template to be used to define projected volumes, projected + volumes will be mounted under `/projected` base folder + properties: + defaultMode: + description: defaultMode are the mode bits used to set permissions + on created files by default. Must be an octal value between + 0000 and 0777 or a decimal value between 0 and 511. YAML accepts + both octal and decimal values, JSON requires decimal values + for mode bits. Directories within the path are not affected + by this setting. This might be in conflict with other options + that affect the file mode, like fsGroup, and the result can + be other mode bits set. + format: int32 + type: integer + sources: + description: sources is the list of volume projections + items: + description: Projection that may be projected along with other + supported volume types + properties: + configMap: + description: configMap information about the configMap data + to project + properties: + items: + description: items if unspecified, each key-value pair + in the Data field of the referenced ConfigMap will + be projected into the volume as a file whose name + is the key and content is the value. If specified, + the listed keys will be projected into the specified + paths, and unlisted keys will not be present. If a + key is specified which is not present in the ConfigMap, + the volume setup will error unless it is marked optional. + Paths must be relative and may not contain the '..' + path or start with '..'. + items: + description: Maps a string key to a path within a + volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: mode bits used + to set permissions on this file. Must be an + octal value between 0000 and 0777 or a decimal + value between 0 and 511. YAML accepts both octal + and decimal values, JSON requires decimal values + for mode bits. If not specified, the volume + defaultMode will be used. This might be in conflict + with other options that affect the file mode, + like fsGroup, and the result can be other mode + bits set.' + format: int32 + type: integer + path: + description: path is the relative path of the + file to map the key to. May not be an absolute + path. May not contain the path element '..'. + May not start with the string '..'. + type: string + required: + - key + - path + type: object + type: array + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + optional: + description: optional specify whether the ConfigMap + or its keys must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + downwardAPI: + description: downwardAPI information about the downwardAPI + data to project + properties: + items: + description: Items is a list of DownwardAPIVolume file + items: + description: DownwardAPIVolumeFile represents information + to create the file containing the pod field + properties: + fieldRef: + description: 'Required: Selects a field of the + pod: only annotations, labels, name and namespace + are supported.' + 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 + mode: + description: 'Optional: mode bits used to set + permissions on this file, must be an octal value + between 0000 and 0777 or a decimal value between + 0 and 511. YAML accepts both octal and decimal + values, JSON requires decimal values for mode + bits. If not specified, the volume defaultMode + will be used. This might be in conflict with + other options that affect the file mode, like + fsGroup, and the result can be other mode bits + set.' + format: int32 + type: integer + path: + description: 'Required: Path is the relative + path name of the file to be created. Must not + be absolute or contain the ''..'' path. Must + be utf-8 encoded. The first item of the relative + path must not start with ''..''' + type: string + resourceFieldRef: + description: 'Selects a resource of the container: + only resources limits and requests (limits.cpu, + limits.memory, requests.cpu and requests.memory) + 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 + required: + - path + type: object + type: array + type: object + secret: + description: secret information about the secret data to + project + properties: + items: + description: items if unspecified, each key-value pair + in the Data field of the referenced Secret will be + projected into the volume as a file whose name is + the key and content is the value. If specified, the + listed keys will be projected into the specified paths, + and unlisted keys will not be present. If a key is + specified which is not present in the Secret, the + volume setup will error unless it is marked optional. + Paths must be relative and may not contain the '..' + path or start with '..'. + items: + description: Maps a string key to a path within a + volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: mode bits used + to set permissions on this file. Must be an + octal value between 0000 and 0777 or a decimal + value between 0 and 511. YAML accepts both octal + and decimal values, JSON requires decimal values + for mode bits. If not specified, the volume + defaultMode will be used. This might be in conflict + with other options that affect the file mode, + like fsGroup, and the result can be other mode + bits set.' + format: int32 + type: integer + path: + description: path is the relative path of the + file to map the key to. May not be an absolute + path. May not contain the path element '..'. + May not start with the string '..'. + type: string + required: + - key + - path + type: object + type: array + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + optional: + description: optional field specify whether the Secret + or its key must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + serviceAccountToken: + description: serviceAccountToken is information about the + serviceAccountToken data to project + properties: + audience: + description: audience is the intended audience of the + token. A recipient of a token must identify itself + with an identifier specified in the audience of the + token, and otherwise should reject the token. The + audience defaults to the identifier of the apiserver. + type: string + expirationSeconds: + description: expirationSeconds is the requested duration + of validity of the service account token. As the token + approaches expiration, the kubelet volume plugin will + proactively rotate the service account token. The + kubelet will start trying to rotate the token if the + token is older than 80 percent of its time to live + or if the token is older than 24 hours.Defaults to + 1 hour and must be at least 10 minutes. + format: int64 + type: integer + path: + description: path is the path relative to the mount + point of the file to project the token into. + type: string + required: + - path + type: object + type: object + type: array + type: object + replica: + description: Replica cluster configuration + properties: + enabled: + description: If replica mode is enabled, this cluster will be + a replica of an existing cluster. Replica cluster can be created + from a recovery object store or via streaming through pg_basebackup. + Refer to the Replica clusters page of the documentation for + more information. + type: boolean + source: + description: The name of the external cluster which is the replication + origin + minLength: 1 + type: string + required: + - enabled + - source + type: object + replicationSlots: + default: + highAvailability: + enabled: true + description: Replication slots management configuration + properties: + highAvailability: + default: + enabled: true + description: Replication slots for high availability configuration + properties: + enabled: + default: true + description: If enabled (default), the operator will automatically + manage replication slots on the primary instance and use + them in streaming replication connections with all the standby + instances that are part of the HA cluster. If disabled, + the operator will not take advantage of replication slots + in streaming connections with the replicas. This feature + also controls replication slots in replica cluster, from + the designated primary to its cascading replicas. + type: boolean + slotPrefix: + default: _cnpg_ + description: Prefix for replication slots managed by the operator + for HA. It may only contain lower case letters, numbers, + and the underscore character. This can only be set at creation + time. By default set to `_cnpg_`. + pattern: ^[0-9a-z_]*$ + type: string + type: object + updateInterval: + default: 30 + description: Standby will update the status of the local replication + slots every `updateInterval` seconds (default 30). + minimum: 1 + type: integer + type: object + resources: + description: Resources requirements of every generated Pod. Please + refer to https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + for more information. + properties: + claims: + description: "Claims lists the names of resources, defined in + spec.resourceClaims, that are used by this container. \n This + is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n 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 + 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 + schedulerName: + description: 'If specified, the pod will be dispatched by specified + Kubernetes scheduler. If not specified, the pod will be dispatched + by the default scheduler. More info: https://kubernetes.io/docs/concepts/scheduling-eviction/kube-scheduler/' + type: string + seccompProfile: + description: 'The SeccompProfile applied to every Pod and Container. + Defaults to: `RuntimeDefault`' + properties: + localhostProfile: + description: localhostProfile indicates a profile defined in a + file on the node should be used. The profile must be preconfigured + on the node to work. Must be a descending path, relative to + the kubelet's configured seccomp profile location. Must be set + if type is "Localhost". Must NOT be set for any other type. + type: string + type: + description: "type indicates which kind of seccomp profile will + be applied. Valid options are: \n Localhost - a profile defined + in a file on the node should be used. RuntimeDefault - the container + runtime default profile should be used. Unconfined - no profile + should be applied." + type: string + required: + - type + type: object + serviceAccountTemplate: + description: Configure the generation of the service account + properties: + metadata: + description: Metadata are the metadata to be used for the generated + service account + properties: + annotations: + additionalProperties: + type: string + description: 'Annotations is an unstructured key value map + stored with a resource that may be set by external tools + to store and retrieve arbitrary metadata. They are not queryable + and should be preserved when modifying objects. More info: + http://kubernetes.io/docs/user-guide/annotations' + type: object + labels: + additionalProperties: + type: string + description: 'Map of string keys and values that can be used + to organize and categorize (scope and select) objects. May + match selectors of replication controllers and services. + More info: http://kubernetes.io/docs/user-guide/labels' + type: object + type: object + required: + - metadata + type: object + smartShutdownTimeout: + default: 180 + description: 'The time in seconds that controls the window of time + reserved for the smart shutdown of Postgres to complete. Make sure + you reserve enough time for the operator to request a fast shutdown + of Postgres (that is: `stopDelay` - `smartShutdownTimeout`).' + format: int32 + type: integer + startDelay: + default: 3600 + description: 'The time in seconds that is allowed for a PostgreSQL + instance to successfully start up (default 3600). The startup probe + failure threshold is derived from this value using the formula: + ceiling(startDelay / 10).' + format: int32 + type: integer + stopDelay: + default: 1800 + description: The time in seconds that is allowed for a PostgreSQL + instance to gracefully shutdown (default 1800) + format: int32 + type: integer + storage: + description: Configuration of the storage of the instances + properties: + pvcTemplate: + description: Template to be used to generate the Persistent Volume + Claim + properties: + accessModes: + description: 'accessModes contains the desired access modes + the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' + items: + type: string + type: array + dataSource: + description: 'dataSource field can be used to specify either: + * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) + * An existing PVC (PersistentVolumeClaim) If the provisioner + or an external controller can support the specified data + source, it will create a new volume based on the contents + of the specified data source. When the AnyVolumeDataSource + feature gate is enabled, dataSource contents will be copied + to dataSourceRef, and dataSourceRef contents will be copied + to dataSource when dataSourceRef.namespace is not specified. + If the namespace is specified, then dataSourceRef will not + be copied to dataSource.' + properties: + apiGroup: + description: APIGroup is the group for the resource being + referenced. If APIGroup is not specified, the specified + Kind must be in the core API group. For any other third-party + types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource being referenced + type: string + name: + description: Name is the name of resource being referenced + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + description: 'dataSourceRef specifies the object from which + to populate the volume with data, if a non-empty volume + is desired. This may be any object from a non-empty API + group (non core object) or a PersistentVolumeClaim object. + When this field is specified, volume binding will only succeed + if the type of the specified object matches some installed + volume populator or dynamic provisioner. This field will + replace the functionality of the dataSource field and as + such if both fields are non-empty, they must have the same + value. For backwards compatibility, when namespace isn''t + specified in dataSourceRef, both fields (dataSource and + dataSourceRef) will be set to the same value automatically + if one of them is empty and the other is non-empty. When + namespace is specified in dataSourceRef, dataSource isn''t + set to the same value and must be empty. There are three + important differences between dataSource and dataSourceRef: + * While dataSource only allows two specific types of objects, + dataSourceRef allows any non-core object, as well as PersistentVolumeClaim + objects. * While dataSource ignores disallowed values (dropping + them), dataSourceRef preserves all values, and generates + an error if a disallowed value is specified. * While dataSource + only allows local objects, dataSourceRef allows objects + in any namespaces. (Beta) Using this field requires the + AnyVolumeDataSource feature gate to be enabled. (Alpha) + Using the namespace field of dataSourceRef requires the + CrossNamespaceVolumeDataSource feature gate to be enabled.' + properties: + apiGroup: + description: APIGroup is the group for the resource being + referenced. If APIGroup is not specified, the specified + Kind must be in the core API group. For any other third-party + types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource being referenced + type: string + name: + description: Name is the name of resource being referenced + type: string + namespace: + description: Namespace is the namespace of resource being + referenced Note that when a namespace is specified, + a gateway.networking.k8s.io/ReferenceGrant object is + required in the referent namespace to allow that namespace's + owner to accept the reference. See the ReferenceGrant + documentation for details. (Alpha) This field requires + the CrossNamespaceVolumeDataSource feature gate to be + enabled. + type: string + required: + - kind + - name + type: object + resources: + description: 'resources represents the minimum resources the + volume should have. If RecoverVolumeExpansionFailure feature + is enabled users are allowed to specify resource requirements + that are lower than previous value but must still be higher + than capacity recorded in the status field of the claim. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. \n 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 + 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 + selector: + description: selector is a label query over volumes to consider + for binding. + 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 + required: + - key + - operator + type: object + type: array + 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 + storageClassName: + description: 'storageClassName is the name of the StorageClass + required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' + type: string + volumeMode: + description: volumeMode defines what type of volume is required + by the claim. Value of Filesystem is implied when not included + in claim spec. + type: string + volumeName: + description: volumeName is the binding reference to the PersistentVolume + backing this claim. + type: string + type: object + resizeInUseVolumes: + default: true + description: Resize existent PVCs, defaults to true + type: boolean + size: + description: Size of the storage. Required if not already specified + in the PVC template. Changes to this field are automatically + reapplied to the created PVCs. Size cannot be decreased. + type: string + storageClass: + description: StorageClass to use for database data (`PGDATA`). + Applied after evaluating the PVC template, if available. If + not specified, generated PVCs will be satisfied by the default + storage class + type: string + type: object + superuserSecret: + description: The secret containing the superuser password. If not + defined a new secret will be created with a randomly generated password + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + switchoverDelay: + default: 3600 + description: The time in seconds that is allowed for a primary PostgreSQL + instance to gracefully shutdown during a switchover. Default value + is 3600 seconds (1 hour). + format: int32 + type: integer + topologySpreadConstraints: + description: 'TopologySpreadConstraints specifies how to spread matching + pods among the given topology. More info: https://kubernetes.io/docs/concepts/scheduling-eviction/topology-spread-constraints/' + 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 + required: + - key + - operator + type: object + type: array + 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. Keys that don't exist + in the incoming pod labels will be ignored. A null or empty + list means only match against labelSelector. \n This is a + beta field and requires the MatchLabelKeysInPodTopologySpread + feature gate to be enabled (enabled by default)." + 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. For example, in a 3-zone cluster, + MaxSkew is set to 1, and pods with the same labelSelector + spread as 2/2/1: In this case, the global minimum is 1. | + zone1 | zone2 | zone3 | | P P | P P | P | - if MaxSkew + is 1, incoming pod can only be scheduled to zone3 to become + 2/2/2; scheduling it onto zone1(zone2) would make the ActualSkew(3-1) + on zone1(zone2) violate MaxSkew(1). - if MaxSkew is 2, incoming + pod can be scheduled onto any zone. When `whenUnsatisfiable=ScheduleAnyway`, + it is used to give higher precedence to topologies that satisfy + it. It''s a required field. Default value is 1 and 0 is not + allowed.' + 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. As a result, when + the number of eligible domains is less than minDomains, scheduler + won't schedule more than maxSkew Pods to those domains. If + value is nil, the constraint behaves as if MinDomains is equal + to 1. Valid values are integers greater than 0. When value + is not nil, WhenUnsatisfiable must be DoNotSchedule. \n For + example, in a 3-zone cluster, MaxSkew is set to 2, MinDomains + is set to 5 and pods with the same labelSelector spread as + 2/2/2: | zone1 | zone2 | zone3 | | P P | P P | P P | + The number of domains is less than 5(MinDomains), so \"global + minimum\" is treated as 0. In this situation, new pod with + the same labelSelector cannot be scheduled, because computed + skew will be 3(3 - 0) if new Pod is scheduled to any of the + three zones, it will violate MaxSkew. \n This is a beta field + and requires the MinDomainsInPodTopologySpread feature gate + to be enabled (enabled by default)." + 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. \n + 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. + \n 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.io/hostname", + each Node is a domain of that topology. And, if TopologyKey + is "topology.kubernetes.io/zone", each zone is a domain of + that topology. It's a required field. + 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. For + example, in a 3-zone cluster, MaxSkew is set to 1, and pods + with the same labelSelector spread as 3/1/1: | zone1 | zone2 + | zone3 | | P P P | P | P | If WhenUnsatisfiable is + set to DoNotSchedule, incoming pod can only be scheduled to + zone2(zone3) to become 3/2/1(3/1/2) as ActualSkew(2-1) on + zone2(zone3) satisfies MaxSkew(1). In other words, the cluster + can still be imbalanced, but scheduler won''t make it *more* + imbalanced. It''s a required field.' + type: string + required: + - maxSkew + - topologyKey + - whenUnsatisfiable + type: object + type: array + walStorage: + description: Configuration of the storage for PostgreSQL WAL (Write-Ahead + Log) + properties: + pvcTemplate: + description: Template to be used to generate the Persistent Volume + Claim + properties: + accessModes: + description: 'accessModes contains the desired access modes + the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' + items: + type: string + type: array + dataSource: + description: 'dataSource field can be used to specify either: + * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) + * An existing PVC (PersistentVolumeClaim) If the provisioner + or an external controller can support the specified data + source, it will create a new volume based on the contents + of the specified data source. When the AnyVolumeDataSource + feature gate is enabled, dataSource contents will be copied + to dataSourceRef, and dataSourceRef contents will be copied + to dataSource when dataSourceRef.namespace is not specified. + If the namespace is specified, then dataSourceRef will not + be copied to dataSource.' + properties: + apiGroup: + description: APIGroup is the group for the resource being + referenced. If APIGroup is not specified, the specified + Kind must be in the core API group. For any other third-party + types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource being referenced + type: string + name: + description: Name is the name of resource being referenced + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + description: 'dataSourceRef specifies the object from which + to populate the volume with data, if a non-empty volume + is desired. This may be any object from a non-empty API + group (non core object) or a PersistentVolumeClaim object. + When this field is specified, volume binding will only succeed + if the type of the specified object matches some installed + volume populator or dynamic provisioner. This field will + replace the functionality of the dataSource field and as + such if both fields are non-empty, they must have the same + value. For backwards compatibility, when namespace isn''t + specified in dataSourceRef, both fields (dataSource and + dataSourceRef) will be set to the same value automatically + if one of them is empty and the other is non-empty. When + namespace is specified in dataSourceRef, dataSource isn''t + set to the same value and must be empty. There are three + important differences between dataSource and dataSourceRef: + * While dataSource only allows two specific types of objects, + dataSourceRef allows any non-core object, as well as PersistentVolumeClaim + objects. * While dataSource ignores disallowed values (dropping + them), dataSourceRef preserves all values, and generates + an error if a disallowed value is specified. * While dataSource + only allows local objects, dataSourceRef allows objects + in any namespaces. (Beta) Using this field requires the + AnyVolumeDataSource feature gate to be enabled. (Alpha) + Using the namespace field of dataSourceRef requires the + CrossNamespaceVolumeDataSource feature gate to be enabled.' + properties: + apiGroup: + description: APIGroup is the group for the resource being + referenced. If APIGroup is not specified, the specified + Kind must be in the core API group. For any other third-party + types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource being referenced + type: string + name: + description: Name is the name of resource being referenced + type: string + namespace: + description: Namespace is the namespace of resource being + referenced Note that when a namespace is specified, + a gateway.networking.k8s.io/ReferenceGrant object is + required in the referent namespace to allow that namespace's + owner to accept the reference. See the ReferenceGrant + documentation for details. (Alpha) This field requires + the CrossNamespaceVolumeDataSource feature gate to be + enabled. + type: string + required: + - kind + - name + type: object + resources: + description: 'resources represents the minimum resources the + volume should have. If RecoverVolumeExpansionFailure feature + is enabled users are allowed to specify resource requirements + that are lower than previous value but must still be higher + than capacity recorded in the status field of the claim. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. \n 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 + 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 + selector: + description: selector is a label query over volumes to consider + for binding. + 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 + required: + - key + - operator + type: object + type: array + 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 + storageClassName: + description: 'storageClassName is the name of the StorageClass + required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' + type: string + volumeMode: + description: volumeMode defines what type of volume is required + by the claim. Value of Filesystem is implied when not included + in claim spec. + type: string + volumeName: + description: volumeName is the binding reference to the PersistentVolume + backing this claim. + type: string + type: object + resizeInUseVolumes: + default: true + description: Resize existent PVCs, defaults to true + type: boolean + size: + description: Size of the storage. Required if not already specified + in the PVC template. Changes to this field are automatically + reapplied to the created PVCs. Size cannot be decreased. + type: string + storageClass: + description: StorageClass to use for database data (`PGDATA`). + Applied after evaluating the PVC template, if available. If + not specified, generated PVCs will be satisfied by the default + storage class + type: string + type: object + required: + - instances + type: object + status: + description: 'Most recently observed status of the cluster. This data + may not be up to date. Populated by the system. Read-only. More info: + https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status' + properties: + azurePVCUpdateEnabled: + description: AzurePVCUpdateEnabled shows if the PVC online upgrade + is enabled for this cluster + type: boolean + certificates: + description: The configuration for the CA and related certificates, + initialized with defaults. + properties: + clientCASecret: + description: 'The secret containing the Client CA certificate. + If not defined, a new secret will be created with a self-signed + CA and will be used to generate all the client certificates.

    Contains:

    - `ca.crt`: CA that should + be used to validate the client certificates, used as `ssl_ca_file` + of all the instances.
    - `ca.key`: key used to generate + client certificates, if ReplicationTLSSecret is provided, this + can be omitted.
    ' + type: string + expirations: + additionalProperties: + type: string + description: Expiration dates for all certificates. + type: object + replicationTLSSecret: + description: The secret of type kubernetes.io/tls containing the + client certificate to authenticate as the `streaming_replica` + user. If not defined, ClientCASecret must provide also `ca.key`, + and a new secret will be created using the provided CA. + type: string + serverAltDNSNames: + description: The list of the server alternative DNS names to be + added to the generated server TLS certificates, when required. + items: + type: string + type: array + serverCASecret: + description: 'The secret containing the Server CA certificate. + If not defined, a new secret will be created with a self-signed + CA and will be used to generate the TLS certificate ServerTLSSecret.

    Contains:

    - `ca.crt`: CA that should + be used to validate the server certificate, used as `sslrootcert` + in client connection strings.
    - `ca.key`: key used to + generate Server SSL certs, if ServerTLSSecret is provided, this + can be omitted.
    ' + type: string + serverTLSSecret: + description: The secret of type kubernetes.io/tls containing the + server TLS certificate and key that will be set as `ssl_cert_file` + and `ssl_key_file` so that clients can connect to postgres securely. + If not defined, ServerCASecret must provide also `ca.key` and + a new secret will be created using the provided CA. + type: string + type: object + cloudNativePGCommitHash: + description: The commit hash number of which this operator running + type: string + cloudNativePGOperatorHash: + description: The hash of the binary of the operator + type: string + conditions: + description: Conditions for cluster object + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + \n type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + 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 + configMapResourceVersion: + description: The list of resource versions of the configmaps, managed + by the operator. Every change here is done in the interest of the + instance manager, which will refresh the configmap data + properties: + metrics: + additionalProperties: + type: string + description: A map with the versions of all the config maps used + to pass metrics. Map keys are the config map names, map values + are the versions + type: object + type: object + currentPrimary: + description: Current primary instance + type: string + currentPrimaryFailingSinceTimestamp: + description: The timestamp when the primary was detected to be unhealthy + This field is reported when spec.failoverDelay is populated or during + online upgrades + type: string + currentPrimaryTimestamp: + description: The timestamp when the last actual promotion to primary + has occurred + type: string + danglingPVC: + description: List of all the PVCs created by this cluster and still + available which are not attached to a Pod + items: + type: string + type: array + firstRecoverabilityPoint: + description: The first recoverability point, stored as a date in RFC3339 + format + type: string + healthyPVC: + description: List of all the PVCs not dangling nor initializing + items: + type: string + type: array + initializingPVC: + description: List of all the PVCs that are being initialized by this + cluster + items: + type: string + type: array + instanceNames: + description: List of instance names in the cluster + items: + type: string + type: array + instances: + description: The total number of PVC Groups detected in the cluster. + It may differ from the number of existing instance pods. + type: integer + instancesReportedState: + additionalProperties: + description: InstanceReportedState describes the last reported state + of an instance during a reconciliation loop + properties: + isPrimary: + description: indicates if an instance is the primary one + type: boolean + timeLineID: + description: indicates on which TimelineId the instance is + type: integer + required: + - isPrimary + type: object + description: The reported state of the instances during the last reconciliation + loop + type: object + instancesStatus: + additionalProperties: + items: + type: string + type: array + description: InstancesStatus indicates in which status the instances + are + type: object + jobCount: + description: How many Jobs have been created by this cluster + format: int32 + type: integer + lastFailedBackup: + description: Stored as a date in RFC3339 format + type: string + lastSuccessfulBackup: + description: Stored as a date in RFC3339 format + type: string + latestGeneratedNode: + description: ID of the latest generated node (used to avoid node name + clashing) + type: integer + managedRolesStatus: + description: ManagedRolesStatus reports the state of the managed roles + in the cluster + properties: + byStatus: + additionalProperties: + items: + type: string + type: array + description: ByStatus gives the list of roles in each state + type: object + cannotReconcile: + additionalProperties: + items: + type: string + type: array + description: CannotReconcile lists roles that cannot be reconciled + in PostgreSQL, with an explanation of the cause + type: object + passwordStatus: + additionalProperties: + description: PasswordState represents the state of the password + of a managed RoleConfiguration + properties: + resourceVersion: + description: the resource version of the password secret + type: string + transactionID: + description: the last transaction ID to affect the role + definition in PostgreSQL + format: int64 + type: integer + type: object + description: PasswordStatus gives the last transaction id and + password secret version for each managed role + type: object + type: object + onlineUpdateEnabled: + description: OnlineUpdateEnabled shows if the online upgrade is enabled + inside the cluster + type: boolean + phase: + description: Current phase of the cluster + type: string + phaseReason: + description: Reason for the current phase + type: string + poolerIntegrations: + description: The integration needed by poolers referencing the cluster + properties: + pgBouncerIntegration: + description: PgBouncerIntegrationStatus encapsulates the needed + integration for the pgbouncer poolers referencing the cluster + properties: + secrets: + items: + type: string + type: array + type: object + type: object + pvcCount: + description: How many PVCs have been created by this cluster + format: int32 + type: integer + readService: + description: Current list of read pods + type: string + readyInstances: + description: The total number of ready instances in the cluster. It + is equal to the number of ready instance pods. + type: integer + resizingPVC: + description: List of all the PVCs that have ResizingPVC condition. + items: + type: string + type: array + secretsResourceVersion: + description: The list of resource versions of the secrets managed + by the operator. Every change here is done in the interest of the + instance manager, which will refresh the secret data + properties: + applicationSecretVersion: + description: The resource version of the "app" user secret + type: string + barmanEndpointCA: + description: The resource version of the Barman Endpoint CA if + provided + type: string + caSecretVersion: + description: Unused. Retained for compatibility with old versions. + type: string + clientCaSecretVersion: + description: The resource version of the PostgreSQL client-side + CA secret version + type: string + managedRoleSecretVersion: + additionalProperties: + type: string + description: The resource versions of the managed roles secrets + type: object + metrics: + additionalProperties: + type: string + description: A map with the versions of all the secrets used to + pass metrics. Map keys are the secret names, map values are + the versions + type: object + replicationSecretVersion: + description: The resource version of the "streaming_replica" user + secret + type: string + serverCaSecretVersion: + description: The resource version of the PostgreSQL server-side + CA secret version + type: string + serverSecretVersion: + description: The resource version of the PostgreSQL server-side + secret version + type: string + superuserSecretVersion: + description: The resource version of the "postgres" user secret + type: string + type: object + targetPrimary: + description: Target primary instance, this is different from the previous + one during a switchover or a failover + type: string + targetPrimaryTimestamp: + description: The timestamp when the last request for a new primary + has occurred + type: string + timelineID: + description: The timeline of the Postgres cluster + type: integer + topology: + description: Instances topology. + properties: + instances: + additionalProperties: + additionalProperties: + type: string + description: PodTopologyLabels represent the topology of a Pod. + map[labelName]labelValue + type: object + description: Instances contains the pod topology of the instances + type: object + nodesUsed: + description: NodesUsed represents the count of distinct nodes + accommodating the instances. A value of '1' suggests that all + instances are hosted on a single node, implying the absence + of High Availability (HA). Ideally, this value should be the + same as the number of instances in the Postgres HA cluster, + implying shared nothing architecture on the compute side. + format: int32 + type: integer + successfullyExtracted: + description: SuccessfullyExtracted indicates if the topology data + was extract. It is useful to enact fallback behaviors in synchronous + replica election in case of failures + type: boolean + type: object + unusablePVC: + description: List of all the PVCs that are unusable because another + PVC is missing + items: + type: string + type: array + writeService: + description: Current write pod + type: string + type: object + required: + - metadata + - spec + type: object + served: true + storage: true + subresources: + scale: + specReplicasPath: .spec.instances + statusReplicasPath: .status.instances + status: {} +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.13.0 + helm.sh/resource-policy: keep + name: poolers.postgresql.cnpg.io +spec: + group: postgresql.cnpg.io + names: + kind: Pooler + listKind: PoolerList + plural: poolers + singular: pooler + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + - jsonPath: .spec.cluster.name + name: Cluster + type: string + - jsonPath: .spec.type + name: Type + type: string + name: v1 + schema: + openAPIV3Schema: + description: Pooler is the Schema for the poolers 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: 'Specification of the desired behavior of the Pooler. More + info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status' + properties: + cluster: + description: This is the cluster reference on which the Pooler will + work. Pooler name should never match with any cluster name within + the same namespace. + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + deploymentStrategy: + description: The deployment strategy to use for pgbouncer to replace + existing pods with new ones + properties: + rollingUpdate: + description: 'Rolling update config params. Present only if DeploymentStrategyType + = RollingUpdate. --- TODO: Update this to follow our convention + for oneOf, whatever we decide it to be.' + properties: + maxSurge: + anyOf: + - type: integer + - type: string + description: 'The maximum number of pods that can be scheduled + above the desired number of pods. Value can be an absolute + number (ex: 5) or a percentage of desired pods (ex: 10%). + This can not be 0 if MaxUnavailable is 0. Absolute number + is calculated from percentage by rounding up. Defaults to + 25%. Example: when this is set to 30%, the new ReplicaSet + can be scaled up immediately when the rolling update starts, + such that the total number of old and new pods do not exceed + 130% of desired pods. Once old pods have been killed, new + ReplicaSet can be scaled up further, ensuring that total + number of pods running at any time during the update is + at most 130% of desired pods.' + x-kubernetes-int-or-string: true + maxUnavailable: + anyOf: + - type: integer + - type: string + description: 'The maximum number of pods that can be unavailable + during the update. Value can be an absolute number (ex: + 5) or a percentage of desired pods (ex: 10%). Absolute number + is calculated from percentage by rounding down. This can + not be 0 if MaxSurge is 0. Defaults to 25%. Example: when + this is set to 30%, the old ReplicaSet can be scaled down + to 70% of desired pods immediately when the rolling update + starts. Once new pods are ready, old ReplicaSet can be scaled + down further, followed by scaling up the new ReplicaSet, + ensuring that the total number of pods available at all + times during the update is at least 70% of desired pods.' + x-kubernetes-int-or-string: true + type: object + type: + description: Type of deployment. Can be "Recreate" or "RollingUpdate". + Default is RollingUpdate. + type: string + type: object + instances: + default: 1 + description: 'The number of replicas we want. Default: 1.' + format: int32 + type: integer + monitoring: + description: The configuration of the monitoring infrastructure of + this pooler. + properties: + enablePodMonitor: + default: false + description: Enable or disable the `PodMonitor` + type: boolean + type: object + pgbouncer: + description: The PgBouncer configuration + properties: + authQuery: + description: 'The query that will be used to download the hash + of the password of a certain user. Default: "SELECT usename, + passwd FROM user_search($1)". In case it is specified, also + an AuthQuerySecret has to be specified and no automatic CNPG + Cluster integration will be triggered.' + type: string + authQuerySecret: + description: The credentials of the user that need to be used + for the authentication query. In case it is specified, also + an AuthQuery (e.g. "SELECT usename, passwd FROM pg_shadow WHERE + usename=$1") has to be specified and no automatic CNPG Cluster + integration will be triggered. + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + parameters: + additionalProperties: + type: string + description: Additional parameters to be passed to PgBouncer - + please check the CNPG documentation for a list of options you + can configure + type: object + paused: + default: false + description: When set to `true`, PgBouncer will disconnect from + the PostgreSQL server, first waiting for all queries to complete, + and pause all new client connections until this value is set + to `false` (default). Internally, the operator calls PgBouncer's + `PAUSE` and `RESUME` commands. + type: boolean + pg_hba: + description: PostgreSQL Host Based Authentication rules (lines + to be appended to the pg_hba.conf file) + items: + type: string + type: array + poolMode: + default: session + description: 'The pool mode. Default: `session`.' + enum: + - session + - transaction + type: string + type: object + template: + description: The template of the Pod to be created + properties: + metadata: + description: 'Standard object''s metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata' + properties: + annotations: + additionalProperties: + type: string + description: 'Annotations is an unstructured key value map + stored with a resource that may be set by external tools + to store and retrieve arbitrary metadata. They are not queryable + and should be preserved when modifying objects. More info: + http://kubernetes.io/docs/user-guide/annotations' + type: object + labels: + additionalProperties: + type: string + description: 'Map of string keys and values that can be used + to organize and categorize (scope and select) objects. May + match selectors of replication controllers and services. + More info: http://kubernetes.io/docs/user-guide/labels' + type: object + type: object + spec: + description: 'Specification of the desired behavior of the pod. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status' + properties: + activeDeadlineSeconds: + description: Optional duration in seconds the pod may be active + on the node relative to StartTime before the system will + actively try to mark it failed and kill associated containers. + Value must be a positive integer. + format: int64 + type: integer + affinity: + description: If specified, the pod's scheduling constraints + properties: + nodeAffinity: + description: Describes node affinity scheduling rules + for the pod. + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule + pods to nodes that satisfy the affinity expressions + specified by this field, but it may choose a node + that violates one or more of the expressions. The + node that is most preferred is the one with the + greatest sum of weights, i.e. for each node that + meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, + etc.), compute a sum by iterating through the elements + of this field and adding "weight" to the sum if + the node matches the corresponding matchExpressions; + the node(s) with the highest sum are the most preferred. + items: + description: An empty preferred scheduling term + matches all objects with implicit weight 0 (i.e. + it's a no-op). A null preferred scheduling term + matches no objects (i.e. is also a no-op). + properties: + preference: + description: A node selector term, associated + with the corresponding weight. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: The label key that the + selector applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: 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. + If the operator is Gt or Lt, the + values array must have a single + element, which will be interpreted + as an integer. This array is replaced + during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: The label key that the + selector applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: 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. + If the operator is Gt or Lt, the + values array must have a single + element, which will be interpreted + as an integer. This array is replaced + during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + x-kubernetes-map-type: atomic + weight: + description: Weight associated with matching + the corresponding nodeSelectorTerm, in the + range 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified + by this field are not met at scheduling time, the + pod will not be scheduled onto the node. If the + affinity requirements specified by this field cease + to be met at some point during pod execution (e.g. + due to an update), the system may or may not try + to eventually evict the pod from its node. + properties: + nodeSelectorTerms: + description: Required. A list of node selector + terms. The terms are ORed. + items: + description: A null or empty node selector term + matches no objects. The requirements of them + are ANDed. The TopologySelectorTerm type implements + a subset of the NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: The label key that the + selector applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: 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. + If the operator is Gt or Lt, the + values array must have a single + element, which will be interpreted + as an integer. This array is replaced + during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: The label key that the + selector applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: 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. + If the operator is Gt or Lt, the + values array must have a single + element, which will be interpreted + as an integer. This array is replaced + during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + x-kubernetes-map-type: atomic + type: array + required: + - nodeSelectorTerms + type: object + x-kubernetes-map-type: atomic + type: object + podAffinity: + description: Describes pod affinity scheduling rules (e.g. + co-locate this pod in the same node, zone, etc. as some + other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule + pods to nodes that satisfy the affinity expressions + specified by this field, but it may choose a node + that violates one or more of the expressions. The + node that is most preferred is the one with the + greatest sum of weights, i.e. for each node that + meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, + etc.), compute a sum by iterating through the elements + of this field and adding "weight" to the sum if + the node has pods which matches the corresponding + podAffinityTerm; the node(s) with the highest sum + are the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, + associated with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of + resources, in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set + of namespaces that the term applies to. + The term is applied to the union of the + namespaces selected by this field and + the ones listed in the namespaces field. + null selector and null or empty namespaces + list means "this pod's namespace". An + empty selector ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static + list of namespace names that the term + applies to. The term is applied to the + union of the namespaces listed in this + field and the ones selected by namespaceSelector. + null or empty namespaces list and null + namespaceSelector means "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located + (affinity) or not co-located (anti-affinity) + with the pods matching the labelSelector + in the specified namespaces, where co-located + is defined as running on a node whose + value of the label with key topologyKey + matches that of any node on which any + of the selected pods is running. Empty + topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching + the corresponding podAffinityTerm, in the + range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified + by this field are not met at scheduling time, the + pod will not be scheduled onto the node. If the + affinity requirements specified by this field cease + to be met at some point during pod execution (e.g. + due to a pod label update), the system may or may + not try to eventually evict the pod from its node. + When there are multiple elements, the lists of nodes + corresponding to each podAffinityTerm are intersected, + i.e. all terms must be satisfied. + items: + description: Defines a set of pods (namely those + matching the labelSelector relative to the given + namespace(s)) that this pod should be co-located + (affinity) or not co-located (anti-affinity) with, + where co-located is defined as running on a node + whose value of the label with key + matches that of any node on which a pod of the + set of pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by + this field and the ones listed in the namespaces + field. null selector and null or empty namespaces + list means "this pod's namespace". An empty + selector ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. + The term is applied to the union of the namespaces + listed in this field and the ones selected + by namespaceSelector. null or empty namespaces + list and null namespaceSelector means "this + pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the + pods matching the labelSelector in the specified + namespaces, where co-located is defined as + running on a node whose value of the label + with key topologyKey matches that of any node + on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + podAntiAffinity: + description: Describes pod anti-affinity scheduling rules + (e.g. avoid putting this pod in the same node, zone, + etc. as some other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule + pods to nodes that satisfy the anti-affinity expressions + specified by this field, but it may choose a node + that violates one or more of the expressions. The + node that is most preferred is the one with the + greatest sum of weights, i.e. for each node that + meets all of the scheduling requirements (resource + request, requiredDuringScheduling anti-affinity + expressions, etc.), compute a sum by iterating through + the elements of this field and adding "weight" to + the sum if the node has pods which matches the corresponding + podAffinityTerm; the node(s) with the highest sum + are the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, + associated with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of + resources, in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set + of namespaces that the term applies to. + The term is applied to the union of the + namespaces selected by this field and + the ones listed in the namespaces field. + null selector and null or empty namespaces + list means "this pod's namespace". An + empty selector ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static + list of namespace names that the term + applies to. The term is applied to the + union of the namespaces listed in this + field and the ones selected by namespaceSelector. + null or empty namespaces list and null + namespaceSelector means "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located + (affinity) or not co-located (anti-affinity) + with the pods matching the labelSelector + in the specified namespaces, where co-located + is defined as running on a node whose + value of the label with key topologyKey + matches that of any node on which any + of the selected pods is running. Empty + topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching + the corresponding podAffinityTerm, in the + range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the anti-affinity requirements specified + by this field are not met at scheduling time, the + pod will not be scheduled onto the node. If the + anti-affinity requirements specified by this field + cease to be met at some point during pod execution + (e.g. due to a pod label update), the system may + or may not try to eventually evict the pod from + its node. When there are multiple elements, the + lists of nodes corresponding to each podAffinityTerm + are intersected, i.e. all terms must be satisfied. + items: + description: Defines a set of pods (namely those + matching the labelSelector relative to the given + namespace(s)) that this pod should be co-located + (affinity) or not co-located (anti-affinity) with, + where co-located is defined as running on a node + whose value of the label with key + matches that of any node on which a pod of the + set of pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by + this field and the ones listed in the namespaces + field. null selector and null or empty namespaces + list means "this pod's namespace". An empty + selector ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. + The term is applied to the union of the namespaces + listed in this field and the ones selected + by namespaceSelector. null or empty namespaces + list and null namespaceSelector means "this + pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the + pods matching the labelSelector in the specified + namespaces, where co-located is defined as + running on a node whose value of the label + with key topologyKey matches that of any node + on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + type: object + automountServiceAccountToken: + description: AutomountServiceAccountToken indicates whether + a service account token should be automatically mounted. + type: boolean + containers: + description: List of containers belonging to the pod. Containers + cannot currently be added or removed. There must be at least + one container in a Pod. Cannot be updated. + items: + description: A single application container that you want + to run within a pod. + properties: + args: + description: 'Arguments to the entrypoint. The container + image''s CMD is used if this is not provided. Variable + references $(VAR_NAME) are expanded using the container''s + environment. 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. Cannot be updated. More info: + https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell' + items: + type: string + type: array + command: + description: 'Entrypoint array. Not executed within + a shell. The container image''s ENTRYPOINT is used + if this is not provided. Variable references $(VAR_NAME) + are expanded using the container''s environment. 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. Cannot be updated. More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell' + items: + type: string + type: array + env: + description: List of environment variables to set in + the container. Cannot be updated. + 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: + description: 'Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + 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: + description: 'Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + 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 + envFrom: + description: List of sources to populate environment + variables in the container. The keys defined within + a source must be a C_IDENTIFIER. All invalid keys + will be reported as an event when the container is + starting. 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. Cannot be updated. + items: + description: EnvFromSource represents the source of + a set of ConfigMaps + properties: + configMapRef: + description: The ConfigMap to select from + properties: + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + optional: + description: Specify whether the ConfigMap + must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + description: An optional identifier to prepend + to each key in the ConfigMap. Must be a C_IDENTIFIER. + type: string + secretRef: + description: The Secret to select from + properties: + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + optional: + description: Specify whether the Secret must + be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + image: + description: 'Container image name. More info: https://kubernetes.io/docs/concepts/containers/images + This field is optional to allow higher level config + management to default or override container images + in workload controllers like Deployments and StatefulSets.' + type: string + imagePullPolicy: + description: 'Image pull policy. One of Always, Never, + IfNotPresent. Defaults to Always if :latest tag is + specified, or IfNotPresent otherwise. Cannot be updated. + More info: https://kubernetes.io/docs/concepts/containers/images#updating-images' + type: string + lifecycle: + description: Actions that the management system should + take in response to container lifecycle events. Cannot + be updated. + properties: + postStart: + description: 'PostStart is called immediately after + a container is created. If the handler fails, + the container is terminated and restarted according + to its restart policy. Other management of the + container blocks until the hook completes. More + info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks' + properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line + to execute inside the container, the working + directory for the command is root ('/') + in the container's filesystem. The command + is simply exec'd, it is not run inside + a shell, so traditional shell instructions + ('|', etc) won't work. To use a shell, + you need to explicitly call out to that + shell. Exit status of 0 is treated as + live/healthy and non-zero is unhealthy. + items: + type: string + type: array + type: object + httpGet: + description: HTTPGet specifies the http request + to perform. + properties: + host: + description: Host name to connect to, defaults + to the pod IP. You probably want to set + "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the + request. HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom + header to be used in HTTP probes + properties: + name: + description: The header field name. + This will be canonicalized upon + output, so case-variant names will + be understood as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP + server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port + to access on the container. Number must + be in the range 1 to 65535. Name must + be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting + to the host. Defaults to HTTP. + type: string + required: + - port + type: object + tcpSocket: + description: Deprecated. TCPSocket is NOT supported + as a LifecycleHandler and kept for the backward + compatibility. There are no validation of + this field and lifecycle hooks will fail in + runtime when tcp handler is specified. + properties: + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port + to access on the container. Number must + be in the range 1 to 65535. Name must + be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + preStop: + description: 'PreStop is called immediately before + a container is terminated due to an API request + or management event such as liveness/startup probe + failure, preemption, resource contention, etc. + The handler is not called if the container crashes + or exits. The Pod''s termination grace period + countdown begins before the PreStop hook is executed. + Regardless of the outcome of the handler, the + container will eventually terminate within the + Pod''s termination grace period (unless delayed + by finalizers). Other management of the container + blocks until the hook completes or until the termination + grace period is reached. More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks' + properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line + to execute inside the container, the working + directory for the command is root ('/') + in the container's filesystem. The command + is simply exec'd, it is not run inside + a shell, so traditional shell instructions + ('|', etc) won't work. To use a shell, + you need to explicitly call out to that + shell. Exit status of 0 is treated as + live/healthy and non-zero is unhealthy. + items: + type: string + type: array + type: object + httpGet: + description: HTTPGet specifies the http request + to perform. + properties: + host: + description: Host name to connect to, defaults + to the pod IP. You probably want to set + "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the + request. HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom + header to be used in HTTP probes + properties: + name: + description: The header field name. + This will be canonicalized upon + output, so case-variant names will + be understood as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP + server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port + to access on the container. Number must + be in the range 1 to 65535. Name must + be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting + to the host. Defaults to HTTP. + type: string + required: + - port + type: object + tcpSocket: + description: Deprecated. TCPSocket is NOT supported + as a LifecycleHandler and kept for the backward + compatibility. There are no validation of + this field and lifecycle hooks will fail in + runtime when tcp handler is specified. + properties: + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port + to access on the container. Number must + be in the range 1 to 65535. Name must + be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + type: object + livenessProbe: + description: 'Periodic probe of container liveness. + Container will be restarted if the probe fails. Cannot + be updated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to + execute inside the container, the working + directory for the command is root ('/') in + the container's filesystem. The command is + simply exec'd, it is not run inside a shell, + so traditional shell instructions ('|', etc) + won't work. To use a shell, you need to explicitly + call out to that shell. Exit status of 0 is + treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + type: object + failureThreshold: + description: Minimum consecutive failures for the + probe to be considered failed after having succeeded. + Defaults to 3. Minimum value is 1. + format: int32 + type: integer + grpc: + description: GRPC specifies an action involving + a GRPC port. + properties: + port: + description: Port number of the gRPC service. + Number must be in the range 1 to 65535. + format: int32 + type: integer + service: + description: "Service is the name of the service + to place in the gRPC HealthCheckRequest (see + https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + \n If this is not specified, the default behavior + is defined by gRPC." + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies the http request + to perform. + properties: + host: + description: Host name to connect to, defaults + to the pod IP. You probably want to set "Host" + in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the request. + HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom + header to be used in HTTP probes + properties: + name: + description: The header field name. This + will be canonicalized upon output, so + case-variant names will be understood + as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to + the host. Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: 'Number of seconds after the container + has started before liveness probes are initiated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + periodSeconds: + description: How often (in seconds) to perform the + probe. Default to 10 seconds. Minimum value is + 1. + format: int32 + type: integer + successThreshold: + description: Minimum consecutive successes for the + probe to be considered successful after having + failed. Defaults to 1. Must be 1 for liveness + and startup. Minimum value is 1. + format: int32 + type: integer + tcpSocket: + description: TCPSocket specifies an action involving + a TCP port. + properties: + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: Optional duration in seconds the pod + needs to terminate gracefully upon probe failure. + The grace period is the duration in seconds after + the processes running in the pod are sent a termination + signal and the time when the processes are forcibly + halted with a kill signal. Set this value longer + than the expected cleanup time for your process. + If this value is nil, the pod's terminationGracePeriodSeconds + will be used. Otherwise, this value overrides + the value provided by the pod spec. Value must + be non-negative integer. The value zero indicates + stop immediately via the kill signal (no opportunity + to shut down). This is a beta field and requires + enabling ProbeTerminationGracePeriod feature gate. + Minimum value is 1. spec.terminationGracePeriodSeconds + is used if unset. + format: int64 + type: integer + timeoutSeconds: + description: 'Number of seconds after which the + probe times out. Defaults to 1 second. Minimum + value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + type: object + name: + description: Name of the container specified as a DNS_LABEL. + Each container in a pod must have a unique name (DNS_LABEL). + Cannot be updated. + type: string + ports: + description: List of ports to expose from the container. + Not specifying a port here DOES NOT prevent that port + from being exposed. Any port which is listening on + the default "0.0.0.0" address inside a container will + be accessible from the network. Modifying this array + with strategic merge patch may corrupt the data. For + more information See https://github.com/kubernetes/kubernetes/issues/108255. + Cannot be updated. + items: + description: ContainerPort represents a network port + in a single container. + properties: + containerPort: + description: Number of port to expose on the pod's + IP address. This must be a valid port number, + 0 < x < 65536. + format: int32 + type: integer + hostIP: + description: What host IP to bind the external + port to. + type: string + hostPort: + description: Number of port to expose on the host. + If specified, this must be a valid port number, + 0 < x < 65536. If HostNetwork is specified, + this must match ContainerPort. Most containers + do not need this. + format: int32 + type: integer + name: + description: If specified, this must be an IANA_SVC_NAME + and unique within the pod. Each named port in + a pod must have a unique name. Name for the + port that can be referred to by services. + type: string + protocol: + default: TCP + description: Protocol for port. Must be UDP, TCP, + or SCTP. Defaults to "TCP". + type: string + required: + - containerPort + type: object + type: array + x-kubernetes-list-map-keys: + - containerPort + - protocol + x-kubernetes-list-type: map + readinessProbe: + description: 'Periodic probe of container service readiness. + Container will be removed from service endpoints if + the probe fails. Cannot be updated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to + execute inside the container, the working + directory for the command is root ('/') in + the container's filesystem. The command is + simply exec'd, it is not run inside a shell, + so traditional shell instructions ('|', etc) + won't work. To use a shell, you need to explicitly + call out to that shell. Exit status of 0 is + treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + type: object + failureThreshold: + description: Minimum consecutive failures for the + probe to be considered failed after having succeeded. + Defaults to 3. Minimum value is 1. + format: int32 + type: integer + grpc: + description: GRPC specifies an action involving + a GRPC port. + properties: + port: + description: Port number of the gRPC service. + Number must be in the range 1 to 65535. + format: int32 + type: integer + service: + description: "Service is the name of the service + to place in the gRPC HealthCheckRequest (see + https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + \n If this is not specified, the default behavior + is defined by gRPC." + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies the http request + to perform. + properties: + host: + description: Host name to connect to, defaults + to the pod IP. You probably want to set "Host" + in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the request. + HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom + header to be used in HTTP probes + properties: + name: + description: The header field name. This + will be canonicalized upon output, so + case-variant names will be understood + as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to + the host. Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: 'Number of seconds after the container + has started before liveness probes are initiated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + periodSeconds: + description: How often (in seconds) to perform the + probe. Default to 10 seconds. Minimum value is + 1. + format: int32 + type: integer + successThreshold: + description: Minimum consecutive successes for the + probe to be considered successful after having + failed. Defaults to 1. Must be 1 for liveness + and startup. Minimum value is 1. + format: int32 + type: integer + tcpSocket: + description: TCPSocket specifies an action involving + a TCP port. + properties: + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: Optional duration in seconds the pod + needs to terminate gracefully upon probe failure. + The grace period is the duration in seconds after + the processes running in the pod are sent a termination + signal and the time when the processes are forcibly + halted with a kill signal. Set this value longer + than the expected cleanup time for your process. + If this value is nil, the pod's terminationGracePeriodSeconds + will be used. Otherwise, this value overrides + the value provided by the pod spec. Value must + be non-negative integer. The value zero indicates + stop immediately via the kill signal (no opportunity + to shut down). This is a beta field and requires + enabling ProbeTerminationGracePeriod feature gate. + Minimum value is 1. spec.terminationGracePeriodSeconds + is used if unset. + format: int64 + type: integer + timeoutSeconds: + description: 'Number of seconds after which the + probe times out. Defaults to 1 second. Minimum + value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + type: object + resizePolicy: + description: Resources resize policy for the container. + items: + description: ContainerResizePolicy represents resource + resize policy for the container. + properties: + resourceName: + description: 'Name of the resource to which this + resource resize policy applies. Supported values: + cpu, memory.' + type: string + restartPolicy: + description: Restart policy to apply when specified + resource is resized. If not specified, it defaults + to NotRequired. + type: string + required: + - resourceName + - restartPolicy + type: object + type: array + x-kubernetes-list-type: atomic + resources: + description: 'Compute Resources required by this container. + Cannot be updated. More info: 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. \n This is an alpha field and + requires enabling the DynamicResourceAllocation + feature gate. \n 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 + 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 + restartPolicy: + description: 'RestartPolicy defines the restart behavior + of individual containers in a pod. This field may + only be set for init containers, and the only allowed + value is "Always". For non-init containers or when + this field is not specified, the restart behavior + is defined by the Pod''s restart policy and the container + type. Setting the RestartPolicy as "Always" for the + init container will have the following effect: this + init container will be continually restarted on exit + until all regular containers have terminated. Once + all regular containers have completed, all init containers + with restartPolicy "Always" will be shut down. This + lifecycle differs from normal init containers and + is often referred to as a "sidecar" container. Although + this init container still starts in the init container + sequence, it does not wait for the container to complete + before proceeding to the next init container. Instead, + the next init container starts immediately after this + init container is started, or after any startupProbe + has successfully completed.' + type: string + securityContext: + description: 'SecurityContext defines the security options + the container should be run with. If set, the fields + of SecurityContext override the equivalent fields + of PodSecurityContext. More info: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/' + properties: + allowPrivilegeEscalation: + description: 'AllowPrivilegeEscalation controls + whether a process can gain more privileges than + its parent process. This bool directly controls + if the no_new_privs flag will be set on the container + process. AllowPrivilegeEscalation is true always + when the container is: 1) run as Privileged 2) + has CAP_SYS_ADMIN Note that this field cannot + be set when spec.os.name is windows.' + type: boolean + capabilities: + description: The capabilities to add/drop when running + containers. Defaults to the default set of capabilities + granted by the container runtime. Note that this + field cannot be set when spec.os.name is windows. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + type: object + privileged: + description: Run container in privileged mode. Processes + in privileged containers are essentially equivalent + to root on the host. Defaults to false. Note that + this field cannot be set when spec.os.name is + windows. + type: boolean + procMount: + description: procMount denotes the type of proc + mount to use for the containers. The default is + DefaultProcMount which uses the container runtime + defaults for readonly paths and masked paths. + This requires the ProcMountType feature flag to + be enabled. Note that this field cannot be set + when spec.os.name is windows. + type: string + readOnlyRootFilesystem: + description: Whether this container has a read-only + root filesystem. Default is false. Note that this + field cannot be set when spec.os.name is windows. + type: boolean + runAsGroup: + description: The GID to run the entrypoint of the + container process. Uses runtime default if unset. + May also be set in PodSecurityContext. If set + in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name + is windows. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run + as a non-root user. If true, the Kubelet will + validate the image at runtime to ensure that it + does not run as UID 0 (root) and fail to start + the container if it does. If unset or false, no + such validation will be performed. May also be + set in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in + SecurityContext takes precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the + container process. Defaults to user specified + in image metadata if unspecified. May also be + set in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in + SecurityContext takes precedence. Note that this + field cannot be set when spec.os.name is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to + the container. If unspecified, the container runtime + will allocate a random SELinux context for each + container. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name + is windows. + properties: + level: + description: Level is SELinux level label that + applies to the container. + type: string + role: + description: Role is a SELinux role label that + applies to the container. + type: string + type: + description: Type is a SELinux type label that + applies to the container. + type: string + user: + description: User is a SELinux user label that + applies to the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by this + container. If seccomp options are provided at + both the pod & container level, the container + options override the pod options. Note that this + field cannot be set when spec.os.name is windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile + defined in a file on the node should be used. + The profile must be preconfigured on the node + to work. Must be a descending path, relative + to the kubelet's configured seccomp profile + location. Must be set if type is "Localhost". + Must NOT be set for any other type. + type: string + type: + description: "type indicates which kind of seccomp + profile will be applied. Valid options are: + \n Localhost - a profile defined in a file + on the node should be used. RuntimeDefault + - the container runtime default profile should + be used. Unconfined - no profile should be + applied." + type: string + required: + - type + type: object + windowsOptions: + description: The Windows specific settings applied + to all containers. If unspecified, the options + from the PodSecurityContext will be used. If set + in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name + is linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the + GMSA admission webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential + spec named by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name + of the GMSA credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container + should be run as a 'Host Process' container. + All of a Pod's containers must have the same + effective HostProcess value (it is not allowed + to have a mix of HostProcess containers and + non-HostProcess containers). In addition, + if HostProcess is true then HostNetwork must + also be set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run + the entrypoint of the container process. Defaults + to the user specified in image metadata if + unspecified. May also be set in PodSecurityContext. + If set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes + precedence. + type: string + type: object + type: object + startupProbe: + description: 'StartupProbe indicates that the Pod has + successfully initialized. If specified, no other probes + are executed until this completes successfully. If + this probe fails, the Pod will be restarted, just + as if the livenessProbe failed. This can be used to + provide different probe parameters at the beginning + of a Pod''s lifecycle, when it might take a long time + to load data or warm a cache, than during steady-state + operation. This cannot be updated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to + execute inside the container, the working + directory for the command is root ('/') in + the container's filesystem. The command is + simply exec'd, it is not run inside a shell, + so traditional shell instructions ('|', etc) + won't work. To use a shell, you need to explicitly + call out to that shell. Exit status of 0 is + treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + type: object + failureThreshold: + description: Minimum consecutive failures for the + probe to be considered failed after having succeeded. + Defaults to 3. Minimum value is 1. + format: int32 + type: integer + grpc: + description: GRPC specifies an action involving + a GRPC port. + properties: + port: + description: Port number of the gRPC service. + Number must be in the range 1 to 65535. + format: int32 + type: integer + service: + description: "Service is the name of the service + to place in the gRPC HealthCheckRequest (see + https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + \n If this is not specified, the default behavior + is defined by gRPC." + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies the http request + to perform. + properties: + host: + description: Host name to connect to, defaults + to the pod IP. You probably want to set "Host" + in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the request. + HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom + header to be used in HTTP probes + properties: + name: + description: The header field name. This + will be canonicalized upon output, so + case-variant names will be understood + as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to + the host. Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: 'Number of seconds after the container + has started before liveness probes are initiated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + periodSeconds: + description: How often (in seconds) to perform the + probe. Default to 10 seconds. Minimum value is + 1. + format: int32 + type: integer + successThreshold: + description: Minimum consecutive successes for the + probe to be considered successful after having + failed. Defaults to 1. Must be 1 for liveness + and startup. Minimum value is 1. + format: int32 + type: integer + tcpSocket: + description: TCPSocket specifies an action involving + a TCP port. + properties: + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: Optional duration in seconds the pod + needs to terminate gracefully upon probe failure. + The grace period is the duration in seconds after + the processes running in the pod are sent a termination + signal and the time when the processes are forcibly + halted with a kill signal. Set this value longer + than the expected cleanup time for your process. + If this value is nil, the pod's terminationGracePeriodSeconds + will be used. Otherwise, this value overrides + the value provided by the pod spec. Value must + be non-negative integer. The value zero indicates + stop immediately via the kill signal (no opportunity + to shut down). This is a beta field and requires + enabling ProbeTerminationGracePeriod feature gate. + Minimum value is 1. spec.terminationGracePeriodSeconds + is used if unset. + format: int64 + type: integer + timeoutSeconds: + description: 'Number of seconds after which the + probe times out. Defaults to 1 second. Minimum + value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + type: object + stdin: + description: Whether this container should allocate + a buffer for stdin in the container runtime. If this + is not set, reads from stdin in the container will + always result in EOF. Default is false. + type: boolean + stdinOnce: + description: Whether the container runtime should close + the stdin channel after it has been opened by a single + attach. When stdin is true the stdin stream will remain + open across multiple attach sessions. If stdinOnce + is set to true, stdin is opened on container start, + is empty until the first client attaches to stdin, + and then remains open and accepts data until the client + disconnects, at which time stdin is closed and remains + closed until the container is restarted. If this flag + is false, a container processes that reads from stdin + will never receive an EOF. Default is false + type: boolean + terminationMessagePath: + description: 'Optional: Path at which the file to which + the container''s termination message will be written + is mounted into the container''s filesystem. Message + written is intended to be brief final status, such + as an assertion failure message. Will be truncated + by the node if greater than 4096 bytes. The total + message length across all containers will be limited + to 12kb. Defaults to /dev/termination-log. Cannot + be updated.' + type: string + terminationMessagePolicy: + description: Indicate how the termination message should + be populated. File will use the contents of terminationMessagePath + to populate the container status message on both success + and failure. FallbackToLogsOnError will use the last + chunk of container log output if the termination message + file is empty and the container exited with an error. + The log output is limited to 2048 bytes or 80 lines, + whichever is smaller. Defaults to File. Cannot be + updated. + type: string + tty: + description: Whether this container should allocate + a TTY for itself, also requires 'stdin' to be true. + Default is false. + type: boolean + volumeDevices: + description: volumeDevices is the list of block devices + to be used by the container. + items: + description: volumeDevice describes a mapping of a + raw block device within a container. + properties: + devicePath: + description: devicePath is the path inside of + the container that the device will be mapped + to. + type: string + name: + description: name must match the name of a persistentVolumeClaim + in the pod + type: string + required: + - devicePath + - name + type: object + type: array + volumeMounts: + description: Pod volumes to mount into the container's + filesystem. Cannot be updated. + items: + description: VolumeMount describes a mounting of a + Volume within a container. + properties: + mountPath: + description: Path within the container at which + the volume should be mounted. Must not contain + ':'. + type: string + mountPropagation: + description: mountPropagation determines how mounts + are propagated from the host to container and + the other way around. When not set, MountPropagationNone + is used. This field is beta in 1.10. + type: string + name: + description: This must match the Name of a Volume. + type: string + readOnly: + description: Mounted read-only if true, read-write + otherwise (false or unspecified). Defaults to + false. + type: boolean + subPath: + description: Path within the volume from which + the container's volume should be mounted. Defaults + to "" (volume's root). + type: string + subPathExpr: + description: Expanded path within the volume from + which the container's volume should be mounted. + Behaves similarly to SubPath but environment + variable references $(VAR_NAME) are expanded + using the container's environment. Defaults + to "" (volume's root). SubPathExpr and SubPath + are mutually exclusive. + type: string + required: + - mountPath + - name + type: object + type: array + workingDir: + description: Container's working directory. If not specified, + the container runtime's default will be used, which + might be configured in the container image. Cannot + be updated. + type: string + required: + - name + type: object + type: array + dnsConfig: + description: Specifies the DNS parameters of a pod. Parameters + specified here will be merged to the generated DNS configuration + based on DNSPolicy. + properties: + nameservers: + description: A list of DNS name server IP addresses. This + will be appended to the base nameservers generated from + DNSPolicy. Duplicated nameservers will be removed. + items: + type: string + type: array + options: + description: A list of DNS resolver options. This will + be merged with the base options generated from DNSPolicy. + Duplicated entries will be removed. Resolution options + given in Options will override those that appear in + the base DNSPolicy. + items: + description: PodDNSConfigOption defines DNS resolver + options of a pod. + properties: + name: + description: Required. + type: string + value: + type: string + type: object + type: array + searches: + description: A list of DNS search domains for host-name + lookup. This will be appended to the base search paths + generated from DNSPolicy. Duplicated search paths will + be removed. + items: + type: string + type: array + type: object + dnsPolicy: + description: Set DNS policy for the pod. Defaults to "ClusterFirst". + Valid values are 'ClusterFirstWithHostNet', 'ClusterFirst', + 'Default' or 'None'. DNS parameters given in DNSConfig will + be merged with the policy selected with DNSPolicy. To have + DNS options set along with hostNetwork, you have to specify + DNS policy explicitly to 'ClusterFirstWithHostNet'. + type: string + enableServiceLinks: + description: 'EnableServiceLinks indicates whether information + about services should be injected into pod''s environment + variables, matching the syntax of Docker links. Optional: + Defaults to true.' + type: boolean + ephemeralContainers: + description: List of ephemeral containers run in this pod. + Ephemeral containers may be run in an existing pod to perform + user-initiated actions such as debugging. This list cannot + be specified when creating a pod, and it cannot be modified + by updating the pod spec. In order to add an ephemeral container + to an existing pod, use the pod's ephemeralcontainers subresource. + items: + description: "An EphemeralContainer is a temporary container + that you may add to an existing Pod for user-initiated + activities such as debugging. Ephemeral containers have + no resource or scheduling guarantees, and they will not + be restarted when they exit or when a Pod is removed or + restarted. The kubelet may evict a Pod if an ephemeral + container causes the Pod to exceed its resource allocation. + \n To add an ephemeral container, use the ephemeralcontainers + subresource of an existing Pod. Ephemeral containers may + not be removed or restarted." + properties: + args: + description: 'Arguments to the entrypoint. The image''s + CMD is used if this is not provided. Variable references + $(VAR_NAME) are expanded using the container''s environment. + 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. Cannot be updated. More info: + https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell' + items: + type: string + type: array + command: + description: 'Entrypoint array. Not executed within + a shell. The image''s ENTRYPOINT is used if this is + not provided. Variable references $(VAR_NAME) are + expanded using the container''s environment. 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. Cannot be updated. More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell' + items: + type: string + type: array + env: + description: List of environment variables to set in + the container. Cannot be updated. + 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: + description: 'Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + 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: + description: 'Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + 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 + envFrom: + description: List of sources to populate environment + variables in the container. The keys defined within + a source must be a C_IDENTIFIER. All invalid keys + will be reported as an event when the container is + starting. 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. Cannot be updated. + items: + description: EnvFromSource represents the source of + a set of ConfigMaps + properties: + configMapRef: + description: The ConfigMap to select from + properties: + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + optional: + description: Specify whether the ConfigMap + must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + description: An optional identifier to prepend + to each key in the ConfigMap. Must be a C_IDENTIFIER. + type: string + secretRef: + description: The Secret to select from + properties: + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + optional: + description: Specify whether the Secret must + be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + image: + description: 'Container image name. More info: https://kubernetes.io/docs/concepts/containers/images' + type: string + imagePullPolicy: + description: 'Image pull policy. One of Always, Never, + IfNotPresent. Defaults to Always if :latest tag is + specified, or IfNotPresent otherwise. Cannot be updated. + More info: https://kubernetes.io/docs/concepts/containers/images#updating-images' + type: string + lifecycle: + description: Lifecycle is not allowed for ephemeral + containers. + properties: + postStart: + description: 'PostStart is called immediately after + a container is created. If the handler fails, + the container is terminated and restarted according + to its restart policy. Other management of the + container blocks until the hook completes. More + info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks' + properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line + to execute inside the container, the working + directory for the command is root ('/') + in the container's filesystem. The command + is simply exec'd, it is not run inside + a shell, so traditional shell instructions + ('|', etc) won't work. To use a shell, + you need to explicitly call out to that + shell. Exit status of 0 is treated as + live/healthy and non-zero is unhealthy. + items: + type: string + type: array + type: object + httpGet: + description: HTTPGet specifies the http request + to perform. + properties: + host: + description: Host name to connect to, defaults + to the pod IP. You probably want to set + "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the + request. HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom + header to be used in HTTP probes + properties: + name: + description: The header field name. + This will be canonicalized upon + output, so case-variant names will + be understood as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP + server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port + to access on the container. Number must + be in the range 1 to 65535. Name must + be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting + to the host. Defaults to HTTP. + type: string + required: + - port + type: object + tcpSocket: + description: Deprecated. TCPSocket is NOT supported + as a LifecycleHandler and kept for the backward + compatibility. There are no validation of + this field and lifecycle hooks will fail in + runtime when tcp handler is specified. + properties: + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port + to access on the container. Number must + be in the range 1 to 65535. Name must + be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + preStop: + description: 'PreStop is called immediately before + a container is terminated due to an API request + or management event such as liveness/startup probe + failure, preemption, resource contention, etc. + The handler is not called if the container crashes + or exits. The Pod''s termination grace period + countdown begins before the PreStop hook is executed. + Regardless of the outcome of the handler, the + container will eventually terminate within the + Pod''s termination grace period (unless delayed + by finalizers). Other management of the container + blocks until the hook completes or until the termination + grace period is reached. More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks' + properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line + to execute inside the container, the working + directory for the command is root ('/') + in the container's filesystem. The command + is simply exec'd, it is not run inside + a shell, so traditional shell instructions + ('|', etc) won't work. To use a shell, + you need to explicitly call out to that + shell. Exit status of 0 is treated as + live/healthy and non-zero is unhealthy. + items: + type: string + type: array + type: object + httpGet: + description: HTTPGet specifies the http request + to perform. + properties: + host: + description: Host name to connect to, defaults + to the pod IP. You probably want to set + "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the + request. HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom + header to be used in HTTP probes + properties: + name: + description: The header field name. + This will be canonicalized upon + output, so case-variant names will + be understood as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP + server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port + to access on the container. Number must + be in the range 1 to 65535. Name must + be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting + to the host. Defaults to HTTP. + type: string + required: + - port + type: object + tcpSocket: + description: Deprecated. TCPSocket is NOT supported + as a LifecycleHandler and kept for the backward + compatibility. There are no validation of + this field and lifecycle hooks will fail in + runtime when tcp handler is specified. + properties: + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port + to access on the container. Number must + be in the range 1 to 65535. Name must + be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + type: object + livenessProbe: + description: Probes are not allowed for ephemeral containers. + properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to + execute inside the container, the working + directory for the command is root ('/') in + the container's filesystem. The command is + simply exec'd, it is not run inside a shell, + so traditional shell instructions ('|', etc) + won't work. To use a shell, you need to explicitly + call out to that shell. Exit status of 0 is + treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + type: object + failureThreshold: + description: Minimum consecutive failures for the + probe to be considered failed after having succeeded. + Defaults to 3. Minimum value is 1. + format: int32 + type: integer + grpc: + description: GRPC specifies an action involving + a GRPC port. + properties: + port: + description: Port number of the gRPC service. + Number must be in the range 1 to 65535. + format: int32 + type: integer + service: + description: "Service is the name of the service + to place in the gRPC HealthCheckRequest (see + https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + \n If this is not specified, the default behavior + is defined by gRPC." + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies the http request + to perform. + properties: + host: + description: Host name to connect to, defaults + to the pod IP. You probably want to set "Host" + in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the request. + HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom + header to be used in HTTP probes + properties: + name: + description: The header field name. This + will be canonicalized upon output, so + case-variant names will be understood + as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to + the host. Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: 'Number of seconds after the container + has started before liveness probes are initiated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + periodSeconds: + description: How often (in seconds) to perform the + probe. Default to 10 seconds. Minimum value is + 1. + format: int32 + type: integer + successThreshold: + description: Minimum consecutive successes for the + probe to be considered successful after having + failed. Defaults to 1. Must be 1 for liveness + and startup. Minimum value is 1. + format: int32 + type: integer + tcpSocket: + description: TCPSocket specifies an action involving + a TCP port. + properties: + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: Optional duration in seconds the pod + needs to terminate gracefully upon probe failure. + The grace period is the duration in seconds after + the processes running in the pod are sent a termination + signal and the time when the processes are forcibly + halted with a kill signal. Set this value longer + than the expected cleanup time for your process. + If this value is nil, the pod's terminationGracePeriodSeconds + will be used. Otherwise, this value overrides + the value provided by the pod spec. Value must + be non-negative integer. The value zero indicates + stop immediately via the kill signal (no opportunity + to shut down). This is a beta field and requires + enabling ProbeTerminationGracePeriod feature gate. + Minimum value is 1. spec.terminationGracePeriodSeconds + is used if unset. + format: int64 + type: integer + timeoutSeconds: + description: 'Number of seconds after which the + probe times out. Defaults to 1 second. Minimum + value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + type: object + name: + description: Name of the ephemeral container specified + as a DNS_LABEL. This name must be unique among all + containers, init containers and ephemeral containers. + type: string + ports: + description: Ports are not allowed for ephemeral containers. + items: + description: ContainerPort represents a network port + in a single container. + properties: + containerPort: + description: Number of port to expose on the pod's + IP address. This must be a valid port number, + 0 < x < 65536. + format: int32 + type: integer + hostIP: + description: What host IP to bind the external + port to. + type: string + hostPort: + description: Number of port to expose on the host. + If specified, this must be a valid port number, + 0 < x < 65536. If HostNetwork is specified, + this must match ContainerPort. Most containers + do not need this. + format: int32 + type: integer + name: + description: If specified, this must be an IANA_SVC_NAME + and unique within the pod. Each named port in + a pod must have a unique name. Name for the + port that can be referred to by services. + type: string + protocol: + default: TCP + description: Protocol for port. Must be UDP, TCP, + or SCTP. Defaults to "TCP". + type: string + required: + - containerPort + type: object + type: array + x-kubernetes-list-map-keys: + - containerPort + - protocol + x-kubernetes-list-type: map + readinessProbe: + description: Probes are not allowed for ephemeral containers. + properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to + execute inside the container, the working + directory for the command is root ('/') in + the container's filesystem. The command is + simply exec'd, it is not run inside a shell, + so traditional shell instructions ('|', etc) + won't work. To use a shell, you need to explicitly + call out to that shell. Exit status of 0 is + treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + type: object + failureThreshold: + description: Minimum consecutive failures for the + probe to be considered failed after having succeeded. + Defaults to 3. Minimum value is 1. + format: int32 + type: integer + grpc: + description: GRPC specifies an action involving + a GRPC port. + properties: + port: + description: Port number of the gRPC service. + Number must be in the range 1 to 65535. + format: int32 + type: integer + service: + description: "Service is the name of the service + to place in the gRPC HealthCheckRequest (see + https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + \n If this is not specified, the default behavior + is defined by gRPC." + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies the http request + to perform. + properties: + host: + description: Host name to connect to, defaults + to the pod IP. You probably want to set "Host" + in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the request. + HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom + header to be used in HTTP probes + properties: + name: + description: The header field name. This + will be canonicalized upon output, so + case-variant names will be understood + as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to + the host. Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: 'Number of seconds after the container + has started before liveness probes are initiated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + periodSeconds: + description: How often (in seconds) to perform the + probe. Default to 10 seconds. Minimum value is + 1. + format: int32 + type: integer + successThreshold: + description: Minimum consecutive successes for the + probe to be considered successful after having + failed. Defaults to 1. Must be 1 for liveness + and startup. Minimum value is 1. + format: int32 + type: integer + tcpSocket: + description: TCPSocket specifies an action involving + a TCP port. + properties: + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: Optional duration in seconds the pod + needs to terminate gracefully upon probe failure. + The grace period is the duration in seconds after + the processes running in the pod are sent a termination + signal and the time when the processes are forcibly + halted with a kill signal. Set this value longer + than the expected cleanup time for your process. + If this value is nil, the pod's terminationGracePeriodSeconds + will be used. Otherwise, this value overrides + the value provided by the pod spec. Value must + be non-negative integer. The value zero indicates + stop immediately via the kill signal (no opportunity + to shut down). This is a beta field and requires + enabling ProbeTerminationGracePeriod feature gate. + Minimum value is 1. spec.terminationGracePeriodSeconds + is used if unset. + format: int64 + type: integer + timeoutSeconds: + description: 'Number of seconds after which the + probe times out. Defaults to 1 second. Minimum + value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + type: object + resizePolicy: + description: Resources resize policy for the container. + items: + description: ContainerResizePolicy represents resource + resize policy for the container. + properties: + resourceName: + description: 'Name of the resource to which this + resource resize policy applies. Supported values: + cpu, memory.' + type: string + restartPolicy: + description: Restart policy to apply when specified + resource is resized. If not specified, it defaults + to NotRequired. + type: string + required: + - resourceName + - restartPolicy + type: object + type: array + x-kubernetes-list-type: atomic + resources: + description: Resources are not allowed for ephemeral + containers. Ephemeral containers use spare resources + already allocated to the pod. + properties: + claims: + description: "Claims lists the names of resources, + defined in spec.resourceClaims, that are used + by this container. \n This is an alpha field and + requires enabling the DynamicResourceAllocation + feature gate. \n 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 + 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 + restartPolicy: + description: Restart policy for the container to manage + the restart behavior of each container within a pod. + This may only be set for init containers. You cannot + set this field on ephemeral containers. + type: string + securityContext: + description: 'Optional: SecurityContext defines the + security options the ephemeral container should be + run with. If set, the fields of SecurityContext override + the equivalent fields of PodSecurityContext.' + properties: + allowPrivilegeEscalation: + description: 'AllowPrivilegeEscalation controls + whether a process can gain more privileges than + its parent process. This bool directly controls + if the no_new_privs flag will be set on the container + process. AllowPrivilegeEscalation is true always + when the container is: 1) run as Privileged 2) + has CAP_SYS_ADMIN Note that this field cannot + be set when spec.os.name is windows.' + type: boolean + capabilities: + description: The capabilities to add/drop when running + containers. Defaults to the default set of capabilities + granted by the container runtime. Note that this + field cannot be set when spec.os.name is windows. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + type: object + privileged: + description: Run container in privileged mode. Processes + in privileged containers are essentially equivalent + to root on the host. Defaults to false. Note that + this field cannot be set when spec.os.name is + windows. + type: boolean + procMount: + description: procMount denotes the type of proc + mount to use for the containers. The default is + DefaultProcMount which uses the container runtime + defaults for readonly paths and masked paths. + This requires the ProcMountType feature flag to + be enabled. Note that this field cannot be set + when spec.os.name is windows. + type: string + readOnlyRootFilesystem: + description: Whether this container has a read-only + root filesystem. Default is false. Note that this + field cannot be set when spec.os.name is windows. + type: boolean + runAsGroup: + description: The GID to run the entrypoint of the + container process. Uses runtime default if unset. + May also be set in PodSecurityContext. If set + in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name + is windows. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run + as a non-root user. If true, the Kubelet will + validate the image at runtime to ensure that it + does not run as UID 0 (root) and fail to start + the container if it does. If unset or false, no + such validation will be performed. May also be + set in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in + SecurityContext takes precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the + container process. Defaults to user specified + in image metadata if unspecified. May also be + set in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in + SecurityContext takes precedence. Note that this + field cannot be set when spec.os.name is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to + the container. If unspecified, the container runtime + will allocate a random SELinux context for each + container. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name + is windows. + properties: + level: + description: Level is SELinux level label that + applies to the container. + type: string + role: + description: Role is a SELinux role label that + applies to the container. + type: string + type: + description: Type is a SELinux type label that + applies to the container. + type: string + user: + description: User is a SELinux user label that + applies to the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by this + container. If seccomp options are provided at + both the pod & container level, the container + options override the pod options. Note that this + field cannot be set when spec.os.name is windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile + defined in a file on the node should be used. + The profile must be preconfigured on the node + to work. Must be a descending path, relative + to the kubelet's configured seccomp profile + location. Must be set if type is "Localhost". + Must NOT be set for any other type. + type: string + type: + description: "type indicates which kind of seccomp + profile will be applied. Valid options are: + \n Localhost - a profile defined in a file + on the node should be used. RuntimeDefault + - the container runtime default profile should + be used. Unconfined - no profile should be + applied." + type: string + required: + - type + type: object + windowsOptions: + description: The Windows specific settings applied + to all containers. If unspecified, the options + from the PodSecurityContext will be used. If set + in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name + is linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the + GMSA admission webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential + spec named by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name + of the GMSA credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container + should be run as a 'Host Process' container. + All of a Pod's containers must have the same + effective HostProcess value (it is not allowed + to have a mix of HostProcess containers and + non-HostProcess containers). In addition, + if HostProcess is true then HostNetwork must + also be set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run + the entrypoint of the container process. Defaults + to the user specified in image metadata if + unspecified. May also be set in PodSecurityContext. + If set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes + precedence. + type: string + type: object + type: object + startupProbe: + description: Probes are not allowed for ephemeral containers. + properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to + execute inside the container, the working + directory for the command is root ('/') in + the container's filesystem. The command is + simply exec'd, it is not run inside a shell, + so traditional shell instructions ('|', etc) + won't work. To use a shell, you need to explicitly + call out to that shell. Exit status of 0 is + treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + type: object + failureThreshold: + description: Minimum consecutive failures for the + probe to be considered failed after having succeeded. + Defaults to 3. Minimum value is 1. + format: int32 + type: integer + grpc: + description: GRPC specifies an action involving + a GRPC port. + properties: + port: + description: Port number of the gRPC service. + Number must be in the range 1 to 65535. + format: int32 + type: integer + service: + description: "Service is the name of the service + to place in the gRPC HealthCheckRequest (see + https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + \n If this is not specified, the default behavior + is defined by gRPC." + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies the http request + to perform. + properties: + host: + description: Host name to connect to, defaults + to the pod IP. You probably want to set "Host" + in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the request. + HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom + header to be used in HTTP probes + properties: + name: + description: The header field name. This + will be canonicalized upon output, so + case-variant names will be understood + as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to + the host. Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: 'Number of seconds after the container + has started before liveness probes are initiated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + periodSeconds: + description: How often (in seconds) to perform the + probe. Default to 10 seconds. Minimum value is + 1. + format: int32 + type: integer + successThreshold: + description: Minimum consecutive successes for the + probe to be considered successful after having + failed. Defaults to 1. Must be 1 for liveness + and startup. Minimum value is 1. + format: int32 + type: integer + tcpSocket: + description: TCPSocket specifies an action involving + a TCP port. + properties: + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: Optional duration in seconds the pod + needs to terminate gracefully upon probe failure. + The grace period is the duration in seconds after + the processes running in the pod are sent a termination + signal and the time when the processes are forcibly + halted with a kill signal. Set this value longer + than the expected cleanup time for your process. + If this value is nil, the pod's terminationGracePeriodSeconds + will be used. Otherwise, this value overrides + the value provided by the pod spec. Value must + be non-negative integer. The value zero indicates + stop immediately via the kill signal (no opportunity + to shut down). This is a beta field and requires + enabling ProbeTerminationGracePeriod feature gate. + Minimum value is 1. spec.terminationGracePeriodSeconds + is used if unset. + format: int64 + type: integer + timeoutSeconds: + description: 'Number of seconds after which the + probe times out. Defaults to 1 second. Minimum + value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + type: object + stdin: + description: Whether this container should allocate + a buffer for stdin in the container runtime. If this + is not set, reads from stdin in the container will + always result in EOF. Default is false. + type: boolean + stdinOnce: + description: Whether the container runtime should close + the stdin channel after it has been opened by a single + attach. When stdin is true the stdin stream will remain + open across multiple attach sessions. If stdinOnce + is set to true, stdin is opened on container start, + is empty until the first client attaches to stdin, + and then remains open and accepts data until the client + disconnects, at which time stdin is closed and remains + closed until the container is restarted. If this flag + is false, a container processes that reads from stdin + will never receive an EOF. Default is false + type: boolean + targetContainerName: + description: "If set, the name of the container from + PodSpec that this ephemeral container targets. The + ephemeral container will be run in the namespaces + (IPC, PID, etc) of this container. If not set then + the ephemeral container uses the namespaces configured + in the Pod spec. \n The container runtime must implement + support for this feature. If the runtime does not + support namespace targeting then the result of setting + this field is undefined." + type: string + terminationMessagePath: + description: 'Optional: Path at which the file to which + the container''s termination message will be written + is mounted into the container''s filesystem. Message + written is intended to be brief final status, such + as an assertion failure message. Will be truncated + by the node if greater than 4096 bytes. The total + message length across all containers will be limited + to 12kb. Defaults to /dev/termination-log. Cannot + be updated.' + type: string + terminationMessagePolicy: + description: Indicate how the termination message should + be populated. File will use the contents of terminationMessagePath + to populate the container status message on both success + and failure. FallbackToLogsOnError will use the last + chunk of container log output if the termination message + file is empty and the container exited with an error. + The log output is limited to 2048 bytes or 80 lines, + whichever is smaller. Defaults to File. Cannot be + updated. + type: string + tty: + description: Whether this container should allocate + a TTY for itself, also requires 'stdin' to be true. + Default is false. + type: boolean + volumeDevices: + description: volumeDevices is the list of block devices + to be used by the container. + items: + description: volumeDevice describes a mapping of a + raw block device within a container. + properties: + devicePath: + description: devicePath is the path inside of + the container that the device will be mapped + to. + type: string + name: + description: name must match the name of a persistentVolumeClaim + in the pod + type: string + required: + - devicePath + - name + type: object + type: array + volumeMounts: + description: Pod volumes to mount into the container's + filesystem. Subpath mounts are not allowed for ephemeral + containers. Cannot be updated. + items: + description: VolumeMount describes a mounting of a + Volume within a container. + properties: + mountPath: + description: Path within the container at which + the volume should be mounted. Must not contain + ':'. + type: string + mountPropagation: + description: mountPropagation determines how mounts + are propagated from the host to container and + the other way around. When not set, MountPropagationNone + is used. This field is beta in 1.10. + type: string + name: + description: This must match the Name of a Volume. + type: string + readOnly: + description: Mounted read-only if true, read-write + otherwise (false or unspecified). Defaults to + false. + type: boolean + subPath: + description: Path within the volume from which + the container's volume should be mounted. Defaults + to "" (volume's root). + type: string + subPathExpr: + description: Expanded path within the volume from + which the container's volume should be mounted. + Behaves similarly to SubPath but environment + variable references $(VAR_NAME) are expanded + using the container's environment. Defaults + to "" (volume's root). SubPathExpr and SubPath + are mutually exclusive. + type: string + required: + - mountPath + - name + type: object + type: array + workingDir: + description: Container's working directory. If not specified, + the container runtime's default will be used, which + might be configured in the container image. Cannot + be updated. + type: string + required: + - name + type: object + type: array + hostAliases: + description: HostAliases is an optional list of hosts and + IPs that will be injected into the pod's hosts file if specified. + This is only valid for non-hostNetwork pods. + items: + description: HostAlias holds the mapping between IP and + hostnames that will be injected as an entry in the pod's + hosts file. + properties: + hostnames: + description: Hostnames for the above IP address. + items: + type: string + type: array + ip: + description: IP address of the host file entry. + type: string + type: object + type: array + hostIPC: + description: 'Use the host''s ipc namespace. Optional: Default + to false.' + type: boolean + hostNetwork: + description: Host networking requested for this pod. Use the + host's network namespace. If this option is set, the ports + that will be used must be specified. Default to false. + type: boolean + hostPID: + description: 'Use the host''s pid namespace. Optional: Default + to false.' + type: boolean + hostUsers: + description: 'Use the host''s user namespace. Optional: Default + to true. If set to true or not present, the pod will be + run in the host user namespace, useful for when the pod + needs a feature only available to the host user namespace, + such as loading a kernel module with CAP_SYS_MODULE. When + set to false, a new userns is created for the pod. Setting + false is useful for mitigating container breakout vulnerabilities + even allowing users to run their containers as root without + actually having root privileges on the host. This field + is alpha-level and is only honored by servers that enable + the UserNamespacesSupport feature.' + type: boolean + hostname: + description: Specifies the hostname of the Pod If not specified, + the pod's hostname will be set to a system-defined value. + type: string + imagePullSecrets: + description: 'ImagePullSecrets is an optional list of references + to secrets in the same namespace to use for pulling any + of the images used by this PodSpec. If specified, these + secrets will be passed to individual puller implementations + for them to use. More info: https://kubernetes.io/docs/concepts/containers/images#specifying-imagepullsecrets-on-a-pod' + items: + description: LocalObjectReference contains enough information + to let you locate the referenced object inside the same + namespace. + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + x-kubernetes-map-type: atomic + type: array + initContainers: + description: 'List of initialization containers belonging + to the pod. Init containers are executed in order prior + to containers being started. If any init container fails, + the pod is considered to have failed and is handled according + to its restartPolicy. The name for an init container or + normal container must be unique among all containers. Init + containers may not have Lifecycle actions, Readiness probes, + Liveness probes, or Startup probes. The resourceRequirements + of an init container are taken into account during scheduling + by finding the highest request/limit for each resource type, + and then using the max of of that value or the sum of the + normal containers. Limits are applied to init containers + in a similar fashion. Init containers cannot currently be + added or removed. Cannot be updated. More info: https://kubernetes.io/docs/concepts/workloads/pods/init-containers/' + items: + description: A single application container that you want + to run within a pod. + properties: + args: + description: 'Arguments to the entrypoint. The container + image''s CMD is used if this is not provided. Variable + references $(VAR_NAME) are expanded using the container''s + environment. 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. Cannot be updated. More info: + https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell' + items: + type: string + type: array + command: + description: 'Entrypoint array. Not executed within + a shell. The container image''s ENTRYPOINT is used + if this is not provided. Variable references $(VAR_NAME) + are expanded using the container''s environment. 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. Cannot be updated. More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell' + items: + type: string + type: array + env: + description: List of environment variables to set in + the container. Cannot be updated. + 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: + description: 'Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + 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: + description: 'Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + 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 + envFrom: + description: List of sources to populate environment + variables in the container. The keys defined within + a source must be a C_IDENTIFIER. All invalid keys + will be reported as an event when the container is + starting. 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. Cannot be updated. + items: + description: EnvFromSource represents the source of + a set of ConfigMaps + properties: + configMapRef: + description: The ConfigMap to select from + properties: + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + optional: + description: Specify whether the ConfigMap + must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + description: An optional identifier to prepend + to each key in the ConfigMap. Must be a C_IDENTIFIER. + type: string + secretRef: + description: The Secret to select from + properties: + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + optional: + description: Specify whether the Secret must + be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + image: + description: 'Container image name. More info: https://kubernetes.io/docs/concepts/containers/images + This field is optional to allow higher level config + management to default or override container images + in workload controllers like Deployments and StatefulSets.' + type: string + imagePullPolicy: + description: 'Image pull policy. One of Always, Never, + IfNotPresent. Defaults to Always if :latest tag is + specified, or IfNotPresent otherwise. Cannot be updated. + More info: https://kubernetes.io/docs/concepts/containers/images#updating-images' + type: string + lifecycle: + description: Actions that the management system should + take in response to container lifecycle events. Cannot + be updated. + properties: + postStart: + description: 'PostStart is called immediately after + a container is created. If the handler fails, + the container is terminated and restarted according + to its restart policy. Other management of the + container blocks until the hook completes. More + info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks' + properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line + to execute inside the container, the working + directory for the command is root ('/') + in the container's filesystem. The command + is simply exec'd, it is not run inside + a shell, so traditional shell instructions + ('|', etc) won't work. To use a shell, + you need to explicitly call out to that + shell. Exit status of 0 is treated as + live/healthy and non-zero is unhealthy. + items: + type: string + type: array + type: object + httpGet: + description: HTTPGet specifies the http request + to perform. + properties: + host: + description: Host name to connect to, defaults + to the pod IP. You probably want to set + "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the + request. HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom + header to be used in HTTP probes + properties: + name: + description: The header field name. + This will be canonicalized upon + output, so case-variant names will + be understood as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP + server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port + to access on the container. Number must + be in the range 1 to 65535. Name must + be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting + to the host. Defaults to HTTP. + type: string + required: + - port + type: object + tcpSocket: + description: Deprecated. TCPSocket is NOT supported + as a LifecycleHandler and kept for the backward + compatibility. There are no validation of + this field and lifecycle hooks will fail in + runtime when tcp handler is specified. + properties: + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port + to access on the container. Number must + be in the range 1 to 65535. Name must + be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + preStop: + description: 'PreStop is called immediately before + a container is terminated due to an API request + or management event such as liveness/startup probe + failure, preemption, resource contention, etc. + The handler is not called if the container crashes + or exits. The Pod''s termination grace period + countdown begins before the PreStop hook is executed. + Regardless of the outcome of the handler, the + container will eventually terminate within the + Pod''s termination grace period (unless delayed + by finalizers). Other management of the container + blocks until the hook completes or until the termination + grace period is reached. More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks' + properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line + to execute inside the container, the working + directory for the command is root ('/') + in the container's filesystem. The command + is simply exec'd, it is not run inside + a shell, so traditional shell instructions + ('|', etc) won't work. To use a shell, + you need to explicitly call out to that + shell. Exit status of 0 is treated as + live/healthy and non-zero is unhealthy. + items: + type: string + type: array + type: object + httpGet: + description: HTTPGet specifies the http request + to perform. + properties: + host: + description: Host name to connect to, defaults + to the pod IP. You probably want to set + "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the + request. HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom + header to be used in HTTP probes + properties: + name: + description: The header field name. + This will be canonicalized upon + output, so case-variant names will + be understood as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP + server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port + to access on the container. Number must + be in the range 1 to 65535. Name must + be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting + to the host. Defaults to HTTP. + type: string + required: + - port + type: object + tcpSocket: + description: Deprecated. TCPSocket is NOT supported + as a LifecycleHandler and kept for the backward + compatibility. There are no validation of + this field and lifecycle hooks will fail in + runtime when tcp handler is specified. + properties: + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port + to access on the container. Number must + be in the range 1 to 65535. Name must + be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + type: object + livenessProbe: + description: 'Periodic probe of container liveness. + Container will be restarted if the probe fails. Cannot + be updated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to + execute inside the container, the working + directory for the command is root ('/') in + the container's filesystem. The command is + simply exec'd, it is not run inside a shell, + so traditional shell instructions ('|', etc) + won't work. To use a shell, you need to explicitly + call out to that shell. Exit status of 0 is + treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + type: object + failureThreshold: + description: Minimum consecutive failures for the + probe to be considered failed after having succeeded. + Defaults to 3. Minimum value is 1. + format: int32 + type: integer + grpc: + description: GRPC specifies an action involving + a GRPC port. + properties: + port: + description: Port number of the gRPC service. + Number must be in the range 1 to 65535. + format: int32 + type: integer + service: + description: "Service is the name of the service + to place in the gRPC HealthCheckRequest (see + https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + \n If this is not specified, the default behavior + is defined by gRPC." + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies the http request + to perform. + properties: + host: + description: Host name to connect to, defaults + to the pod IP. You probably want to set "Host" + in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the request. + HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom + header to be used in HTTP probes + properties: + name: + description: The header field name. This + will be canonicalized upon output, so + case-variant names will be understood + as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to + the host. Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: 'Number of seconds after the container + has started before liveness probes are initiated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + periodSeconds: + description: How often (in seconds) to perform the + probe. Default to 10 seconds. Minimum value is + 1. + format: int32 + type: integer + successThreshold: + description: Minimum consecutive successes for the + probe to be considered successful after having + failed. Defaults to 1. Must be 1 for liveness + and startup. Minimum value is 1. + format: int32 + type: integer + tcpSocket: + description: TCPSocket specifies an action involving + a TCP port. + properties: + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: Optional duration in seconds the pod + needs to terminate gracefully upon probe failure. + The grace period is the duration in seconds after + the processes running in the pod are sent a termination + signal and the time when the processes are forcibly + halted with a kill signal. Set this value longer + than the expected cleanup time for your process. + If this value is nil, the pod's terminationGracePeriodSeconds + will be used. Otherwise, this value overrides + the value provided by the pod spec. Value must + be non-negative integer. The value zero indicates + stop immediately via the kill signal (no opportunity + to shut down). This is a beta field and requires + enabling ProbeTerminationGracePeriod feature gate. + Minimum value is 1. spec.terminationGracePeriodSeconds + is used if unset. + format: int64 + type: integer + timeoutSeconds: + description: 'Number of seconds after which the + probe times out. Defaults to 1 second. Minimum + value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + type: object + name: + description: Name of the container specified as a DNS_LABEL. + Each container in a pod must have a unique name (DNS_LABEL). + Cannot be updated. + type: string + ports: + description: List of ports to expose from the container. + Not specifying a port here DOES NOT prevent that port + from being exposed. Any port which is listening on + the default "0.0.0.0" address inside a container will + be accessible from the network. Modifying this array + with strategic merge patch may corrupt the data. For + more information See https://github.com/kubernetes/kubernetes/issues/108255. + Cannot be updated. + items: + description: ContainerPort represents a network port + in a single container. + properties: + containerPort: + description: Number of port to expose on the pod's + IP address. This must be a valid port number, + 0 < x < 65536. + format: int32 + type: integer + hostIP: + description: What host IP to bind the external + port to. + type: string + hostPort: + description: Number of port to expose on the host. + If specified, this must be a valid port number, + 0 < x < 65536. If HostNetwork is specified, + this must match ContainerPort. Most containers + do not need this. + format: int32 + type: integer + name: + description: If specified, this must be an IANA_SVC_NAME + and unique within the pod. Each named port in + a pod must have a unique name. Name for the + port that can be referred to by services. + type: string + protocol: + default: TCP + description: Protocol for port. Must be UDP, TCP, + or SCTP. Defaults to "TCP". + type: string + required: + - containerPort + type: object + type: array + x-kubernetes-list-map-keys: + - containerPort + - protocol + x-kubernetes-list-type: map + readinessProbe: + description: 'Periodic probe of container service readiness. + Container will be removed from service endpoints if + the probe fails. Cannot be updated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to + execute inside the container, the working + directory for the command is root ('/') in + the container's filesystem. The command is + simply exec'd, it is not run inside a shell, + so traditional shell instructions ('|', etc) + won't work. To use a shell, you need to explicitly + call out to that shell. Exit status of 0 is + treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + type: object + failureThreshold: + description: Minimum consecutive failures for the + probe to be considered failed after having succeeded. + Defaults to 3. Minimum value is 1. + format: int32 + type: integer + grpc: + description: GRPC specifies an action involving + a GRPC port. + properties: + port: + description: Port number of the gRPC service. + Number must be in the range 1 to 65535. + format: int32 + type: integer + service: + description: "Service is the name of the service + to place in the gRPC HealthCheckRequest (see + https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + \n If this is not specified, the default behavior + is defined by gRPC." + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies the http request + to perform. + properties: + host: + description: Host name to connect to, defaults + to the pod IP. You probably want to set "Host" + in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the request. + HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom + header to be used in HTTP probes + properties: + name: + description: The header field name. This + will be canonicalized upon output, so + case-variant names will be understood + as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to + the host. Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: 'Number of seconds after the container + has started before liveness probes are initiated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + periodSeconds: + description: How often (in seconds) to perform the + probe. Default to 10 seconds. Minimum value is + 1. + format: int32 + type: integer + successThreshold: + description: Minimum consecutive successes for the + probe to be considered successful after having + failed. Defaults to 1. Must be 1 for liveness + and startup. Minimum value is 1. + format: int32 + type: integer + tcpSocket: + description: TCPSocket specifies an action involving + a TCP port. + properties: + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: Optional duration in seconds the pod + needs to terminate gracefully upon probe failure. + The grace period is the duration in seconds after + the processes running in the pod are sent a termination + signal and the time when the processes are forcibly + halted with a kill signal. Set this value longer + than the expected cleanup time for your process. + If this value is nil, the pod's terminationGracePeriodSeconds + will be used. Otherwise, this value overrides + the value provided by the pod spec. Value must + be non-negative integer. The value zero indicates + stop immediately via the kill signal (no opportunity + to shut down). This is a beta field and requires + enabling ProbeTerminationGracePeriod feature gate. + Minimum value is 1. spec.terminationGracePeriodSeconds + is used if unset. + format: int64 + type: integer + timeoutSeconds: + description: 'Number of seconds after which the + probe times out. Defaults to 1 second. Minimum + value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + type: object + resizePolicy: + description: Resources resize policy for the container. + items: + description: ContainerResizePolicy represents resource + resize policy for the container. + properties: + resourceName: + description: 'Name of the resource to which this + resource resize policy applies. Supported values: + cpu, memory.' + type: string + restartPolicy: + description: Restart policy to apply when specified + resource is resized. If not specified, it defaults + to NotRequired. + type: string + required: + - resourceName + - restartPolicy + type: object + type: array + x-kubernetes-list-type: atomic + resources: + description: 'Compute Resources required by this container. + Cannot be updated. More info: 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. \n This is an alpha field and + requires enabling the DynamicResourceAllocation + feature gate. \n 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 + 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 + restartPolicy: + description: 'RestartPolicy defines the restart behavior + of individual containers in a pod. This field may + only be set for init containers, and the only allowed + value is "Always". For non-init containers or when + this field is not specified, the restart behavior + is defined by the Pod''s restart policy and the container + type. Setting the RestartPolicy as "Always" for the + init container will have the following effect: this + init container will be continually restarted on exit + until all regular containers have terminated. Once + all regular containers have completed, all init containers + with restartPolicy "Always" will be shut down. This + lifecycle differs from normal init containers and + is often referred to as a "sidecar" container. Although + this init container still starts in the init container + sequence, it does not wait for the container to complete + before proceeding to the next init container. Instead, + the next init container starts immediately after this + init container is started, or after any startupProbe + has successfully completed.' + type: string + securityContext: + description: 'SecurityContext defines the security options + the container should be run with. If set, the fields + of SecurityContext override the equivalent fields + of PodSecurityContext. More info: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/' + properties: + allowPrivilegeEscalation: + description: 'AllowPrivilegeEscalation controls + whether a process can gain more privileges than + its parent process. This bool directly controls + if the no_new_privs flag will be set on the container + process. AllowPrivilegeEscalation is true always + when the container is: 1) run as Privileged 2) + has CAP_SYS_ADMIN Note that this field cannot + be set when spec.os.name is windows.' + type: boolean + capabilities: + description: The capabilities to add/drop when running + containers. Defaults to the default set of capabilities + granted by the container runtime. Note that this + field cannot be set when spec.os.name is windows. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + type: object + privileged: + description: Run container in privileged mode. Processes + in privileged containers are essentially equivalent + to root on the host. Defaults to false. Note that + this field cannot be set when spec.os.name is + windows. + type: boolean + procMount: + description: procMount denotes the type of proc + mount to use for the containers. The default is + DefaultProcMount which uses the container runtime + defaults for readonly paths and masked paths. + This requires the ProcMountType feature flag to + be enabled. Note that this field cannot be set + when spec.os.name is windows. + type: string + readOnlyRootFilesystem: + description: Whether this container has a read-only + root filesystem. Default is false. Note that this + field cannot be set when spec.os.name is windows. + type: boolean + runAsGroup: + description: The GID to run the entrypoint of the + container process. Uses runtime default if unset. + May also be set in PodSecurityContext. If set + in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name + is windows. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run + as a non-root user. If true, the Kubelet will + validate the image at runtime to ensure that it + does not run as UID 0 (root) and fail to start + the container if it does. If unset or false, no + such validation will be performed. May also be + set in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in + SecurityContext takes precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the + container process. Defaults to user specified + in image metadata if unspecified. May also be + set in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in + SecurityContext takes precedence. Note that this + field cannot be set when spec.os.name is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to + the container. If unspecified, the container runtime + will allocate a random SELinux context for each + container. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name + is windows. + properties: + level: + description: Level is SELinux level label that + applies to the container. + type: string + role: + description: Role is a SELinux role label that + applies to the container. + type: string + type: + description: Type is a SELinux type label that + applies to the container. + type: string + user: + description: User is a SELinux user label that + applies to the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by this + container. If seccomp options are provided at + both the pod & container level, the container + options override the pod options. Note that this + field cannot be set when spec.os.name is windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile + defined in a file on the node should be used. + The profile must be preconfigured on the node + to work. Must be a descending path, relative + to the kubelet's configured seccomp profile + location. Must be set if type is "Localhost". + Must NOT be set for any other type. + type: string + type: + description: "type indicates which kind of seccomp + profile will be applied. Valid options are: + \n Localhost - a profile defined in a file + on the node should be used. RuntimeDefault + - the container runtime default profile should + be used. Unconfined - no profile should be + applied." + type: string + required: + - type + type: object + windowsOptions: + description: The Windows specific settings applied + to all containers. If unspecified, the options + from the PodSecurityContext will be used. If set + in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name + is linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the + GMSA admission webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential + spec named by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name + of the GMSA credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container + should be run as a 'Host Process' container. + All of a Pod's containers must have the same + effective HostProcess value (it is not allowed + to have a mix of HostProcess containers and + non-HostProcess containers). In addition, + if HostProcess is true then HostNetwork must + also be set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run + the entrypoint of the container process. Defaults + to the user specified in image metadata if + unspecified. May also be set in PodSecurityContext. + If set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes + precedence. + type: string + type: object + type: object + startupProbe: + description: 'StartupProbe indicates that the Pod has + successfully initialized. If specified, no other probes + are executed until this completes successfully. If + this probe fails, the Pod will be restarted, just + as if the livenessProbe failed. This can be used to + provide different probe parameters at the beginning + of a Pod''s lifecycle, when it might take a long time + to load data or warm a cache, than during steady-state + operation. This cannot be updated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to + execute inside the container, the working + directory for the command is root ('/') in + the container's filesystem. The command is + simply exec'd, it is not run inside a shell, + so traditional shell instructions ('|', etc) + won't work. To use a shell, you need to explicitly + call out to that shell. Exit status of 0 is + treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + type: object + failureThreshold: + description: Minimum consecutive failures for the + probe to be considered failed after having succeeded. + Defaults to 3. Minimum value is 1. + format: int32 + type: integer + grpc: + description: GRPC specifies an action involving + a GRPC port. + properties: + port: + description: Port number of the gRPC service. + Number must be in the range 1 to 65535. + format: int32 + type: integer + service: + description: "Service is the name of the service + to place in the gRPC HealthCheckRequest (see + https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + \n If this is not specified, the default behavior + is defined by gRPC." + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies the http request + to perform. + properties: + host: + description: Host name to connect to, defaults + to the pod IP. You probably want to set "Host" + in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the request. + HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom + header to be used in HTTP probes + properties: + name: + description: The header field name. This + will be canonicalized upon output, so + case-variant names will be understood + as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to + the host. Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: 'Number of seconds after the container + has started before liveness probes are initiated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + periodSeconds: + description: How often (in seconds) to perform the + probe. Default to 10 seconds. Minimum value is + 1. + format: int32 + type: integer + successThreshold: + description: Minimum consecutive successes for the + probe to be considered successful after having + failed. Defaults to 1. Must be 1 for liveness + and startup. Minimum value is 1. + format: int32 + type: integer + tcpSocket: + description: TCPSocket specifies an action involving + a TCP port. + properties: + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: Optional duration in seconds the pod + needs to terminate gracefully upon probe failure. + The grace period is the duration in seconds after + the processes running in the pod are sent a termination + signal and the time when the processes are forcibly + halted with a kill signal. Set this value longer + than the expected cleanup time for your process. + If this value is nil, the pod's terminationGracePeriodSeconds + will be used. Otherwise, this value overrides + the value provided by the pod spec. Value must + be non-negative integer. The value zero indicates + stop immediately via the kill signal (no opportunity + to shut down). This is a beta field and requires + enabling ProbeTerminationGracePeriod feature gate. + Minimum value is 1. spec.terminationGracePeriodSeconds + is used if unset. + format: int64 + type: integer + timeoutSeconds: + description: 'Number of seconds after which the + probe times out. Defaults to 1 second. Minimum + value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + type: object + stdin: + description: Whether this container should allocate + a buffer for stdin in the container runtime. If this + is not set, reads from stdin in the container will + always result in EOF. Default is false. + type: boolean + stdinOnce: + description: Whether the container runtime should close + the stdin channel after it has been opened by a single + attach. When stdin is true the stdin stream will remain + open across multiple attach sessions. If stdinOnce + is set to true, stdin is opened on container start, + is empty until the first client attaches to stdin, + and then remains open and accepts data until the client + disconnects, at which time stdin is closed and remains + closed until the container is restarted. If this flag + is false, a container processes that reads from stdin + will never receive an EOF. Default is false + type: boolean + terminationMessagePath: + description: 'Optional: Path at which the file to which + the container''s termination message will be written + is mounted into the container''s filesystem. Message + written is intended to be brief final status, such + as an assertion failure message. Will be truncated + by the node if greater than 4096 bytes. The total + message length across all containers will be limited + to 12kb. Defaults to /dev/termination-log. Cannot + be updated.' + type: string + terminationMessagePolicy: + description: Indicate how the termination message should + be populated. File will use the contents of terminationMessagePath + to populate the container status message on both success + and failure. FallbackToLogsOnError will use the last + chunk of container log output if the termination message + file is empty and the container exited with an error. + The log output is limited to 2048 bytes or 80 lines, + whichever is smaller. Defaults to File. Cannot be + updated. + type: string + tty: + description: Whether this container should allocate + a TTY for itself, also requires 'stdin' to be true. + Default is false. + type: boolean + volumeDevices: + description: volumeDevices is the list of block devices + to be used by the container. + items: + description: volumeDevice describes a mapping of a + raw block device within a container. + properties: + devicePath: + description: devicePath is the path inside of + the container that the device will be mapped + to. + type: string + name: + description: name must match the name of a persistentVolumeClaim + in the pod + type: string + required: + - devicePath + - name + type: object + type: array + volumeMounts: + description: Pod volumes to mount into the container's + filesystem. Cannot be updated. + items: + description: VolumeMount describes a mounting of a + Volume within a container. + properties: + mountPath: + description: Path within the container at which + the volume should be mounted. Must not contain + ':'. + type: string + mountPropagation: + description: mountPropagation determines how mounts + are propagated from the host to container and + the other way around. When not set, MountPropagationNone + is used. This field is beta in 1.10. + type: string + name: + description: This must match the Name of a Volume. + type: string + readOnly: + description: Mounted read-only if true, read-write + otherwise (false or unspecified). Defaults to + false. + type: boolean + subPath: + description: Path within the volume from which + the container's volume should be mounted. Defaults + to "" (volume's root). + type: string + subPathExpr: + description: Expanded path within the volume from + which the container's volume should be mounted. + Behaves similarly to SubPath but environment + variable references $(VAR_NAME) are expanded + using the container's environment. Defaults + to "" (volume's root). SubPathExpr and SubPath + are mutually exclusive. + type: string + required: + - mountPath + - name + type: object + type: array + workingDir: + description: Container's working directory. If not specified, + the container runtime's default will be used, which + might be configured in the container image. Cannot + be updated. + type: string + required: + - name + type: object + type: array + nodeName: + description: NodeName is a request to schedule this pod onto + a specific node. If it is non-empty, the scheduler simply + schedules this pod onto that node, assuming that it fits + resource requirements. + type: string + nodeSelector: + additionalProperties: + type: string + description: 'NodeSelector is a selector which must be true + for the pod to fit on a node. Selector which must match + a node''s labels for the pod to be scheduled on that node. + More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/' + type: object + x-kubernetes-map-type: atomic + os: + description: "Specifies the OS of the containers in the pod. + Some pod and container fields are restricted if this is + set. \n If the OS field is set to linux, the following fields + must be unset: -securityContext.windowsOptions \n If the + OS field is set to windows, following fields must be unset: + - spec.hostPID - spec.hostIPC - spec.hostUsers - spec.securityContext.seLinuxOptions + - spec.securityContext.seccompProfile - spec.securityContext.fsGroup + - spec.securityContext.fsGroupChangePolicy - spec.securityContext.sysctls + - spec.shareProcessNamespace - spec.securityContext.runAsUser + - spec.securityContext.runAsGroup - spec.securityContext.supplementalGroups + - spec.containers[*].securityContext.seLinuxOptions - spec.containers[*].securityContext.seccompProfile + - spec.containers[*].securityContext.capabilities - spec.containers[*].securityContext.readOnlyRootFilesystem + - spec.containers[*].securityContext.privileged - spec.containers[*].securityContext.allowPrivilegeEscalation + - spec.containers[*].securityContext.procMount - spec.containers[*].securityContext.runAsUser + - spec.containers[*].securityContext.runAsGroup" + properties: + name: + description: 'Name is the name of the operating system. + The currently supported values are linux and windows. + Additional value may be defined in future and can be + one of: https://github.com/opencontainers/runtime-spec/blob/master/config.md#platform-specific-configuration + Clients should expect to handle additional values and + treat unrecognized values in this field as os: null' + type: string + required: + - name + type: object + overhead: + 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: 'Overhead represents the resource overhead associated + with running a pod for a given RuntimeClass. This field + will be autopopulated at admission time by the RuntimeClass + admission controller. If the RuntimeClass admission controller + is enabled, overhead must not be set in Pod create requests. + The RuntimeClass admission controller will reject Pod create + requests which have the overhead already set. If RuntimeClass + is configured and selected in the PodSpec, Overhead will + be set to the value defined in the corresponding RuntimeClass, + otherwise it will remain unset and treated as zero. More + info: https://git.k8s.io/enhancements/keps/sig-node/688-pod-overhead/README.md' + type: object + preemptionPolicy: + description: PreemptionPolicy is the Policy for preempting + pods with lower priority. One of Never, PreemptLowerPriority. + Defaults to PreemptLowerPriority if unset. + type: string + priority: + description: The priority value. Various system components + use this field to find the priority of the pod. When Priority + Admission Controller is enabled, it prevents users from + setting this field. The admission controller populates this + field from PriorityClassName. The higher the value, the + higher the priority. + format: int32 + type: integer + priorityClassName: + description: If specified, indicates the pod's priority. "system-node-critical" + and "system-cluster-critical" are two special keywords which + indicate the highest priorities with the former being the + highest priority. Any other name must be defined by creating + a PriorityClass object with that name. If not specified, + the pod priority will be default or zero if there is no + default. + type: string + readinessGates: + description: 'If specified, all readiness gates will be evaluated + for pod readiness. A pod is ready when all its containers + are ready AND all conditions specified in the readiness + gates have status equal to "True" More info: https://git.k8s.io/enhancements/keps/sig-network/580-pod-readiness-gates' + items: + description: PodReadinessGate contains the reference to + a pod condition + properties: + conditionType: + description: ConditionType refers to a condition in + the pod's condition list with matching type. + type: string + required: + - conditionType + type: object + type: array + resourceClaims: + description: "ResourceClaims defines which ResourceClaims + must be allocated and reserved before the Pod is allowed + to start. The resources will be made available to those + containers which consume them by name. \n This is an alpha + field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable." + items: + description: PodResourceClaim references exactly one ResourceClaim + through a ClaimSource. It adds a name to it that uniquely + identifies the ResourceClaim inside the Pod. Containers + that need access to the ResourceClaim reference it with + this name. + properties: + name: + description: Name uniquely identifies this resource + claim inside the pod. This must be a DNS_LABEL. + type: string + source: + description: Source describes where to find the ResourceClaim. + properties: + resourceClaimName: + description: ResourceClaimName is the name of a + ResourceClaim object in the same namespace as + this pod. + type: string + resourceClaimTemplateName: + description: "ResourceClaimTemplateName is the name + of a ResourceClaimTemplate object in the same + namespace as this pod. \n The template will be + used to create a new ResourceClaim, which will + be bound to this pod. When this pod is deleted, + the ResourceClaim will also be deleted. The pod + name and resource name, along with a generated + component, will be used to form a unique name + for the ResourceClaim, which will be recorded + in pod.status.resourceClaimStatuses. \n This field + is immutable and no changes will be made to the + corresponding ResourceClaim by the control plane + after creating the ResourceClaim." + type: string + type: object + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + restartPolicy: + description: 'Restart policy for all containers within the + pod. One of Always, OnFailure, Never. In some contexts, + only a subset of those values may be permitted. Default + to Always. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#restart-policy' + type: string + runtimeClassName: + description: 'RuntimeClassName refers to a RuntimeClass object + in the node.k8s.io group, which should be used to run this + pod. If no RuntimeClass resource matches the named class, + the pod will not be run. If unset or empty, the "legacy" + RuntimeClass will be used, which is an implicit class with + an empty definition that uses the default runtime handler. + More info: https://git.k8s.io/enhancements/keps/sig-node/585-runtime-class' + type: string + schedulerName: + description: If specified, the pod will be dispatched by specified + scheduler. If not specified, the pod will be dispatched + by default scheduler. + type: string + schedulingGates: + description: "SchedulingGates is an opaque list of values + that if specified will block scheduling the pod. If schedulingGates + is not empty, the pod will stay in the SchedulingGated state + and the scheduler will not attempt to schedule the pod. + \n SchedulingGates can only be set at pod creation time, + and be removed only afterwards. \n This is a beta feature + enabled by the PodSchedulingReadiness feature gate." + items: + description: PodSchedulingGate is associated to a Pod to + guard its scheduling. + properties: + name: + description: Name of the scheduling gate. Each scheduling + gate must have a unique name field. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + securityContext: + description: 'SecurityContext holds pod-level security attributes + and common container settings. Optional: Defaults to empty. See + type description for default values of each field.' + properties: + fsGroup: + description: "A special supplemental group that applies + to all containers in a pod. Some volume types allow + the Kubelet to change the ownership of that volume to + be owned by the pod: \n 1. The owning GID will be the + FSGroup 2. The setgid bit is set (new files created + in the volume will be owned by FSGroup) 3. The permission + bits are OR'd with rw-rw---- \n If unset, the Kubelet + will not modify the ownership and permissions of any + volume. Note that this field cannot be set when spec.os.name + is windows." + format: int64 + type: integer + fsGroupChangePolicy: + description: 'fsGroupChangePolicy defines behavior of + changing ownership and permission of the volume before + being exposed inside Pod. This field will only apply + to volume types which support fsGroup based ownership(and + permissions). It will have no effect on ephemeral volume + types such as: secret, configmaps and emptydir. Valid + values are "OnRootMismatch" and "Always". If not specified, + "Always" is used. Note that this field cannot be set + when spec.os.name is windows.' + type: string + runAsGroup: + description: The GID to run the entrypoint of the container + process. Uses runtime default if unset. May also be + set in SecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence for that container. Note that this + field cannot be set when spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as + a non-root user. If true, the Kubelet will validate + the image at runtime to ensure that it does not run + as UID 0 (root) and fail to start the container if it + does. If unset or false, no such validation will be + performed. May also be set in SecurityContext. If set + in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container + process. Defaults to user specified in image metadata + if unspecified. May also be set in SecurityContext. If + set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence + for that container. Note that this field cannot be set + when spec.os.name is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to all + containers. If unspecified, the container runtime will + allocate a random SELinux context for each container. May + also be set in SecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence for that container. Note that this + field cannot be set when spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by the containers + in this pod. Note that this field cannot be set when + spec.os.name is windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile + defined in a file on the node should be used. The + profile must be preconfigured on the node to work. + Must be a descending path, relative to the kubelet's + configured seccomp profile location. Must be set + if type is "Localhost". Must NOT be set for any + other type. + type: string + type: + description: "type indicates which kind of seccomp + profile will be applied. Valid options are: \n Localhost + - a profile defined in a file on the node should + be used. RuntimeDefault - the container runtime + default profile should be used. Unconfined - no + profile should be applied." + type: string + required: + - type + type: object + supplementalGroups: + description: A list of groups applied to the first process + run in each container, in addition to the container's + primary GID, the fsGroup (if specified), and group memberships + defined in the container image for the uid of the container + process. If unspecified, no additional groups are added + to any container. Note that group memberships defined + in the container image for the uid of the container + process are still effective, even if they are not included + in this list. Note that this field cannot be set when + spec.os.name is windows. + items: + format: int64 + type: integer + type: array + sysctls: + description: Sysctls hold a list of namespaced sysctls + used for the pod. Pods with unsupported sysctls (by + the container runtime) might fail to launch. Note that + this field cannot be set when spec.os.name is windows. + items: + description: Sysctl defines a kernel parameter to be + set + properties: + name: + description: Name of a property to set + type: string + value: + description: Value of a property to set + type: string + required: + - name + - value + type: object + type: array + windowsOptions: + description: The Windows specific settings applied to + all containers. If unspecified, the options within a + container's SecurityContext will be used. If set in + both SecurityContext and PodSecurityContext, the value + specified in SecurityContext takes precedence. Note + that this field cannot be set when spec.os.name is linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA + admission webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec + named by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of + the GMSA credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container + should be run as a 'Host Process' container. All + of a Pod's containers must have the same effective + HostProcess value (it is not allowed to have a mix + of HostProcess containers and non-HostProcess containers). + In addition, if HostProcess is true then HostNetwork + must also be set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set + in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. + type: string + type: object + type: object + serviceAccount: + description: 'DeprecatedServiceAccount is a depreciated alias + for ServiceAccountName. Deprecated: Use serviceAccountName + instead.' + type: string + serviceAccountName: + description: 'ServiceAccountName is the name of the ServiceAccount + to use to run this pod. More info: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/' + type: string + setHostnameAsFQDN: + description: If true the pod's hostname will be configured + as the pod's FQDN, rather than the leaf name (the default). + In Linux containers, this means setting the FQDN in the + hostname field of the kernel (the nodename field of struct + utsname). In Windows containers, this means setting the + registry value of hostname for the registry key HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters + to FQDN. If a pod does not have FQDN, this has no effect. + Default to false. + type: boolean + shareProcessNamespace: + description: 'Share a single process namespace between all + of the containers in a pod. When this is set containers + will be able to view and signal processes from other containers + in the same pod, and the first process in each container + will not be assigned PID 1. HostPID and ShareProcessNamespace + cannot both be set. Optional: Default to false.' + type: boolean + subdomain: + description: If specified, the fully qualified Pod hostname + will be "...svc.". If not specified, the pod will not have a domainname + at all. + type: string + terminationGracePeriodSeconds: + description: Optional duration in seconds the pod needs to + terminate gracefully. May be decreased in delete request. + Value must be non-negative integer. The value zero indicates + stop immediately via the kill signal (no opportunity to + shut down). If this value is nil, the default grace period + will be used instead. The grace period is the duration in + seconds after the processes running in the pod are sent + a termination signal and the time when the processes are + forcibly halted with a kill signal. Set this value longer + than the expected cleanup time for your process. Defaults + to 30 seconds. + format: int64 + type: integer + tolerations: + description: If specified, the pod's tolerations. + 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: TopologySpreadConstraints describes how a group + of pods ought to spread across topology domains. Scheduler + will schedule pods in a way which abides by the constraints. + All topologySpreadConstraints are ANDed. + 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 + required: + - key + - operator + type: object + type: array + 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. Keys that don't exist in + the incoming pod labels will be ignored. A null or + empty list means only match against labelSelector. + \n This is a beta field and requires the MatchLabelKeysInPodTopologySpread + feature gate to be enabled (enabled by default)." + 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. + For example, in a 3-zone cluster, MaxSkew is set to + 1, and pods with the same labelSelector spread as + 2/2/1: In this case, the global minimum is 1. | zone1 + | zone2 | zone3 | | P P | P P | P | - if MaxSkew + is 1, incoming pod can only be scheduled to zone3 + to become 2/2/2; scheduling it onto zone1(zone2) would + make the ActualSkew(3-1) on zone1(zone2) violate MaxSkew(1). + - if MaxSkew is 2, incoming pod can be scheduled onto + any zone. When `whenUnsatisfiable=ScheduleAnyway`, + it is used to give higher precedence to topologies + that satisfy it. It''s a required field. Default value + is 1 and 0 is not allowed.' + 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. As a result, when + the number of eligible domains is less than minDomains, + scheduler won't schedule more than maxSkew Pods to + those domains. If value is nil, the constraint behaves + as if MinDomains is equal to 1. Valid values are integers + greater than 0. When value is not nil, WhenUnsatisfiable + must be DoNotSchedule. \n For example, in a 3-zone + cluster, MaxSkew is set to 2, MinDomains is set to + 5 and pods with the same labelSelector spread as 2/2/2: + | zone1 | zone2 | zone3 | | P P | P P | P P | + The number of domains is less than 5(MinDomains), + so \"global minimum\" is treated as 0. In this situation, + new pod with the same labelSelector cannot be scheduled, + because computed skew will be 3(3 - 0) if new Pod + is scheduled to any of the three zones, it will violate + MaxSkew. \n This is a beta field and requires the + MinDomainsInPodTopologySpread feature gate to be enabled + (enabled by default)." + 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. + \n 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. \n 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.io/hostname", + each Node is a domain of that topology. And, if TopologyKey + is "topology.kubernetes.io/zone", each zone is a domain + of that topology. It's a required field. + 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. For example, in a 3-zone cluster, MaxSkew + is set to 1, and pods with the same labelSelector + spread as 3/1/1: | zone1 | zone2 | zone3 | | P P P + | P | P | If WhenUnsatisfiable is set to DoNotSchedule, + incoming pod can only be scheduled to zone2(zone3) + to become 3/2/1(3/1/2) as ActualSkew(2-1) on zone2(zone3) + satisfies MaxSkew(1). In other words, the cluster + can still be imbalanced, but scheduler won''t make + it *more* imbalanced. It''s a required field.' + type: string + required: + - maxSkew + - topologyKey + - whenUnsatisfiable + type: object + type: array + x-kubernetes-list-map-keys: + - topologyKey + - whenUnsatisfiable + x-kubernetes-list-type: map + volumes: + description: 'List of volumes that can be mounted by containers + belonging to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes' + items: + description: Volume represents a named volume in a pod that + may be accessed by any container in the pod. + properties: + awsElasticBlockStore: + description: 'awsElasticBlockStore represents an AWS + Disk resource that is attached to a kubelet''s host + machine and then exposed to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' + properties: + fsType: + description: 'fsType is the filesystem type of the + volume that you want to mount. Tip: Ensure that + the filesystem type is supported by the host operating + system. Examples: "ext4", "xfs", "ntfs". Implicitly + inferred to be "ext4" if unspecified. More info: + https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore + TODO: how do we prevent errors in the filesystem + from compromising the machine' + type: string + partition: + description: 'partition is the partition in the + volume that you want to mount. If omitted, the + default is to mount by volume name. Examples: + For volume /dev/sda1, you specify the partition + as "1". Similarly, the volume partition for /dev/sda + is "0" (or you can leave the property empty).' + format: int32 + type: integer + readOnly: + description: 'readOnly value true will force the + readOnly setting in VolumeMounts. More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' + type: boolean + volumeID: + description: 'volumeID is unique ID of the persistent + disk resource in AWS (Amazon EBS volume). More + info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' + type: string + required: + - volumeID + type: object + azureDisk: + description: azureDisk represents an Azure Data Disk + mount on the host and bind mount to the pod. + properties: + cachingMode: + description: 'cachingMode is the Host Caching mode: + None, Read Only, Read Write.' + type: string + diskName: + description: diskName is the Name of the data disk + in the blob storage + type: string + diskURI: + description: diskURI is the URI of data disk in + the blob storage + type: string + fsType: + description: fsType is Filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". Implicitly + inferred to be "ext4" if unspecified. + type: string + kind: + description: 'kind expected values are Shared: multiple + blob disks per storage account Dedicated: single + blob disk per storage account Managed: azure + managed data disk (only in managed availability + set). defaults to shared' + type: string + readOnly: + description: readOnly Defaults to false (read/write). + ReadOnly here will force the ReadOnly setting + in VolumeMounts. + type: boolean + required: + - diskName + - diskURI + type: object + azureFile: + description: azureFile represents an Azure File Service + mount on the host and bind mount to the pod. + properties: + readOnly: + description: readOnly defaults to false (read/write). + ReadOnly here will force the ReadOnly setting + in VolumeMounts. + type: boolean + secretName: + description: secretName is the name of secret that + contains Azure Storage Account Name and Key + type: string + shareName: + description: shareName is the azure share Name + type: string + required: + - secretName + - shareName + type: object + cephfs: + description: cephFS represents a Ceph FS mount on the + host that shares a pod's lifetime + properties: + monitors: + description: 'monitors is Required: Monitors is + a collection of Ceph monitors More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + items: + type: string + type: array + path: + description: 'path is Optional: Used as the mounted + root, rather than the full Ceph tree, default + is /' + type: string + readOnly: + description: 'readOnly is Optional: Defaults to + false (read/write). ReadOnly here will force the + ReadOnly setting in VolumeMounts. More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + type: boolean + secretFile: + description: 'secretFile is Optional: SecretFile + is the path to key ring for User, default is /etc/ceph/user.secret + More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + type: string + secretRef: + description: 'secretRef is Optional: SecretRef is + reference to the authentication secret for User, + default is empty. More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + properties: + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + type: object + x-kubernetes-map-type: atomic + user: + description: 'user is optional: User is the rados + user name, default is admin More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + type: string + required: + - monitors + type: object + cinder: + description: 'cinder represents a cinder volume attached + and mounted on kubelets host machine. More info: https://examples.k8s.io/mysql-cinder-pd/README.md' + properties: + fsType: + description: 'fsType is the filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Examples: "ext4", "xfs", "ntfs". + Implicitly inferred to be "ext4" if unspecified. + More info: https://examples.k8s.io/mysql-cinder-pd/README.md' + type: string + readOnly: + description: 'readOnly defaults to false (read/write). + ReadOnly here will force the ReadOnly setting + in VolumeMounts. More info: https://examples.k8s.io/mysql-cinder-pd/README.md' + type: boolean + secretRef: + description: 'secretRef is optional: points to a + secret object containing parameters used to connect + to OpenStack.' + properties: + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + type: object + x-kubernetes-map-type: atomic + volumeID: + description: 'volumeID used to identify the volume + in cinder. More info: https://examples.k8s.io/mysql-cinder-pd/README.md' + type: string + required: + - volumeID + type: object + configMap: + description: configMap represents a configMap that should + populate this volume + properties: + defaultMode: + description: 'defaultMode is optional: mode bits + used to set permissions on created files by default. + Must be an octal value between 0000 and 0777 or + a decimal value between 0 and 511. YAML accepts + both octal and decimal values, JSON requires decimal + values for mode bits. Defaults to 0644. Directories + within the path are not affected by this setting. + This might be in conflict with other options that + affect the file mode, like fsGroup, and the result + can be other mode bits set.' + format: int32 + type: integer + items: + description: items if unspecified, each key-value + pair in the Data field of the referenced ConfigMap + will be projected into the volume as a file whose + name is the key and content is the value. If specified, + the listed keys will be projected into the specified + paths, and unlisted keys will not be present. + If a key is specified which is not present in + the ConfigMap, the volume setup will error unless + it is marked optional. Paths must be relative + and may not contain the '..' path or start with + '..'. + items: + description: Maps a string key to a path within + a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: mode bits + used to set permissions on this file. Must + be an octal value between 0000 and 0777 + or a decimal value between 0 and 511. YAML + accepts both octal and decimal values, JSON + requires decimal values for mode bits. If + not specified, the volume defaultMode will + be used. This might be in conflict with + other options that affect the file mode, + like fsGroup, and the result can be other + mode bits set.' + format: int32 + type: integer + path: + description: path is the relative path of + the file to map the key to. May not be an + absolute path. May not contain the path + element '..'. May not start with the string + '..'. + type: string + required: + - key + - path + type: object + type: array + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: optional specify whether the ConfigMap + or its keys must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + csi: + description: csi (Container Storage Interface) represents + ephemeral storage that is handled by certain external + CSI drivers (Beta feature). + properties: + driver: + description: driver is the name of the CSI driver + that handles this volume. Consult with your admin + for the correct name as registered in the cluster. + type: string + fsType: + description: fsType to mount. Ex. "ext4", "xfs", + "ntfs". If not provided, the empty value is passed + to the associated CSI driver which will determine + the default filesystem to apply. + type: string + nodePublishSecretRef: + description: nodePublishSecretRef is a reference + to the secret object containing sensitive information + to pass to the CSI driver to complete the CSI + NodePublishVolume and NodeUnpublishVolume calls. + This field is optional, and may be empty if no + secret is required. If the secret object contains + more than one secret, all secret references are + passed. + properties: + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + type: object + x-kubernetes-map-type: atomic + readOnly: + description: readOnly specifies a read-only configuration + for the volume. Defaults to false (read/write). + type: boolean + volumeAttributes: + additionalProperties: + type: string + description: volumeAttributes stores driver-specific + properties that are passed to the CSI driver. + Consult your driver's documentation for supported + values. + type: object + required: + - driver + type: object + downwardAPI: + description: downwardAPI represents downward API about + the pod that should populate this volume + properties: + defaultMode: + description: 'Optional: mode bits to use on created + files by default. Must be a Optional: mode bits + used to set permissions on created files by default. + Must be an octal value between 0000 and 0777 or + a decimal value between 0 and 511. YAML accepts + both octal and decimal values, JSON requires decimal + values for mode bits. Defaults to 0644. Directories + within the path are not affected by this setting. + This might be in conflict with other options that + affect the file mode, like fsGroup, and the result + can be other mode bits set.' + format: int32 + type: integer + items: + description: Items is a list of downward API volume + file + items: + description: DownwardAPIVolumeFile represents + information to create the file containing the + pod field + properties: + fieldRef: + description: 'Required: Selects a field of + the pod: only annotations, labels, name + and namespace are supported.' + 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 + mode: + description: 'Optional: mode bits used to + set permissions on this file, must be an + octal value between 0000 and 0777 or a decimal + value between 0 and 511. YAML accepts both + octal and decimal values, JSON requires + decimal values for mode bits. If not specified, + the volume defaultMode will be used. This + might be in conflict with other options + that affect the file mode, like fsGroup, + and the result can be other mode bits set.' + format: int32 + type: integer + path: + description: 'Required: Path is the relative + path name of the file to be created. Must + not be absolute or contain the ''..'' path. + Must be utf-8 encoded. The first item of + the relative path must not start with ''..''' + type: string + resourceFieldRef: + description: 'Selects a resource of the container: + only resources limits and requests (limits.cpu, + limits.memory, requests.cpu and requests.memory) + 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 + required: + - path + type: object + type: array + type: object + emptyDir: + description: 'emptyDir represents a temporary directory + that shares a pod''s lifetime. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' + properties: + medium: + description: 'medium represents what type of storage + medium should back this directory. The default + is "" which means to use the node''s default medium. + Must be an empty string (default) or Memory. More + info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' + type: string + sizeLimit: + anyOf: + - type: integer + - type: string + description: 'sizeLimit is the total amount of local + storage required for this EmptyDir volume. The + size limit is also applicable for memory medium. + The maximum usage on memory medium EmptyDir would + be the minimum value between the SizeLimit specified + here and the sum of memory limits of all containers + in a pod. The default is nil which means that + the limit is undefined. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + ephemeral: + description: "ephemeral represents a volume that is + handled by a cluster storage driver. The volume's + lifecycle is tied to the pod that defines it - it + will be created before the pod starts, and deleted + when the pod is removed. \n Use this if: a) the volume + is only needed while the pod runs, b) features of + normal volumes like restoring from snapshot or capacity + tracking are needed, c) the storage driver is specified + through a storage class, and d) the storage driver + supports dynamic volume provisioning through a PersistentVolumeClaim + (see EphemeralVolumeSource for more information on + the connection between this volume type and PersistentVolumeClaim). + \n Use PersistentVolumeClaim or one of the vendor-specific + APIs for volumes that persist for longer than the + lifecycle of an individual pod. \n Use CSI for light-weight + local ephemeral volumes if the CSI driver is meant + to be used that way - see the documentation of the + driver for more information. \n A pod can use both + types of ephemeral volumes and persistent volumes + at the same time." + properties: + volumeClaimTemplate: + description: "Will be used to create a stand-alone + PVC to provision the volume. The pod in which + this EphemeralVolumeSource is embedded will be + the owner of the PVC, i.e. the PVC will be deleted + together with the pod. The name of the PVC will + be `-` where `` + is the name from the `PodSpec.Volumes` array entry. + Pod validation will reject the pod if the concatenated + name is not valid for a PVC (for example, too + long). \n An existing PVC with that name that + is not owned by the pod will *not* be used for + the pod to avoid using an unrelated volume by + mistake. Starting the pod is then blocked until + the unrelated PVC is removed. If such a pre-created + PVC is meant to be used by the pod, the PVC has + to updated with an owner reference to the pod + once the pod exists. Normally this should not + be necessary, but it may be useful when manually + reconstructing a broken cluster. \n This field + is read-only and no changes will be made by Kubernetes + to the PVC after it has been created. \n Required, + must not be nil." + properties: + metadata: + description: May contain labels and annotations + that will be copied into the PVC when creating + it. No other fields are allowed and will be + rejected during validation. + type: object + spec: + description: The specification for the PersistentVolumeClaim. + The entire content is copied unchanged into + the PVC that gets created from this template. + The same fields as in a PersistentVolumeClaim + are also valid here. + properties: + accessModes: + description: 'accessModes contains the desired + access modes the volume should have. More + info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' + items: + type: string + type: array + dataSource: + description: 'dataSource field can be used + to specify either: * An existing VolumeSnapshot + object (snapshot.storage.k8s.io/VolumeSnapshot) + * An existing PVC (PersistentVolumeClaim) + If the provisioner or an external controller + can support the specified data source, + it will create a new volume based on the + contents of the specified data source. + When the AnyVolumeDataSource feature gate + is enabled, dataSource contents will be + copied to dataSourceRef, and dataSourceRef + contents will be copied to dataSource + when dataSourceRef.namespace is not specified. + If the namespace is specified, then dataSourceRef + will not be copied to dataSource.' + properties: + apiGroup: + description: APIGroup is the group for + the resource being referenced. If + APIGroup is not specified, the specified + Kind must be in the core API group. + For any other third-party types, APIGroup + is required. + type: string + kind: + description: Kind is the type of resource + being referenced + type: string + name: + description: Name is the name of resource + being referenced + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + description: 'dataSourceRef specifies the + object from which to populate the volume + with data, if a non-empty volume is desired. + This may be any object from a non-empty + API group (non core object) or a PersistentVolumeClaim + object. When this field is specified, + volume binding will only succeed if the + type of the specified object matches some + installed volume populator or dynamic + provisioner. This field will replace the + functionality of the dataSource field + and as such if both fields are non-empty, + they must have the same value. For backwards + compatibility, when namespace isn''t specified + in dataSourceRef, both fields (dataSource + and dataSourceRef) will be set to the + same value automatically if one of them + is empty and the other is non-empty. When + namespace is specified in dataSourceRef, + dataSource isn''t set to the same value + and must be empty. There are three important + differences between dataSource and dataSourceRef: + * While dataSource only allows two specific + types of objects, dataSourceRef allows + any non-core object, as well as PersistentVolumeClaim + objects. * While dataSource ignores disallowed + values (dropping them), dataSourceRef + preserves all values, and generates an + error if a disallowed value is specified. + * While dataSource only allows local objects, + dataSourceRef allows objects in any namespaces. + (Beta) Using this field requires the AnyVolumeDataSource + feature gate to be enabled. (Alpha) Using + the namespace field of dataSourceRef requires + the CrossNamespaceVolumeDataSource feature + gate to be enabled.' + properties: + apiGroup: + description: APIGroup is the group for + the resource being referenced. If + APIGroup is not specified, the specified + Kind must be in the core API group. + For any other third-party types, APIGroup + is required. + type: string + kind: + description: Kind is the type of resource + being referenced + type: string + name: + description: Name is the name of resource + being referenced + type: string + namespace: + description: Namespace is the namespace + of resource being referenced Note + that when a namespace is specified, + a gateway.networking.k8s.io/ReferenceGrant + object is required in the referent + namespace to allow that namespace's + owner to accept the reference. See + the ReferenceGrant documentation for + details. (Alpha) This field requires + the CrossNamespaceVolumeDataSource + feature gate to be enabled. + type: string + required: + - kind + - name + type: object + resources: + description: 'resources represents the minimum + resources the volume should have. If RecoverVolumeExpansionFailure + feature is enabled users are allowed to + specify resource requirements that are + lower than previous value but must still + be higher than capacity recorded in the + status field of the claim. More info: + https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' + properties: + claims: + description: "Claims lists the names + of resources, defined in spec.resourceClaims, + that are used by this container. \n + This is an alpha field and requires + enabling the DynamicResourceAllocation + feature gate. \n 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 + 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 + selector: + description: selector is a label query over + volumes to consider for binding. + 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 + required: + - key + - operator + type: object + type: array + 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 + storageClassName: + description: 'storageClassName is the name + of the StorageClass required by the claim. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' + type: string + volumeMode: + description: volumeMode defines what type + of volume is required by the claim. Value + of Filesystem is implied when not included + in claim spec. + type: string + volumeName: + description: volumeName is the binding reference + to the PersistentVolume backing this claim. + type: string + type: object + required: + - spec + type: object + type: object + fc: + description: fc represents a Fibre Channel resource + that is attached to a kubelet's host machine and then + exposed to the pod. + properties: + fsType: + description: 'fsType is the filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". Implicitly + inferred to be "ext4" if unspecified. TODO: how + do we prevent errors in the filesystem from compromising + the machine' + type: string + lun: + description: 'lun is Optional: FC target lun number' + format: int32 + type: integer + readOnly: + description: 'readOnly is Optional: Defaults to + false (read/write). ReadOnly here will force the + ReadOnly setting in VolumeMounts.' + type: boolean + targetWWNs: + description: 'targetWWNs is Optional: FC target + worldwide names (WWNs)' + items: + type: string + type: array + wwids: + description: 'wwids Optional: FC volume world wide + identifiers (wwids) Either wwids or combination + of targetWWNs and lun must be set, but not both + simultaneously.' + items: + type: string + type: array + type: object + flexVolume: + description: flexVolume represents a generic volume + resource that is provisioned/attached using an exec + based plugin. + properties: + driver: + description: driver is the name of the driver to + use for this volume. + type: string + fsType: + description: fsType is the filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". The + default filesystem depends on FlexVolume script. + type: string + options: + additionalProperties: + type: string + description: 'options is Optional: this field holds + extra command options if any.' + type: object + readOnly: + description: 'readOnly is Optional: defaults to + false (read/write). ReadOnly here will force the + ReadOnly setting in VolumeMounts.' + type: boolean + secretRef: + description: 'secretRef is Optional: secretRef is + reference to the secret object containing sensitive + information to pass to the plugin scripts. This + may be empty if no secret object is specified. + If the secret object contains more than one secret, + all secrets are passed to the plugin scripts.' + properties: + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + type: object + x-kubernetes-map-type: atomic + required: + - driver + type: object + flocker: + description: flocker represents a Flocker volume attached + to a kubelet's host machine. This depends on the Flocker + control service being running + properties: + datasetName: + description: datasetName is Name of the dataset + stored as metadata -> name on the dataset for + Flocker should be considered as deprecated + type: string + datasetUUID: + description: datasetUUID is the UUID of the dataset. + This is unique identifier of a Flocker dataset + type: string + type: object + gcePersistentDisk: + description: 'gcePersistentDisk represents a GCE Disk + resource that is attached to a kubelet''s host machine + and then exposed to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' + properties: + fsType: + description: 'fsType is filesystem type of the volume + that you want to mount. Tip: Ensure that the filesystem + type is supported by the host operating system. + Examples: "ext4", "xfs", "ntfs". Implicitly inferred + to be "ext4" if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk + TODO: how do we prevent errors in the filesystem + from compromising the machine' + type: string + partition: + description: 'partition is the partition in the + volume that you want to mount. If omitted, the + default is to mount by volume name. Examples: + For volume /dev/sda1, you specify the partition + as "1". Similarly, the volume partition for /dev/sda + is "0" (or you can leave the property empty). + More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' + format: int32 + type: integer + pdName: + description: 'pdName is unique name of the PD resource + in GCE. Used to identify the disk in GCE. More + info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' + type: string + readOnly: + description: 'readOnly here will force the ReadOnly + setting in VolumeMounts. Defaults to false. More + info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' + type: boolean + required: + - pdName + type: object + gitRepo: + description: 'gitRepo represents a git repository at + a particular revision. DEPRECATED: GitRepo is deprecated. + To provision a container with a git repo, mount an + EmptyDir into an InitContainer that clones the repo + using git, then mount the EmptyDir into the Pod''s + container.' + properties: + directory: + description: directory is the target directory name. + Must not contain or start with '..'. If '.' is + supplied, the volume directory will be the git + repository. Otherwise, if specified, the volume + will contain the git repository in the subdirectory + with the given name. + type: string + repository: + description: repository is the URL + type: string + revision: + description: revision is the commit hash for the + specified revision. + type: string + required: + - repository + type: object + glusterfs: + description: 'glusterfs represents a Glusterfs mount + on the host that shares a pod''s lifetime. More info: + https://examples.k8s.io/volumes/glusterfs/README.md' + properties: + endpoints: + description: 'endpoints is the endpoint name that + details Glusterfs topology. More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' + type: string + path: + description: 'path is the Glusterfs volume path. + More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' + type: string + readOnly: + description: 'readOnly here will force the Glusterfs + volume to be mounted with read-only permissions. + Defaults to false. More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' + type: boolean + required: + - endpoints + - path + type: object + hostPath: + description: 'hostPath represents a pre-existing file + or directory on the host machine that is directly + exposed to the container. This is generally used for + system agents or other privileged things that are + allowed to see the host machine. Most containers will + NOT need this. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath + --- TODO(jonesdl) We need to restrict who can use + host directory mounts and who can/can not mount host + directories as read/write.' + properties: + path: + description: 'path of the directory on the host. + If the path is a symlink, it will follow the link + to the real path. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath' + type: string + type: + description: 'type for HostPath Volume Defaults + to "" More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath' + type: string + required: + - path + type: object + iscsi: + description: 'iscsi represents an ISCSI Disk resource + that is attached to a kubelet''s host machine and + then exposed to the pod. More info: https://examples.k8s.io/volumes/iscsi/README.md' + properties: + chapAuthDiscovery: + description: chapAuthDiscovery defines whether support + iSCSI Discovery CHAP authentication + type: boolean + chapAuthSession: + description: chapAuthSession defines whether support + iSCSI Session CHAP authentication + type: boolean + fsType: + description: 'fsType is the filesystem type of the + volume that you want to mount. Tip: Ensure that + the filesystem type is supported by the host operating + system. Examples: "ext4", "xfs", "ntfs". Implicitly + inferred to be "ext4" if unspecified. More info: + https://kubernetes.io/docs/concepts/storage/volumes#iscsi + TODO: how do we prevent errors in the filesystem + from compromising the machine' + type: string + initiatorName: + description: initiatorName is the custom iSCSI Initiator + Name. If initiatorName is specified with iscsiInterface + simultaneously, new iSCSI interface : will be created for the connection. + type: string + iqn: + description: iqn is the target iSCSI Qualified Name. + type: string + iscsiInterface: + description: iscsiInterface is the interface Name + that uses an iSCSI transport. Defaults to 'default' + (tcp). + type: string + lun: + description: lun represents iSCSI Target Lun number. + format: int32 + type: integer + portals: + description: portals is the iSCSI Target Portal + List. The portal is either an IP or ip_addr:port + if the port is other than default (typically TCP + ports 860 and 3260). + items: + type: string + type: array + readOnly: + description: readOnly here will force the ReadOnly + setting in VolumeMounts. Defaults to false. + type: boolean + secretRef: + description: secretRef is the CHAP Secret for iSCSI + target and initiator authentication + properties: + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + type: object + x-kubernetes-map-type: atomic + targetPortal: + description: targetPortal is iSCSI Target Portal. + The Portal is either an IP or ip_addr:port if + the port is other than default (typically TCP + ports 860 and 3260). + type: string + required: + - iqn + - lun + - targetPortal + type: object + name: + description: 'name of the volume. Must be a DNS_LABEL + and unique within the pod. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + nfs: + description: 'nfs represents an NFS mount on the host + that shares a pod''s lifetime More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' + properties: + path: + description: 'path that is exported by the NFS server. + More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' + type: string + readOnly: + description: 'readOnly here will force the NFS export + to be mounted with read-only permissions. Defaults + to false. More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' + type: boolean + server: + description: 'server is the hostname or IP address + of the NFS server. More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' + type: string + required: + - path + - server + type: object + persistentVolumeClaim: + description: 'persistentVolumeClaimVolumeSource represents + a reference to a PersistentVolumeClaim in the same + namespace. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' + properties: + claimName: + description: 'claimName is the name of a PersistentVolumeClaim + in the same namespace as the pod using this volume. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' + type: string + readOnly: + description: readOnly Will force the ReadOnly setting + in VolumeMounts. Default false. + type: boolean + required: + - claimName + type: object + photonPersistentDisk: + description: photonPersistentDisk represents a PhotonController + persistent disk attached and mounted on kubelets host + machine + properties: + fsType: + description: fsType is the filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". Implicitly + inferred to be "ext4" if unspecified. + type: string + pdID: + description: pdID is the ID that identifies Photon + Controller persistent disk + type: string + required: + - pdID + type: object + portworxVolume: + description: portworxVolume represents a portworx volume + attached and mounted on kubelets host machine + properties: + fsType: + description: fSType represents the filesystem type + to mount Must be a filesystem type supported by + the host operating system. Ex. "ext4", "xfs". + Implicitly inferred to be "ext4" if unspecified. + type: string + readOnly: + description: readOnly defaults to false (read/write). + ReadOnly here will force the ReadOnly setting + in VolumeMounts. + type: boolean + volumeID: + description: volumeID uniquely identifies a Portworx + volume + type: string + required: + - volumeID + type: object + projected: + description: projected items for all in one resources + secrets, configmaps, and downward API + properties: + defaultMode: + description: defaultMode are the mode bits used + to set permissions on created files by default. + Must be an octal value between 0000 and 0777 or + a decimal value between 0 and 511. YAML accepts + both octal and decimal values, JSON requires decimal + values for mode bits. Directories within the path + are not affected by this setting. This might be + in conflict with other options that affect the + file mode, like fsGroup, and the result can be + other mode bits set. + format: int32 + type: integer + sources: + description: sources is the list of volume projections + items: + description: Projection that may be projected + along with other supported volume types + properties: + configMap: + description: configMap information about the + configMap data to project + properties: + items: + description: items if unspecified, each + key-value pair in the Data field of + the referenced ConfigMap will be projected + into the volume as a file whose name + is the key and content is the value. + If specified, the listed keys will be + projected into the specified paths, + and unlisted keys will not be present. + If a key is specified which is not present + in the ConfigMap, the volume setup will + error unless it is marked optional. + Paths must be relative and may not contain + the '..' path or start with '..'. + items: + description: Maps a string key to a + path within a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: + mode bits used to set permissions + on this file. Must be an octal + value between 0000 and 0777 or + a decimal value between 0 and + 511. YAML accepts both octal and + decimal values, JSON requires + decimal values for mode bits. + If not specified, the volume defaultMode + will be used. This might be in + conflict with other options that + affect the file mode, like fsGroup, + and the result can be other mode + bits set.' + format: int32 + type: integer + path: + description: path is the relative + path of the file to map the key + to. May not be an absolute path. + May not contain the path element + '..'. May not start with the string + '..'. + type: string + required: + - key + - path + type: object + type: array + name: + description: 'Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + optional: + description: optional specify whether + the ConfigMap or its keys must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + downwardAPI: + description: downwardAPI information about + the downwardAPI data to project + properties: + items: + description: Items is a list of DownwardAPIVolume + file + items: + description: DownwardAPIVolumeFile represents + information to create the file containing + the pod field + properties: + fieldRef: + description: 'Required: Selects + a field of the pod: only annotations, + labels, name and namespace are + supported.' + 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 + mode: + description: 'Optional: mode bits + used to set permissions on this + file, must be an octal value between + 0000 and 0777 or a decimal value + between 0 and 511. YAML accepts + both octal and decimal values, + JSON requires decimal values for + mode bits. If not specified, the + volume defaultMode will be used. + This might be in conflict with + other options that affect the + file mode, like fsGroup, and the + result can be other mode bits + set.' + format: int32 + type: integer + path: + description: 'Required: Path is the + relative path name of the file + to be created. Must not be absolute + or contain the ''..'' path. Must + be utf-8 encoded. The first item + of the relative path must not + start with ''..''' + type: string + resourceFieldRef: + description: 'Selects a resource + of the container: only resources + limits and requests (limits.cpu, + limits.memory, requests.cpu and + requests.memory) 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 + required: + - path + type: object + type: array + type: object + secret: + description: secret information about the + secret data to project + properties: + items: + description: items if unspecified, each + key-value pair in the Data field of + the referenced Secret will be projected + into the volume as a file whose name + is the key and content is the value. + If specified, the listed keys will be + projected into the specified paths, + and unlisted keys will not be present. + If a key is specified which is not present + in the Secret, the volume setup will + error unless it is marked optional. + Paths must be relative and may not contain + the '..' path or start with '..'. + items: + description: Maps a string key to a + path within a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: + mode bits used to set permissions + on this file. Must be an octal + value between 0000 and 0777 or + a decimal value between 0 and + 511. YAML accepts both octal and + decimal values, JSON requires + decimal values for mode bits. + If not specified, the volume defaultMode + will be used. This might be in + conflict with other options that + affect the file mode, like fsGroup, + and the result can be other mode + bits set.' + format: int32 + type: integer + path: + description: path is the relative + path of the file to map the key + to. May not be an absolute path. + May not contain the path element + '..'. May not start with the string + '..'. + type: string + required: + - key + - path + type: object + type: array + name: + description: 'Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + optional: + description: optional field specify whether + the Secret or its key must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + serviceAccountToken: + description: serviceAccountToken is information + about the serviceAccountToken data to project + properties: + audience: + description: audience is the intended + audience of the token. A recipient of + a token must identify itself with an + identifier specified in the audience + of the token, and otherwise should reject + the token. The audience defaults to + the identifier of the apiserver. + type: string + expirationSeconds: + description: expirationSeconds is the + requested duration of validity of the + service account token. As the token + approaches expiration, the kubelet volume + plugin will proactively rotate the service + account token. The kubelet will start + trying to rotate the token if the token + is older than 80 percent of its time + to live or if the token is older than + 24 hours.Defaults to 1 hour and must + be at least 10 minutes. + format: int64 + type: integer + path: + description: path is the path relative + to the mount point of the file to project + the token into. + type: string + required: + - path + type: object + type: object + type: array + type: object + quobyte: + description: quobyte represents a Quobyte mount on the + host that shares a pod's lifetime + properties: + group: + description: group to map volume access to Default + is no group + type: string + readOnly: + description: readOnly here will force the Quobyte + volume to be mounted with read-only permissions. + Defaults to false. + type: boolean + registry: + description: registry represents a single or multiple + Quobyte Registry services specified as a string + as host:port pair (multiple entries are separated + with commas) which acts as the central registry + for volumes + type: string + tenant: + description: tenant owning the given Quobyte volume + in the Backend Used with dynamically provisioned + Quobyte volumes, value is set by the plugin + type: string + user: + description: user to map volume access to Defaults + to serivceaccount user + type: string + volume: + description: volume is a string that references + an already created Quobyte volume by name. + type: string + required: + - registry + - volume + type: object + rbd: + description: 'rbd represents a Rados Block Device mount + on the host that shares a pod''s lifetime. More info: + https://examples.k8s.io/volumes/rbd/README.md' + properties: + fsType: + description: 'fsType is the filesystem type of the + volume that you want to mount. Tip: Ensure that + the filesystem type is supported by the host operating + system. Examples: "ext4", "xfs", "ntfs". Implicitly + inferred to be "ext4" if unspecified. More info: + https://kubernetes.io/docs/concepts/storage/volumes#rbd + TODO: how do we prevent errors in the filesystem + from compromising the machine' + type: string + image: + description: 'image is the rados image name. More + info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: string + keyring: + description: 'keyring is the path to key ring for + RBDUser. Default is /etc/ceph/keyring. More info: + https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: string + monitors: + description: 'monitors is a collection of Ceph monitors. + More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + items: + type: string + type: array + pool: + description: 'pool is the rados pool name. Default + is rbd. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: string + readOnly: + description: 'readOnly here will force the ReadOnly + setting in VolumeMounts. Defaults to false. More + info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: boolean + secretRef: + description: 'secretRef is name of the authentication + secret for RBDUser. If provided overrides keyring. + Default is nil. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + properties: + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + type: object + x-kubernetes-map-type: atomic + user: + description: 'user is the rados user name. Default + is admin. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: string + required: + - image + - monitors + type: object + scaleIO: + description: scaleIO represents a ScaleIO persistent + volume attached and mounted on Kubernetes nodes. + properties: + fsType: + description: fsType is the filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". Default + is "xfs". + type: string + gateway: + description: gateway is the host address of the + ScaleIO API Gateway. + type: string + protectionDomain: + description: protectionDomain is the name of the + ScaleIO Protection Domain for the configured storage. + type: string + readOnly: + description: readOnly Defaults to false (read/write). + ReadOnly here will force the ReadOnly setting + in VolumeMounts. + type: boolean + secretRef: + description: secretRef references to the secret + for ScaleIO user and other sensitive information. + If this is not provided, Login operation will + fail. + properties: + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + type: object + x-kubernetes-map-type: atomic + sslEnabled: + description: sslEnabled Flag enable/disable SSL + communication with Gateway, default false + type: boolean + storageMode: + description: storageMode indicates whether the storage + for a volume should be ThickProvisioned or ThinProvisioned. + Default is ThinProvisioned. + type: string + storagePool: + description: storagePool is the ScaleIO Storage + Pool associated with the protection domain. + type: string + system: + description: system is the name of the storage system + as configured in ScaleIO. + type: string + volumeName: + description: volumeName is the name of a volume + already created in the ScaleIO system that is + associated with this volume source. + type: string + required: + - gateway + - secretRef + - system + type: object + secret: + description: 'secret represents a secret that should + populate this volume. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' + properties: + defaultMode: + description: 'defaultMode is Optional: mode bits + used to set permissions on created files by default. + Must be an octal value between 0000 and 0777 or + a decimal value between 0 and 511. YAML accepts + both octal and decimal values, JSON requires decimal + values for mode bits. Defaults to 0644. Directories + within the path are not affected by this setting. + This might be in conflict with other options that + affect the file mode, like fsGroup, and the result + can be other mode bits set.' + format: int32 + type: integer + items: + description: items If unspecified, each key-value + pair in the Data field of the referenced Secret + will be projected into the volume as a file whose + name is the key and content is the value. If specified, + the listed keys will be projected into the specified + paths, and unlisted keys will not be present. + If a key is specified which is not present in + the Secret, the volume setup will error unless + it is marked optional. Paths must be relative + and may not contain the '..' path or start with + '..'. + items: + description: Maps a string key to a path within + a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: mode bits + used to set permissions on this file. Must + be an octal value between 0000 and 0777 + or a decimal value between 0 and 511. YAML + accepts both octal and decimal values, JSON + requires decimal values for mode bits. If + not specified, the volume defaultMode will + be used. This might be in conflict with + other options that affect the file mode, + like fsGroup, and the result can be other + mode bits set.' + format: int32 + type: integer + path: + description: path is the relative path of + the file to map the key to. May not be an + absolute path. May not contain the path + element '..'. May not start with the string + '..'. + type: string + required: + - key + - path + type: object + type: array + optional: + description: optional field specify whether the + Secret or its keys must be defined + type: boolean + secretName: + description: 'secretName is the name of the secret + in the pod''s namespace to use. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' + type: string + type: object + storageos: + description: storageOS represents a StorageOS volume + attached and mounted on Kubernetes nodes. + properties: + fsType: + description: fsType is the filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". Implicitly + inferred to be "ext4" if unspecified. + type: string + readOnly: + description: readOnly defaults to false (read/write). + ReadOnly here will force the ReadOnly setting + in VolumeMounts. + type: boolean + secretRef: + description: secretRef specifies the secret to use + for obtaining the StorageOS API credentials. If + not specified, default values will be attempted. + properties: + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + type: object + x-kubernetes-map-type: atomic + volumeName: + description: volumeName is the human-readable name + of the StorageOS volume. Volume names are only + unique within a namespace. + type: string + volumeNamespace: + description: volumeNamespace specifies the scope + of the volume within StorageOS. If no namespace + is specified then the Pod's namespace will be + used. This allows the Kubernetes name scoping + to be mirrored within StorageOS for tighter integration. + Set VolumeName to any name to override the default + behaviour. Set to "default" if you are not using + namespaces within StorageOS. Namespaces that do + not pre-exist within StorageOS will be created. + type: string + type: object + vsphereVolume: + description: vsphereVolume represents a vSphere volume + attached and mounted on kubelets host machine + properties: + fsType: + description: fsType is filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". Implicitly + inferred to be "ext4" if unspecified. + type: string + storagePolicyID: + description: storagePolicyID is the storage Policy + Based Management (SPBM) profile ID associated + with the StoragePolicyName. + type: string + storagePolicyName: + description: storagePolicyName is the storage Policy + Based Management (SPBM) profile name. + type: string + volumePath: + description: volumePath is the path that identifies + vSphere volume vmdk + type: string + required: + - volumePath + type: object + required: + - name + type: object + type: array + required: + - containers + type: object + type: object + type: + default: rw + description: 'Type of service to forward traffic to. Default: `rw`.' + enum: + - rw + - ro + type: string + required: + - cluster + - pgbouncer + type: object + status: + description: 'Most recently observed status of the Pooler. This data may + not be up to date. Populated by the system. Read-only. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status' + properties: + instances: + description: The number of pods trying to be scheduled + format: int32 + type: integer + secrets: + description: The resource version of the config object + properties: + clientCA: + description: The client CA secret version + properties: + name: + description: The name of the secret + type: string + version: + description: The ResourceVersion of the secret + type: string + type: object + pgBouncerSecrets: + description: The version of the secrets used by PgBouncer + properties: + authQuery: + description: The auth query secret version + properties: + name: + description: The name of the secret + type: string + version: + description: The ResourceVersion of the secret + type: string + type: object + type: object + serverCA: + description: The server CA secret version + properties: + name: + description: The name of the secret + type: string + version: + description: The ResourceVersion of the secret + type: string + type: object + serverTLS: + description: The server TLS secret version + properties: + name: + description: The name of the secret + type: string + version: + description: The ResourceVersion of the secret + type: string + type: object + type: object + type: object + required: + - metadata + - spec + type: object + served: true + storage: true + subresources: + scale: + specReplicasPath: .spec.instances + statusReplicasPath: .status.instances + status: {} +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.13.0 + helm.sh/resource-policy: keep + name: scheduledbackups.postgresql.cnpg.io +spec: + group: postgresql.cnpg.io + names: + kind: ScheduledBackup + listKind: ScheduledBackupList + plural: scheduledbackups + singular: scheduledbackup + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + - jsonPath: .spec.cluster.name + name: Cluster + type: string + - jsonPath: .status.lastScheduleTime + name: Last Backup + type: date + name: v1 + schema: + openAPIV3Schema: + description: ScheduledBackup is the Schema for the scheduledbackups 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: 'Specification of the desired behavior of the ScheduledBackup. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status' + properties: + backupOwnerReference: + default: none + description: 'Indicates which ownerReference should be put inside + the created backup resources.
    - none: no owner reference for + created backup objects (same behavior as before the field was introduced)
    - self: sets the Scheduled backup object as owner of the backup
    - cluster: set the cluster as owner of the backup
    ' + enum: + - none + - self + - cluster + type: string + cluster: + description: The cluster to backup + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + immediate: + description: If the first backup has to be immediately start after + creation or not + type: boolean + method: + default: barmanObjectStore + description: 'The backup method to be used, possible options are `barmanObjectStore` + and `volumeSnapshot`. Defaults to: `barmanObjectStore`.' + enum: + - barmanObjectStore + - volumeSnapshot + type: string + online: + description: Whether the default type of backup with volume snapshots + is online/hot (`true`, default) or offline/cold (`false`) Overrides + the default setting specified in the cluster field '.spec.backup.volumeSnapshot.online' + type: boolean + onlineConfiguration: + description: Configuration parameters to control the online/hot backup + with volume snapshots Overrides the default settings specified in + the cluster '.backup.volumeSnapshot.onlineConfiguration' stanza + properties: + immediateCheckpoint: + description: Control whether the I/O workload for the backup initial + checkpoint will be limited, according to the `checkpoint_completion_target` + setting on the PostgreSQL server. If set to true, an immediate + checkpoint will be used, meaning PostgreSQL will complete the + checkpoint as soon as possible. `false` by default. + type: boolean + waitForArchive: + default: true + description: If false, the function will return immediately after + the backup is completed, without waiting for WAL to be archived. + This behavior is only useful with backup software that independently + monitors WAL archiving. Otherwise, WAL required to make the + backup consistent might be missing and make the backup useless. + By default, or when this parameter is true, pg_backup_stop will + wait for WAL to be archived when archiving is enabled. On a + standby, this means that it will wait only when archive_mode + = always. If write activity on the primary is low, it may be + useful to run pg_switch_wal on the primary in order to trigger + an immediate segment switch. + type: boolean + type: object + schedule: + description: The schedule does not follow the same format used in + Kubernetes CronJobs as it includes an additional seconds specifier, + see https://pkg.go.dev/github.com/robfig/cron#hdr-CRON_Expression_Format + type: string + suspend: + description: If this backup is suspended or not + type: boolean + target: + description: The policy to decide which instance should perform this + backup. If empty, it defaults to `cluster.spec.backup.target`. Available + options are empty string, `primary` and `prefer-standby`. `primary` + to have backups run always on primary instances, `prefer-standby` + to have backups run preferably on the most updated standby, if available. + enum: + - primary + - prefer-standby + type: string + required: + - cluster + - schedule + type: object + status: + description: 'Most recently observed status of the ScheduledBackup. This + data may not be up to date. Populated by the system. Read-only. More + info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status' + properties: + lastCheckTime: + description: The latest time the schedule + format: date-time + type: string + lastScheduleTime: + description: Information when was the last time that backup was successfully + scheduled. + format: date-time + type: string + nextScheduleTime: + description: Next time we will run a backup + format: date-time + type: string + type: object + required: + - metadata + - spec + type: object + served: true + storage: true + subresources: + status: {} +{{- end }} diff --git a/packages/system/postgres-operator/charts/cloudnative-pg/templates/deployment.yaml b/packages/system/postgres-operator/charts/cloudnative-pg/templates/deployment.yaml new file mode 100644 index 00000000..45619fa7 --- /dev/null +++ b/packages/system/postgres-operator/charts/cloudnative-pg/templates/deployment.yaml @@ -0,0 +1,137 @@ +# +# Copyright The CloudNativePG Contributors +# +# 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: {{ include "cloudnative-pg.fullname" . }} + labels: + {{- include "cloudnative-pg.labels" . | nindent 4 }} + {{- with .Values.commonAnnotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + replicas: {{ .Values.replicaCount }} + selector: + matchLabels: + {{- include "cloudnative-pg.selectorLabels" . | nindent 6 }} + template: + metadata: + {{- with .Values.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "cloudnative-pg.selectorLabels" . | nindent 8 }} + {{- with .Values.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - args: + - controller + - --leader-elect + {{- if .Values.config.name }} + {{- if not .Values.config.secret }} + - --config-map-name={{ .Values.config.name }} + {{- else }} + - --secret-name={{ .Values.config.name }} + {{- end }} + {{- end }} + - --webhook-port={{ .Values.webhook.port }} + {{- range .Values.additionalArgs }} + - {{ . }} + {{- end }} + command: + - /manager + env: + - name: OPERATOR_IMAGE_NAME + value: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + - name: OPERATOR_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: MONITORING_QUERIES_CONFIGMAP + value: "{{ .Values.monitoringQueriesConfigMap.name }}" + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + livenessProbe: + httpGet: + path: /readyz + port: {{ .Values.webhook.port }} + scheme: HTTPS + {{- if .Values.webhook.livenessProbe.initialDelaySeconds }} + initialDelaySeconds: {{ .Values.webhook.livenessProbe.initialDelaySeconds }} + {{- end }} + name: manager + ports: + - containerPort: 8080 + name: metrics + protocol: TCP + - containerPort: {{ .Values.webhook.port }} + name: webhook-server + protocol: TCP + readinessProbe: + httpGet: + path: /readyz + port: {{ .Values.webhook.port }} + scheme: HTTPS + {{- if .Values.webhook.readinessProbe.initialDelaySeconds }} + initialDelaySeconds: {{ .Values.webhook.readinessProbe.initialDelaySeconds }} + {{- end }} + resources: + {{- toYaml .Values.resources | nindent 10 }} + securityContext: + {{- toYaml .Values.containerSecurityContext | nindent 10 }} + volumeMounts: + - mountPath: /controller + name: scratch-data + - mountPath: /run/secrets/cnpg.io/webhook + name: webhook-certificates + {{- if .Values.priorityClassName }} + priorityClassName: {{ .Values.priorityClassName }} + {{- end }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + serviceAccountName: {{ include "cloudnative-pg.serviceAccountName" . }} + terminationGracePeriodSeconds: 10 + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + volumes: + - emptyDir: {} + name: scratch-data + - name: webhook-certificates + secret: + defaultMode: 420 + optional: true + secretName: cnpg-webhook-cert + + diff --git a/packages/system/postgres-operator/charts/cloudnative-pg/templates/monitoring-configmap.yaml b/packages/system/postgres-operator/charts/cloudnative-pg/templates/monitoring-configmap.yaml new file mode 100644 index 00000000..a987f079 --- /dev/null +++ b/packages/system/postgres-operator/charts/cloudnative-pg/templates/monitoring-configmap.yaml @@ -0,0 +1,29 @@ +# +# Copyright The CloudNativePG Contributors +# +# 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: ConfigMap +metadata: + name: {{ .Values.monitoringQueriesConfigMap.name }} + labels: + {{- include "cloudnative-pg.labels" . | nindent 4 }} + cnpg.io/reload: "" + {{- with .Values.commonAnnotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +data: + queries: {{- toYaml .Values.monitoringQueriesConfigMap.queries | nindent 4 }} diff --git a/packages/system/postgres-operator/charts/cloudnative-pg/templates/mutatingwebhookconfiguration.yaml b/packages/system/postgres-operator/charts/cloudnative-pg/templates/mutatingwebhookconfiguration.yaml new file mode 100644 index 00000000..200695b1 --- /dev/null +++ b/packages/system/postgres-operator/charts/cloudnative-pg/templates/mutatingwebhookconfiguration.yaml @@ -0,0 +1,92 @@ +# +# Copyright The CloudNativePG Contributors +# +# 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. +# +{{- if .Values.webhook.mutating.create }} +--- +apiVersion: admissionregistration.k8s.io/v1 +kind: MutatingWebhookConfiguration +metadata: + name: cnpg-mutating-webhook-configuration + {{- with .Values.commonAnnotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} + labels: + {{- include "cloudnative-pg.labels" . | nindent 4 }} +webhooks: +- admissionReviewVersions: + - v1 + clientConfig: + service: + name: {{ .Values.service.name }} + namespace: {{ .Release.Namespace }} + path: /mutate-postgresql-cnpg-io-v1-backup + port: {{ .Values.service.port }} + failurePolicy: {{ .Values.webhook.mutating.failurePolicy }} + name: mbackup.cnpg.io + rules: + - apiGroups: + - postgresql.cnpg.io + apiVersions: + - v1 + operations: + - CREATE + - UPDATE + resources: + - backups + sideEffects: None +- admissionReviewVersions: + - v1 + clientConfig: + service: + name: {{ .Values.service.name }} + namespace: {{ .Release.Namespace }} + path: /mutate-postgresql-cnpg-io-v1-cluster + port: {{ .Values.service.port }} + failurePolicy: {{ .Values.webhook.mutating.failurePolicy }} + name: mcluster.cnpg.io + rules: + - apiGroups: + - postgresql.cnpg.io + apiVersions: + - v1 + operations: + - CREATE + - UPDATE + resources: + - clusters + sideEffects: None +- admissionReviewVersions: + - v1 + clientConfig: + service: + name: {{ .Values.service.name }} + namespace: {{ .Release.Namespace }} + path: /mutate-postgresql-cnpg-io-v1-scheduledbackup + port: {{ .Values.service.port }} + failurePolicy: {{ .Values.webhook.mutating.failurePolicy }} + name: mscheduledbackup.cnpg.io + rules: + - apiGroups: + - postgresql.cnpg.io + apiVersions: + - v1 + operations: + - CREATE + - UPDATE + resources: + - scheduledbackups + sideEffects: None +{{- end }} diff --git a/packages/system/postgres-operator/charts/cloudnative-pg/templates/podmonitor.yaml b/packages/system/postgres-operator/charts/cloudnative-pg/templates/podmonitor.yaml new file mode 100644 index 00000000..89789127 --- /dev/null +++ b/packages/system/postgres-operator/charts/cloudnative-pg/templates/podmonitor.yaml @@ -0,0 +1,18 @@ +{{- if .Values.monitoring.podMonitorEnabled }} +apiVersion: monitoring.coreos.com/v1 +kind: PodMonitor +metadata: + name: {{ include "cloudnative-pg.fullname" . }} + labels: + {{- include "cloudnative-pg.labels" . | nindent 4 }} + {{- with .Values.commonAnnotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + selector: + matchLabels: + {{- include "cloudnative-pg.selectorLabels" . | nindent 6 }} + podMetricsEndpoints: + - port: metrics +{{- end }} \ No newline at end of file diff --git a/packages/system/postgres-operator/charts/cloudnative-pg/templates/rbac.yaml b/packages/system/postgres-operator/charts/cloudnative-pg/templates/rbac.yaml new file mode 100644 index 00000000..cf798293 --- /dev/null +++ b/packages/system/postgres-operator/charts/cloudnative-pg/templates/rbac.yaml @@ -0,0 +1,443 @@ +# +# Copyright The CloudNativePG Contributors +# +# 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. +# +{{- if .Values.serviceAccount.create }} +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "cloudnative-pg.serviceAccountName" . }} + labels: + {{- include "cloudnative-pg.labels" . | nindent 4 }} + {{- with .Values.commonAnnotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} + +{{- if .Values.rbac.create }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ include "cloudnative-pg.fullname" . }} + labels: + {{- include "cloudnative-pg.labels" . | nindent 4 }} + {{- with .Values.commonAnnotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +rules: +- apiGroups: + - "" + resources: + - configmaps + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - "" + resources: + - configmaps/status + verbs: + - get + - patch + - update +- apiGroups: + - "" + resources: + - events + verbs: + - create + - patch +- apiGroups: + - "" + resources: + - namespaces + verbs: + - get + - list + - watch +- apiGroups: + - "" + resources: + - nodes + verbs: + - get + - list + - watch +- apiGroups: + - "" + resources: + - persistentvolumeclaims + verbs: + - create + - delete + - get + - list + - patch + - watch +- apiGroups: + - "" + resources: + - pods + verbs: + - create + - delete + - get + - list + - patch + - watch +- apiGroups: + - "" + resources: + - pods/exec + verbs: + - create + - delete + - get + - list + - patch + - watch +- apiGroups: + - "" + resources: + - pods/status + verbs: + - get +- apiGroups: + - "" + resources: + - secrets + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - "" + resources: + - secrets/status + verbs: + - get + - patch + - update +- apiGroups: + - "" + resources: + - serviceaccounts + verbs: + - create + - get + - list + - patch + - update + - watch +- apiGroups: + - "" + resources: + - services + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - admissionregistration.k8s.io + resources: + - mutatingwebhookconfigurations + verbs: + - get + - list + - patch + - update +- apiGroups: + - admissionregistration.k8s.io + resources: + - validatingwebhookconfigurations + verbs: + - get + - list + - patch + - update +- apiGroups: + - apiextensions.k8s.io + resources: + - customresourcedefinitions + verbs: + - get + - list + - update +- apiGroups: + - apps + resources: + - deployments + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - batch + resources: + - jobs + verbs: + - create + - delete + - get + - list + - patch + - watch +- apiGroups: + - coordination.k8s.io + resources: + - leases + verbs: + - create + - get + - update +- apiGroups: + - monitoring.coreos.com + resources: + - podmonitors + verbs: + - create + - delete + - get + - list + - patch + - watch +- apiGroups: + - policy + resources: + - poddisruptionbudgets + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - postgresql.cnpg.io + resources: + - backups + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - postgresql.cnpg.io + resources: + - backups/status + verbs: + - get + - patch + - update +- apiGroups: + - postgresql.cnpg.io + resources: + - clusters + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - postgresql.cnpg.io + resources: + - clusters/finalizers + verbs: + - update +- apiGroups: + - postgresql.cnpg.io + resources: + - clusters/status + verbs: + - get + - patch + - update + - watch +- apiGroups: + - postgresql.cnpg.io + resources: + - poolers + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - postgresql.cnpg.io + resources: + - poolers/finalizers + verbs: + - update +- apiGroups: + - postgresql.cnpg.io + resources: + - poolers/status + verbs: + - get + - patch + - update + - watch +- apiGroups: + - postgresql.cnpg.io + resources: + - scheduledbackups + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - postgresql.cnpg.io + resources: + - scheduledbackups/status + verbs: + - get + - patch + - update +- apiGroups: + - rbac.authorization.k8s.io + resources: + - rolebindings + verbs: + - create + - get + - list + - patch + - update + - watch +- apiGroups: + - rbac.authorization.k8s.io + resources: + - roles + verbs: + - create + - get + - list + - patch + - update + - watch +- apiGroups: + - snapshot.storage.k8s.io + resources: + - volumesnapshots + verbs: + - create + - get + - list + - patch + - watch +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ include "cloudnative-pg.fullname" . }} + labels: + {{- include "cloudnative-pg.labels" . | nindent 4 }} + {{- with .Values.commonAnnotations.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ include "cloudnative-pg.fullname" . }} +subjects: +- kind: ServiceAccount + name: {{ include "cloudnative-pg.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ include "cloudnative-pg.fullname" . }}-view + labels: + {{- include "cloudnative-pg.labels" . | nindent 4 }} + {{- if .Values.rbac.aggregateClusterRoles }} + rbac.authorization.k8s.io/aggregate-to-view: "true" + rbac.authorization.k8s.io/aggregate-to-edit: "true" + rbac.authorization.k8s.io/aggregate-to-admin: "true" + {{- end }} +rules: +- apiGroups: + - postgresql.cnpg.io + resources: + - backups + - clusters + - poolers + - scheduledbackups + verbs: + - get + - list + - watch +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ include "cloudnative-pg.fullname" . }}-edit + labels: + {{- include "cloudnative-pg.labels" . | nindent 4 }} + {{- if .Values.rbac.aggregateClusterRoles }} + rbac.authorization.k8s.io/aggregate-to-edit: "true" + rbac.authorization.k8s.io/aggregate-to-admin: "true" + {{- end }} +rules: +- apiGroups: + - postgresql.cnpg.io + resources: + - backups + - clusters + - poolers + - scheduledbackups + verbs: + - create + - delete + - deletecollection + - patch + - update +--- +{{- end }} diff --git a/packages/system/postgres-operator/charts/cloudnative-pg/templates/service.yaml b/packages/system/postgres-operator/charts/cloudnative-pg/templates/service.yaml new file mode 100644 index 00000000..fc8a4127 --- /dev/null +++ b/packages/system/postgres-operator/charts/cloudnative-pg/templates/service.yaml @@ -0,0 +1,34 @@ +# +# Copyright The CloudNativePG Contributors +# +# 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: {{ .Values.service.name }} + labels: + {{- include "cloudnative-pg.labels" . | nindent 4 }} + {{- with .Values.commonAnnotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + type: {{ .Values.service.type }} + ports: + - port: {{ .Values.service.port }} + targetPort: webhook-server + name: webhook-server + selector: + {{- include "cloudnative-pg.selectorLabels" . | nindent 4 }} diff --git a/packages/system/postgres-operator/charts/cloudnative-pg/templates/validatingwebhookconfiguration.yaml b/packages/system/postgres-operator/charts/cloudnative-pg/templates/validatingwebhookconfiguration.yaml new file mode 100644 index 00000000..be9fff18 --- /dev/null +++ b/packages/system/postgres-operator/charts/cloudnative-pg/templates/validatingwebhookconfiguration.yaml @@ -0,0 +1,113 @@ +# +# Copyright The CloudNativePG Contributors +# +# 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. +# +{{- if .Values.webhook.validating.create }} +--- +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingWebhookConfiguration +metadata: + name: cnpg-validating-webhook-configuration + labels: + {{- include "cloudnative-pg.labels" . | nindent 4 }} + {{- with .Values.rbac.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +webhooks: +- admissionReviewVersions: + - v1 + clientConfig: + service: + name: {{ .Values.service.name }} + namespace: {{ .Release.Namespace }} + path: /validate-postgresql-cnpg-io-v1-backup + port: {{ .Values.service.port }} + failurePolicy: {{ .Values.webhook.validating.failurePolicy }} + name: vbackup.cnpg.io + rules: + - apiGroups: + - postgresql.cnpg.io + apiVersions: + - v1 + operations: + - CREATE + - UPDATE + resources: + - backups + sideEffects: None +- admissionReviewVersions: + - v1 + clientConfig: + service: + name: {{ .Values.service.name }} + namespace: {{ .Release.Namespace }} + path: /validate-postgresql-cnpg-io-v1-cluster + port: {{ .Values.service.port }} + failurePolicy: {{ .Values.webhook.validating.failurePolicy }} + name: vcluster.cnpg.io + rules: + - apiGroups: + - postgresql.cnpg.io + apiVersions: + - v1 + operations: + - CREATE + - UPDATE + resources: + - clusters + sideEffects: None +- admissionReviewVersions: + - v1 + clientConfig: + service: + name: {{ .Values.service.name }} + namespace: {{ .Release.Namespace }} + path: /validate-postgresql-cnpg-io-v1-scheduledbackup + port: {{ .Values.service.port }} + failurePolicy: {{ .Values.webhook.validating.failurePolicy }} + name: vscheduledbackup.cnpg.io + rules: + - apiGroups: + - postgresql.cnpg.io + apiVersions: + - v1 + operations: + - CREATE + - UPDATE + resources: + - scheduledbackups + sideEffects: None +- admissionReviewVersions: + - v1 + clientConfig: + service: + name: {{ .Values.service.name }} + namespace: {{ .Release.Namespace }} + path: /validate-postgresql-cnpg-io-v1-pooler + port: {{ .Values.service.port }} + failurePolicy: {{ .Values.webhook.validating.failurePolicy }} + name: vpooler.cnpg.io + rules: + - apiGroups: + - postgresql.cnpg.io + apiVersions: + - v1 + operations: + - CREATE + - UPDATE + resources: + - poolers + sideEffects: None +{{- end }} diff --git a/packages/system/postgres-operator/charts/cloudnative-pg/values.schema.json b/packages/system/postgres-operator/charts/cloudnative-pg/values.schema.json new file mode 100644 index 00000000..b5a5b462 --- /dev/null +++ b/packages/system/postgres-operator/charts/cloudnative-pg/values.schema.json @@ -0,0 +1,237 @@ +{ + "$schema": "http://json-schema.org/schema#", + "type": "object", + "properties": { + "additionalArgs": { + "type": "array" + }, + "affinity": { + "type": "object" + }, + "commonAnnotations": { + "type": "object" + }, + "config": { + "type": "object", + "properties": { + "create": { + "type": "boolean" + }, + "data": { + "type": "object" + }, + "name": { + "type": "string" + }, + "secret": { + "type": "boolean" + } + } + }, + "containerSecurityContext": { + "type": "object", + "properties": { + "allowPrivilegeEscalation": { + "type": "boolean" + }, + "capabilities": { + "type": "object", + "properties": { + "drop": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "readOnlyRootFilesystem": { + "type": "boolean" + }, + "runAsGroup": { + "type": "integer" + }, + "runAsUser": { + "type": "integer" + }, + "seccompProfile": { + "type": "object", + "properties": { + "type": { + "type": "string" + } + } + } + } + }, + "crds": { + "type": "object", + "properties": { + "create": { + "type": "boolean" + } + } + }, + "fullnameOverride": { + "type": "string" + }, + "image": { + "type": "object", + "properties": { + "pullPolicy": { + "type": "string" + }, + "repository": { + "type": "string" + }, + "tag": { + "type": "string" + } + } + }, + "imagePullSecrets": { + "type": "array" + }, + "monitoring": { + "type": "object", + "properties": { + "podMonitorEnabled": { + "type": "boolean" + } + } + }, + "monitoringQueriesConfigMap": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "queries": { + "type": "string" + } + } + }, + "nameOverride": { + "type": "string" + }, + "nodeSelector": { + "type": "object" + }, + "podAnnotations": { + "type": "object" + }, + "podLabels": { + "type": "object" + }, + "podSecurityContext": { + "type": "object", + "properties": { + "runAsNonRoot": { + "type": "boolean" + }, + "seccompProfile": { + "type": "object", + "properties": { + "type": { + "type": "string" + } + } + } + } + }, + "priorityClassName": { + "type": "string" + }, + "rbac": { + "type": "object", + "properties": { + "aggregateClusterRoles": { + "type": "boolean" + }, + "create": { + "type": "boolean" + } + } + }, + "replicaCount": { + "type": "integer" + }, + "resources": { + "type": "object" + }, + "service": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "port": { + "type": "integer" + }, + "type": { + "type": "string" + } + } + }, + "serviceAccount": { + "type": "object", + "properties": { + "create": { + "type": "boolean" + }, + "name": { + "type": "string" + } + } + }, + "tolerations": { + "type": "array" + }, + "webhook": { + "type": "object", + "properties": { + "livenessProbe": { + "type": "object", + "properties": { + "initialDelaySeconds": { + "type": "integer" + } + } + }, + "mutating": { + "type": "object", + "properties": { + "create": { + "type": "boolean" + }, + "failurePolicy": { + "type": "string" + } + } + }, + "port": { + "type": "integer" + }, + "readinessProbe": { + "type": "object", + "properties": { + "initialDelaySeconds": { + "type": "integer" + } + } + }, + "validating": { + "type": "object", + "properties": { + "create": { + "type": "boolean" + }, + "failurePolicy": { + "type": "string" + } + } + } + } + } + } +} diff --git a/packages/system/postgres-operator/charts/cloudnative-pg/values.yaml b/packages/system/postgres-operator/charts/cloudnative-pg/values.yaml new file mode 100644 index 00000000..8849fad6 --- /dev/null +++ b/packages/system/postgres-operator/charts/cloudnative-pg/values.yaml @@ -0,0 +1,528 @@ +# +# Copyright The CloudNativePG Contributors +# +# 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. +# +# Default values for CloudNativePG. +# This is a YAML-formatted file. +# Please declare variables to be passed to your templates. + +replicaCount: 1 + +image: + repository: ghcr.io/cloudnative-pg/cloudnative-pg + pullPolicy: IfNotPresent + # -- Overrides the image tag whose default is the chart appVersion. + tag: "" + +imagePullSecrets: [] +nameOverride: "" +fullnameOverride: "" + +crds: + # -- Specifies whether the CRDs should be created when installing the chart. + create: true + +# -- The webhook configuration. +webhook: + port: 9443 + mutating: + create: true + failurePolicy: Fail + validating: + create: true + failurePolicy: Fail + livenessProbe: + initialDelaySeconds: 3 + readinessProbe: + initialDelaySeconds: 3 + +# -- Operator configuration. +config: + # -- Specifies whether the secret should be created. + create: true + # -- The name of the configmap/secret to use. + name: cnpg-controller-manager-config + # -- Specifies whether it should be stored in a secret, instead of a configmap. + secret: false + # -- The content of the configmap/secret, see + # https://cloudnative-pg.io/documentation/current/operator_conf/#available-options + # for all the available options. + data: {} + # INHERITED_ANNOTATIONS: categories + # INHERITED_LABELS: environment, workload, app + # WATCH_NAMESPACE: namespace-a,namespace-b + +# -- Additinal arguments to be added to the operator's args list. +additionalArgs: [] + +serviceAccount: + # -- Specifies whether the service account should be created. + create: true + # -- The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template. + name: "" + +rbac: + # -- Specifies whether ClusterRole and ClusterRoleBinding should be created. + create: true + # -- Aggregate ClusterRoles to Kubernetes default user-facing roles. + # Ref: https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles + aggregateClusterRoles: false + +# -- Annotations to be added to all other resources. +commonAnnotations: {} +# -- Annotations to be added to the pod. +podAnnotations: {} +# -- Labels to be added to the pod. +podLabels: {} + +# -- Container Security Context. +containerSecurityContext: + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + runAsUser: 10001 + runAsGroup: 10001 + seccompProfile: + type: RuntimeDefault + capabilities: + drop: + - "ALL" + +# -- Security Context for the whole pod. +podSecurityContext: + runAsNonRoot: true + seccompProfile: + type: RuntimeDefault + # fsGroup: 2000 + +# -- Priority indicates the importance of a Pod relative to other Pods. +priorityClassName: "" + +service: + type: ClusterIP + # -- DO NOT CHANGE THE SERVICE NAME as it is currently used to generate the certificate + # and can not be configured + name: cnpg-webhook-service + port: 443 + +resources: {} + # If you want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # + # limits: + # cpu: 100m + # memory: 200Mi + # requests: + # cpu: 100m + # memory: 100Mi + +# -- Nodeselector for the operator to be installed. +nodeSelector: {} + +# -- Tolerations for the operator to be installed. +tolerations: [] + +# -- Affinity for the operator to be installed. +affinity: {} + +monitoring: + # -- Specifies whether the monitoring should be enabled. Requires Prometheus Operator CRDs. + podMonitorEnabled: false + +# Default monitoring queries +monitoringQueriesConfigMap: + # -- The name of the default monitoring configmap. + name: cnpg-default-monitoring + # -- A string representation of a YAML defining monitoring queries. + queries: | + backends: + query: | + SELECT sa.datname + , sa.usename + , sa.application_name + , states.state + , COALESCE(sa.count, 0) AS total + , COALESCE(sa.max_tx_secs, 0) AS max_tx_duration_seconds + FROM ( VALUES ('active') + , ('idle') + , ('idle in transaction') + , ('idle in transaction (aborted)') + , ('fastpath function call') + , ('disabled') + ) AS states(state) + LEFT JOIN ( + SELECT datname + , state + , usename + , COALESCE(application_name, '') AS application_name + , COUNT(*) + , COALESCE(EXTRACT (EPOCH FROM (max(now() - xact_start))), 0) AS max_tx_secs + FROM pg_catalog.pg_stat_activity + GROUP BY datname, state, usename, application_name + ) sa ON states.state = sa.state + WHERE sa.usename IS NOT NULL + metrics: + - datname: + usage: "LABEL" + description: "Name of the database" + - usename: + usage: "LABEL" + description: "Name of the user" + - application_name: + usage: "LABEL" + description: "Name of the application" + - state: + usage: "LABEL" + description: "State of the backend" + - total: + usage: "GAUGE" + description: "Number of backends" + - max_tx_duration_seconds: + usage: "GAUGE" + description: "Maximum duration of a transaction in seconds" + + backends_waiting: + query: | + SELECT count(*) AS total + FROM pg_catalog.pg_locks blocked_locks + JOIN pg_catalog.pg_locks blocking_locks + ON blocking_locks.locktype = blocked_locks.locktype + AND blocking_locks.database IS NOT DISTINCT FROM blocked_locks.database + AND blocking_locks.relation IS NOT DISTINCT FROM blocked_locks.relation + AND blocking_locks.page IS NOT DISTINCT FROM blocked_locks.page + AND blocking_locks.tuple IS NOT DISTINCT FROM blocked_locks.tuple + AND blocking_locks.virtualxid IS NOT DISTINCT FROM blocked_locks.virtualxid + AND blocking_locks.transactionid IS NOT DISTINCT FROM blocked_locks.transactionid + AND blocking_locks.classid IS NOT DISTINCT FROM blocked_locks.classid + AND blocking_locks.objid IS NOT DISTINCT FROM blocked_locks.objid + AND blocking_locks.objsubid IS NOT DISTINCT FROM blocked_locks.objsubid + AND blocking_locks.pid != blocked_locks.pid + JOIN pg_catalog.pg_stat_activity blocking_activity ON blocking_activity.pid = blocking_locks.pid + WHERE NOT blocked_locks.granted + metrics: + - total: + usage: "GAUGE" + description: "Total number of backends that are currently waiting on other queries" + + pg_database: + query: | + SELECT datname + , pg_catalog.pg_database_size(datname) AS size_bytes + , pg_catalog.age(datfrozenxid) AS xid_age + , pg_catalog.mxid_age(datminmxid) AS mxid_age + FROM pg_catalog.pg_database + metrics: + - datname: + usage: "LABEL" + description: "Name of the database" + - size_bytes: + usage: "GAUGE" + description: "Disk space used by the database" + - xid_age: + usage: "GAUGE" + description: "Number of transactions from the frozen XID to the current one" + - mxid_age: + usage: "GAUGE" + description: "Number of multiple transactions (Multixact) from the frozen XID to the current one" + + pg_postmaster: + query: | + SELECT EXTRACT(EPOCH FROM pg_postmaster_start_time) AS start_time + FROM pg_catalog.pg_postmaster_start_time() + metrics: + - start_time: + usage: "GAUGE" + description: "Time at which postgres started (based on epoch)" + + pg_replication: + query: "SELECT CASE WHEN ( + NOT pg_catalog.pg_is_in_recovery() + OR pg_catalog.pg_last_wal_receive_lsn() = pg_catalog.pg_last_wal_replay_lsn()) + THEN 0 + ELSE GREATEST (0, + EXTRACT(EPOCH FROM (now() - pg_catalog.pg_last_xact_replay_timestamp()))) + END AS lag, + pg_catalog.pg_is_in_recovery() AS in_recovery, + EXISTS (TABLE pg_stat_wal_receiver) AS is_wal_receiver_up, + (SELECT count(*) FROM pg_catalog.pg_stat_replication) AS streaming_replicas" + metrics: + - lag: + usage: "GAUGE" + description: "Replication lag behind primary in seconds" + - in_recovery: + usage: "GAUGE" + description: "Whether the instance is in recovery" + - is_wal_receiver_up: + usage: "GAUGE" + description: "Whether the instance wal_receiver is up" + - streaming_replicas: + usage: "GAUGE" + description: "Number of streaming replicas connected to the instance" + + pg_replication_slots: + query: | + SELECT slot_name, + slot_type, + database, + active, + (CASE pg_catalog.pg_is_in_recovery() + WHEN TRUE THEN pg_catalog.pg_wal_lsn_diff(pg_catalog.pg_last_wal_receive_lsn(), restart_lsn) + ELSE pg_catalog.pg_wal_lsn_diff(pg_catalog.pg_current_wal_lsn(), restart_lsn) + END) as pg_wal_lsn_diff + FROM pg_catalog.pg_replication_slots + WHERE NOT temporary + metrics: + - slot_name: + usage: "LABEL" + description: "Name of the replication slot" + - slot_type: + usage: "LABEL" + description: "Type of the replication slot" + - database: + usage: "LABEL" + description: "Name of the database" + - active: + usage: "GAUGE" + description: "Flag indicating whether the slot is active" + - pg_wal_lsn_diff: + usage: "GAUGE" + description: "Replication lag in bytes" + + pg_stat_archiver: + query: | + SELECT archived_count + , failed_count + , COALESCE(EXTRACT(EPOCH FROM (now() - last_archived_time)), -1) AS seconds_since_last_archival + , COALESCE(EXTRACT(EPOCH FROM (now() - last_failed_time)), -1) AS seconds_since_last_failure + , COALESCE(EXTRACT(EPOCH FROM last_archived_time), -1) AS last_archived_time + , COALESCE(EXTRACT(EPOCH FROM last_failed_time), -1) AS last_failed_time + , COALESCE(CAST(CAST('x'||pg_catalog.right(pg_catalog.split_part(last_archived_wal, '.', 1), 16) AS pg_catalog.bit(64)) AS pg_catalog.int8), -1) AS last_archived_wal_start_lsn + , COALESCE(CAST(CAST('x'||pg_catalog.right(pg_catalog.split_part(last_failed_wal, '.', 1), 16) AS pg_catalog.bit(64)) AS pg_catalog.int8), -1) AS last_failed_wal_start_lsn + , EXTRACT(EPOCH FROM stats_reset) AS stats_reset_time + FROM pg_catalog.pg_stat_archiver + metrics: + - archived_count: + usage: "COUNTER" + description: "Number of WAL files that have been successfully archived" + - failed_count: + usage: "COUNTER" + description: "Number of failed attempts for archiving WAL files" + - seconds_since_last_archival: + usage: "GAUGE" + description: "Seconds since the last successful archival operation" + - seconds_since_last_failure: + usage: "GAUGE" + description: "Seconds since the last failed archival operation" + - last_archived_time: + usage: "GAUGE" + description: "Epoch of the last time WAL archiving succeeded" + - last_failed_time: + usage: "GAUGE" + description: "Epoch of the last time WAL archiving failed" + - last_archived_wal_start_lsn: + usage: "GAUGE" + description: "Archived WAL start LSN" + - last_failed_wal_start_lsn: + usage: "GAUGE" + description: "Last failed WAL LSN" + - stats_reset_time: + usage: "GAUGE" + description: "Time at which these statistics were last reset" + + pg_stat_bgwriter: + query: | + SELECT checkpoints_timed + , checkpoints_req + , checkpoint_write_time + , checkpoint_sync_time + , buffers_checkpoint + , buffers_clean + , maxwritten_clean + , buffers_backend + , buffers_backend_fsync + , buffers_alloc + FROM pg_catalog.pg_stat_bgwriter + metrics: + - checkpoints_timed: + usage: "COUNTER" + description: "Number of scheduled checkpoints that have been performed" + - checkpoints_req: + usage: "COUNTER" + description: "Number of requested checkpoints that have been performed" + - checkpoint_write_time: + usage: "COUNTER" + description: "Total amount of time that has been spent in the portion of checkpoint processing where files are written to disk, in milliseconds" + - checkpoint_sync_time: + usage: "COUNTER" + description: "Total amount of time that has been spent in the portion of checkpoint processing where files are synchronized to disk, in milliseconds" + - buffers_checkpoint: + usage: "COUNTER" + description: "Number of buffers written during checkpoints" + - buffers_clean: + usage: "COUNTER" + description: "Number of buffers written by the background writer" + - maxwritten_clean: + usage: "COUNTER" + description: "Number of times the background writer stopped a cleaning scan because it had written too many buffers" + - buffers_backend: + usage: "COUNTER" + description: "Number of buffers written directly by a backend" + - buffers_backend_fsync: + usage: "COUNTER" + description: "Number of times a backend had to execute its own fsync call (normally the background writer handles those even when the backend does its own write)" + - buffers_alloc: + usage: "COUNTER" + description: "Number of buffers allocated" + + pg_stat_database: + query: | + SELECT datname + , xact_commit + , xact_rollback + , blks_read + , blks_hit + , tup_returned + , tup_fetched + , tup_inserted + , tup_updated + , tup_deleted + , conflicts + , temp_files + , temp_bytes + , deadlocks + , blk_read_time + , blk_write_time + FROM pg_catalog.pg_stat_database + metrics: + - datname: + usage: "LABEL" + description: "Name of this database" + - xact_commit: + usage: "COUNTER" + description: "Number of transactions in this database that have been committed" + - xact_rollback: + usage: "COUNTER" + description: "Number of transactions in this database that have been rolled back" + - blks_read: + usage: "COUNTER" + description: "Number of disk blocks read in this database" + - blks_hit: + usage: "COUNTER" + description: "Number of times disk blocks were found already in the buffer cache, so that a read was not necessary (this only includes hits in the PostgreSQL buffer cache, not the operating system's file system cache)" + - tup_returned: + usage: "COUNTER" + description: "Number of rows returned by queries in this database" + - tup_fetched: + usage: "COUNTER" + description: "Number of rows fetched by queries in this database" + - tup_inserted: + usage: "COUNTER" + description: "Number of rows inserted by queries in this database" + - tup_updated: + usage: "COUNTER" + description: "Number of rows updated by queries in this database" + - tup_deleted: + usage: "COUNTER" + description: "Number of rows deleted by queries in this database" + - conflicts: + usage: "COUNTER" + description: "Number of queries canceled due to conflicts with recovery in this database" + - temp_files: + usage: "COUNTER" + description: "Number of temporary files created by queries in this database" + - temp_bytes: + usage: "COUNTER" + description: "Total amount of data written to temporary files by queries in this database" + - deadlocks: + usage: "COUNTER" + description: "Number of deadlocks detected in this database" + - blk_read_time: + usage: "COUNTER" + description: "Time spent reading data file blocks by backends in this database, in milliseconds" + - blk_write_time: + usage: "COUNTER" + description: "Time spent writing data file blocks by backends in this database, in milliseconds" + + pg_stat_replication: + primary: true + query: | + SELECT usename + , COALESCE(application_name, '') AS application_name + , COALESCE(client_addr::text, '') AS client_addr + , COALESCE(client_port::text, '') AS client_port + , EXTRACT(EPOCH FROM backend_start) AS backend_start + , COALESCE(pg_catalog.age(backend_xmin), 0) AS backend_xmin_age + , pg_catalog.pg_wal_lsn_diff(pg_catalog.pg_current_wal_lsn(), sent_lsn) AS sent_diff_bytes + , pg_catalog.pg_wal_lsn_diff(pg_catalog.pg_current_wal_lsn(), write_lsn) AS write_diff_bytes + , pg_catalog.pg_wal_lsn_diff(pg_catalog.pg_current_wal_lsn(), flush_lsn) AS flush_diff_bytes + , COALESCE(pg_catalog.pg_wal_lsn_diff(pg_catalog.pg_current_wal_lsn(), replay_lsn),0) AS replay_diff_bytes + , COALESCE((EXTRACT(EPOCH FROM write_lag)),0)::float AS write_lag_seconds + , COALESCE((EXTRACT(EPOCH FROM flush_lag)),0)::float AS flush_lag_seconds + , COALESCE((EXTRACT(EPOCH FROM replay_lag)),0)::float AS replay_lag_seconds + FROM pg_catalog.pg_stat_replication + metrics: + - usename: + usage: "LABEL" + description: "Name of the replication user" + - application_name: + usage: "LABEL" + description: "Name of the application" + - client_addr: + usage: "LABEL" + description: "Client IP address" + - client_port: + usage: "LABEL" + description: "Client TCP port" + - backend_start: + usage: "COUNTER" + description: "Time when this process was started" + - backend_xmin_age: + usage: "COUNTER" + description: "The age of this standby's xmin horizon" + - sent_diff_bytes: + usage: "GAUGE" + description: "Difference in bytes from the last write-ahead log location sent on this connection" + - write_diff_bytes: + usage: "GAUGE" + description: "Difference in bytes from the last write-ahead log location written to disk by this standby server" + - flush_diff_bytes: + usage: "GAUGE" + description: "Difference in bytes from the last write-ahead log location flushed to disk by this standby server" + - replay_diff_bytes: + usage: "GAUGE" + description: "Difference in bytes from the last write-ahead log location replayed into the database on this standby server" + - write_lag_seconds: + usage: "GAUGE" + description: "Time elapsed between flushing recent WAL locally and receiving notification that this standby server has written it" + - flush_lag_seconds: + usage: "GAUGE" + description: "Time elapsed between flushing recent WAL locally and receiving notification that this standby server has written and flushed it" + - replay_lag_seconds: + usage: "GAUGE" + description: "Time elapsed between flushing recent WAL locally and receiving notification that this standby server has written, flushed and applied it" + + pg_settings: + query: | + SELECT name, + CASE setting WHEN 'on' THEN '1' WHEN 'off' THEN '0' ELSE setting END AS setting + FROM pg_catalog.pg_settings + WHERE vartype IN ('integer', 'real', 'bool') + ORDER BY 1 + metrics: + - name: + usage: "LABEL" + description: "Name of the setting" + - setting: + usage: "GAUGE" + description: "Setting value" diff --git a/packages/system/postgres-operator/values.yaml b/packages/system/postgres-operator/values.yaml new file mode 100644 index 00000000..6bc9595b --- /dev/null +++ b/packages/system/postgres-operator/values.yaml @@ -0,0 +1,3 @@ +cloudnative-pg: + crds: + create: true diff --git a/packages/system/rabbitmq-operator/Chart.yaml b/packages/system/rabbitmq-operator/Chart.yaml new file mode 100644 index 00000000..c833c103 --- /dev/null +++ b/packages/system/rabbitmq-operator/Chart.yaml @@ -0,0 +1,2 @@ +name: cozy-rabbitmq-operator +version: 1.0.0 diff --git a/packages/system/rabbitmq-operator/Makefile b/packages/system/rabbitmq-operator/Makefile new file mode 100644 index 00000000..1b11ad0d --- /dev/null +++ b/packages/system/rabbitmq-operator/Makefile @@ -0,0 +1,17 @@ +NAME=rabbitmq-operator +NAMESPACE=cozy-rabbitmq-operator + +show: + helm template --dry-run=server -n $(NAMESPACE) $(NAME) . + +apply: + helm upgrade -i -n $(NAMESPACE) $(NAME) . + +diff: + helm diff upgrade --allow-unreleased --normalize-manifests -n $(NAMESPACE) $(NAME) . + +update: + rm -rf templates/cluster-operator.yml + wget -O templates/cluster-operator.yml https://github.com/rabbitmq/cluster-operator/releases/latest/download/cluster-operator.yml + yq -i 'del(select(.kind=="Namespace"))' templates/cluster-operator.yml + sed -i 's/rabbitmq-system/cozy-rabbitmq-operator/g' templates/cluster-operator.yml diff --git a/packages/system/rabbitmq-operator/templates/cluster-operator.yml b/packages/system/rabbitmq-operator/templates/cluster-operator.yml new file mode 100644 index 00000000..2cc2322e --- /dev/null +++ b/packages/system/rabbitmq-operator/templates/cluster-operator.yml @@ -0,0 +1,4661 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.13.0 + labels: + app.kubernetes.io/component: rabbitmq-operator + app.kubernetes.io/name: rabbitmq-cluster-operator + app.kubernetes.io/part-of: rabbitmq + servicebinding.io/provisioned-service: "true" + name: rabbitmqclusters.rabbitmq.com +spec: + group: rabbitmq.com + names: + categories: + - all + - rabbitmq + kind: RabbitmqCluster + listKind: RabbitmqClusterList + plural: rabbitmqclusters + shortNames: + - rmq + singular: rabbitmqcluster + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .status.conditions[?(@.type == 'AllReplicasReady')].status + name: AllReplicasReady + type: string + - jsonPath: .status.conditions[?(@.type == 'ReconcileSuccess')].status + name: ReconcileSuccess + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1beta1 + schema: + openAPIV3Schema: + description: RabbitmqCluster is the Schema for the RabbitmqCluster API. Each instance of this object corresponds to a single RabbitMQ cluster. + 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: Spec is the desired state of the RabbitmqCluster Custom Resource. + properties: + affinity: + description: Affinity scheduling rules to be applied on created Pods. + properties: + nodeAffinity: + description: Describes node affinity scheduling rules for the pod. + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods to nodes that satisfy the affinity expressions specified by this field, but it may choose a node that violates one or more of the expressions. The node that is most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling affinity expressions, etc.), compute a sum by iterating through the elements of this field and adding "weight" to the sum if the node matches the corresponding matchExpressions; the node(s) with the highest sum are the most preferred. + items: + description: An empty preferred scheduling term matches all objects with implicit weight 0 (i.e. it's a no-op). A null preferred scheduling term matches no objects (i.e. is also a no-op). + properties: + preference: + description: A node selector term, associated with the corresponding weight. + properties: + matchExpressions: + description: A list of node selector requirements by node's labels. + items: + description: A node selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + properties: + key: + description: The label key that the selector applies to. + type: string + operator: + description: Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: 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. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements by node's fields. + items: + description: A node selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + properties: + key: + description: The label key that the selector applies to. + type: string + operator: + description: Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: 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. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + x-kubernetes-map-type: atomic + weight: + description: Weight associated with matching the corresponding nodeSelectorTerm, in the range 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by this field are not met at scheduling time, the pod will not be scheduled onto the node. If the affinity requirements specified by this field cease to be met at some point during pod execution (e.g. due to an update), the system may or may not try to eventually evict the pod from its node. + properties: + nodeSelectorTerms: + description: Required. A list of node selector terms. The terms are ORed. + items: + description: A null or empty node selector term matches no objects. The requirements of them are ANDed. The TopologySelectorTerm type implements a subset of the NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node selector requirements by node's labels. + items: + description: A node selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + properties: + key: + description: The label key that the selector applies to. + type: string + operator: + description: Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: 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. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements by node's fields. + items: + description: A node selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + properties: + key: + description: The label key that the selector applies to. + type: string + operator: + description: Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: 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. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + x-kubernetes-map-type: atomic + type: array + required: + - nodeSelectorTerms + type: object + x-kubernetes-map-type: atomic + type: object + podAffinity: + description: Describes pod affinity scheduling rules (e.g. co-locate this pod in the same node, zone, etc. as some other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods to nodes that satisfy the affinity expressions specified by this field, but it may choose a node that violates one or more of the expressions. The node that is most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling affinity expressions, etc.), compute a sum by iterating through the elements of this field and adding "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm fields are added per-node to find the most preferred node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of resources, in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces that the term applies to. The term is applied to the union of the namespaces selected by this field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list of namespace names that the term applies to. The term is applied to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching the corresponding podAffinityTerm, in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by this field are not met at scheduling time, the pod will not be scheduled onto the node. If the affinity requirements specified by this field cease to be met at some point during pod execution (e.g. due to a pod label update), the system may or may not try to eventually evict the pod from its node. When there are multiple elements, the lists of nodes corresponding to each podAffinityTerm are intersected, i.e. all terms must be satisfied. + items: + description: Defines a set of pods (namely those matching the labelSelector relative to the given namespace(s)) that this pod should be co-located (affinity) or not co-located (anti-affinity) with, where co-located is defined as running on a node whose value of the label with key matches that of any node on which a pod of the set of pods is running + properties: + labelSelector: + description: A label query over a set of resources, in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces that the term applies to. The term is applied to the union of the namespaces selected by this field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list of namespace names that the term applies to. The term is applied to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + podAntiAffinity: + description: Describes pod anti-affinity scheduling rules (e.g. avoid putting this pod in the same node, zone, etc. as some other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods to nodes that satisfy the anti-affinity expressions specified by this field, but it may choose a node that violates one or more of the expressions. The node that is most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), compute a sum by iterating through the elements of this field and adding "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm fields are added per-node to find the most preferred node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of resources, in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces that the term applies to. The term is applied to the union of the namespaces selected by this field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list of namespace names that the term applies to. The term is applied to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching the corresponding podAffinityTerm, in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the anti-affinity requirements specified by this field are not met at scheduling time, the pod will not be scheduled onto the node. If the anti-affinity requirements specified by this field cease to be met at some point during pod execution (e.g. due to a pod label update), the system may or may not try to eventually evict the pod from its node. When there are multiple elements, the lists of nodes corresponding to each podAffinityTerm are intersected, i.e. all terms must be satisfied. + items: + description: Defines a set of pods (namely those matching the labelSelector relative to the given namespace(s)) that this pod should be co-located (affinity) or not co-located (anti-affinity) with, where co-located is defined as running on a node whose value of the label with key matches that of any node on which a pod of the set of pods is running + properties: + labelSelector: + description: A label query over a set of resources, in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces that the term applies to. The term is applied to the union of the namespaces selected by this field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list of namespace names that the term applies to. The term is applied to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + type: object + delayStartSeconds: + default: 30 + description: DelayStartSeconds is the time the init container (`setup-container`) will sleep before terminating. This effectively delays the time between starting the Pod and starting the `rabbitmq` container. RabbitMQ relies on up-to-date DNS entries early during peer discovery. The purpose of this artificial delay is to ensure that DNS entries are up-to-date when booting RabbitMQ. For more information, see https://github.com/kubernetes/kubernetes/issues/92559 If your Kubernetes DNS backend is configured with a low DNS cache value or publishes not ready addresses promptly, you can decrase this value or set it to 0. + format: int32 + minimum: 0 + type: integer + image: + description: Image is the name of the RabbitMQ docker image to use for RabbitMQ nodes in the RabbitmqCluster. Must be provided together with ImagePullSecrets in order to use an image in a private registry. + type: string + imagePullSecrets: + description: List of Secret resource containing access credentials to the registry for the RabbitMQ image. Required if the docker registry is private. + items: + description: LocalObjectReference contains enough information to let you locate the referenced object inside the same namespace. + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + x-kubernetes-map-type: atomic + type: array + override: + properties: + service: + properties: + metadata: + properties: + annotations: + additionalProperties: + type: string + type: object + labels: + additionalProperties: + type: string + type: object + type: object + spec: + properties: + allocateLoadBalancerNodePorts: + type: boolean + clusterIP: + type: string + clusterIPs: + items: + type: string + type: array + x-kubernetes-list-type: atomic + externalIPs: + items: + type: string + type: array + externalName: + type: string + externalTrafficPolicy: + type: string + healthCheckNodePort: + format: int32 + type: integer + internalTrafficPolicy: + type: string + ipFamilies: + items: + type: string + type: array + x-kubernetes-list-type: atomic + ipFamilyPolicy: + type: string + loadBalancerClass: + type: string + loadBalancerIP: + type: string + loadBalancerSourceRanges: + items: + type: string + type: array + ports: + items: + properties: + appProtocol: + type: string + name: + type: string + nodePort: + format: int32 + type: integer + port: + format: int32 + type: integer + protocol: + default: TCP + type: string + targetPort: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: array + x-kubernetes-list-map-keys: + - port + - protocol + x-kubernetes-list-type: map + publishNotReadyAddresses: + type: boolean + selector: + additionalProperties: + type: string + type: object + x-kubernetes-map-type: atomic + sessionAffinity: + type: string + sessionAffinityConfig: + properties: + clientIP: + properties: + timeoutSeconds: + format: int32 + type: integer + type: object + type: object + type: + type: string + type: object + type: object + statefulSet: + properties: + metadata: + properties: + annotations: + additionalProperties: + type: string + type: object + labels: + additionalProperties: + type: string + type: object + type: object + spec: + properties: + minReadySeconds: + format: int32 + type: integer + persistentVolumeClaimRetentionPolicy: + properties: + whenDeleted: + type: string + whenScaled: + type: string + type: object + podManagementPolicy: + type: string + replicas: + format: int32 + type: integer + selector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + serviceName: + type: string + template: + properties: + metadata: + properties: + annotations: + additionalProperties: + type: string + type: object + labels: + additionalProperties: + type: string + type: object + name: + type: string + namespace: + type: string + type: object + spec: + properties: + activeDeadlineSeconds: + format: int64 + type: integer + affinity: + properties: + nodeAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + preference: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + x-kubernetes-map-type: atomic + weight: + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + properties: + nodeSelectorTerms: + items: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + x-kubernetes-map-type: atomic + type: array + required: + - nodeSelectorTerms + type: object + x-kubernetes-map-type: atomic + type: object + podAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + podAffinityTerm: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + topologyKey: + type: string + required: + - topologyKey + type: object + weight: + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + topologyKey: + type: string + required: + - topologyKey + type: object + type: array + type: object + podAntiAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + podAffinityTerm: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + topologyKey: + type: string + required: + - topologyKey + type: object + weight: + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + topologyKey: + type: string + required: + - topologyKey + type: object + type: array + type: object + type: object + automountServiceAccountToken: + type: boolean + containers: + items: + properties: + args: + items: + type: string + type: array + command: + items: + type: string + type: array + env: + items: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + properties: + containerName: + type: string + divisor: + 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 + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + envFrom: + items: + properties: + configMapRef: + properties: + name: + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + type: string + secretRef: + properties: + name: + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + image: + type: string + imagePullPolicy: + type: string + lifecycle: + properties: + postStart: + properties: + exec: + properties: + command: + items: + type: string + type: array + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + preStop: + properties: + exec: + properties: + command: + items: + type: string + type: array + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + type: object + livenessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + name: + type: string + ports: + items: + properties: + containerPort: + format: int32 + type: integer + hostIP: + type: string + hostPort: + format: int32 + type: integer + name: + type: string + protocol: + default: TCP + type: string + required: + - containerPort + type: object + type: array + x-kubernetes-list-map-keys: + - containerPort + - protocol + x-kubernetes-list-type: map + readinessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + resizePolicy: + items: + properties: + resourceName: + type: string + restartPolicy: + type: string + required: + - resourceName + - restartPolicy + type: object + type: array + x-kubernetes-list-type: atomic + resources: + properties: + claims: + items: + properties: + name: + 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 + 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 + type: object + type: object + restartPolicy: + type: string + securityContext: + properties: + allowPrivilegeEscalation: + type: boolean + capabilities: + properties: + add: + items: + type: string + type: array + drop: + items: + type: string + type: array + type: object + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + startupProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + stdin: + type: boolean + stdinOnce: + type: boolean + terminationMessagePath: + type: string + terminationMessagePolicy: + type: string + tty: + type: boolean + volumeDevices: + items: + properties: + devicePath: + type: string + name: + type: string + required: + - devicePath + - name + type: object + type: array + volumeMounts: + items: + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + subPath: + type: string + subPathExpr: + type: string + required: + - mountPath + - name + type: object + type: array + workingDir: + type: string + required: + - name + type: object + type: array + dnsConfig: + properties: + nameservers: + items: + type: string + type: array + options: + items: + properties: + name: + type: string + value: + type: string + type: object + type: array + searches: + items: + type: string + type: array + type: object + dnsPolicy: + type: string + enableServiceLinks: + type: boolean + ephemeralContainers: + items: + properties: + args: + items: + type: string + type: array + command: + items: + type: string + type: array + env: + items: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + properties: + containerName: + type: string + divisor: + 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 + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + envFrom: + items: + properties: + configMapRef: + properties: + name: + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + type: string + secretRef: + properties: + name: + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + image: + type: string + imagePullPolicy: + type: string + lifecycle: + properties: + postStart: + properties: + exec: + properties: + command: + items: + type: string + type: array + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + preStop: + properties: + exec: + properties: + command: + items: + type: string + type: array + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + type: object + livenessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + name: + type: string + ports: + items: + properties: + containerPort: + format: int32 + type: integer + hostIP: + type: string + hostPort: + format: int32 + type: integer + name: + type: string + protocol: + default: TCP + type: string + required: + - containerPort + type: object + type: array + x-kubernetes-list-map-keys: + - containerPort + - protocol + x-kubernetes-list-type: map + readinessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + resizePolicy: + items: + properties: + resourceName: + type: string + restartPolicy: + type: string + required: + - resourceName + - restartPolicy + type: object + type: array + x-kubernetes-list-type: atomic + resources: + properties: + claims: + items: + properties: + name: + 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 + 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 + type: object + type: object + restartPolicy: + type: string + securityContext: + properties: + allowPrivilegeEscalation: + type: boolean + capabilities: + properties: + add: + items: + type: string + type: array + drop: + items: + type: string + type: array + type: object + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + startupProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + stdin: + type: boolean + stdinOnce: + type: boolean + targetContainerName: + type: string + terminationMessagePath: + type: string + terminationMessagePolicy: + type: string + tty: + type: boolean + volumeDevices: + items: + properties: + devicePath: + type: string + name: + type: string + required: + - devicePath + - name + type: object + type: array + volumeMounts: + items: + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + subPath: + type: string + subPathExpr: + type: string + required: + - mountPath + - name + type: object + type: array + workingDir: + type: string + required: + - name + type: object + type: array + hostAliases: + items: + properties: + hostnames: + items: + type: string + type: array + ip: + type: string + type: object + type: array + hostIPC: + type: boolean + hostNetwork: + type: boolean + hostPID: + type: boolean + hostUsers: + type: boolean + hostname: + type: string + imagePullSecrets: + items: + properties: + name: + type: string + type: object + x-kubernetes-map-type: atomic + type: array + initContainers: + items: + properties: + args: + items: + type: string + type: array + command: + items: + type: string + type: array + env: + items: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + properties: + containerName: + type: string + divisor: + 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 + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + envFrom: + items: + properties: + configMapRef: + properties: + name: + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + type: string + secretRef: + properties: + name: + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + image: + type: string + imagePullPolicy: + type: string + lifecycle: + properties: + postStart: + properties: + exec: + properties: + command: + items: + type: string + type: array + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + preStop: + properties: + exec: + properties: + command: + items: + type: string + type: array + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + type: object + livenessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + name: + type: string + ports: + items: + properties: + containerPort: + format: int32 + type: integer + hostIP: + type: string + hostPort: + format: int32 + type: integer + name: + type: string + protocol: + default: TCP + type: string + required: + - containerPort + type: object + type: array + x-kubernetes-list-map-keys: + - containerPort + - protocol + x-kubernetes-list-type: map + readinessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + resizePolicy: + items: + properties: + resourceName: + type: string + restartPolicy: + type: string + required: + - resourceName + - restartPolicy + type: object + type: array + x-kubernetes-list-type: atomic + resources: + properties: + claims: + items: + properties: + name: + 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 + 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 + type: object + type: object + restartPolicy: + type: string + securityContext: + properties: + allowPrivilegeEscalation: + type: boolean + capabilities: + properties: + add: + items: + type: string + type: array + drop: + items: + type: string + type: array + type: object + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + startupProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + stdin: + type: boolean + stdinOnce: + type: boolean + terminationMessagePath: + type: string + terminationMessagePolicy: + type: string + tty: + type: boolean + volumeDevices: + items: + properties: + devicePath: + type: string + name: + type: string + required: + - devicePath + - name + type: object + type: array + volumeMounts: + items: + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + subPath: + type: string + subPathExpr: + type: string + required: + - mountPath + - name + type: object + type: array + workingDir: + type: string + required: + - name + type: object + type: array + nodeName: + type: string + nodeSelector: + additionalProperties: + type: string + type: object + x-kubernetes-map-type: atomic + os: + properties: + name: + type: string + required: + - name + type: object + overhead: + 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 + type: object + preemptionPolicy: + type: string + priority: + format: int32 + type: integer + priorityClassName: + type: string + readinessGates: + items: + properties: + conditionType: + type: string + required: + - conditionType + type: object + type: array + resourceClaims: + items: + properties: + name: + type: string + source: + properties: + resourceClaimName: + type: string + resourceClaimTemplateName: + type: string + type: object + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + restartPolicy: + type: string + runtimeClassName: + type: string + schedulerName: + type: string + schedulingGates: + items: + properties: + name: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + securityContext: + properties: + fsGroup: + format: int64 + type: integer + fsGroupChangePolicy: + type: string + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + supplementalGroups: + items: + format: int64 + type: integer + type: array + sysctls: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + serviceAccount: + type: string + serviceAccountName: + type: string + setHostnameAsFQDN: + type: boolean + shareProcessNamespace: + type: boolean + subdomain: + type: string + terminationGracePeriodSeconds: + format: int64 + type: integer + tolerations: + items: + properties: + effect: + type: string + key: + type: string + operator: + type: string + tolerationSeconds: + format: int64 + type: integer + value: + type: string + type: object + type: array + topologySpreadConstraints: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + maxSkew: + format: int32 + type: integer + minDomains: + format: int32 + type: integer + nodeAffinityPolicy: + type: string + nodeTaintsPolicy: + type: string + topologyKey: + type: string + whenUnsatisfiable: + type: string + required: + - maxSkew + - topologyKey + - whenUnsatisfiable + type: object + type: array + x-kubernetes-list-map-keys: + - topologyKey + - whenUnsatisfiable + x-kubernetes-list-type: map + volumes: + items: + properties: + awsElasticBlockStore: + properties: + fsType: + type: string + partition: + format: int32 + type: integer + readOnly: + type: boolean + volumeID: + type: string + required: + - volumeID + type: object + azureDisk: + properties: + cachingMode: + type: string + diskName: + type: string + diskURI: + type: string + fsType: + type: string + kind: + type: string + readOnly: + type: boolean + required: + - diskName + - diskURI + type: object + azureFile: + properties: + readOnly: + type: boolean + secretName: + type: string + shareName: + type: string + required: + - secretName + - shareName + type: object + cephfs: + properties: + monitors: + items: + type: string + type: array + path: + type: string + readOnly: + type: boolean + secretFile: + type: string + secretRef: + properties: + name: + type: string + type: object + x-kubernetes-map-type: atomic + user: + type: string + required: + - monitors + type: object + cinder: + properties: + fsType: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + type: string + type: object + x-kubernetes-map-type: atomic + volumeID: + type: string + required: + - volumeID + type: object + configMap: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + name: + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + csi: + properties: + driver: + type: string + fsType: + type: string + nodePublishSecretRef: + properties: + name: + type: string + type: object + x-kubernetes-map-type: atomic + readOnly: + type: boolean + volumeAttributes: + additionalProperties: + type: string + type: object + required: + - driver + type: object + downwardAPI: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + mode: + format: int32 + type: integer + path: + type: string + resourceFieldRef: + properties: + containerName: + type: string + divisor: + 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 + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + required: + - path + type: object + type: array + type: object + emptyDir: + properties: + medium: + type: string + sizeLimit: + 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 + type: object + ephemeral: + properties: + volumeClaimTemplate: + properties: + metadata: + type: object + spec: + properties: + accessModes: + items: + type: string + type: array + dataSource: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + - name + type: object + resources: + properties: + claims: + items: + properties: + name: + 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 + 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 + type: object + type: object + selector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + storageClassName: + type: string + volumeMode: + type: string + volumeName: + type: string + type: object + required: + - spec + type: object + type: object + fc: + properties: + fsType: + type: string + lun: + format: int32 + type: integer + readOnly: + type: boolean + targetWWNs: + items: + type: string + type: array + wwids: + items: + type: string + type: array + type: object + flexVolume: + properties: + driver: + type: string + fsType: + type: string + options: + additionalProperties: + type: string + type: object + readOnly: + type: boolean + secretRef: + properties: + name: + type: string + type: object + x-kubernetes-map-type: atomic + required: + - driver + type: object + flocker: + properties: + datasetName: + type: string + datasetUUID: + type: string + type: object + gcePersistentDisk: + properties: + fsType: + type: string + partition: + format: int32 + type: integer + pdName: + type: string + readOnly: + type: boolean + required: + - pdName + type: object + gitRepo: + properties: + directory: + type: string + repository: + type: string + revision: + type: string + required: + - repository + type: object + glusterfs: + properties: + endpoints: + type: string + path: + type: string + readOnly: + type: boolean + required: + - endpoints + - path + type: object + hostPath: + properties: + path: + type: string + type: + type: string + required: + - path + type: object + iscsi: + properties: + chapAuthDiscovery: + type: boolean + chapAuthSession: + type: boolean + fsType: + type: string + initiatorName: + type: string + iqn: + type: string + iscsiInterface: + type: string + lun: + format: int32 + type: integer + portals: + items: + type: string + type: array + readOnly: + type: boolean + secretRef: + properties: + name: + type: string + type: object + x-kubernetes-map-type: atomic + targetPortal: + type: string + required: + - iqn + - lun + - targetPortal + type: object + name: + type: string + nfs: + properties: + path: + type: string + readOnly: + type: boolean + server: + type: string + required: + - path + - server + type: object + persistentVolumeClaim: + properties: + claimName: + type: string + readOnly: + type: boolean + required: + - claimName + type: object + photonPersistentDisk: + properties: + fsType: + type: string + pdID: + type: string + required: + - pdID + type: object + portworxVolume: + properties: + fsType: + type: string + readOnly: + type: boolean + volumeID: + type: string + required: + - volumeID + type: object + projected: + properties: + defaultMode: + format: int32 + type: integer + sources: + items: + properties: + configMap: + properties: + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + name: + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + downwardAPI: + properties: + items: + items: + properties: + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + mode: + format: int32 + type: integer + path: + type: string + resourceFieldRef: + properties: + containerName: + type: string + divisor: + 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 + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + required: + - path + type: object + type: array + type: object + secret: + properties: + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + name: + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + serviceAccountToken: + properties: + audience: + type: string + expirationSeconds: + format: int64 + type: integer + path: + type: string + required: + - path + type: object + type: object + type: array + type: object + quobyte: + properties: + group: + type: string + readOnly: + type: boolean + registry: + type: string + tenant: + type: string + user: + type: string + volume: + type: string + required: + - registry + - volume + type: object + rbd: + properties: + fsType: + type: string + image: + type: string + keyring: + type: string + monitors: + items: + type: string + type: array + pool: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + type: string + type: object + x-kubernetes-map-type: atomic + user: + type: string + required: + - image + - monitors + type: object + scaleIO: + properties: + fsType: + type: string + gateway: + type: string + protectionDomain: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + type: string + type: object + x-kubernetes-map-type: atomic + sslEnabled: + type: boolean + storageMode: + type: string + storagePool: + type: string + system: + type: string + volumeName: + type: string + required: + - gateway + - secretRef + - system + type: object + secret: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + optional: + type: boolean + secretName: + type: string + type: object + storageos: + properties: + fsType: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + type: string + type: object + x-kubernetes-map-type: atomic + volumeName: + type: string + volumeNamespace: + type: string + type: object + vsphereVolume: + properties: + fsType: + type: string + storagePolicyID: + type: string + storagePolicyName: + type: string + volumePath: + type: string + required: + - volumePath + type: object + required: + - name + type: object + type: array + required: + - containers + type: object + type: object + updateStrategy: + properties: + rollingUpdate: + properties: + maxUnavailable: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + partition: + format: int32 + type: integer + type: object + type: + type: string + type: object + volumeClaimTemplates: + items: + properties: + apiVersion: + type: string + kind: + type: string + metadata: + properties: + annotations: + additionalProperties: + type: string + type: object + labels: + additionalProperties: + type: string + type: object + name: + type: string + namespace: + type: string + type: object + spec: + properties: + accessModes: + items: + type: string + type: array + dataSource: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + - name + type: object + resources: + properties: + claims: + items: + properties: + name: + 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 + 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 + type: object + type: object + selector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + storageClassName: + type: string + volumeMode: + type: string + volumeName: + type: string + type: object + type: object + type: array + type: object + type: object + type: object + persistence: + default: + storage: 10Gi + description: The desired persistent storage configuration for each Pod in the cluster. + properties: + storage: + anyOf: + - type: integer + - type: string + default: 10Gi + description: The requested size of the persistent volume attached to each Pod in the RabbitmqCluster. The format of this field matches that defined by kubernetes/apimachinery. See https://pkg.go.dev/k8s.io/apimachinery/pkg/api/resource#Quantity for more info on the format of this field. + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + storageClassName: + description: The name of the StorageClass to claim a PersistentVolume from. + type: string + type: object + rabbitmq: + description: Configuration options for RabbitMQ Pods created in the cluster. + properties: + additionalConfig: + description: Modify to add to the rabbitmq.conf file in addition to default configurations set by the operator. Modifying this property on an existing RabbitmqCluster will trigger a StatefulSet rolling restart and will cause rabbitmq downtime. For more information on this config, see https://www.rabbitmq.com/configure.html#config-file + maxLength: 2000 + type: string + additionalPlugins: + description: 'List of plugins to enable in addition to essential plugins: rabbitmq_management, rabbitmq_prometheus, and rabbitmq_peer_discovery_k8s.' + items: + description: A Plugin to enable on the RabbitmqCluster. + maxLength: 100 + pattern: ^\w+$ + type: string + maxItems: 100 + type: array + advancedConfig: + description: Specify any rabbitmq advanced.config configurations to apply to the cluster. For more information on advanced config, see https://www.rabbitmq.com/configure.html#advanced-config-file + maxLength: 100000 + type: string + envConfig: + description: Modify to add to the rabbitmq-env.conf file. Modifying this property on an existing RabbitmqCluster will trigger a StatefulSet rolling restart and will cause rabbitmq downtime. For more information on env config, see https://www.rabbitmq.com/man/rabbitmq-env.conf.5.html + maxLength: 100000 + type: string + erlangInetConfig: + description: 'Erlang Inet configuration to apply to the Erlang VM running rabbit. See also: https://www.erlang.org/doc/apps/erts/inet_cfg.html' + maxLength: 2000 + type: string + type: object + replicas: + default: 1 + description: Replicas is the number of nodes in the RabbitMQ cluster. Each node is deployed as a Replica in a StatefulSet. Only 1, 3, 5 replicas clusters are tested. This value should be an odd number to ensure the resultant cluster can establish exactly one quorum of nodes in the event of a fragmenting network partition. + format: int32 + minimum: 0 + type: integer + resources: + default: + limits: + cpu: 2000m + memory: 2Gi + requests: + cpu: 1000m + memory: 2Gi + description: The desired compute resource requirements of Pods in the cluster. + properties: + claims: + description: "Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. \n This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. \n 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 + 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 + secretBackend: + description: Secret backend configuration for the RabbitmqCluster. Enables to fetch default user credentials and certificates from K8s external secret stores. + properties: + externalSecret: + description: LocalObjectReference contains enough information to let you locate the referenced object inside the same namespace. + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + x-kubernetes-map-type: atomic + vault: + description: VaultSpec will add Vault annotations (see https://www.vaultproject.io/docs/platform/k8s/injector/annotations) to RabbitMQ Pods. It requires a Vault Agent Sidecar Injector (https://www.vaultproject.io/docs/platform/k8s/injector) to be installed in the K8s cluster. The injector is a K8s Mutation Webhook Controller that alters RabbitMQ Pod specifications (based on the added Vault annotations) to include Vault Agent containers that render Vault secrets to the volume. + properties: + annotations: + additionalProperties: + type: string + description: Vault annotations that override the Vault annotations set by the cluster-operator. For a list of valid Vault annotations, see https://www.vaultproject.io/docs/platform/k8s/injector/annotations + type: object + defaultUserPath: + description: Path in Vault to access a KV (Key-Value) secret with the fields username and password for the default user. For example "secret/data/rabbitmq/config". + type: string + defaultUserUpdaterImage: + description: Sidecar container that updates the default user's password in RabbitMQ when it changes in Vault. Additionally, it updates /var/lib/rabbitmq/.rabbitmqadmin.conf (used by rabbitmqadmin CLI). Set to empty string to disable the sidecar container. + type: string + role: + description: Role in Vault. If vault.defaultUserPath is set, this role must have capability to read the pre-created default user credential in Vault. If vault.tls is set, this role must have capability to create and update certificates in the Vault PKI engine for the domains "" and ".svc". + type: string + tls: + properties: + altNames: + description: 'Specifies the requested Subject Alternative Names (SANs), in a comma-delimited list. These will be appended to the SANs added by the cluster-operator. The cluster-operator will add SANs: "-server-.-nodes." for each pod, e.g. "myrabbit-server-0.myrabbit-nodes.default".' + type: string + commonName: + description: Specifies the requested certificate Common Name (CN). Defaults to ..svc if not provided. + type: string + ipSans: + description: Specifies the requested IP Subject Alternative Names, in a comma-delimited list. + type: string + pkiIssuerPath: + description: Path in Vault PKI engine. For example "pki/issue/hashicorp-com". required + type: string + type: object + type: object + type: object + service: + default: + type: ClusterIP + description: The desired state of the Kubernetes Service to create for the cluster. + properties: + annotations: + additionalProperties: + type: string + description: Annotations to add to the Service. + type: object + ipFamilyPolicy: + description: 'IPFamilyPolicy represents the dual-stack-ness requested or required by a Service See also: https://pkg.go.dev/k8s.io/api/core/v1#IPFamilyPolicy' + enum: + - SingleStack + - PreferDualStack + - RequireDualStack + type: string + type: + default: ClusterIP + description: 'Type of Service to create for the cluster. Must be one of: ClusterIP, LoadBalancer, NodePort. For more info see https://pkg.go.dev/k8s.io/api/core/v1#ServiceType' + enum: + - ClusterIP + - LoadBalancer + - NodePort + type: string + type: object + skipPostDeploySteps: + description: If unset, or set to false, the cluster will run `rabbitmq-queues rebalance all` whenever the cluster is updated. Set to true to prevent the operator rebalancing queue leaders after a cluster update. Has no effect if the cluster only consists of one node. For more information, see https://www.rabbitmq.com/rabbitmq-queues.8.html#rebalance + type: boolean + terminationGracePeriodSeconds: + default: 604800 + description: 'TerminationGracePeriodSeconds is the timeout that each rabbitmqcluster pod will have to terminate gracefully. It defaults to 604800 seconds ( a week long) to ensure that the container preStop lifecycle hook can finish running. For more information, see: https://github.com/rabbitmq/cluster-operator/blob/main/docs/design/20200520-graceful-pod-termination.md' + format: int64 + minimum: 0 + type: integer + tls: + description: TLS-related configuration for the RabbitMQ cluster. + properties: + caSecretName: + description: Name of a Secret in the same Namespace as the RabbitmqCluster, containing the Certificate Authority's public certificate for TLS. The Secret must store this as ca.crt. This Secret can be created by running `kubectl create secret generic ca-secret --from-file=ca.crt=path/to/ca.cert` Used for mTLS, and TLS for rabbitmq_web_stomp and rabbitmq_web_mqtt. + type: string + disableNonTLSListeners: + description: 'When set to true, the RabbitmqCluster disables non-TLS listeners for RabbitMQ, management plugin and for any enabled plugins in the following list: stomp, mqtt, web_stomp, web_mqtt. Only TLS-enabled clients will be able to connect.' + type: boolean + secretName: + description: Name of a Secret in the same Namespace as the RabbitmqCluster, containing the server's private key & public certificate for TLS. The Secret must store these as tls.key and tls.crt, respectively. This Secret can be created by running `kubectl create secret tls tls-secret --cert=path/to/tls.cert --key=path/to/tls.key` + type: string + type: object + tolerations: + description: Tolerations is the list of Toleration resources attached to each Pod in the RabbitmqCluster. + 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 + type: object + status: + description: Status presents the observed state of RabbitmqCluster + properties: + binding: + description: 'Binding exposes a secret containing the binding information for this RabbitmqCluster. It implements the service binding Provisioned Service duck type. See: https://github.com/servicebinding/spec#provisioned-service' + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + x-kubernetes-map-type: atomic + conditions: + description: Set of Conditions describing the current state of the RabbitmqCluster + items: + properties: + lastTransitionTime: + description: The last time this Condition type changed. + format: date-time + type: string + message: + description: Full text reason for current status of the condition. + type: string + reason: + description: One word, camel-case reason for current status of the condition. + type: string + status: + description: True, False, or Unknown + type: string + type: + description: Type indicates the scope of RabbitmqCluster status addressed by the condition. + type: string + required: + - status + - type + type: object + type: array + defaultUser: + description: Identifying information on internal resources + properties: + secretReference: + description: Reference to the Kubernetes Secret containing the credentials of the default user. + properties: + keys: + additionalProperties: + type: string + description: Key-value pairs in the Secret corresponding to `username`, `password`, `host`, and `port` + type: object + name: + description: Name of the Secret containing the default user credentials + type: string + namespace: + description: Namespace of the Secret containing the default user credentials + type: string + required: + - keys + - name + - namespace + type: object + serviceReference: + description: Reference to the Kubernetes Service serving the cluster. + properties: + name: + description: Name of the Service serving the cluster + type: string + namespace: + description: Namespace of the Service serving the cluster + type: string + required: + - name + - namespace + type: object + type: object + observedGeneration: + description: observedGeneration is the most recent successful generation observed for this RabbitmqCluster. It corresponds to the RabbitmqCluster's generation, which is updated on mutation by the API Server. + format: int64 + type: integer + required: + - conditions + type: object + type: object + served: true + storage: true + subresources: + status: {} +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: rabbitmq-cluster-operator + namespace: cozy-rabbitmq-operator +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + labels: + app.kubernetes.io/component: rabbitmq-operator + app.kubernetes.io/name: rabbitmq-cluster-operator + app.kubernetes.io/part-of: rabbitmq + name: rabbitmq-cluster-leader-election-role + namespace: cozy-rabbitmq-operator +rules: + - apiGroups: + - coordination.k8s.io + resources: + - leases + verbs: + - get + - list + - watch + - create + - update + - patch + - delete + - apiGroups: + - "" + resources: + - events + verbs: + - create +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/component: rabbitmq-operator + app.kubernetes.io/name: rabbitmq-cluster-operator + app.kubernetes.io/part-of: rabbitmq + name: rabbitmq-cluster-operator-role +rules: + - apiGroups: + - "" + resources: + - configmaps + verbs: + - create + - get + - list + - update + - watch + - apiGroups: + - "" + resources: + - endpoints + verbs: + - get + - list + - watch + - apiGroups: + - "" + resources: + - events + verbs: + - create + - get + - patch + - apiGroups: + - "" + resources: + - persistentvolumeclaims + verbs: + - create + - get + - list + - update + - watch + - apiGroups: + - "" + resources: + - pods + verbs: + - get + - list + - update + - watch + - apiGroups: + - "" + resources: + - pods/exec + verbs: + - create + - apiGroups: + - "" + resources: + - secrets + verbs: + - create + - get + - list + - update + - watch + - apiGroups: + - "" + resources: + - serviceaccounts + verbs: + - create + - get + - list + - update + - watch + - apiGroups: + - "" + resources: + - services + verbs: + - create + - get + - list + - update + - watch + - apiGroups: + - apps + resources: + - statefulsets + verbs: + - create + - delete + - get + - list + - update + - watch + - apiGroups: + - rabbitmq.com + resources: + - rabbitmqclusters + verbs: + - create + - get + - list + - update + - watch + - apiGroups: + - rabbitmq.com + resources: + - rabbitmqclusters/finalizers + verbs: + - update + - apiGroups: + - rabbitmq.com + resources: + - rabbitmqclusters/status + verbs: + - get + - update + - apiGroups: + - rbac.authorization.k8s.io + resources: + - rolebindings + verbs: + - create + - get + - list + - update + - watch + - apiGroups: + - rbac.authorization.k8s.io + resources: + - roles + verbs: + - create + - get + - list + - update + - watch +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/component: rabbitmq-operator + app.kubernetes.io/name: rabbitmq-cluster-operator + app.kubernetes.io/part-of: rabbitmq + servicebinding.io/controller: "true" + name: rabbitmq-cluster-service-binding-role +rules: + - apiGroups: + - rabbitmq.com + resources: + - rabbitmqclusters + verbs: + - get + - list + - watch +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + labels: + app.kubernetes.io/component: rabbitmq-operator + app.kubernetes.io/name: rabbitmq-cluster-operator + app.kubernetes.io/part-of: rabbitmq + name: rabbitmq-cluster-leader-election-rolebinding + namespace: cozy-rabbitmq-operator +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: rabbitmq-cluster-leader-election-role +subjects: + - kind: ServiceAccount + name: rabbitmq-cluster-operator + namespace: cozy-rabbitmq-operator +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + labels: + app.kubernetes.io/component: rabbitmq-operator + app.kubernetes.io/name: rabbitmq-cluster-operator + app.kubernetes.io/part-of: rabbitmq + name: rabbitmq-cluster-operator-rolebinding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: rabbitmq-cluster-operator-role +subjects: + - kind: ServiceAccount + name: rabbitmq-cluster-operator + namespace: cozy-rabbitmq-operator +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app.kubernetes.io/component: rabbitmq-operator + app.kubernetes.io/name: rabbitmq-cluster-operator + app.kubernetes.io/part-of: rabbitmq + name: rabbitmq-cluster-operator + namespace: cozy-rabbitmq-operator +spec: + replicas: 1 + selector: + matchLabels: + app.kubernetes.io/name: rabbitmq-cluster-operator + template: + metadata: + labels: + app.kubernetes.io/component: rabbitmq-operator + app.kubernetes.io/name: rabbitmq-cluster-operator + app.kubernetes.io/part-of: rabbitmq + spec: + containers: + - command: + - /manager + env: + - name: OPERATOR_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + image: rabbitmqoperator/cluster-operator:2.6.0 + name: operator + ports: + - containerPort: 9782 + name: metrics + protocol: TCP + resources: + limits: + cpu: 200m + memory: 500Mi + requests: + cpu: 200m + memory: 500Mi + serviceAccountName: rabbitmq-cluster-operator + terminationGracePeriodSeconds: 10 diff --git a/packages/system/rabbitmq-operator/values.yaml b/packages/system/rabbitmq-operator/values.yaml new file mode 100644 index 00000000..e69de29b diff --git a/packages/system/redis-operator/Chart.yaml b/packages/system/redis-operator/Chart.yaml new file mode 100644 index 00000000..7f23bfb3 --- /dev/null +++ b/packages/system/redis-operator/Chart.yaml @@ -0,0 +1,2 @@ +name: cozy-redis-operator +version: 1.0.0 diff --git a/packages/system/redis-operator/Makefile b/packages/system/redis-operator/Makefile new file mode 100644 index 00000000..16ff97ab --- /dev/null +++ b/packages/system/redis-operator/Makefile @@ -0,0 +1,18 @@ +NAME=redis-operator +NAMESPACE=cozy-redis-operator + +show: + helm template --dry-run=server -n $(NAMESPACE) $(NAME) . + +apply: + helm upgrade -i -n $(NAMESPACE) $(NAME) . + +diff: + helm diff upgrade --allow-unreleased --normalize-manifests -n $(NAMESPACE) $(NAME) . + +update: + rm -rf charts + helm repo add redis-operator https://spotahome.github.io/redis-operator + helm repo update redis-operator + helm pull redis-operator/redis-operator --untar --untardir charts + sed -i '/{{/d' charts/redis-operator/crds/databases.spotahome.com_redisfailovers.yaml diff --git a/packages/system/redis-operator/charts/redis-operator/.helmignore b/packages/system/redis-operator/charts/redis-operator/.helmignore new file mode 100644 index 00000000..f0c13194 --- /dev/null +++ b/packages/system/redis-operator/charts/redis-operator/.helmignore @@ -0,0 +1,21 @@ +# 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 +*~ +# Various IDEs +.project +.idea/ +*.tmproj diff --git a/packages/system/redis-operator/charts/redis-operator/Chart.yaml b/packages/system/redis-operator/charts/redis-operator/Chart.yaml new file mode 100644 index 00000000..0d0322d7 --- /dev/null +++ b/packages/system/redis-operator/charts/redis-operator/Chart.yaml @@ -0,0 +1,15 @@ +annotations: + category: Redis Operator +apiVersion: v1 +appVersion: 1.3.0 +description: A Helm chart for the Spotahome Redis Operator +home: https://github.com/spotahome/redis-operator +keywords: +- golang +- operator +- cluster +kubeVersion: '>=1.21.0-0' +name: redis-operator +sources: +- https://github.com/spotahome/redis-operator +version: 3.3.0 diff --git a/packages/system/redis-operator/charts/redis-operator/crds/databases.spotahome.com_redisfailovers.yaml b/packages/system/redis-operator/charts/redis-operator/crds/databases.spotahome.com_redisfailovers.yaml new file mode 100644 index 00000000..4739b126 --- /dev/null +++ b/packages/system/redis-operator/charts/redis-operator/crds/databases.spotahome.com_redisfailovers.yaml @@ -0,0 +1,12398 @@ + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: (devel) + creationTimestamp: null + name: redisfailovers.databases.spotahome.com +spec: + group: databases.spotahome.com + names: + kind: RedisFailover + listKind: RedisFailoverList + plural: redisfailovers + shortNames: + - rf + singular: redisfailover + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .metadata.name + name: NAME + type: string + - jsonPath: .spec.redis.replicas + name: REDIS + type: integer + - jsonPath: .spec.sentinel.replicas + name: SENTINELS + type: integer + - jsonPath: .metadata.creationTimestamp + name: AGE + type: date + name: v1 + schema: + openAPIV3Schema: + description: RedisFailover represents a Redis failover + 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: RedisFailoverSpec represents a Redis failover spec + properties: + auth: + description: AuthSettings contains settings about auth + properties: + secretPath: + type: string + type: object + bootstrapNode: + description: BootstrapSettings contains settings about a potential + bootstrap node + properties: + allowSentinels: + type: boolean + host: + type: string + port: + type: string + type: object + labelWhitelist: + items: + type: string + type: array + redis: + description: RedisSettings defines the specification of the redis + cluster + properties: + affinity: + description: Affinity is a group of affinity scheduling rules. + properties: + nodeAffinity: + description: Describes node affinity scheduling rules for + the pod. + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods + to nodes that satisfy the affinity expressions specified + by this field, but it may choose a node that violates + one or more of the expressions. The node that is most + preferred is the one with the greatest sum of weights, + i.e. for each node that meets all of the scheduling + requirements (resource request, requiredDuringScheduling + affinity expressions, etc.), compute a sum by iterating + through the elements of this field and adding "weight" + to the sum if the node matches the corresponding matchExpressions; + the node(s) with the highest sum are the most preferred. + items: + description: An empty preferred scheduling term matches + all objects with implicit weight 0 (i.e. it's a no-op). + A null preferred scheduling term matches no objects + (i.e. is also a no-op). + properties: + preference: + description: A node selector term, associated with + the corresponding weight. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: 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. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: 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. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + weight: + description: Weight associated with matching the + corresponding nodeSelectorTerm, in the range 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by + this field are not met at scheduling time, the pod will + not be scheduled onto the node. If the affinity requirements + specified by this field cease to be met at some point + during pod execution (e.g. due to an update), the system + may or may not try to eventually evict the pod from + its node. + properties: + nodeSelectorTerms: + description: Required. A list of node selector terms. + The terms are ORed. + items: + description: A null or empty node selector term + matches no objects. The requirements of them are + ANDed. The TopologySelectorTerm type implements + a subset of the NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: 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. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: 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. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + type: array + required: + - nodeSelectorTerms + type: object + type: object + podAffinity: + description: Describes pod affinity scheduling rules (e.g. + co-locate this pod in the same node, zone, etc. as some + other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods + to nodes that satisfy the affinity expressions specified + by this field, but it may choose a node that violates + one or more of the expressions. The node that is most + preferred is the one with the greatest sum of weights, + i.e. for each node that meets all of the scheduling + requirements (resource request, requiredDuringScheduling + affinity expressions, etc.), compute a sum by iterating + through the elements of this field and adding "weight" + to the sum if the node has pods which matches the corresponding + podAffinityTerm; the node(s) with the highest sum are + the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by + this field and the ones listed in the namespaces + field. null selector and null or empty namespaces + list means "this pod's namespace". An empty + selector ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. + The term is applied to the union of the namespaces + listed in this field and the ones selected + by namespaceSelector. null or empty namespaces + list and null namespaceSelector means "this + pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the + pods matching the labelSelector in the specified + namespaces, where co-located is defined as + running on a node whose value of the label + with key topologyKey matches that of any node + on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching the + corresponding podAffinityTerm, in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by + this field are not met at scheduling time, the pod will + not be scheduled onto the node. If the affinity requirements + specified by this field cease to be met at some point + during pod execution (e.g. due to a pod label update), + the system may or may not try to eventually evict the + pod from its node. When there are multiple elements, + the lists of nodes corresponding to each podAffinityTerm + are intersected, i.e. all terms must be satisfied. + items: + description: Defines a set of pods (namely those matching + the labelSelector relative to the given namespace(s)) + that this pod should be co-located (affinity) or not + co-located (anti-affinity) with, where co-located + is defined as running on a node whose value of the + label with key matches that of any node + on which a pod of the set of pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by this + field and the ones listed in the namespaces field. + null selector and null or empty namespaces list + means "this pod's namespace". An empty selector + ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. The + term is applied to the union of the namespaces + listed in this field and the ones selected by + namespaceSelector. null or empty namespaces list + and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods + matching the labelSelector in the specified namespaces, + where co-located is defined as running on a node + whose value of the label with key topologyKey + matches that of any node on which any of the selected + pods is running. Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + podAntiAffinity: + description: Describes pod anti-affinity scheduling rules + (e.g. avoid putting this pod in the same node, zone, etc. + as some other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods + to nodes that satisfy the anti-affinity expressions + specified by this field, but it may choose a node that + violates one or more of the expressions. The node that + is most preferred is the one with the greatest sum of + weights, i.e. for each node that meets all of the scheduling + requirements (resource request, requiredDuringScheduling + anti-affinity expressions, etc.), compute a sum by iterating + through the elements of this field and adding "weight" + to the sum if the node has pods which matches the corresponding + podAffinityTerm; the node(s) with the highest sum are + the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by + this field and the ones listed in the namespaces + field. null selector and null or empty namespaces + list means "this pod's namespace". An empty + selector ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. + The term is applied to the union of the namespaces + listed in this field and the ones selected + by namespaceSelector. null or empty namespaces + list and null namespaceSelector means "this + pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the + pods matching the labelSelector in the specified + namespaces, where co-located is defined as + running on a node whose value of the label + with key topologyKey matches that of any node + on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching the + corresponding podAffinityTerm, in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the anti-affinity requirements specified + by this field are not met at scheduling time, the pod + will not be scheduled onto the node. If the anti-affinity + requirements specified by this field cease to be met + at some point during pod execution (e.g. due to a pod + label update), the system may or may not try to eventually + evict the pod from its node. When there are multiple + elements, the lists of nodes corresponding to each podAffinityTerm + are intersected, i.e. all terms must be satisfied. + items: + description: Defines a set of pods (namely those matching + the labelSelector relative to the given namespace(s)) + that this pod should be co-located (affinity) or not + co-located (anti-affinity) with, where co-located + is defined as running on a node whose value of the + label with key matches that of any node + on which a pod of the set of pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by this + field and the ones listed in the namespaces field. + null selector and null or empty namespaces list + means "this pod's namespace". An empty selector + ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. The + term is applied to the union of the namespaces + listed in this field and the ones selected by + namespaceSelector. null or empty namespaces list + and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods + matching the labelSelector in the specified namespaces, + where co-located is defined as running on a node + whose value of the label with key topologyKey + matches that of any node on which any of the selected + pods is running. Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + type: object + command: + items: + type: string + type: array + containerSecurityContext: + description: SecurityContext holds security configuration that + will be applied to a container. Some fields are present in both + SecurityContext and PodSecurityContext. When both are set, + the values in SecurityContext take precedence. + properties: + allowPrivilegeEscalation: + description: 'AllowPrivilegeEscalation controls whether a + process can gain more privileges than its parent process. + This bool directly controls if the no_new_privs flag will + be set on the container process. AllowPrivilegeEscalation + is true always when the container is: 1) run as Privileged + 2) has CAP_SYS_ADMIN Note that this field cannot be set + when spec.os.name is windows.' + type: boolean + capabilities: + description: The capabilities to add/drop when running containers. + Defaults to the default set of capabilities granted by the + container runtime. Note that this field cannot be set when + spec.os.name is windows. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + type: object + privileged: + description: Run container in privileged mode. Processes in + privileged containers are essentially equivalent to root + on the host. Defaults to false. Note that this field cannot + be set when spec.os.name is windows. + type: boolean + procMount: + description: procMount denotes the type of proc mount to use + for the containers. The default is DefaultProcMount which + uses the container runtime defaults for readonly paths and + masked paths. This requires the ProcMountType feature flag + to be enabled. Note that this field cannot be set when spec.os.name + is windows. + type: string + readOnlyRootFilesystem: + description: Whether this container has a read-only root filesystem. + Default is false. Note that this field cannot be set when + spec.os.name is windows. + type: boolean + runAsGroup: + description: The GID to run the entrypoint of the container + process. Uses runtime default if unset. May also be set + in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as a non-root + user. If true, the Kubelet will validate the image at runtime + to ensure that it does not run as UID 0 (root) and fail + to start the container if it does. If unset or false, no + such validation will be performed. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container + process. Defaults to user specified in image metadata if + unspecified. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. Note + that this field cannot be set when spec.os.name is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to the container. + If unspecified, the container runtime will allocate a random + SELinux context for each container. May also be set in + PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by this container. + If seccomp options are provided at both the pod & container + level, the container options override the pod options. Note + that this field cannot be set when spec.os.name is windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile defined + in a file on the node should be used. The profile must + be preconfigured on the node to work. Must be a descending + path, relative to the kubelet's configured seccomp profile + location. Must only be set if type is "Localhost". + type: string + type: + description: "type indicates which kind of seccomp profile + will be applied. Valid options are: \n Localhost - a + profile defined in a file on the node should be used. + RuntimeDefault - the container runtime default profile + should be used. Unconfined - no profile should be applied." + type: string + required: + - type + type: object + windowsOptions: + description: The Windows specific settings applied to all + containers. If unspecified, the options from the PodSecurityContext + will be used. If set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is + linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA admission + webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec named + by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of the + GMSA credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container should + be run as a 'Host Process' container. This field is + alpha-level and will only be honored by components that + enable the WindowsHostProcessContainers feature flag. + Setting this field without the feature flag will result + in errors when validating the Pod. All of a Pod's containers + must have the same effective HostProcess value (it is + not allowed to have a mix of HostProcess containers + and non-HostProcess containers). In addition, if HostProcess + is true then HostNetwork must also be set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set in + PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. + type: string + type: object + type: object + customCommandRenames: + items: + description: RedisCommandRename defines the specification of + a "rename-command" configuration option + properties: + from: + type: string + to: + type: string + type: object + type: array + customConfig: + items: + type: string + type: array + dnsPolicy: + description: DNSPolicy defines how a pod's DNS will be configured. + type: string + exporter: + description: Exporter defines the specification for the redis/sentinel + exporter + properties: + args: + items: + type: string + type: array + containerSecurityContext: + description: SecurityContext holds security configuration + that will be applied to a container. Some fields are present + in both SecurityContext and PodSecurityContext. When both + are set, the values in SecurityContext take precedence. + properties: + allowPrivilegeEscalation: + description: 'AllowPrivilegeEscalation controls whether + a process can gain more privileges than its parent process. + This bool directly controls if the no_new_privs flag + will be set on the container process. AllowPrivilegeEscalation + is true always when the container is: 1) run as Privileged + 2) has CAP_SYS_ADMIN Note that this field cannot be + set when spec.os.name is windows.' + type: boolean + capabilities: + description: The capabilities to add/drop when running + containers. Defaults to the default set of capabilities + granted by the container runtime. Note that this field + cannot be set when spec.os.name is windows. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + type: object + privileged: + description: Run container in privileged mode. Processes + in privileged containers are essentially equivalent + to root on the host. Defaults to false. Note that this + field cannot be set when spec.os.name is windows. + type: boolean + procMount: + description: procMount denotes the type of proc mount + to use for the containers. The default is DefaultProcMount + which uses the container runtime defaults for readonly + paths and masked paths. This requires the ProcMountType + feature flag to be enabled. Note that this field cannot + be set when spec.os.name is windows. + type: string + readOnlyRootFilesystem: + description: Whether this container has a read-only root + filesystem. Default is false. Note that this field cannot + be set when spec.os.name is windows. + type: boolean + runAsGroup: + description: The GID to run the entrypoint of the container + process. Uses runtime default if unset. May also be + set in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set + when spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as + a non-root user. If true, the Kubelet will validate + the image at runtime to ensure that it does not run + as UID 0 (root) and fail to start the container if it + does. If unset or false, no such validation will be + performed. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container + process. Defaults to user specified in image metadata + if unspecified. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name + is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to the + container. If unspecified, the container runtime will + allocate a random SELinux context for each container. May + also be set in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set + when spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by this container. + If seccomp options are provided at both the pod & container + level, the container options override the pod options. + Note that this field cannot be set when spec.os.name + is windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile + defined in a file on the node should be used. The + profile must be preconfigured on the node to work. + Must be a descending path, relative to the kubelet's + configured seccomp profile location. Must only be + set if type is "Localhost". + type: string + type: + description: "type indicates which kind of seccomp + profile will be applied. Valid options are: \n Localhost + - a profile defined in a file on the node should + be used. RuntimeDefault - the container runtime + default profile should be used. Unconfined - no + profile should be applied." + type: string + required: + - type + type: object + windowsOptions: + description: The Windows specific settings applied to + all containers. If unspecified, the options from the + PodSecurityContext will be used. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set + when spec.os.name is linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA + admission webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec + named by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of + the GMSA credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container + should be run as a 'Host Process' container. This + field is alpha-level and will only be honored by + components that enable the WindowsHostProcessContainers + feature flag. Setting this field without the feature + flag will result in errors when validating the Pod. + All of a Pod's containers must have the same effective + HostProcess value (it is not allowed to have a mix + of HostProcess containers and non-HostProcess containers). In + addition, if HostProcess is true then HostNetwork + must also be set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set + in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. + type: string + type: object + type: object + enabled: + type: boolean + env: + 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: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + optional: + description: Specify whether the ConfigMap or + its key must be defined + type: boolean + required: + - key + type: object + 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 + 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 + 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: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + optional: + description: Specify whether the Secret or its + key must be defined + type: boolean + required: + - key + type: object + type: object + required: + - name + type: object + type: array + image: + type: string + imagePullPolicy: + description: PullPolicy describes a policy for if/when to + pull a container image + type: string + resources: + description: ResourceRequirements describes the compute resource + requirements. + properties: + 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. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + type: object + extraContainers: + items: + description: A single application container that you want to + run within a pod. + properties: + args: + description: 'Arguments to the entrypoint. The container + image''s CMD is used if this is not provided. Variable + references $(VAR_NAME) are expanded using the container''s + environment. 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. Cannot + be updated. More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell' + items: + type: string + type: array + command: + description: 'Entrypoint array. Not executed within a shell. + The container image''s ENTRYPOINT is used if this is not + provided. Variable references $(VAR_NAME) are expanded + using the container''s environment. 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. Cannot be updated. More info: + https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell' + items: + type: string + type: array + env: + description: List of environment variables to set in the + container. Cannot be updated. + 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: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + optional: + description: Specify whether the ConfigMap + or its key must be defined + type: boolean + required: + - key + type: object + 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 + 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 + 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: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + optional: + description: Specify whether the Secret or + its key must be defined + type: boolean + required: + - key + type: object + type: object + required: + - name + type: object + type: array + envFrom: + description: List of sources to populate environment variables + in the container. The keys defined within a source must + be a C_IDENTIFIER. All invalid keys will be reported as + an event when the container is starting. 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. Cannot be updated. + items: + description: EnvFromSource represents the source of a + set of ConfigMaps + properties: + configMapRef: + description: The ConfigMap to select from + properties: + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the ConfigMap must + be defined + type: boolean + type: object + prefix: + description: An optional identifier to prepend to + each key in the ConfigMap. Must be a C_IDENTIFIER. + type: string + secretRef: + description: The Secret to select from + properties: + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the Secret must be + defined + type: boolean + type: object + type: object + type: array + image: + description: 'Container image name. More info: https://kubernetes.io/docs/concepts/containers/images + This field is optional to allow higher level config management + to default or override container images in workload controllers + like Deployments and StatefulSets.' + type: string + imagePullPolicy: + description: 'Image pull policy. One of Always, Never, IfNotPresent. + Defaults to Always if :latest tag is specified, or IfNotPresent + otherwise. Cannot be updated. More info: https://kubernetes.io/docs/concepts/containers/images#updating-images' + type: string + lifecycle: + description: Actions that the management system should take + in response to container lifecycle events. Cannot be updated. + properties: + postStart: + description: 'PostStart is called immediately after + a container is created. If the handler fails, the + container is terminated and restarted according to + its restart policy. Other management of the container + blocks until the hook completes. More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks' + properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to + execute inside the container, the working + directory for the command is root ('/') in + the container's filesystem. The command is + simply exec'd, it is not run inside a shell, + so traditional shell instructions ('|', etc) + won't work. To use a shell, you need to explicitly + call out to that shell. Exit status of 0 is + treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + type: object + httpGet: + description: HTTPGet specifies the http request + to perform. + properties: + host: + description: Host name to connect to, defaults + to the pod IP. You probably want to set "Host" + in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the request. + HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom + header to be used in HTTP probes + properties: + name: + description: The header field name + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to + the host. Defaults to HTTP. + type: string + required: + - port + type: object + tcpSocket: + description: Deprecated. TCPSocket is NOT supported + as a LifecycleHandler and kept for the backward + compatibility. There are no validation of this + field and lifecycle hooks will fail in runtime + when tcp handler is specified. + properties: + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + preStop: + description: 'PreStop is called immediately before a + container is terminated due to an API request or management + event such as liveness/startup probe failure, preemption, + resource contention, etc. The handler is not called + if the container crashes or exits. The Pod''s termination + grace period countdown begins before the PreStop hook + is executed. Regardless of the outcome of the handler, + the container will eventually terminate within the + Pod''s termination grace period (unless delayed by + finalizers). Other management of the container blocks + until the hook completes or until the termination + grace period is reached. More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks' + properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to + execute inside the container, the working + directory for the command is root ('/') in + the container's filesystem. The command is + simply exec'd, it is not run inside a shell, + so traditional shell instructions ('|', etc) + won't work. To use a shell, you need to explicitly + call out to that shell. Exit status of 0 is + treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + type: object + httpGet: + description: HTTPGet specifies the http request + to perform. + properties: + host: + description: Host name to connect to, defaults + to the pod IP. You probably want to set "Host" + in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the request. + HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom + header to be used in HTTP probes + properties: + name: + description: The header field name + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to + the host. Defaults to HTTP. + type: string + required: + - port + type: object + tcpSocket: + description: Deprecated. TCPSocket is NOT supported + as a LifecycleHandler and kept for the backward + compatibility. There are no validation of this + field and lifecycle hooks will fail in runtime + when tcp handler is specified. + properties: + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + type: object + livenessProbe: + description: 'Periodic probe of container liveness. Container + will be restarted if the probe fails. Cannot be updated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to execute + inside the container, the working directory for + the command is root ('/') in the container's + filesystem. The command is simply exec'd, it is + not run inside a shell, so traditional shell instructions + ('|', etc) won't work. To use a shell, you need + to explicitly call out to that shell. Exit status + of 0 is treated as live/healthy and non-zero is + unhealthy. + items: + type: string + type: array + type: object + failureThreshold: + description: Minimum consecutive failures for the probe + to be considered failed after having succeeded. Defaults + to 3. Minimum value is 1. + format: int32 + type: integer + grpc: + description: GRPC specifies an action involving a GRPC + port. This is a beta field and requires enabling GRPCContainerProbe + feature gate. + properties: + port: + description: Port number of the gRPC service. Number + must be in the range 1 to 65535. + format: int32 + type: integer + service: + description: "Service is the name of the service + to place in the gRPC HealthCheckRequest (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + \n If this is not specified, the default behavior + is defined by gRPC." + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies the http request to perform. + properties: + host: + description: Host name to connect to, defaults to + the pod IP. You probably want to set "Host" in + httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the request. + HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom header + to be used in HTTP probes + properties: + name: + description: The header field name + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to the + host. Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: 'Number of seconds after the container + has started before liveness probes are initiated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + periodSeconds: + description: How often (in seconds) to perform the probe. + Default to 10 seconds. Minimum value is 1. + format: int32 + type: integer + successThreshold: + description: Minimum consecutive successes for the probe + to be considered successful after having failed. Defaults + to 1. Must be 1 for liveness and startup. Minimum + value is 1. + format: int32 + type: integer + tcpSocket: + description: TCPSocket specifies an action involving + a TCP port. + properties: + host: + description: 'Optional: Host name to connect to, + defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: Optional duration in seconds the pod needs + to terminate gracefully upon probe failure. The grace + period is the duration in seconds after the processes + running in the pod are sent a termination signal and + the time when the processes are forcibly halted with + a kill signal. Set this value longer than the expected + cleanup time for your process. If this value is nil, + the pod's terminationGracePeriodSeconds will be used. + Otherwise, this value overrides the value provided + by the pod spec. Value must be non-negative integer. + The value zero indicates stop immediately via the + kill signal (no opportunity to shut down). This is + a beta field and requires enabling ProbeTerminationGracePeriod + feature gate. Minimum value is 1. spec.terminationGracePeriodSeconds + is used if unset. + format: int64 + type: integer + timeoutSeconds: + description: 'Number of seconds after which the probe + times out. Defaults to 1 second. Minimum value is + 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + type: object + name: + description: Name of the container specified as a DNS_LABEL. + Each container in a pod must have a unique name (DNS_LABEL). + Cannot be updated. + type: string + ports: + description: List of ports to expose from the container. + Exposing a port here gives the system additional information + about the network connections a container uses, but is + primarily informational. Not specifying a port here DOES + NOT prevent that port from being exposed. Any port which + is listening on the default "0.0.0.0" address inside a + container will be accessible from the network. Cannot + be updated. + items: + description: ContainerPort represents a network port in + a single container. + properties: + containerPort: + description: Number of port to expose on the pod's + IP address. This must be a valid port number, 0 + < x < 65536. + format: int32 + type: integer + hostIP: + description: What host IP to bind the external port + to. + type: string + hostPort: + description: Number of port to expose on the host. + If specified, this must be a valid port number, + 0 < x < 65536. If HostNetwork is specified, this + must match ContainerPort. Most containers do not + need this. + format: int32 + type: integer + name: + description: If specified, this must be an IANA_SVC_NAME + and unique within the pod. Each named port in a + pod must have a unique name. Name for the port that + can be referred to by services. + type: string + protocol: + default: TCP + description: Protocol for port. Must be UDP, TCP, + or SCTP. Defaults to "TCP". + type: string + required: + - containerPort + type: object + type: array + x-kubernetes-list-map-keys: + - containerPort + - protocol + x-kubernetes-list-type: map + readinessProbe: + description: 'Periodic probe of container service readiness. + Container will be removed from service endpoints if the + probe fails. Cannot be updated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to execute + inside the container, the working directory for + the command is root ('/') in the container's + filesystem. The command is simply exec'd, it is + not run inside a shell, so traditional shell instructions + ('|', etc) won't work. To use a shell, you need + to explicitly call out to that shell. Exit status + of 0 is treated as live/healthy and non-zero is + unhealthy. + items: + type: string + type: array + type: object + failureThreshold: + description: Minimum consecutive failures for the probe + to be considered failed after having succeeded. Defaults + to 3. Minimum value is 1. + format: int32 + type: integer + grpc: + description: GRPC specifies an action involving a GRPC + port. This is a beta field and requires enabling GRPCContainerProbe + feature gate. + properties: + port: + description: Port number of the gRPC service. Number + must be in the range 1 to 65535. + format: int32 + type: integer + service: + description: "Service is the name of the service + to place in the gRPC HealthCheckRequest (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + \n If this is not specified, the default behavior + is defined by gRPC." + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies the http request to perform. + properties: + host: + description: Host name to connect to, defaults to + the pod IP. You probably want to set "Host" in + httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the request. + HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom header + to be used in HTTP probes + properties: + name: + description: The header field name + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to the + host. Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: 'Number of seconds after the container + has started before liveness probes are initiated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + periodSeconds: + description: How often (in seconds) to perform the probe. + Default to 10 seconds. Minimum value is 1. + format: int32 + type: integer + successThreshold: + description: Minimum consecutive successes for the probe + to be considered successful after having failed. Defaults + to 1. Must be 1 for liveness and startup. Minimum + value is 1. + format: int32 + type: integer + tcpSocket: + description: TCPSocket specifies an action involving + a TCP port. + properties: + host: + description: 'Optional: Host name to connect to, + defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: Optional duration in seconds the pod needs + to terminate gracefully upon probe failure. The grace + period is the duration in seconds after the processes + running in the pod are sent a termination signal and + the time when the processes are forcibly halted with + a kill signal. Set this value longer than the expected + cleanup time for your process. If this value is nil, + the pod's terminationGracePeriodSeconds will be used. + Otherwise, this value overrides the value provided + by the pod spec. Value must be non-negative integer. + The value zero indicates stop immediately via the + kill signal (no opportunity to shut down). This is + a beta field and requires enabling ProbeTerminationGracePeriod + feature gate. Minimum value is 1. spec.terminationGracePeriodSeconds + is used if unset. + format: int64 + type: integer + timeoutSeconds: + description: 'Number of seconds after which the probe + times out. Defaults to 1 second. Minimum value is + 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + type: object + resources: + description: 'Compute Resources required by this container. + Cannot be updated. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + properties: + 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. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + securityContext: + description: 'SecurityContext defines the security options + the container should be run with. If set, the fields of + SecurityContext override the equivalent fields of PodSecurityContext. + More info: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/' + properties: + allowPrivilegeEscalation: + description: 'AllowPrivilegeEscalation controls whether + a process can gain more privileges than its parent + process. This bool directly controls if the no_new_privs + flag will be set on the container process. AllowPrivilegeEscalation + is true always when the container is: 1) run as Privileged + 2) has CAP_SYS_ADMIN Note that this field cannot be + set when spec.os.name is windows.' + type: boolean + capabilities: + description: The capabilities to add/drop when running + containers. Defaults to the default set of capabilities + granted by the container runtime. Note that this field + cannot be set when spec.os.name is windows. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + type: object + privileged: + description: Run container in privileged mode. Processes + in privileged containers are essentially equivalent + to root on the host. Defaults to false. Note that + this field cannot be set when spec.os.name is windows. + type: boolean + procMount: + description: procMount denotes the type of proc mount + to use for the containers. The default is DefaultProcMount + which uses the container runtime defaults for readonly + paths and masked paths. This requires the ProcMountType + feature flag to be enabled. Note that this field cannot + be set when spec.os.name is windows. + type: string + readOnlyRootFilesystem: + description: Whether this container has a read-only + root filesystem. Default is false. Note that this + field cannot be set when spec.os.name is windows. + type: boolean + runAsGroup: + description: The GID to run the entrypoint of the container + process. Uses runtime default if unset. May also be + set in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set + when spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as + a non-root user. If true, the Kubelet will validate + the image at runtime to ensure that it does not run + as UID 0 (root) and fail to start the container if + it does. If unset or false, no such validation will + be performed. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container + process. Defaults to user specified in image metadata + if unspecified. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name + is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to the + container. If unspecified, the container runtime will + allocate a random SELinux context for each container. May + also be set in PodSecurityContext. If set in both + SecurityContext and PodSecurityContext, the value + specified in SecurityContext takes precedence. Note + that this field cannot be set when spec.os.name is + windows. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by this container. + If seccomp options are provided at both the pod & + container level, the container options override the + pod options. Note that this field cannot be set when + spec.os.name is windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile + defined in a file on the node should be used. + The profile must be preconfigured on the node + to work. Must be a descending path, relative to + the kubelet's configured seccomp profile location. + Must only be set if type is "Localhost". + type: string + type: + description: "type indicates which kind of seccomp + profile will be applied. Valid options are: \n + Localhost - a profile defined in a file on the + node should be used. RuntimeDefault - the container + runtime default profile should be used. Unconfined + - no profile should be applied." + type: string + required: + - type + type: object + windowsOptions: + description: The Windows specific settings applied to + all containers. If unspecified, the options from the + PodSecurityContext will be used. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set + when spec.os.name is linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA + admission webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec + named by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name + of the GMSA credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container + should be run as a 'Host Process' container. This + field is alpha-level and will only be honored + by components that enable the WindowsHostProcessContainers + feature flag. Setting this field without the feature + flag will result in errors when validating the + Pod. All of a Pod's containers must have the same + effective HostProcess value (it is not allowed + to have a mix of HostProcess containers and non-HostProcess + containers). In addition, if HostProcess is true + then HostNetwork must also be set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the + entrypoint of the container process. Defaults + to the user specified in image metadata if unspecified. + May also be set in PodSecurityContext. If set + in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + type: string + type: object + type: object + startupProbe: + description: 'StartupProbe indicates that the Pod has successfully + initialized. If specified, no other probes are executed + until this completes successfully. If this probe fails, + the Pod will be restarted, just as if the livenessProbe + failed. This can be used to provide different probe parameters + at the beginning of a Pod''s lifecycle, when it might + take a long time to load data or warm a cache, than during + steady-state operation. This cannot be updated. More info: + https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to execute + inside the container, the working directory for + the command is root ('/') in the container's + filesystem. The command is simply exec'd, it is + not run inside a shell, so traditional shell instructions + ('|', etc) won't work. To use a shell, you need + to explicitly call out to that shell. Exit status + of 0 is treated as live/healthy and non-zero is + unhealthy. + items: + type: string + type: array + type: object + failureThreshold: + description: Minimum consecutive failures for the probe + to be considered failed after having succeeded. Defaults + to 3. Minimum value is 1. + format: int32 + type: integer + grpc: + description: GRPC specifies an action involving a GRPC + port. This is a beta field and requires enabling GRPCContainerProbe + feature gate. + properties: + port: + description: Port number of the gRPC service. Number + must be in the range 1 to 65535. + format: int32 + type: integer + service: + description: "Service is the name of the service + to place in the gRPC HealthCheckRequest (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + \n If this is not specified, the default behavior + is defined by gRPC." + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies the http request to perform. + properties: + host: + description: Host name to connect to, defaults to + the pod IP. You probably want to set "Host" in + httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the request. + HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom header + to be used in HTTP probes + properties: + name: + description: The header field name + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to the + host. Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: 'Number of seconds after the container + has started before liveness probes are initiated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + periodSeconds: + description: How often (in seconds) to perform the probe. + Default to 10 seconds. Minimum value is 1. + format: int32 + type: integer + successThreshold: + description: Minimum consecutive successes for the probe + to be considered successful after having failed. Defaults + to 1. Must be 1 for liveness and startup. Minimum + value is 1. + format: int32 + type: integer + tcpSocket: + description: TCPSocket specifies an action involving + a TCP port. + properties: + host: + description: 'Optional: Host name to connect to, + defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: Optional duration in seconds the pod needs + to terminate gracefully upon probe failure. The grace + period is the duration in seconds after the processes + running in the pod are sent a termination signal and + the time when the processes are forcibly halted with + a kill signal. Set this value longer than the expected + cleanup time for your process. If this value is nil, + the pod's terminationGracePeriodSeconds will be used. + Otherwise, this value overrides the value provided + by the pod spec. Value must be non-negative integer. + The value zero indicates stop immediately via the + kill signal (no opportunity to shut down). This is + a beta field and requires enabling ProbeTerminationGracePeriod + feature gate. Minimum value is 1. spec.terminationGracePeriodSeconds + is used if unset. + format: int64 + type: integer + timeoutSeconds: + description: 'Number of seconds after which the probe + times out. Defaults to 1 second. Minimum value is + 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + type: object + stdin: + description: Whether this container should allocate a buffer + for stdin in the container runtime. If this is not set, + reads from stdin in the container will always result in + EOF. Default is false. + type: boolean + stdinOnce: + description: Whether the container runtime should close + the stdin channel after it has been opened by a single + attach. When stdin is true the stdin stream will remain + open across multiple attach sessions. If stdinOnce is + set to true, stdin is opened on container start, is empty + until the first client attaches to stdin, and then remains + open and accepts data until the client disconnects, at + which time stdin is closed and remains closed until the + container is restarted. If this flag is false, a container + processes that reads from stdin will never receive an + EOF. Default is false + type: boolean + terminationMessagePath: + description: 'Optional: Path at which the file to which + the container''s termination message will be written is + mounted into the container''s filesystem. Message written + is intended to be brief final status, such as an assertion + failure message. Will be truncated by the node if greater + than 4096 bytes. The total message length across all containers + will be limited to 12kb. Defaults to /dev/termination-log. + Cannot be updated.' + type: string + terminationMessagePolicy: + description: Indicate how the termination message should + be populated. File will use the contents of terminationMessagePath + to populate the container status message on both success + and failure. FallbackToLogsOnError will use the last chunk + of container log output if the termination message file + is empty and the container exited with an error. The log + output is limited to 2048 bytes or 80 lines, whichever + is smaller. Defaults to File. Cannot be updated. + type: string + tty: + description: Whether this container should allocate a TTY + for itself, also requires 'stdin' to be true. Default + is false. + type: boolean + volumeDevices: + description: volumeDevices is the list of block devices + to be used by the container. + items: + description: volumeDevice describes a mapping of a raw + block device within a container. + properties: + devicePath: + description: devicePath is the path inside of the + container that the device will be mapped to. + type: string + name: + description: name must match the name of a persistentVolumeClaim + in the pod + type: string + required: + - devicePath + - name + type: object + type: array + volumeMounts: + description: Pod volumes to mount into the container's filesystem. + Cannot be updated. + items: + description: VolumeMount describes a mounting of a Volume + within a container. + properties: + mountPath: + description: Path within the container at which the + volume should be mounted. Must not contain ':'. + type: string + mountPropagation: + description: mountPropagation determines how mounts + are propagated from the host to container and the + other way around. When not set, MountPropagationNone + is used. This field is beta in 1.10. + type: string + name: + description: This must match the Name of a Volume. + type: string + readOnly: + description: Mounted read-only if true, read-write + otherwise (false or unspecified). Defaults to false. + type: boolean + subPath: + description: Path within the volume from which the + container's volume should be mounted. Defaults to + "" (volume's root). + type: string + subPathExpr: + description: Expanded path within the volume from + which the container's volume should be mounted. + Behaves similarly to SubPath but environment variable + references $(VAR_NAME) are expanded using the container's + environment. Defaults to "" (volume's root). SubPathExpr + and SubPath are mutually exclusive. + type: string + required: + - mountPath + - name + type: object + type: array + workingDir: + description: Container's working directory. If not specified, + the container runtime's default will be used, which might + be configured in the container image. Cannot be updated. + type: string + required: + - name + type: object + type: array + extraVolumeMounts: + items: + description: VolumeMount describes a mounting of a Volume within + a container. + properties: + mountPath: + description: Path within the container at which the volume + should be mounted. Must not contain ':'. + type: string + mountPropagation: + description: mountPropagation determines how mounts are + propagated from the host to container and the other way + around. When not set, MountPropagationNone is used. This + field is beta in 1.10. + type: string + name: + description: This must match the Name of a Volume. + type: string + readOnly: + description: Mounted read-only if true, read-write otherwise + (false or unspecified). Defaults to false. + type: boolean + subPath: + description: Path within the volume from which the container's + volume should be mounted. Defaults to "" (volume's root). + type: string + subPathExpr: + description: Expanded path within the volume from which + the container's volume should be mounted. Behaves similarly + to SubPath but environment variable references $(VAR_NAME) + are expanded using the container's environment. Defaults + to "" (volume's root). SubPathExpr and SubPath are mutually + exclusive. + type: string + required: + - mountPath + - name + type: object + type: array + extraVolumes: + items: + description: Volume represents a named volume in a pod that + may be accessed by any container in the pod. + properties: + awsElasticBlockStore: + description: 'awsElasticBlockStore represents an AWS Disk + resource that is attached to a kubelet''s host machine + and then exposed to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' + properties: + fsType: + description: 'fsType is the filesystem type of the volume + that you want to mount. Tip: Ensure that the filesystem + type is supported by the host operating system. Examples: + "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" + if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore + TODO: how do we prevent errors in the filesystem from + compromising the machine' + type: string + partition: + description: 'partition is the partition in the volume + that you want to mount. If omitted, the default is + to mount by volume name. Examples: For volume /dev/sda1, + you specify the partition as "1". Similarly, the volume + partition for /dev/sda is "0" (or you can leave the + property empty).' + format: int32 + type: integer + readOnly: + description: 'readOnly value true will force the readOnly + setting in VolumeMounts. More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' + type: boolean + volumeID: + description: 'volumeID is unique ID of the persistent + disk resource in AWS (Amazon EBS volume). More info: + https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' + type: string + required: + - volumeID + type: object + azureDisk: + description: azureDisk represents an Azure Data Disk mount + on the host and bind mount to the pod. + properties: + cachingMode: + description: 'cachingMode is the Host Caching mode: + None, Read Only, Read Write.' + type: string + diskName: + description: diskName is the Name of the data disk in + the blob storage + type: string + diskURI: + description: diskURI is the URI of data disk in the + blob storage + type: string + fsType: + description: fsType is Filesystem type to mount. Must + be a filesystem type supported by the host operating + system. Ex. "ext4", "xfs", "ntfs". Implicitly inferred + to be "ext4" if unspecified. + type: string + kind: + description: 'kind expected values are Shared: multiple + blob disks per storage account Dedicated: single + blob disk per storage account Managed: azure managed + data disk (only in managed availability set). defaults + to shared' + type: string + readOnly: + description: readOnly Defaults to false (read/write). + ReadOnly here will force the ReadOnly setting in VolumeMounts. + type: boolean + required: + - diskName + - diskURI + type: object + azureFile: + description: azureFile represents an Azure File Service + mount on the host and bind mount to the pod. + properties: + readOnly: + description: readOnly defaults to false (read/write). + ReadOnly here will force the ReadOnly setting in VolumeMounts. + type: boolean + secretName: + description: secretName is the name of secret that + contains Azure Storage Account Name and Key + type: string + shareName: + description: shareName is the azure share Name + type: string + required: + - secretName + - shareName + type: object + cephfs: + description: cephFS represents a Ceph FS mount on the host + that shares a pod's lifetime + properties: + monitors: + description: 'monitors is Required: Monitors is a collection + of Ceph monitors More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + items: + type: string + type: array + path: + description: 'path is Optional: Used as the mounted + root, rather than the full Ceph tree, default is /' + type: string + readOnly: + description: 'readOnly is Optional: Defaults to false + (read/write). ReadOnly here will force the ReadOnly + setting in VolumeMounts. More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + type: boolean + secretFile: + description: 'secretFile is Optional: SecretFile is + the path to key ring for User, default is /etc/ceph/user.secret + More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + type: string + secretRef: + description: 'secretRef is Optional: SecretRef is reference + to the authentication secret for User, default is + empty. More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + type: object + user: + description: 'user is optional: User is the rados user + name, default is admin More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + type: string + required: + - monitors + type: object + cinder: + description: 'cinder represents a cinder volume attached + and mounted on kubelets host machine. More info: https://examples.k8s.io/mysql-cinder-pd/README.md' + properties: + fsType: + description: 'fsType is the filesystem type to mount. + Must be a filesystem type supported by the host operating + system. Examples: "ext4", "xfs", "ntfs". Implicitly + inferred to be "ext4" if unspecified. More info: https://examples.k8s.io/mysql-cinder-pd/README.md' + type: string + readOnly: + description: 'readOnly defaults to false (read/write). + ReadOnly here will force the ReadOnly setting in VolumeMounts. + More info: https://examples.k8s.io/mysql-cinder-pd/README.md' + type: boolean + secretRef: + description: 'secretRef is optional: points to a secret + object containing parameters used to connect to OpenStack.' + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + type: object + volumeID: + description: 'volumeID used to identify the volume in + cinder. More info: https://examples.k8s.io/mysql-cinder-pd/README.md' + type: string + required: + - volumeID + type: object + configMap: + description: configMap represents a configMap that should + populate this volume + properties: + defaultMode: + description: 'defaultMode is optional: mode bits used + to set permissions on created files by default. Must + be an octal value between 0000 and 0777 or a decimal + value between 0 and 511. YAML accepts both octal and + decimal values, JSON requires decimal values for mode + bits. Defaults to 0644. Directories within the path + are not affected by this setting. This might be in + conflict with other options that affect the file mode, + like fsGroup, and the result can be other mode bits + set.' + format: int32 + type: integer + items: + description: items if unspecified, each key-value pair + in the Data field of the referenced ConfigMap will + be projected into the volume as a file whose name + is the key and content is the value. If specified, + the listed keys will be projected into the specified + paths, and unlisted keys will not be present. If a + key is specified which is not present in the ConfigMap, + the volume setup will error unless it is marked optional. + Paths must be relative and may not contain the '..' + path or start with '..'. + items: + description: Maps a string key to a path within a + volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: mode bits used + to set permissions on this file. Must be an + octal value between 0000 and 0777 or a decimal + value between 0 and 511. YAML accepts both octal + and decimal values, JSON requires decimal values + for mode bits. If not specified, the volume + defaultMode will be used. This might be in conflict + with other options that affect the file mode, + like fsGroup, and the result can be other mode + bits set.' + format: int32 + type: integer + path: + description: path is the relative path of the + file to map the key to. May not be an absolute + path. May not contain the path element '..'. + May not start with the string '..'. + type: string + required: + - key + - path + type: object + type: array + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + optional: + description: optional specify whether the ConfigMap + or its keys must be defined + type: boolean + type: object + csi: + description: csi (Container Storage Interface) represents + ephemeral storage that is handled by certain external + CSI drivers (Beta feature). + properties: + driver: + description: driver is the name of the CSI driver that + handles this volume. Consult with your admin for the + correct name as registered in the cluster. + type: string + fsType: + description: fsType to mount. Ex. "ext4", "xfs", "ntfs". + If not provided, the empty value is passed to the + associated CSI driver which will determine the default + filesystem to apply. + type: string + nodePublishSecretRef: + description: nodePublishSecretRef is a reference to + the secret object containing sensitive information + to pass to the CSI driver to complete the CSI NodePublishVolume + and NodeUnpublishVolume calls. This field is optional, + and may be empty if no secret is required. If the + secret object contains more than one secret, all secret + references are passed. + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + type: object + readOnly: + description: readOnly specifies a read-only configuration + for the volume. Defaults to false (read/write). + type: boolean + volumeAttributes: + additionalProperties: + type: string + description: volumeAttributes stores driver-specific + properties that are passed to the CSI driver. Consult + your driver's documentation for supported values. + type: object + required: + - driver + type: object + downwardAPI: + description: downwardAPI represents downward API about the + pod that should populate this volume + properties: + defaultMode: + description: 'Optional: mode bits to use on created + files by default. Must be a Optional: mode bits used + to set permissions on created files by default. Must + be an octal value between 0000 and 0777 or a decimal + value between 0 and 511. YAML accepts both octal and + decimal values, JSON requires decimal values for mode + bits. Defaults to 0644. Directories within the path + are not affected by this setting. This might be in + conflict with other options that affect the file mode, + like fsGroup, and the result can be other mode bits + set.' + format: int32 + type: integer + items: + description: Items is a list of downward API volume + file + items: + description: DownwardAPIVolumeFile represents information + to create the file containing the pod field + properties: + fieldRef: + description: 'Required: Selects a field of the + pod: only annotations, labels, name and namespace + are supported.' + 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 + mode: + description: 'Optional: mode bits used to set + permissions on this file, must be an octal value + between 0000 and 0777 or a decimal value between + 0 and 511. YAML accepts both octal and decimal + values, JSON requires decimal values for mode + bits. If not specified, the volume defaultMode + will be used. This might be in conflict with + other options that affect the file mode, like + fsGroup, and the result can be other mode bits + set.' + format: int32 + type: integer + path: + description: 'Required: Path is the relative + path name of the file to be created. Must not + be absolute or contain the ''..'' path. Must + be utf-8 encoded. The first item of the relative + path must not start with ''..''' + type: string + resourceFieldRef: + description: 'Selects a resource of the container: + only resources limits and requests (limits.cpu, + limits.memory, requests.cpu and requests.memory) + 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 + required: + - path + type: object + type: array + type: object + emptyDir: + description: 'emptyDir represents a temporary directory + that shares a pod''s lifetime. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' + properties: + medium: + description: 'medium represents what type of storage + medium should back this directory. The default is + "" which means to use the node''s default medium. + Must be an empty string (default) or Memory. More + info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' + type: string + sizeLimit: + anyOf: + - type: integer + - type: string + description: 'sizeLimit is the total amount of local + storage required for this EmptyDir volume. The size + limit is also applicable for memory medium. The maximum + usage on memory medium EmptyDir would be the minimum + value between the SizeLimit specified here and the + sum of memory limits of all containers in a pod. The + default is nil which means that the limit is undefined. + More info: http://kubernetes.io/docs/user-guide/volumes#emptydir' + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + ephemeral: + description: "ephemeral represents a volume that is handled + by a cluster storage driver. The volume's lifecycle is + tied to the pod that defines it - it will be created before + the pod starts, and deleted when the pod is removed. \n + Use this if: a) the volume is only needed while the pod + runs, b) features of normal volumes like restoring from + snapshot or capacity tracking are needed, c) the storage + driver is specified through a storage class, and d) the + storage driver supports dynamic volume provisioning through + \ a PersistentVolumeClaim (see EphemeralVolumeSource + for more information on the connection between this + volume type and PersistentVolumeClaim). \n Use PersistentVolumeClaim + or one of the vendor-specific APIs for volumes that persist + for longer than the lifecycle of an individual pod. \n + Use CSI for light-weight local ephemeral volumes if the + CSI driver is meant to be used that way - see the documentation + of the driver for more information. \n A pod can use both + types of ephemeral volumes and persistent volumes at the + same time." + properties: + volumeClaimTemplate: + description: "Will be used to create a stand-alone PVC + to provision the volume. The pod in which this EphemeralVolumeSource + is embedded will be the owner of the PVC, i.e. the + PVC will be deleted together with the pod. The name + of the PVC will be `-` where + `` is the name from the `PodSpec.Volumes` + array entry. Pod validation will reject the pod if + the concatenated name is not valid for a PVC (for + example, too long). \n An existing PVC with that name + that is not owned by the pod will *not* be used for + the pod to avoid using an unrelated volume by mistake. + Starting the pod is then blocked until the unrelated + PVC is removed. If such a pre-created PVC is meant + to be used by the pod, the PVC has to updated with + an owner reference to the pod once the pod exists. + Normally this should not be necessary, but it may + be useful when manually reconstructing a broken cluster. + \n This field is read-only and no changes will be + made by Kubernetes to the PVC after it has been created. + \n Required, must not be nil." + properties: + metadata: + description: May contain labels and annotations + that will be copied into the PVC when creating + it. No other fields are allowed and will be rejected + during validation. + type: object + spec: + description: The specification for the PersistentVolumeClaim. + The entire content is copied unchanged into the + PVC that gets created from this template. The + same fields as in a PersistentVolumeClaim are + also valid here. + properties: + accessModes: + description: 'accessModes contains the desired + access modes the volume should have. More + info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' + items: + type: string + type: array + dataSource: + description: 'dataSource field can be used to + specify either: * An existing VolumeSnapshot + object (snapshot.storage.k8s.io/VolumeSnapshot) + * An existing PVC (PersistentVolumeClaim) + If the provisioner or an external controller + can support the specified data source, it + will create a new volume based on the contents + of the specified data source. If the AnyVolumeDataSource + feature gate is enabled, this field will always + have the same contents as the DataSourceRef + field.' + properties: + apiGroup: + description: APIGroup is the group for the + resource being referenced. If APIGroup + is not specified, the specified Kind must + be in the core API group. For any other + third-party types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource + being referenced + type: string + name: + description: Name is the name of resource + being referenced + type: string + required: + - kind + - name + type: object + dataSourceRef: + description: 'dataSourceRef specifies the object + from which to populate the volume with data, + if a non-empty volume is desired. This may + be any local object from a non-empty API group + (non core object) or a PersistentVolumeClaim + object. When this field is specified, volume + binding will only succeed if the type of the + specified object matches some installed volume + populator or dynamic provisioner. This field + will replace the functionality of the DataSource + field and as such if both fields are non-empty, + they must have the same value. For backwards + compatibility, both fields (DataSource and + DataSourceRef) will be set to the same value + automatically if one of them is empty and + the other is non-empty. There are two important + differences between DataSource and DataSourceRef: + * While DataSource only allows two specific + types of objects, DataSourceRef allows any + non-core object, as well as PersistentVolumeClaim + objects. * While DataSource ignores disallowed + values (dropping them), DataSourceRef preserves + all values, and generates an error if a disallowed + value is specified. (Beta) Using this field + requires the AnyVolumeDataSource feature gate + to be enabled.' + properties: + apiGroup: + description: APIGroup is the group for the + resource being referenced. If APIGroup + is not specified, the specified Kind must + be in the core API group. For any other + third-party types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource + being referenced + type: string + name: + description: Name is the name of resource + being referenced + type: string + required: + - kind + - name + type: object + resources: + description: 'resources represents the minimum + resources the volume should have. If RecoverVolumeExpansionFailure + feature is enabled users are allowed to specify + resource requirements that are lower than + previous value but must still be higher than + capacity recorded in the status field of the + claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' + properties: + 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. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + selector: + description: selector is a label query over + volumes to consider for binding. + 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 + required: + - key + - operator + type: object + type: array + 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 + storageClassName: + description: 'storageClassName is the name of + the StorageClass required by the claim. More + info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' + type: string + volumeMode: + description: volumeMode defines what type of + volume is required by the claim. Value of + Filesystem is implied when not included in + claim spec. + type: string + volumeName: + description: volumeName is the binding reference + to the PersistentVolume backing this claim. + type: string + type: object + required: + - spec + type: object + type: object + fc: + description: fc represents a Fibre Channel resource that + is attached to a kubelet's host machine and then exposed + to the pod. + properties: + fsType: + description: 'fsType is the filesystem type to mount. + Must be a filesystem type supported by the host operating + system. Ex. "ext4", "xfs", "ntfs". Implicitly inferred + to be "ext4" if unspecified. TODO: how do we prevent + errors in the filesystem from compromising the machine' + type: string + lun: + description: 'lun is Optional: FC target lun number' + format: int32 + type: integer + readOnly: + description: 'readOnly is Optional: Defaults to false + (read/write). ReadOnly here will force the ReadOnly + setting in VolumeMounts.' + type: boolean + targetWWNs: + description: 'targetWWNs is Optional: FC target worldwide + names (WWNs)' + items: + type: string + type: array + wwids: + description: 'wwids Optional: FC volume world wide identifiers + (wwids) Either wwids or combination of targetWWNs + and lun must be set, but not both simultaneously.' + items: + type: string + type: array + type: object + flexVolume: + description: flexVolume represents a generic volume resource + that is provisioned/attached using an exec based plugin. + properties: + driver: + description: driver is the name of the driver to use + for this volume. + type: string + fsType: + description: fsType is the filesystem type to mount. + Must be a filesystem type supported by the host operating + system. Ex. "ext4", "xfs", "ntfs". The default filesystem + depends on FlexVolume script. + type: string + options: + additionalProperties: + type: string + description: 'options is Optional: this field holds + extra command options if any.' + type: object + readOnly: + description: 'readOnly is Optional: defaults to false + (read/write). ReadOnly here will force the ReadOnly + setting in VolumeMounts.' + type: boolean + secretRef: + description: 'secretRef is Optional: secretRef is reference + to the secret object containing sensitive information + to pass to the plugin scripts. This may be empty if + no secret object is specified. If the secret object + contains more than one secret, all secrets are passed + to the plugin scripts.' + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + type: object + required: + - driver + type: object + flocker: + description: flocker represents a Flocker volume attached + to a kubelet's host machine. This depends on the Flocker + control service being running + properties: + datasetName: + description: datasetName is Name of the dataset stored + as metadata -> name on the dataset for Flocker should + be considered as deprecated + type: string + datasetUUID: + description: datasetUUID is the UUID of the dataset. + This is unique identifier of a Flocker dataset + type: string + type: object + gcePersistentDisk: + description: 'gcePersistentDisk represents a GCE Disk resource + that is attached to a kubelet''s host machine and then + exposed to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' + properties: + fsType: + description: 'fsType is filesystem type of the volume + that you want to mount. Tip: Ensure that the filesystem + type is supported by the host operating system. Examples: + "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" + if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk + TODO: how do we prevent errors in the filesystem from + compromising the machine' + type: string + partition: + description: 'partition is the partition in the volume + that you want to mount. If omitted, the default is + to mount by volume name. Examples: For volume /dev/sda1, + you specify the partition as "1". Similarly, the volume + partition for /dev/sda is "0" (or you can leave the + property empty). More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' + format: int32 + type: integer + pdName: + description: 'pdName is unique name of the PD resource + in GCE. Used to identify the disk in GCE. More info: + https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' + type: string + readOnly: + description: 'readOnly here will force the ReadOnly + setting in VolumeMounts. Defaults to false. More info: + https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' + type: boolean + required: + - pdName + type: object + gitRepo: + description: 'gitRepo represents a git repository at a particular + revision. DEPRECATED: GitRepo is deprecated. To provision + a container with a git repo, mount an EmptyDir into an + InitContainer that clones the repo using git, then mount + the EmptyDir into the Pod''s container.' + properties: + directory: + description: directory is the target directory name. + Must not contain or start with '..'. If '.' is supplied, + the volume directory will be the git repository. Otherwise, + if specified, the volume will contain the git repository + in the subdirectory with the given name. + type: string + repository: + description: repository is the URL + type: string + revision: + description: revision is the commit hash for the specified + revision. + type: string + required: + - repository + type: object + glusterfs: + description: 'glusterfs represents a Glusterfs mount on + the host that shares a pod''s lifetime. More info: https://examples.k8s.io/volumes/glusterfs/README.md' + properties: + endpoints: + description: 'endpoints is the endpoint name that details + Glusterfs topology. More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' + type: string + path: + description: 'path is the Glusterfs volume path. More + info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' + type: string + readOnly: + description: 'readOnly here will force the Glusterfs + volume to be mounted with read-only permissions. Defaults + to false. More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' + type: boolean + required: + - endpoints + - path + type: object + hostPath: + description: 'hostPath represents a pre-existing file or + directory on the host machine that is directly exposed + to the container. This is generally used for system agents + or other privileged things that are allowed to see the + host machine. Most containers will NOT need this. More + info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath + --- TODO(jonesdl) We need to restrict who can use host + directory mounts and who can/can not mount host directories + as read/write.' + properties: + path: + description: 'path of the directory on the host. If + the path is a symlink, it will follow the link to + the real path. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath' + type: string + type: + description: 'type for HostPath Volume Defaults to "" + More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath' + type: string + required: + - path + type: object + iscsi: + description: 'iscsi represents an ISCSI Disk resource that + is attached to a kubelet''s host machine and then exposed + to the pod. More info: https://examples.k8s.io/volumes/iscsi/README.md' + properties: + chapAuthDiscovery: + description: chapAuthDiscovery defines whether support + iSCSI Discovery CHAP authentication + type: boolean + chapAuthSession: + description: chapAuthSession defines whether support + iSCSI Session CHAP authentication + type: boolean + fsType: + description: 'fsType is the filesystem type of the volume + that you want to mount. Tip: Ensure that the filesystem + type is supported by the host operating system. Examples: + "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" + if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#iscsi + TODO: how do we prevent errors in the filesystem from + compromising the machine' + type: string + initiatorName: + description: initiatorName is the custom iSCSI Initiator + Name. If initiatorName is specified with iscsiInterface + simultaneously, new iSCSI interface : will be created for the connection. + type: string + iqn: + description: iqn is the target iSCSI Qualified Name. + type: string + iscsiInterface: + description: iscsiInterface is the interface Name that + uses an iSCSI transport. Defaults to 'default' (tcp). + type: string + lun: + description: lun represents iSCSI Target Lun number. + format: int32 + type: integer + portals: + description: portals is the iSCSI Target Portal List. + The portal is either an IP or ip_addr:port if the + port is other than default (typically TCP ports 860 + and 3260). + items: + type: string + type: array + readOnly: + description: readOnly here will force the ReadOnly setting + in VolumeMounts. Defaults to false. + type: boolean + secretRef: + description: secretRef is the CHAP Secret for iSCSI + target and initiator authentication + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + type: object + targetPortal: + description: targetPortal is iSCSI Target Portal. The + Portal is either an IP or ip_addr:port if the port + is other than default (typically TCP ports 860 and + 3260). + type: string + required: + - iqn + - lun + - targetPortal + type: object + name: + description: 'name of the volume. Must be a DNS_LABEL and + unique within the pod. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + nfs: + description: 'nfs represents an NFS mount on the host that + shares a pod''s lifetime More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' + properties: + path: + description: 'path that is exported by the NFS server. + More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' + type: string + readOnly: + description: 'readOnly here will force the NFS export + to be mounted with read-only permissions. Defaults + to false. More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' + type: boolean + server: + description: 'server is the hostname or IP address of + the NFS server. More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' + type: string + required: + - path + - server + type: object + persistentVolumeClaim: + description: 'persistentVolumeClaimVolumeSource represents + a reference to a PersistentVolumeClaim in the same namespace. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' + properties: + claimName: + description: 'claimName is the name of a PersistentVolumeClaim + in the same namespace as the pod using this volume. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' + type: string + readOnly: + description: readOnly Will force the ReadOnly setting + in VolumeMounts. Default false. + type: boolean + required: + - claimName + type: object + photonPersistentDisk: + description: photonPersistentDisk represents a PhotonController + persistent disk attached and mounted on kubelets host + machine + properties: + fsType: + description: fsType is the filesystem type to mount. + Must be a filesystem type supported by the host operating + system. Ex. "ext4", "xfs", "ntfs". Implicitly inferred + to be "ext4" if unspecified. + type: string + pdID: + description: pdID is the ID that identifies Photon Controller + persistent disk + type: string + required: + - pdID + type: object + portworxVolume: + description: portworxVolume represents a portworx volume + attached and mounted on kubelets host machine + properties: + fsType: + description: fSType represents the filesystem type to + mount Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs". Implicitly inferred + to be "ext4" if unspecified. + type: string + readOnly: + description: readOnly defaults to false (read/write). + ReadOnly here will force the ReadOnly setting in VolumeMounts. + type: boolean + volumeID: + description: volumeID uniquely identifies a Portworx + volume + type: string + required: + - volumeID + type: object + projected: + description: projected items for all in one resources secrets, + configmaps, and downward API + properties: + defaultMode: + description: defaultMode are the mode bits used to set + permissions on created files by default. Must be an + octal value between 0000 and 0777 or a decimal value + between 0 and 511. YAML accepts both octal and decimal + values, JSON requires decimal values for mode bits. + Directories within the path are not affected by this + setting. This might be in conflict with other options + that affect the file mode, like fsGroup, and the result + can be other mode bits set. + format: int32 + type: integer + sources: + description: sources is the list of volume projections + items: + description: Projection that may be projected along + with other supported volume types + properties: + configMap: + description: configMap information about the configMap + data to project + properties: + items: + description: items if unspecified, each key-value + pair in the Data field of the referenced + ConfigMap will be projected into the volume + as a file whose name is the key and content + is the value. If specified, the listed keys + will be projected into the specified paths, + and unlisted keys will not be present. If + a key is specified which is not present + in the ConfigMap, the volume setup will + error unless it is marked optional. Paths + must be relative and may not contain the + '..' path or start with '..'. + items: + description: Maps a string key to a path + within a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: mode + bits used to set permissions on this + file. Must be an octal value between + 0000 and 0777 or a decimal value between + 0 and 511. YAML accepts both octal + and decimal values, JSON requires + decimal values for mode bits. If not + specified, the volume defaultMode + will be used. This might be in conflict + with other options that affect the + file mode, like fsGroup, and the result + can be other mode bits set.' + format: int32 + type: integer + path: + description: path is the relative path + of the file to map the key to. May + not be an absolute path. May not contain + the path element '..'. May not start + with the string '..'. + type: string + required: + - key + - path + type: object + type: array + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + optional: + description: optional specify whether the + ConfigMap or its keys must be defined + type: boolean + type: object + downwardAPI: + description: downwardAPI information about the + downwardAPI data to project + properties: + items: + description: Items is a list of DownwardAPIVolume + file + items: + description: DownwardAPIVolumeFile represents + information to create the file containing + the pod field + properties: + fieldRef: + description: 'Required: Selects a field + of the pod: only annotations, labels, + name and namespace are supported.' + 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 + mode: + description: 'Optional: mode bits used + to set permissions on this file, must + be an octal value between 0000 and + 0777 or a decimal value between 0 + and 511. YAML accepts both octal and + decimal values, JSON requires decimal + values for mode bits. If not specified, + the volume defaultMode will be used. + This might be in conflict with other + options that affect the file mode, + like fsGroup, and the result can be + other mode bits set.' + format: int32 + type: integer + path: + description: 'Required: Path is the + relative path name of the file to + be created. Must not be absolute or + contain the ''..'' path. Must be utf-8 + encoded. The first item of the relative + path must not start with ''..''' + type: string + resourceFieldRef: + description: 'Selects a resource of + the container: only resources limits + and requests (limits.cpu, limits.memory, + requests.cpu and requests.memory) + 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 + required: + - path + type: object + type: array + type: object + secret: + description: secret information about the secret + data to project + properties: + items: + description: items if unspecified, each key-value + pair in the Data field of the referenced + Secret will be projected into the volume + as a file whose name is the key and content + is the value. If specified, the listed keys + will be projected into the specified paths, + and unlisted keys will not be present. If + a key is specified which is not present + in the Secret, the volume setup will error + unless it is marked optional. Paths must + be relative and may not contain the '..' + path or start with '..'. + items: + description: Maps a string key to a path + within a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: mode + bits used to set permissions on this + file. Must be an octal value between + 0000 and 0777 or a decimal value between + 0 and 511. YAML accepts both octal + and decimal values, JSON requires + decimal values for mode bits. If not + specified, the volume defaultMode + will be used. This might be in conflict + with other options that affect the + file mode, like fsGroup, and the result + can be other mode bits set.' + format: int32 + type: integer + path: + description: path is the relative path + of the file to map the key to. May + not be an absolute path. May not contain + the path element '..'. May not start + with the string '..'. + type: string + required: + - key + - path + type: object + type: array + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + optional: + description: optional field specify whether + the Secret or its key must be defined + type: boolean + type: object + serviceAccountToken: + description: serviceAccountToken is information + about the serviceAccountToken data to project + properties: + audience: + description: audience is the intended audience + of the token. A recipient of a token must + identify itself with an identifier specified + in the audience of the token, and otherwise + should reject the token. The audience defaults + to the identifier of the apiserver. + type: string + expirationSeconds: + description: expirationSeconds is the requested + duration of validity of the service account + token. As the token approaches expiration, + the kubelet volume plugin will proactively + rotate the service account token. The kubelet + will start trying to rotate the token if + the token is older than 80 percent of its + time to live or if the token is older than + 24 hours.Defaults to 1 hour and must be + at least 10 minutes. + format: int64 + type: integer + path: + description: path is the path relative to + the mount point of the file to project the + token into. + type: string + required: + - path + type: object + type: object + type: array + type: object + quobyte: + description: quobyte represents a Quobyte mount on the host + that shares a pod's lifetime + properties: + group: + description: group to map volume access to Default is + no group + type: string + readOnly: + description: readOnly here will force the Quobyte volume + to be mounted with read-only permissions. Defaults + to false. + type: boolean + registry: + description: registry represents a single or multiple + Quobyte Registry services specified as a string as + host:port pair (multiple entries are separated with + commas) which acts as the central registry for volumes + type: string + tenant: + description: tenant owning the given Quobyte volume + in the Backend Used with dynamically provisioned Quobyte + volumes, value is set by the plugin + type: string + user: + description: user to map volume access to Defaults to + serivceaccount user + type: string + volume: + description: volume is a string that references an already + created Quobyte volume by name. + type: string + required: + - registry + - volume + type: object + rbd: + description: 'rbd represents a Rados Block Device mount + on the host that shares a pod''s lifetime. More info: + https://examples.k8s.io/volumes/rbd/README.md' + properties: + fsType: + description: 'fsType is the filesystem type of the volume + that you want to mount. Tip: Ensure that the filesystem + type is supported by the host operating system. Examples: + "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" + if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#rbd + TODO: how do we prevent errors in the filesystem from + compromising the machine' + type: string + image: + description: 'image is the rados image name. More info: + https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: string + keyring: + description: 'keyring is the path to key ring for RBDUser. + Default is /etc/ceph/keyring. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: string + monitors: + description: 'monitors is a collection of Ceph monitors. + More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + items: + type: string + type: array + pool: + description: 'pool is the rados pool name. Default is + rbd. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: string + readOnly: + description: 'readOnly here will force the ReadOnly + setting in VolumeMounts. Defaults to false. More info: + https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: boolean + secretRef: + description: 'secretRef is name of the authentication + secret for RBDUser. If provided overrides keyring. + Default is nil. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + type: object + user: + description: 'user is the rados user name. Default is + admin. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: string + required: + - image + - monitors + type: object + scaleIO: + description: scaleIO represents a ScaleIO persistent volume + attached and mounted on Kubernetes nodes. + properties: + fsType: + description: fsType is the filesystem type to mount. + Must be a filesystem type supported by the host operating + system. Ex. "ext4", "xfs", "ntfs". Default is "xfs". + type: string + gateway: + description: gateway is the host address of the ScaleIO + API Gateway. + type: string + protectionDomain: + description: protectionDomain is the name of the ScaleIO + Protection Domain for the configured storage. + type: string + readOnly: + description: readOnly Defaults to false (read/write). + ReadOnly here will force the ReadOnly setting in VolumeMounts. + type: boolean + secretRef: + description: secretRef references to the secret for + ScaleIO user and other sensitive information. If this + is not provided, Login operation will fail. + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + type: object + sslEnabled: + description: sslEnabled Flag enable/disable SSL communication + with Gateway, default false + type: boolean + storageMode: + description: storageMode indicates whether the storage + for a volume should be ThickProvisioned or ThinProvisioned. + Default is ThinProvisioned. + type: string + storagePool: + description: storagePool is the ScaleIO Storage Pool + associated with the protection domain. + type: string + system: + description: system is the name of the storage system + as configured in ScaleIO. + type: string + volumeName: + description: volumeName is the name of a volume already + created in the ScaleIO system that is associated with + this volume source. + type: string + required: + - gateway + - secretRef + - system + type: object + secret: + description: 'secret represents a secret that should populate + this volume. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' + properties: + defaultMode: + description: 'defaultMode is Optional: mode bits used + to set permissions on created files by default. Must + be an octal value between 0000 and 0777 or a decimal + value between 0 and 511. YAML accepts both octal and + decimal values, JSON requires decimal values for mode + bits. Defaults to 0644. Directories within the path + are not affected by this setting. This might be in + conflict with other options that affect the file mode, + like fsGroup, and the result can be other mode bits + set.' + format: int32 + type: integer + items: + description: items If unspecified, each key-value pair + in the Data field of the referenced Secret will be + projected into the volume as a file whose name is + the key and content is the value. If specified, the + listed keys will be projected into the specified paths, + and unlisted keys will not be present. If a key is + specified which is not present in the Secret, the + volume setup will error unless it is marked optional. + Paths must be relative and may not contain the '..' + path or start with '..'. + items: + description: Maps a string key to a path within a + volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: mode bits used + to set permissions on this file. Must be an + octal value between 0000 and 0777 or a decimal + value between 0 and 511. YAML accepts both octal + and decimal values, JSON requires decimal values + for mode bits. If not specified, the volume + defaultMode will be used. This might be in conflict + with other options that affect the file mode, + like fsGroup, and the result can be other mode + bits set.' + format: int32 + type: integer + path: + description: path is the relative path of the + file to map the key to. May not be an absolute + path. May not contain the path element '..'. + May not start with the string '..'. + type: string + required: + - key + - path + type: object + type: array + optional: + description: optional field specify whether the Secret + or its keys must be defined + type: boolean + secretName: + description: 'secretName is the name of the secret in + the pod''s namespace to use. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' + type: string + type: object + storageos: + description: storageOS represents a StorageOS volume attached + and mounted on Kubernetes nodes. + properties: + fsType: + description: fsType is the filesystem type to mount. + Must be a filesystem type supported by the host operating + system. Ex. "ext4", "xfs", "ntfs". Implicitly inferred + to be "ext4" if unspecified. + type: string + readOnly: + description: readOnly defaults to false (read/write). + ReadOnly here will force the ReadOnly setting in VolumeMounts. + type: boolean + secretRef: + description: secretRef specifies the secret to use for + obtaining the StorageOS API credentials. If not specified, + default values will be attempted. + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + type: object + volumeName: + description: volumeName is the human-readable name of + the StorageOS volume. Volume names are only unique + within a namespace. + type: string + volumeNamespace: + description: volumeNamespace specifies the scope of + the volume within StorageOS. If no namespace is specified + then the Pod's namespace will be used. This allows + the Kubernetes name scoping to be mirrored within + StorageOS for tighter integration. Set VolumeName + to any name to override the default behaviour. Set + to "default" if you are not using namespaces within + StorageOS. Namespaces that do not pre-exist within + StorageOS will be created. + type: string + type: object + vsphereVolume: + description: vsphereVolume represents a vSphere volume attached + and mounted on kubelets host machine + properties: + fsType: + description: fsType is filesystem type to mount. Must + be a filesystem type supported by the host operating + system. Ex. "ext4", "xfs", "ntfs". Implicitly inferred + to be "ext4" if unspecified. + type: string + storagePolicyID: + description: storagePolicyID is the storage Policy Based + Management (SPBM) profile ID associated with the StoragePolicyName. + type: string + storagePolicyName: + description: storagePolicyName is the storage Policy + Based Management (SPBM) profile name. + type: string + volumePath: + description: volumePath is the path that identifies + vSphere volume vmdk + type: string + required: + - volumePath + type: object + required: + - name + type: object + type: array + hostNetwork: + type: boolean + image: + type: string + imagePullPolicy: + description: PullPolicy describes a policy for if/when to pull + a container image + type: string + imagePullSecrets: + items: + description: LocalObjectReference contains enough information + to let you locate the referenced object inside the same namespace. + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + type: array + initContainers: + items: + description: A single application container that you want to + run within a pod. + properties: + args: + description: 'Arguments to the entrypoint. The container + image''s CMD is used if this is not provided. Variable + references $(VAR_NAME) are expanded using the container''s + environment. 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. Cannot + be updated. More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell' + items: + type: string + type: array + command: + description: 'Entrypoint array. Not executed within a shell. + The container image''s ENTRYPOINT is used if this is not + provided. Variable references $(VAR_NAME) are expanded + using the container''s environment. 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. Cannot be updated. More info: + https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell' + items: + type: string + type: array + env: + description: List of environment variables to set in the + container. Cannot be updated. + 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: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + optional: + description: Specify whether the ConfigMap + or its key must be defined + type: boolean + required: + - key + type: object + 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 + 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 + 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: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + optional: + description: Specify whether the Secret or + its key must be defined + type: boolean + required: + - key + type: object + type: object + required: + - name + type: object + type: array + envFrom: + description: List of sources to populate environment variables + in the container. The keys defined within a source must + be a C_IDENTIFIER. All invalid keys will be reported as + an event when the container is starting. 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. Cannot be updated. + items: + description: EnvFromSource represents the source of a + set of ConfigMaps + properties: + configMapRef: + description: The ConfigMap to select from + properties: + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the ConfigMap must + be defined + type: boolean + type: object + prefix: + description: An optional identifier to prepend to + each key in the ConfigMap. Must be a C_IDENTIFIER. + type: string + secretRef: + description: The Secret to select from + properties: + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the Secret must be + defined + type: boolean + type: object + type: object + type: array + image: + description: 'Container image name. More info: https://kubernetes.io/docs/concepts/containers/images + This field is optional to allow higher level config management + to default or override container images in workload controllers + like Deployments and StatefulSets.' + type: string + imagePullPolicy: + description: 'Image pull policy. One of Always, Never, IfNotPresent. + Defaults to Always if :latest tag is specified, or IfNotPresent + otherwise. Cannot be updated. More info: https://kubernetes.io/docs/concepts/containers/images#updating-images' + type: string + lifecycle: + description: Actions that the management system should take + in response to container lifecycle events. Cannot be updated. + properties: + postStart: + description: 'PostStart is called immediately after + a container is created. If the handler fails, the + container is terminated and restarted according to + its restart policy. Other management of the container + blocks until the hook completes. More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks' + properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to + execute inside the container, the working + directory for the command is root ('/') in + the container's filesystem. The command is + simply exec'd, it is not run inside a shell, + so traditional shell instructions ('|', etc) + won't work. To use a shell, you need to explicitly + call out to that shell. Exit status of 0 is + treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + type: object + httpGet: + description: HTTPGet specifies the http request + to perform. + properties: + host: + description: Host name to connect to, defaults + to the pod IP. You probably want to set "Host" + in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the request. + HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom + header to be used in HTTP probes + properties: + name: + description: The header field name + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to + the host. Defaults to HTTP. + type: string + required: + - port + type: object + tcpSocket: + description: Deprecated. TCPSocket is NOT supported + as a LifecycleHandler and kept for the backward + compatibility. There are no validation of this + field and lifecycle hooks will fail in runtime + when tcp handler is specified. + properties: + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + preStop: + description: 'PreStop is called immediately before a + container is terminated due to an API request or management + event such as liveness/startup probe failure, preemption, + resource contention, etc. The handler is not called + if the container crashes or exits. The Pod''s termination + grace period countdown begins before the PreStop hook + is executed. Regardless of the outcome of the handler, + the container will eventually terminate within the + Pod''s termination grace period (unless delayed by + finalizers). Other management of the container blocks + until the hook completes or until the termination + grace period is reached. More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks' + properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to + execute inside the container, the working + directory for the command is root ('/') in + the container's filesystem. The command is + simply exec'd, it is not run inside a shell, + so traditional shell instructions ('|', etc) + won't work. To use a shell, you need to explicitly + call out to that shell. Exit status of 0 is + treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + type: object + httpGet: + description: HTTPGet specifies the http request + to perform. + properties: + host: + description: Host name to connect to, defaults + to the pod IP. You probably want to set "Host" + in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the request. + HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom + header to be used in HTTP probes + properties: + name: + description: The header field name + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to + the host. Defaults to HTTP. + type: string + required: + - port + type: object + tcpSocket: + description: Deprecated. TCPSocket is NOT supported + as a LifecycleHandler and kept for the backward + compatibility. There are no validation of this + field and lifecycle hooks will fail in runtime + when tcp handler is specified. + properties: + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + type: object + livenessProbe: + description: 'Periodic probe of container liveness. Container + will be restarted if the probe fails. Cannot be updated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to execute + inside the container, the working directory for + the command is root ('/') in the container's + filesystem. The command is simply exec'd, it is + not run inside a shell, so traditional shell instructions + ('|', etc) won't work. To use a shell, you need + to explicitly call out to that shell. Exit status + of 0 is treated as live/healthy and non-zero is + unhealthy. + items: + type: string + type: array + type: object + failureThreshold: + description: Minimum consecutive failures for the probe + to be considered failed after having succeeded. Defaults + to 3. Minimum value is 1. + format: int32 + type: integer + grpc: + description: GRPC specifies an action involving a GRPC + port. This is a beta field and requires enabling GRPCContainerProbe + feature gate. + properties: + port: + description: Port number of the gRPC service. Number + must be in the range 1 to 65535. + format: int32 + type: integer + service: + description: "Service is the name of the service + to place in the gRPC HealthCheckRequest (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + \n If this is not specified, the default behavior + is defined by gRPC." + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies the http request to perform. + properties: + host: + description: Host name to connect to, defaults to + the pod IP. You probably want to set "Host" in + httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the request. + HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom header + to be used in HTTP probes + properties: + name: + description: The header field name + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to the + host. Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: 'Number of seconds after the container + has started before liveness probes are initiated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + periodSeconds: + description: How often (in seconds) to perform the probe. + Default to 10 seconds. Minimum value is 1. + format: int32 + type: integer + successThreshold: + description: Minimum consecutive successes for the probe + to be considered successful after having failed. Defaults + to 1. Must be 1 for liveness and startup. Minimum + value is 1. + format: int32 + type: integer + tcpSocket: + description: TCPSocket specifies an action involving + a TCP port. + properties: + host: + description: 'Optional: Host name to connect to, + defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: Optional duration in seconds the pod needs + to terminate gracefully upon probe failure. The grace + period is the duration in seconds after the processes + running in the pod are sent a termination signal and + the time when the processes are forcibly halted with + a kill signal. Set this value longer than the expected + cleanup time for your process. If this value is nil, + the pod's terminationGracePeriodSeconds will be used. + Otherwise, this value overrides the value provided + by the pod spec. Value must be non-negative integer. + The value zero indicates stop immediately via the + kill signal (no opportunity to shut down). This is + a beta field and requires enabling ProbeTerminationGracePeriod + feature gate. Minimum value is 1. spec.terminationGracePeriodSeconds + is used if unset. + format: int64 + type: integer + timeoutSeconds: + description: 'Number of seconds after which the probe + times out. Defaults to 1 second. Minimum value is + 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + type: object + name: + description: Name of the container specified as a DNS_LABEL. + Each container in a pod must have a unique name (DNS_LABEL). + Cannot be updated. + type: string + ports: + description: List of ports to expose from the container. + Exposing a port here gives the system additional information + about the network connections a container uses, but is + primarily informational. Not specifying a port here DOES + NOT prevent that port from being exposed. Any port which + is listening on the default "0.0.0.0" address inside a + container will be accessible from the network. Cannot + be updated. + items: + description: ContainerPort represents a network port in + a single container. + properties: + containerPort: + description: Number of port to expose on the pod's + IP address. This must be a valid port number, 0 + < x < 65536. + format: int32 + type: integer + hostIP: + description: What host IP to bind the external port + to. + type: string + hostPort: + description: Number of port to expose on the host. + If specified, this must be a valid port number, + 0 < x < 65536. If HostNetwork is specified, this + must match ContainerPort. Most containers do not + need this. + format: int32 + type: integer + name: + description: If specified, this must be an IANA_SVC_NAME + and unique within the pod. Each named port in a + pod must have a unique name. Name for the port that + can be referred to by services. + type: string + protocol: + default: TCP + description: Protocol for port. Must be UDP, TCP, + or SCTP. Defaults to "TCP". + type: string + required: + - containerPort + type: object + type: array + x-kubernetes-list-map-keys: + - containerPort + - protocol + x-kubernetes-list-type: map + readinessProbe: + description: 'Periodic probe of container service readiness. + Container will be removed from service endpoints if the + probe fails. Cannot be updated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to execute + inside the container, the working directory for + the command is root ('/') in the container's + filesystem. The command is simply exec'd, it is + not run inside a shell, so traditional shell instructions + ('|', etc) won't work. To use a shell, you need + to explicitly call out to that shell. Exit status + of 0 is treated as live/healthy and non-zero is + unhealthy. + items: + type: string + type: array + type: object + failureThreshold: + description: Minimum consecutive failures for the probe + to be considered failed after having succeeded. Defaults + to 3. Minimum value is 1. + format: int32 + type: integer + grpc: + description: GRPC specifies an action involving a GRPC + port. This is a beta field and requires enabling GRPCContainerProbe + feature gate. + properties: + port: + description: Port number of the gRPC service. Number + must be in the range 1 to 65535. + format: int32 + type: integer + service: + description: "Service is the name of the service + to place in the gRPC HealthCheckRequest (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + \n If this is not specified, the default behavior + is defined by gRPC." + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies the http request to perform. + properties: + host: + description: Host name to connect to, defaults to + the pod IP. You probably want to set "Host" in + httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the request. + HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom header + to be used in HTTP probes + properties: + name: + description: The header field name + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to the + host. Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: 'Number of seconds after the container + has started before liveness probes are initiated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + periodSeconds: + description: How often (in seconds) to perform the probe. + Default to 10 seconds. Minimum value is 1. + format: int32 + type: integer + successThreshold: + description: Minimum consecutive successes for the probe + to be considered successful after having failed. Defaults + to 1. Must be 1 for liveness and startup. Minimum + value is 1. + format: int32 + type: integer + tcpSocket: + description: TCPSocket specifies an action involving + a TCP port. + properties: + host: + description: 'Optional: Host name to connect to, + defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: Optional duration in seconds the pod needs + to terminate gracefully upon probe failure. The grace + period is the duration in seconds after the processes + running in the pod are sent a termination signal and + the time when the processes are forcibly halted with + a kill signal. Set this value longer than the expected + cleanup time for your process. If this value is nil, + the pod's terminationGracePeriodSeconds will be used. + Otherwise, this value overrides the value provided + by the pod spec. Value must be non-negative integer. + The value zero indicates stop immediately via the + kill signal (no opportunity to shut down). This is + a beta field and requires enabling ProbeTerminationGracePeriod + feature gate. Minimum value is 1. spec.terminationGracePeriodSeconds + is used if unset. + format: int64 + type: integer + timeoutSeconds: + description: 'Number of seconds after which the probe + times out. Defaults to 1 second. Minimum value is + 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + type: object + resources: + description: 'Compute Resources required by this container. + Cannot be updated. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + properties: + 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. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + securityContext: + description: 'SecurityContext defines the security options + the container should be run with. If set, the fields of + SecurityContext override the equivalent fields of PodSecurityContext. + More info: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/' + properties: + allowPrivilegeEscalation: + description: 'AllowPrivilegeEscalation controls whether + a process can gain more privileges than its parent + process. This bool directly controls if the no_new_privs + flag will be set on the container process. AllowPrivilegeEscalation + is true always when the container is: 1) run as Privileged + 2) has CAP_SYS_ADMIN Note that this field cannot be + set when spec.os.name is windows.' + type: boolean + capabilities: + description: The capabilities to add/drop when running + containers. Defaults to the default set of capabilities + granted by the container runtime. Note that this field + cannot be set when spec.os.name is windows. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + type: object + privileged: + description: Run container in privileged mode. Processes + in privileged containers are essentially equivalent + to root on the host. Defaults to false. Note that + this field cannot be set when spec.os.name is windows. + type: boolean + procMount: + description: procMount denotes the type of proc mount + to use for the containers. The default is DefaultProcMount + which uses the container runtime defaults for readonly + paths and masked paths. This requires the ProcMountType + feature flag to be enabled. Note that this field cannot + be set when spec.os.name is windows. + type: string + readOnlyRootFilesystem: + description: Whether this container has a read-only + root filesystem. Default is false. Note that this + field cannot be set when spec.os.name is windows. + type: boolean + runAsGroup: + description: The GID to run the entrypoint of the container + process. Uses runtime default if unset. May also be + set in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set + when spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as + a non-root user. If true, the Kubelet will validate + the image at runtime to ensure that it does not run + as UID 0 (root) and fail to start the container if + it does. If unset or false, no such validation will + be performed. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container + process. Defaults to user specified in image metadata + if unspecified. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name + is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to the + container. If unspecified, the container runtime will + allocate a random SELinux context for each container. May + also be set in PodSecurityContext. If set in both + SecurityContext and PodSecurityContext, the value + specified in SecurityContext takes precedence. Note + that this field cannot be set when spec.os.name is + windows. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by this container. + If seccomp options are provided at both the pod & + container level, the container options override the + pod options. Note that this field cannot be set when + spec.os.name is windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile + defined in a file on the node should be used. + The profile must be preconfigured on the node + to work. Must be a descending path, relative to + the kubelet's configured seccomp profile location. + Must only be set if type is "Localhost". + type: string + type: + description: "type indicates which kind of seccomp + profile will be applied. Valid options are: \n + Localhost - a profile defined in a file on the + node should be used. RuntimeDefault - the container + runtime default profile should be used. Unconfined + - no profile should be applied." + type: string + required: + - type + type: object + windowsOptions: + description: The Windows specific settings applied to + all containers. If unspecified, the options from the + PodSecurityContext will be used. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set + when spec.os.name is linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA + admission webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec + named by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name + of the GMSA credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container + should be run as a 'Host Process' container. This + field is alpha-level and will only be honored + by components that enable the WindowsHostProcessContainers + feature flag. Setting this field without the feature + flag will result in errors when validating the + Pod. All of a Pod's containers must have the same + effective HostProcess value (it is not allowed + to have a mix of HostProcess containers and non-HostProcess + containers). In addition, if HostProcess is true + then HostNetwork must also be set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the + entrypoint of the container process. Defaults + to the user specified in image metadata if unspecified. + May also be set in PodSecurityContext. If set + in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + type: string + type: object + type: object + startupProbe: + description: 'StartupProbe indicates that the Pod has successfully + initialized. If specified, no other probes are executed + until this completes successfully. If this probe fails, + the Pod will be restarted, just as if the livenessProbe + failed. This can be used to provide different probe parameters + at the beginning of a Pod''s lifecycle, when it might + take a long time to load data or warm a cache, than during + steady-state operation. This cannot be updated. More info: + https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to execute + inside the container, the working directory for + the command is root ('/') in the container's + filesystem. The command is simply exec'd, it is + not run inside a shell, so traditional shell instructions + ('|', etc) won't work. To use a shell, you need + to explicitly call out to that shell. Exit status + of 0 is treated as live/healthy and non-zero is + unhealthy. + items: + type: string + type: array + type: object + failureThreshold: + description: Minimum consecutive failures for the probe + to be considered failed after having succeeded. Defaults + to 3. Minimum value is 1. + format: int32 + type: integer + grpc: + description: GRPC specifies an action involving a GRPC + port. This is a beta field and requires enabling GRPCContainerProbe + feature gate. + properties: + port: + description: Port number of the gRPC service. Number + must be in the range 1 to 65535. + format: int32 + type: integer + service: + description: "Service is the name of the service + to place in the gRPC HealthCheckRequest (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + \n If this is not specified, the default behavior + is defined by gRPC." + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies the http request to perform. + properties: + host: + description: Host name to connect to, defaults to + the pod IP. You probably want to set "Host" in + httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the request. + HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom header + to be used in HTTP probes + properties: + name: + description: The header field name + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to the + host. Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: 'Number of seconds after the container + has started before liveness probes are initiated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + periodSeconds: + description: How often (in seconds) to perform the probe. + Default to 10 seconds. Minimum value is 1. + format: int32 + type: integer + successThreshold: + description: Minimum consecutive successes for the probe + to be considered successful after having failed. Defaults + to 1. Must be 1 for liveness and startup. Minimum + value is 1. + format: int32 + type: integer + tcpSocket: + description: TCPSocket specifies an action involving + a TCP port. + properties: + host: + description: 'Optional: Host name to connect to, + defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: Optional duration in seconds the pod needs + to terminate gracefully upon probe failure. The grace + period is the duration in seconds after the processes + running in the pod are sent a termination signal and + the time when the processes are forcibly halted with + a kill signal. Set this value longer than the expected + cleanup time for your process. If this value is nil, + the pod's terminationGracePeriodSeconds will be used. + Otherwise, this value overrides the value provided + by the pod spec. Value must be non-negative integer. + The value zero indicates stop immediately via the + kill signal (no opportunity to shut down). This is + a beta field and requires enabling ProbeTerminationGracePeriod + feature gate. Minimum value is 1. spec.terminationGracePeriodSeconds + is used if unset. + format: int64 + type: integer + timeoutSeconds: + description: 'Number of seconds after which the probe + times out. Defaults to 1 second. Minimum value is + 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + type: object + stdin: + description: Whether this container should allocate a buffer + for stdin in the container runtime. If this is not set, + reads from stdin in the container will always result in + EOF. Default is false. + type: boolean + stdinOnce: + description: Whether the container runtime should close + the stdin channel after it has been opened by a single + attach. When stdin is true the stdin stream will remain + open across multiple attach sessions. If stdinOnce is + set to true, stdin is opened on container start, is empty + until the first client attaches to stdin, and then remains + open and accepts data until the client disconnects, at + which time stdin is closed and remains closed until the + container is restarted. If this flag is false, a container + processes that reads from stdin will never receive an + EOF. Default is false + type: boolean + terminationMessagePath: + description: 'Optional: Path at which the file to which + the container''s termination message will be written is + mounted into the container''s filesystem. Message written + is intended to be brief final status, such as an assertion + failure message. Will be truncated by the node if greater + than 4096 bytes. The total message length across all containers + will be limited to 12kb. Defaults to /dev/termination-log. + Cannot be updated.' + type: string + terminationMessagePolicy: + description: Indicate how the termination message should + be populated. File will use the contents of terminationMessagePath + to populate the container status message on both success + and failure. FallbackToLogsOnError will use the last chunk + of container log output if the termination message file + is empty and the container exited with an error. The log + output is limited to 2048 bytes or 80 lines, whichever + is smaller. Defaults to File. Cannot be updated. + type: string + tty: + description: Whether this container should allocate a TTY + for itself, also requires 'stdin' to be true. Default + is false. + type: boolean + volumeDevices: + description: volumeDevices is the list of block devices + to be used by the container. + items: + description: volumeDevice describes a mapping of a raw + block device within a container. + properties: + devicePath: + description: devicePath is the path inside of the + container that the device will be mapped to. + type: string + name: + description: name must match the name of a persistentVolumeClaim + in the pod + type: string + required: + - devicePath + - name + type: object + type: array + volumeMounts: + description: Pod volumes to mount into the container's filesystem. + Cannot be updated. + items: + description: VolumeMount describes a mounting of a Volume + within a container. + properties: + mountPath: + description: Path within the container at which the + volume should be mounted. Must not contain ':'. + type: string + mountPropagation: + description: mountPropagation determines how mounts + are propagated from the host to container and the + other way around. When not set, MountPropagationNone + is used. This field is beta in 1.10. + type: string + name: + description: This must match the Name of a Volume. + type: string + readOnly: + description: Mounted read-only if true, read-write + otherwise (false or unspecified). Defaults to false. + type: boolean + subPath: + description: Path within the volume from which the + container's volume should be mounted. Defaults to + "" (volume's root). + type: string + subPathExpr: + description: Expanded path within the volume from + which the container's volume should be mounted. + Behaves similarly to SubPath but environment variable + references $(VAR_NAME) are expanded using the container's + environment. Defaults to "" (volume's root). SubPathExpr + and SubPath are mutually exclusive. + type: string + required: + - mountPath + - name + type: object + type: array + workingDir: + description: Container's working directory. If not specified, + the container runtime's default will be used, which might + be configured in the container image. Cannot be updated. + type: string + required: + - name + type: object + type: array + nodeSelector: + additionalProperties: + type: string + type: object + podAnnotations: + additionalProperties: + type: string + type: object + port: + format: int32 + type: integer + priorityClassName: + type: string + replicas: + format: int32 + type: integer + resources: + description: ResourceRequirements describes the compute resource + requirements. + properties: + 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. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + securityContext: + description: PodSecurityContext holds pod-level security attributes + and common container settings. Some fields are also present + in container.securityContext. Field values of container.securityContext + take precedence over field values of PodSecurityContext. + properties: + fsGroup: + description: "A special supplemental group that applies to + all containers in a pod. Some volume types allow the Kubelet + to change the ownership of that volume to be owned by the + pod: \n 1. The owning GID will be the FSGroup 2. The setgid + bit is set (new files created in the volume will be owned + by FSGroup) 3. The permission bits are OR'd with rw-rw---- + \n If unset, the Kubelet will not modify the ownership and + permissions of any volume. Note that this field cannot be + set when spec.os.name is windows." + format: int64 + type: integer + fsGroupChangePolicy: + description: 'fsGroupChangePolicy defines behavior of changing + ownership and permission of the volume before being exposed + inside Pod. This field will only apply to volume types which + support fsGroup based ownership(and permissions). It will + have no effect on ephemeral volume types such as: secret, + configmaps and emptydir. Valid values are "OnRootMismatch" + and "Always". If not specified, "Always" is used. Note that + this field cannot be set when spec.os.name is windows.' + type: string + runAsGroup: + description: The GID to run the entrypoint of the container + process. Uses runtime default if unset. May also be set + in SecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence for that container. Note that this field + cannot be set when spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as a non-root + user. If true, the Kubelet will validate the image at runtime + to ensure that it does not run as UID 0 (root) and fail + to start the container if it does. If unset or false, no + such validation will be performed. May also be set in SecurityContext. If + set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container + process. Defaults to user specified in image metadata if + unspecified. May also be set in SecurityContext. If set + in both SecurityContext and PodSecurityContext, the value + specified in SecurityContext takes precedence for that container. + Note that this field cannot be set when spec.os.name is + windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to all containers. + If unspecified, the container runtime will allocate a random + SELinux context for each container. May also be set in + SecurityContext. If set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence + for that container. Note that this field cannot be set when + spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by the containers + in this pod. Note that this field cannot be set when spec.os.name + is windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile defined + in a file on the node should be used. The profile must + be preconfigured on the node to work. Must be a descending + path, relative to the kubelet's configured seccomp profile + location. Must only be set if type is "Localhost". + type: string + type: + description: "type indicates which kind of seccomp profile + will be applied. Valid options are: \n Localhost - a + profile defined in a file on the node should be used. + RuntimeDefault - the container runtime default profile + should be used. Unconfined - no profile should be applied." + type: string + required: + - type + type: object + supplementalGroups: + description: A list of groups applied to the first process + run in each container, in addition to the container's primary + GID. If unspecified, no groups will be added to any container. + Note that this field cannot be set when spec.os.name is + windows. + items: + format: int64 + type: integer + type: array + sysctls: + description: Sysctls hold a list of namespaced sysctls used + for the pod. Pods with unsupported sysctls (by the container + runtime) might fail to launch. Note that this field cannot + be set when spec.os.name is windows. + items: + description: Sysctl defines a kernel parameter to be set + properties: + name: + description: Name of a property to set + type: string + value: + description: Value of a property to set + type: string + required: + - name + - value + type: object + type: array + windowsOptions: + description: The Windows specific settings applied to all + containers. If unspecified, the options within a container's + SecurityContext will be used. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA admission + webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec named + by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of the + GMSA credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container should + be run as a 'Host Process' container. This field is + alpha-level and will only be honored by components that + enable the WindowsHostProcessContainers feature flag. + Setting this field without the feature flag will result + in errors when validating the Pod. All of a Pod's containers + must have the same effective HostProcess value (it is + not allowed to have a mix of HostProcess containers + and non-HostProcess containers). In addition, if HostProcess + is true then HostNetwork must also be set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set in + PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. + type: string + type: object + type: object + serviceAccountName: + type: string + serviceAnnotations: + additionalProperties: + type: string + type: object + shutdownConfigMap: + type: string + storage: + description: RedisStorage defines the structure used to store + the Redis Data + properties: + emptyDir: + description: Represents an empty directory for a pod. Empty + directory volumes support ownership management and SELinux + relabeling. + properties: + medium: + description: 'medium represents what type of storage medium + should back this directory. The default is "" which + means to use the node''s default medium. Must be an + empty string (default) or Memory. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' + type: string + sizeLimit: + anyOf: + - type: integer + - type: string + description: 'sizeLimit is the total amount of local storage + required for this EmptyDir volume. The size limit is + also applicable for memory medium. The maximum usage + on memory medium EmptyDir would be the minimum value + between the SizeLimit specified here and the sum of + memory limits of all containers in a pod. The default + is nil which means that the limit is undefined. More + info: http://kubernetes.io/docs/user-guide/volumes#emptydir' + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + keepAfterDeletion: + type: boolean + persistentVolumeClaim: + description: EmbeddedPersistentVolumeClaim is an embedded + version of k8s.io/api/core/v1.PersistentVolumeClaim. It + contains TypeMeta and a reduced ObjectMeta. + 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: + description: EmbeddedMetadata contains metadata relevant + to an EmbeddedResource. + properties: + annotations: + additionalProperties: + type: string + description: 'Annotations is an unstructured key value + map stored with a resource that may be set by external + tools to store and retrieve arbitrary metadata. + They are not queryable and should be preserved when + modifying objects. More info: http://kubernetes.io/docs/user-guide/annotations' + type: object + labels: + additionalProperties: + type: string + description: 'Map of string keys and values that can + be used to organize and categorize (scope and select) + objects. May match selectors of replication controllers + and services. More info: http://kubernetes.io/docs/user-guide/labels' + type: object + name: + description: 'Name must be unique within a namespace. + Is required when creating resources, although some + resources may allow a client to request the generation + of an appropriate name automatically. Name is primarily + intended for creation idempotence and configuration + definition. Cannot be updated. More info: http://kubernetes.io/docs/user-guide/identifiers#names' + type: string + type: object + spec: + description: 'Spec defines the desired characteristics + of a volume requested by a pod author. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' + properties: + accessModes: + description: 'accessModes contains the desired access + modes the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' + items: + type: string + type: array + dataSource: + description: 'dataSource field can be used to specify + either: * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) + * An existing PVC (PersistentVolumeClaim) If the + provisioner or an external controller can support + the specified data source, it will create a new + volume based on the contents of the specified data + source. If the AnyVolumeDataSource feature gate + is enabled, this field will always have the same + contents as the DataSourceRef field.' + properties: + apiGroup: + description: APIGroup is the group for the resource + being referenced. If APIGroup is not specified, + the specified Kind must be in the core API group. + For any other third-party types, APIGroup is + required. + type: string + kind: + description: Kind is the type of resource being + referenced + type: string + name: + description: Name is the name of resource being + referenced + type: string + required: + - kind + - name + type: object + dataSourceRef: + description: 'dataSourceRef specifies the object from + which to populate the volume with data, if a non-empty + volume is desired. This may be any local object + from a non-empty API group (non core object) or + a PersistentVolumeClaim object. When this field + is specified, volume binding will only succeed if + the type of the specified object matches some installed + volume populator or dynamic provisioner. This field + will replace the functionality of the DataSource + field and as such if both fields are non-empty, + they must have the same value. For backwards compatibility, + both fields (DataSource and DataSourceRef) will + be set to the same value automatically if one of + them is empty and the other is non-empty. There + are two important differences between DataSource + and DataSourceRef: * While DataSource only allows + two specific types of objects, DataSourceRef allows + any non-core object, as well as PersistentVolumeClaim + objects. * While DataSource ignores disallowed values + (dropping them), DataSourceRef preserves all values, + and generates an error if a disallowed value is specified. + (Beta) Using this field requires the AnyVolumeDataSource + feature gate to be enabled.' + properties: + apiGroup: + description: APIGroup is the group for the resource + being referenced. If APIGroup is not specified, + the specified Kind must be in the core API group. + For any other third-party types, APIGroup is + required. + type: string + kind: + description: Kind is the type of resource being + referenced + type: string + name: + description: Name is the name of resource being + referenced + type: string + required: + - kind + - name + type: object + resources: + description: 'resources represents the minimum resources + the volume should have. If RecoverVolumeExpansionFailure + feature is enabled users are allowed to specify + resource requirements that are lower than previous + value but must still be higher than capacity recorded + in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' + properties: + 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. More info: + https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + selector: + description: selector is a label query over volumes + to consider for binding. + 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 + required: + - key + - operator + type: object + type: array + 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 + storageClassName: + description: 'storageClassName is the name of the + StorageClass required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' + type: string + volumeMode: + description: volumeMode defines what type of volume + is required by the claim. Value of Filesystem is + implied when not included in claim spec. + type: string + volumeName: + description: volumeName is the binding reference to + the PersistentVolume backing this claim. + type: string + type: object + status: + description: 'Status represents the current information/status + of a persistent volume claim. Read-only. More info: + https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' + properties: + accessModes: + description: 'accessModes contains the actual access + modes the volume backing the PVC has. More info: + https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' + items: + type: string + type: array + allocatedResources: + 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: allocatedResources is the storage resource + within AllocatedResources tracks the capacity allocated + to a PVC. It may be larger than the actual capacity + when a volume expansion operation is requested. + For storage quota, the larger value from allocatedResources + and PVC.spec.resources is used. If allocatedResources + is not set, PVC.spec.resources alone is used for + quota calculation. If a volume expansion capacity + request is lowered, allocatedResources is only lowered + if there are no expansion operations in progress + and if the actual volume capacity is equal or lower + than the requested capacity. This is an alpha field + and requires enabling RecoverVolumeExpansionFailure + feature. + type: object + capacity: + 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: capacity represents the actual resources + of the underlying volume. + type: object + conditions: + description: conditions is the current Condition of + persistent volume claim. If underlying persistent + volume is being resized then the Condition will + be set to 'ResizeStarted'. + items: + description: PersistentVolumeClaimCondition contails + details about state of pvc + properties: + lastProbeTime: + description: lastProbeTime is the time we probed + the condition. + format: date-time + type: string + lastTransitionTime: + description: lastTransitionTime is the time + the condition transitioned from one status + to another. + format: date-time + type: string + message: + description: message is the human-readable message + indicating details about last transition. + type: string + reason: + description: reason is a unique, this should + be a short, machine understandable string + that gives the reason for condition's last + transition. If it reports "ResizeStarted" + that means the underlying persistent volume + is being resized. + type: string + status: + type: string + type: + description: PersistentVolumeClaimConditionType + is a valid value of PersistentVolumeClaimCondition.Type + type: string + required: + - status + - type + type: object + type: array + phase: + description: phase represents the current phase of + PersistentVolumeClaim. + type: string + resizeStatus: + description: resizeStatus stores status of resize + operation. ResizeStatus is not set by default but + when expansion is complete resizeStatus is set to + empty string by resize controller or kubelet. This + is an alpha field and requires enabling RecoverVolumeExpansionFailure + feature. + type: string + type: object + type: object + type: object + terminationGracePeriod: + format: int64 + type: integer + tolerations: + 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: + 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 + required: + - key + - operator + type: object + type: array + 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 + 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. For example, in a 3-zone + cluster, MaxSkew is set to 1, and pods with the same labelSelector + spread as 2/2/1: In this case, the global minimum is 1. + | zone1 | zone2 | zone3 | | P P | P P | P | - + if MaxSkew is 1, incoming pod can only be scheduled to + zone3 to become 2/2/2; scheduling it onto zone1(zone2) + would make the ActualSkew(3-1) on zone1(zone2) violate + MaxSkew(1). - if MaxSkew is 2, incoming pod can be scheduled + onto any zone. When `whenUnsatisfiable=ScheduleAnyway`, + it is used to give higher precedence to topologies that + satisfy it. It''s a required field. Default value is 1 + and 0 is not allowed.' + 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. + As a result, when the number of eligible domains is less + than minDomains, scheduler won't schedule more than maxSkew + Pods to those domains. If value is nil, the constraint + behaves as if MinDomains is equal to 1. Valid values are + integers greater than 0. When value is not nil, WhenUnsatisfiable + must be DoNotSchedule. \n For example, in a 3-zone cluster, + MaxSkew is set to 2, MinDomains is set to 5 and pods with + the same labelSelector spread as 2/2/2: | zone1 | zone2 + | zone3 | | P P | P P | P P | The number of domains + is less than 5(MinDomains), so \"global minimum\" is treated + as 0. In this situation, new pod with the same labelSelector + cannot be scheduled, because computed skew will be 3(3 + - 0) if new Pod is scheduled to any of the three zones, + it will violate MaxSkew. \n This is an alpha field and + requires enabling MinDomainsInPodTopologySpread feature + gate." + format: int32 + type: integer + 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 match the node selector. e.g. + If TopologyKey is "kubernetes.io/hostname", each Node + is a domain of that topology. And, if TopologyKey is "topology.kubernetes.io/zone", + each zone is a domain of that topology. It's a required + field. + 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. For example, in a + 3-zone cluster, MaxSkew is set to 1, and pods with the + same labelSelector spread as 3/1/1: | zone1 | zone2 | + zone3 | | P P P | P | P | If WhenUnsatisfiable + is set to DoNotSchedule, incoming pod can only be scheduled + to zone2(zone3) to become 3/2/1(3/1/2) as ActualSkew(2-1) + on zone2(zone3) satisfies MaxSkew(1). In other words, + the cluster can still be imbalanced, but scheduler won''t + make it *more* imbalanced. It''s a required field.' + type: string + required: + - maxSkew + - topologyKey + - whenUnsatisfiable + type: object + type: array + type: object + sentinel: + description: SentinelSettings defines the specification of the sentinel + cluster + properties: + affinity: + description: Affinity is a group of affinity scheduling rules. + properties: + nodeAffinity: + description: Describes node affinity scheduling rules for + the pod. + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods + to nodes that satisfy the affinity expressions specified + by this field, but it may choose a node that violates + one or more of the expressions. The node that is most + preferred is the one with the greatest sum of weights, + i.e. for each node that meets all of the scheduling + requirements (resource request, requiredDuringScheduling + affinity expressions, etc.), compute a sum by iterating + through the elements of this field and adding "weight" + to the sum if the node matches the corresponding matchExpressions; + the node(s) with the highest sum are the most preferred. + items: + description: An empty preferred scheduling term matches + all objects with implicit weight 0 (i.e. it's a no-op). + A null preferred scheduling term matches no objects + (i.e. is also a no-op). + properties: + preference: + description: A node selector term, associated with + the corresponding weight. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: 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. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: 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. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + weight: + description: Weight associated with matching the + corresponding nodeSelectorTerm, in the range 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by + this field are not met at scheduling time, the pod will + not be scheduled onto the node. If the affinity requirements + specified by this field cease to be met at some point + during pod execution (e.g. due to an update), the system + may or may not try to eventually evict the pod from + its node. + properties: + nodeSelectorTerms: + description: Required. A list of node selector terms. + The terms are ORed. + items: + description: A null or empty node selector term + matches no objects. The requirements of them are + ANDed. The TopologySelectorTerm type implements + a subset of the NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: 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. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: 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. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + type: array + required: + - nodeSelectorTerms + type: object + type: object + podAffinity: + description: Describes pod affinity scheduling rules (e.g. + co-locate this pod in the same node, zone, etc. as some + other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods + to nodes that satisfy the affinity expressions specified + by this field, but it may choose a node that violates + one or more of the expressions. The node that is most + preferred is the one with the greatest sum of weights, + i.e. for each node that meets all of the scheduling + requirements (resource request, requiredDuringScheduling + affinity expressions, etc.), compute a sum by iterating + through the elements of this field and adding "weight" + to the sum if the node has pods which matches the corresponding + podAffinityTerm; the node(s) with the highest sum are + the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by + this field and the ones listed in the namespaces + field. null selector and null or empty namespaces + list means "this pod's namespace". An empty + selector ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. + The term is applied to the union of the namespaces + listed in this field and the ones selected + by namespaceSelector. null or empty namespaces + list and null namespaceSelector means "this + pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the + pods matching the labelSelector in the specified + namespaces, where co-located is defined as + running on a node whose value of the label + with key topologyKey matches that of any node + on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching the + corresponding podAffinityTerm, in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by + this field are not met at scheduling time, the pod will + not be scheduled onto the node. If the affinity requirements + specified by this field cease to be met at some point + during pod execution (e.g. due to a pod label update), + the system may or may not try to eventually evict the + pod from its node. When there are multiple elements, + the lists of nodes corresponding to each podAffinityTerm + are intersected, i.e. all terms must be satisfied. + items: + description: Defines a set of pods (namely those matching + the labelSelector relative to the given namespace(s)) + that this pod should be co-located (affinity) or not + co-located (anti-affinity) with, where co-located + is defined as running on a node whose value of the + label with key matches that of any node + on which a pod of the set of pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by this + field and the ones listed in the namespaces field. + null selector and null or empty namespaces list + means "this pod's namespace". An empty selector + ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. The + term is applied to the union of the namespaces + listed in this field and the ones selected by + namespaceSelector. null or empty namespaces list + and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods + matching the labelSelector in the specified namespaces, + where co-located is defined as running on a node + whose value of the label with key topologyKey + matches that of any node on which any of the selected + pods is running. Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + podAntiAffinity: + description: Describes pod anti-affinity scheduling rules + (e.g. avoid putting this pod in the same node, zone, etc. + as some other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods + to nodes that satisfy the anti-affinity expressions + specified by this field, but it may choose a node that + violates one or more of the expressions. The node that + is most preferred is the one with the greatest sum of + weights, i.e. for each node that meets all of the scheduling + requirements (resource request, requiredDuringScheduling + anti-affinity expressions, etc.), compute a sum by iterating + through the elements of this field and adding "weight" + to the sum if the node has pods which matches the corresponding + podAffinityTerm; the node(s) with the highest sum are + the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by + this field and the ones listed in the namespaces + field. null selector and null or empty namespaces + list means "this pod's namespace". An empty + selector ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. + The term is applied to the union of the namespaces + listed in this field and the ones selected + by namespaceSelector. null or empty namespaces + list and null namespaceSelector means "this + pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the + pods matching the labelSelector in the specified + namespaces, where co-located is defined as + running on a node whose value of the label + with key topologyKey matches that of any node + on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching the + corresponding podAffinityTerm, in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the anti-affinity requirements specified + by this field are not met at scheduling time, the pod + will not be scheduled onto the node. If the anti-affinity + requirements specified by this field cease to be met + at some point during pod execution (e.g. due to a pod + label update), the system may or may not try to eventually + evict the pod from its node. When there are multiple + elements, the lists of nodes corresponding to each podAffinityTerm + are intersected, i.e. all terms must be satisfied. + items: + description: Defines a set of pods (namely those matching + the labelSelector relative to the given namespace(s)) + that this pod should be co-located (affinity) or not + co-located (anti-affinity) with, where co-located + is defined as running on a node whose value of the + label with key matches that of any node + on which a pod of the set of pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by this + field and the ones listed in the namespaces field. + null selector and null or empty namespaces list + means "this pod's namespace". An empty selector + ({}) matches all namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. The + term is applied to the union of the namespaces + listed in this field and the ones selected by + namespaceSelector. null or empty namespaces list + and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods + matching the labelSelector in the specified namespaces, + where co-located is defined as running on a node + whose value of the label with key topologyKey + matches that of any node on which any of the selected + pods is running. Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + type: object + command: + items: + type: string + type: array + configCopy: + description: SentinelConfigCopy defines the specification for + the sentinel exporter + properties: + containerSecurityContext: + description: SecurityContext holds security configuration + that will be applied to a container. Some fields are present + in both SecurityContext and PodSecurityContext. When both + are set, the values in SecurityContext take precedence. + properties: + allowPrivilegeEscalation: + description: 'AllowPrivilegeEscalation controls whether + a process can gain more privileges than its parent process. + This bool directly controls if the no_new_privs flag + will be set on the container process. AllowPrivilegeEscalation + is true always when the container is: 1) run as Privileged + 2) has CAP_SYS_ADMIN Note that this field cannot be + set when spec.os.name is windows.' + type: boolean + capabilities: + description: The capabilities to add/drop when running + containers. Defaults to the default set of capabilities + granted by the container runtime. Note that this field + cannot be set when spec.os.name is windows. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + type: object + privileged: + description: Run container in privileged mode. Processes + in privileged containers are essentially equivalent + to root on the host. Defaults to false. Note that this + field cannot be set when spec.os.name is windows. + type: boolean + procMount: + description: procMount denotes the type of proc mount + to use for the containers. The default is DefaultProcMount + which uses the container runtime defaults for readonly + paths and masked paths. This requires the ProcMountType + feature flag to be enabled. Note that this field cannot + be set when spec.os.name is windows. + type: string + readOnlyRootFilesystem: + description: Whether this container has a read-only root + filesystem. Default is false. Note that this field cannot + be set when spec.os.name is windows. + type: boolean + runAsGroup: + description: The GID to run the entrypoint of the container + process. Uses runtime default if unset. May also be + set in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set + when spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as + a non-root user. If true, the Kubelet will validate + the image at runtime to ensure that it does not run + as UID 0 (root) and fail to start the container if it + does. If unset or false, no such validation will be + performed. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container + process. Defaults to user specified in image metadata + if unspecified. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name + is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to the + container. If unspecified, the container runtime will + allocate a random SELinux context for each container. May + also be set in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set + when spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by this container. + If seccomp options are provided at both the pod & container + level, the container options override the pod options. + Note that this field cannot be set when spec.os.name + is windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile + defined in a file on the node should be used. The + profile must be preconfigured on the node to work. + Must be a descending path, relative to the kubelet's + configured seccomp profile location. Must only be + set if type is "Localhost". + type: string + type: + description: "type indicates which kind of seccomp + profile will be applied. Valid options are: \n Localhost + - a profile defined in a file on the node should + be used. RuntimeDefault - the container runtime + default profile should be used. Unconfined - no + profile should be applied." + type: string + required: + - type + type: object + windowsOptions: + description: The Windows specific settings applied to + all containers. If unspecified, the options from the + PodSecurityContext will be used. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set + when spec.os.name is linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA + admission webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec + named by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of + the GMSA credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container + should be run as a 'Host Process' container. This + field is alpha-level and will only be honored by + components that enable the WindowsHostProcessContainers + feature flag. Setting this field without the feature + flag will result in errors when validating the Pod. + All of a Pod's containers must have the same effective + HostProcess value (it is not allowed to have a mix + of HostProcess containers and non-HostProcess containers). In + addition, if HostProcess is true then HostNetwork + must also be set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set + in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. + type: string + type: object + type: object + type: object + containerSecurityContext: + description: SecurityContext holds security configuration that + will be applied to a container. Some fields are present in both + SecurityContext and PodSecurityContext. When both are set, + the values in SecurityContext take precedence. + properties: + allowPrivilegeEscalation: + description: 'AllowPrivilegeEscalation controls whether a + process can gain more privileges than its parent process. + This bool directly controls if the no_new_privs flag will + be set on the container process. AllowPrivilegeEscalation + is true always when the container is: 1) run as Privileged + 2) has CAP_SYS_ADMIN Note that this field cannot be set + when spec.os.name is windows.' + type: boolean + capabilities: + description: The capabilities to add/drop when running containers. + Defaults to the default set of capabilities granted by the + container runtime. Note that this field cannot be set when + spec.os.name is windows. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + type: object + privileged: + description: Run container in privileged mode. Processes in + privileged containers are essentially equivalent to root + on the host. Defaults to false. Note that this field cannot + be set when spec.os.name is windows. + type: boolean + procMount: + description: procMount denotes the type of proc mount to use + for the containers. The default is DefaultProcMount which + uses the container runtime defaults for readonly paths and + masked paths. This requires the ProcMountType feature flag + to be enabled. Note that this field cannot be set when spec.os.name + is windows. + type: string + readOnlyRootFilesystem: + description: Whether this container has a read-only root filesystem. + Default is false. Note that this field cannot be set when + spec.os.name is windows. + type: boolean + runAsGroup: + description: The GID to run the entrypoint of the container + process. Uses runtime default if unset. May also be set + in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as a non-root + user. If true, the Kubelet will validate the image at runtime + to ensure that it does not run as UID 0 (root) and fail + to start the container if it does. If unset or false, no + such validation will be performed. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container + process. Defaults to user specified in image metadata if + unspecified. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. Note + that this field cannot be set when spec.os.name is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to the container. + If unspecified, the container runtime will allocate a random + SELinux context for each container. May also be set in + PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by this container. + If seccomp options are provided at both the pod & container + level, the container options override the pod options. Note + that this field cannot be set when spec.os.name is windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile defined + in a file on the node should be used. The profile must + be preconfigured on the node to work. Must be a descending + path, relative to the kubelet's configured seccomp profile + location. Must only be set if type is "Localhost". + type: string + type: + description: "type indicates which kind of seccomp profile + will be applied. Valid options are: \n Localhost - a + profile defined in a file on the node should be used. + RuntimeDefault - the container runtime default profile + should be used. Unconfined - no profile should be applied." + type: string + required: + - type + type: object + windowsOptions: + description: The Windows specific settings applied to all + containers. If unspecified, the options from the PodSecurityContext + will be used. If set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is + linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA admission + webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec named + by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of the + GMSA credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container should + be run as a 'Host Process' container. This field is + alpha-level and will only be honored by components that + enable the WindowsHostProcessContainers feature flag. + Setting this field without the feature flag will result + in errors when validating the Pod. All of a Pod's containers + must have the same effective HostProcess value (it is + not allowed to have a mix of HostProcess containers + and non-HostProcess containers). In addition, if HostProcess + is true then HostNetwork must also be set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set in + PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. + type: string + type: object + type: object + customConfig: + items: + type: string + type: array + dnsPolicy: + description: DNSPolicy defines how a pod's DNS will be configured. + type: string + exporter: + description: Exporter defines the specification for the redis/sentinel + exporter + properties: + args: + items: + type: string + type: array + containerSecurityContext: + description: SecurityContext holds security configuration + that will be applied to a container. Some fields are present + in both SecurityContext and PodSecurityContext. When both + are set, the values in SecurityContext take precedence. + properties: + allowPrivilegeEscalation: + description: 'AllowPrivilegeEscalation controls whether + a process can gain more privileges than its parent process. + This bool directly controls if the no_new_privs flag + will be set on the container process. AllowPrivilegeEscalation + is true always when the container is: 1) run as Privileged + 2) has CAP_SYS_ADMIN Note that this field cannot be + set when spec.os.name is windows.' + type: boolean + capabilities: + description: The capabilities to add/drop when running + containers. Defaults to the default set of capabilities + granted by the container runtime. Note that this field + cannot be set when spec.os.name is windows. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + type: object + privileged: + description: Run container in privileged mode. Processes + in privileged containers are essentially equivalent + to root on the host. Defaults to false. Note that this + field cannot be set when spec.os.name is windows. + type: boolean + procMount: + description: procMount denotes the type of proc mount + to use for the containers. The default is DefaultProcMount + which uses the container runtime defaults for readonly + paths and masked paths. This requires the ProcMountType + feature flag to be enabled. Note that this field cannot + be set when spec.os.name is windows. + type: string + readOnlyRootFilesystem: + description: Whether this container has a read-only root + filesystem. Default is false. Note that this field cannot + be set when spec.os.name is windows. + type: boolean + runAsGroup: + description: The GID to run the entrypoint of the container + process. Uses runtime default if unset. May also be + set in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set + when spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as + a non-root user. If true, the Kubelet will validate + the image at runtime to ensure that it does not run + as UID 0 (root) and fail to start the container if it + does. If unset or false, no such validation will be + performed. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container + process. Defaults to user specified in image metadata + if unspecified. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name + is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to the + container. If unspecified, the container runtime will + allocate a random SELinux context for each container. May + also be set in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set + when spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by this container. + If seccomp options are provided at both the pod & container + level, the container options override the pod options. + Note that this field cannot be set when spec.os.name + is windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile + defined in a file on the node should be used. The + profile must be preconfigured on the node to work. + Must be a descending path, relative to the kubelet's + configured seccomp profile location. Must only be + set if type is "Localhost". + type: string + type: + description: "type indicates which kind of seccomp + profile will be applied. Valid options are: \n Localhost + - a profile defined in a file on the node should + be used. RuntimeDefault - the container runtime + default profile should be used. Unconfined - no + profile should be applied." + type: string + required: + - type + type: object + windowsOptions: + description: The Windows specific settings applied to + all containers. If unspecified, the options from the + PodSecurityContext will be used. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set + when spec.os.name is linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA + admission webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec + named by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of + the GMSA credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container + should be run as a 'Host Process' container. This + field is alpha-level and will only be honored by + components that enable the WindowsHostProcessContainers + feature flag. Setting this field without the feature + flag will result in errors when validating the Pod. + All of a Pod's containers must have the same effective + HostProcess value (it is not allowed to have a mix + of HostProcess containers and non-HostProcess containers). In + addition, if HostProcess is true then HostNetwork + must also be set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set + in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. + type: string + type: object + type: object + enabled: + type: boolean + env: + 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: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + optional: + description: Specify whether the ConfigMap or + its key must be defined + type: boolean + required: + - key + type: object + 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 + 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 + 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: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + optional: + description: Specify whether the Secret or its + key must be defined + type: boolean + required: + - key + type: object + type: object + required: + - name + type: object + type: array + image: + type: string + imagePullPolicy: + description: PullPolicy describes a policy for if/when to + pull a container image + type: string + resources: + description: ResourceRequirements describes the compute resource + requirements. + properties: + 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. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + type: object + extraContainers: + items: + description: A single application container that you want to + run within a pod. + properties: + args: + description: 'Arguments to the entrypoint. The container + image''s CMD is used if this is not provided. Variable + references $(VAR_NAME) are expanded using the container''s + environment. 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. Cannot + be updated. More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell' + items: + type: string + type: array + command: + description: 'Entrypoint array. Not executed within a shell. + The container image''s ENTRYPOINT is used if this is not + provided. Variable references $(VAR_NAME) are expanded + using the container''s environment. 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. Cannot be updated. More info: + https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell' + items: + type: string + type: array + env: + description: List of environment variables to set in the + container. Cannot be updated. + 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: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + optional: + description: Specify whether the ConfigMap + or its key must be defined + type: boolean + required: + - key + type: object + 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 + 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 + 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: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + optional: + description: Specify whether the Secret or + its key must be defined + type: boolean + required: + - key + type: object + type: object + required: + - name + type: object + type: array + envFrom: + description: List of sources to populate environment variables + in the container. The keys defined within a source must + be a C_IDENTIFIER. All invalid keys will be reported as + an event when the container is starting. 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. Cannot be updated. + items: + description: EnvFromSource represents the source of a + set of ConfigMaps + properties: + configMapRef: + description: The ConfigMap to select from + properties: + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the ConfigMap must + be defined + type: boolean + type: object + prefix: + description: An optional identifier to prepend to + each key in the ConfigMap. Must be a C_IDENTIFIER. + type: string + secretRef: + description: The Secret to select from + properties: + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the Secret must be + defined + type: boolean + type: object + type: object + type: array + image: + description: 'Container image name. More info: https://kubernetes.io/docs/concepts/containers/images + This field is optional to allow higher level config management + to default or override container images in workload controllers + like Deployments and StatefulSets.' + type: string + imagePullPolicy: + description: 'Image pull policy. One of Always, Never, IfNotPresent. + Defaults to Always if :latest tag is specified, or IfNotPresent + otherwise. Cannot be updated. More info: https://kubernetes.io/docs/concepts/containers/images#updating-images' + type: string + lifecycle: + description: Actions that the management system should take + in response to container lifecycle events. Cannot be updated. + properties: + postStart: + description: 'PostStart is called immediately after + a container is created. If the handler fails, the + container is terminated and restarted according to + its restart policy. Other management of the container + blocks until the hook completes. More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks' + properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to + execute inside the container, the working + directory for the command is root ('/') in + the container's filesystem. The command is + simply exec'd, it is not run inside a shell, + so traditional shell instructions ('|', etc) + won't work. To use a shell, you need to explicitly + call out to that shell. Exit status of 0 is + treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + type: object + httpGet: + description: HTTPGet specifies the http request + to perform. + properties: + host: + description: Host name to connect to, defaults + to the pod IP. You probably want to set "Host" + in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the request. + HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom + header to be used in HTTP probes + properties: + name: + description: The header field name + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to + the host. Defaults to HTTP. + type: string + required: + - port + type: object + tcpSocket: + description: Deprecated. TCPSocket is NOT supported + as a LifecycleHandler and kept for the backward + compatibility. There are no validation of this + field and lifecycle hooks will fail in runtime + when tcp handler is specified. + properties: + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + preStop: + description: 'PreStop is called immediately before a + container is terminated due to an API request or management + event such as liveness/startup probe failure, preemption, + resource contention, etc. The handler is not called + if the container crashes or exits. The Pod''s termination + grace period countdown begins before the PreStop hook + is executed. Regardless of the outcome of the handler, + the container will eventually terminate within the + Pod''s termination grace period (unless delayed by + finalizers). Other management of the container blocks + until the hook completes or until the termination + grace period is reached. More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks' + properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to + execute inside the container, the working + directory for the command is root ('/') in + the container's filesystem. The command is + simply exec'd, it is not run inside a shell, + so traditional shell instructions ('|', etc) + won't work. To use a shell, you need to explicitly + call out to that shell. Exit status of 0 is + treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + type: object + httpGet: + description: HTTPGet specifies the http request + to perform. + properties: + host: + description: Host name to connect to, defaults + to the pod IP. You probably want to set "Host" + in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the request. + HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom + header to be used in HTTP probes + properties: + name: + description: The header field name + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to + the host. Defaults to HTTP. + type: string + required: + - port + type: object + tcpSocket: + description: Deprecated. TCPSocket is NOT supported + as a LifecycleHandler and kept for the backward + compatibility. There are no validation of this + field and lifecycle hooks will fail in runtime + when tcp handler is specified. + properties: + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + type: object + livenessProbe: + description: 'Periodic probe of container liveness. Container + will be restarted if the probe fails. Cannot be updated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to execute + inside the container, the working directory for + the command is root ('/') in the container's + filesystem. The command is simply exec'd, it is + not run inside a shell, so traditional shell instructions + ('|', etc) won't work. To use a shell, you need + to explicitly call out to that shell. Exit status + of 0 is treated as live/healthy and non-zero is + unhealthy. + items: + type: string + type: array + type: object + failureThreshold: + description: Minimum consecutive failures for the probe + to be considered failed after having succeeded. Defaults + to 3. Minimum value is 1. + format: int32 + type: integer + grpc: + description: GRPC specifies an action involving a GRPC + port. This is a beta field and requires enabling GRPCContainerProbe + feature gate. + properties: + port: + description: Port number of the gRPC service. Number + must be in the range 1 to 65535. + format: int32 + type: integer + service: + description: "Service is the name of the service + to place in the gRPC HealthCheckRequest (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + \n If this is not specified, the default behavior + is defined by gRPC." + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies the http request to perform. + properties: + host: + description: Host name to connect to, defaults to + the pod IP. You probably want to set "Host" in + httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the request. + HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom header + to be used in HTTP probes + properties: + name: + description: The header field name + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to the + host. Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: 'Number of seconds after the container + has started before liveness probes are initiated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + periodSeconds: + description: How often (in seconds) to perform the probe. + Default to 10 seconds. Minimum value is 1. + format: int32 + type: integer + successThreshold: + description: Minimum consecutive successes for the probe + to be considered successful after having failed. Defaults + to 1. Must be 1 for liveness and startup. Minimum + value is 1. + format: int32 + type: integer + tcpSocket: + description: TCPSocket specifies an action involving + a TCP port. + properties: + host: + description: 'Optional: Host name to connect to, + defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: Optional duration in seconds the pod needs + to terminate gracefully upon probe failure. The grace + period is the duration in seconds after the processes + running in the pod are sent a termination signal and + the time when the processes are forcibly halted with + a kill signal. Set this value longer than the expected + cleanup time for your process. If this value is nil, + the pod's terminationGracePeriodSeconds will be used. + Otherwise, this value overrides the value provided + by the pod spec. Value must be non-negative integer. + The value zero indicates stop immediately via the + kill signal (no opportunity to shut down). This is + a beta field and requires enabling ProbeTerminationGracePeriod + feature gate. Minimum value is 1. spec.terminationGracePeriodSeconds + is used if unset. + format: int64 + type: integer + timeoutSeconds: + description: 'Number of seconds after which the probe + times out. Defaults to 1 second. Minimum value is + 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + type: object + name: + description: Name of the container specified as a DNS_LABEL. + Each container in a pod must have a unique name (DNS_LABEL). + Cannot be updated. + type: string + ports: + description: List of ports to expose from the container. + Exposing a port here gives the system additional information + about the network connections a container uses, but is + primarily informational. Not specifying a port here DOES + NOT prevent that port from being exposed. Any port which + is listening on the default "0.0.0.0" address inside a + container will be accessible from the network. Cannot + be updated. + items: + description: ContainerPort represents a network port in + a single container. + properties: + containerPort: + description: Number of port to expose on the pod's + IP address. This must be a valid port number, 0 + < x < 65536. + format: int32 + type: integer + hostIP: + description: What host IP to bind the external port + to. + type: string + hostPort: + description: Number of port to expose on the host. + If specified, this must be a valid port number, + 0 < x < 65536. If HostNetwork is specified, this + must match ContainerPort. Most containers do not + need this. + format: int32 + type: integer + name: + description: If specified, this must be an IANA_SVC_NAME + and unique within the pod. Each named port in a + pod must have a unique name. Name for the port that + can be referred to by services. + type: string + protocol: + default: TCP + description: Protocol for port. Must be UDP, TCP, + or SCTP. Defaults to "TCP". + type: string + required: + - containerPort + type: object + type: array + x-kubernetes-list-map-keys: + - containerPort + - protocol + x-kubernetes-list-type: map + readinessProbe: + description: 'Periodic probe of container service readiness. + Container will be removed from service endpoints if the + probe fails. Cannot be updated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to execute + inside the container, the working directory for + the command is root ('/') in the container's + filesystem. The command is simply exec'd, it is + not run inside a shell, so traditional shell instructions + ('|', etc) won't work. To use a shell, you need + to explicitly call out to that shell. Exit status + of 0 is treated as live/healthy and non-zero is + unhealthy. + items: + type: string + type: array + type: object + failureThreshold: + description: Minimum consecutive failures for the probe + to be considered failed after having succeeded. Defaults + to 3. Minimum value is 1. + format: int32 + type: integer + grpc: + description: GRPC specifies an action involving a GRPC + port. This is a beta field and requires enabling GRPCContainerProbe + feature gate. + properties: + port: + description: Port number of the gRPC service. Number + must be in the range 1 to 65535. + format: int32 + type: integer + service: + description: "Service is the name of the service + to place in the gRPC HealthCheckRequest (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + \n If this is not specified, the default behavior + is defined by gRPC." + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies the http request to perform. + properties: + host: + description: Host name to connect to, defaults to + the pod IP. You probably want to set "Host" in + httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the request. + HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom header + to be used in HTTP probes + properties: + name: + description: The header field name + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to the + host. Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: 'Number of seconds after the container + has started before liveness probes are initiated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + periodSeconds: + description: How often (in seconds) to perform the probe. + Default to 10 seconds. Minimum value is 1. + format: int32 + type: integer + successThreshold: + description: Minimum consecutive successes for the probe + to be considered successful after having failed. Defaults + to 1. Must be 1 for liveness and startup. Minimum + value is 1. + format: int32 + type: integer + tcpSocket: + description: TCPSocket specifies an action involving + a TCP port. + properties: + host: + description: 'Optional: Host name to connect to, + defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: Optional duration in seconds the pod needs + to terminate gracefully upon probe failure. The grace + period is the duration in seconds after the processes + running in the pod are sent a termination signal and + the time when the processes are forcibly halted with + a kill signal. Set this value longer than the expected + cleanup time for your process. If this value is nil, + the pod's terminationGracePeriodSeconds will be used. + Otherwise, this value overrides the value provided + by the pod spec. Value must be non-negative integer. + The value zero indicates stop immediately via the + kill signal (no opportunity to shut down). This is + a beta field and requires enabling ProbeTerminationGracePeriod + feature gate. Minimum value is 1. spec.terminationGracePeriodSeconds + is used if unset. + format: int64 + type: integer + timeoutSeconds: + description: 'Number of seconds after which the probe + times out. Defaults to 1 second. Minimum value is + 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + type: object + resources: + description: 'Compute Resources required by this container. + Cannot be updated. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + properties: + 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. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + securityContext: + description: 'SecurityContext defines the security options + the container should be run with. If set, the fields of + SecurityContext override the equivalent fields of PodSecurityContext. + More info: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/' + properties: + allowPrivilegeEscalation: + description: 'AllowPrivilegeEscalation controls whether + a process can gain more privileges than its parent + process. This bool directly controls if the no_new_privs + flag will be set on the container process. AllowPrivilegeEscalation + is true always when the container is: 1) run as Privileged + 2) has CAP_SYS_ADMIN Note that this field cannot be + set when spec.os.name is windows.' + type: boolean + capabilities: + description: The capabilities to add/drop when running + containers. Defaults to the default set of capabilities + granted by the container runtime. Note that this field + cannot be set when spec.os.name is windows. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + type: object + privileged: + description: Run container in privileged mode. Processes + in privileged containers are essentially equivalent + to root on the host. Defaults to false. Note that + this field cannot be set when spec.os.name is windows. + type: boolean + procMount: + description: procMount denotes the type of proc mount + to use for the containers. The default is DefaultProcMount + which uses the container runtime defaults for readonly + paths and masked paths. This requires the ProcMountType + feature flag to be enabled. Note that this field cannot + be set when spec.os.name is windows. + type: string + readOnlyRootFilesystem: + description: Whether this container has a read-only + root filesystem. Default is false. Note that this + field cannot be set when spec.os.name is windows. + type: boolean + runAsGroup: + description: The GID to run the entrypoint of the container + process. Uses runtime default if unset. May also be + set in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set + when spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as + a non-root user. If true, the Kubelet will validate + the image at runtime to ensure that it does not run + as UID 0 (root) and fail to start the container if + it does. If unset or false, no such validation will + be performed. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container + process. Defaults to user specified in image metadata + if unspecified. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name + is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to the + container. If unspecified, the container runtime will + allocate a random SELinux context for each container. May + also be set in PodSecurityContext. If set in both + SecurityContext and PodSecurityContext, the value + specified in SecurityContext takes precedence. Note + that this field cannot be set when spec.os.name is + windows. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by this container. + If seccomp options are provided at both the pod & + container level, the container options override the + pod options. Note that this field cannot be set when + spec.os.name is windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile + defined in a file on the node should be used. + The profile must be preconfigured on the node + to work. Must be a descending path, relative to + the kubelet's configured seccomp profile location. + Must only be set if type is "Localhost". + type: string + type: + description: "type indicates which kind of seccomp + profile will be applied. Valid options are: \n + Localhost - a profile defined in a file on the + node should be used. RuntimeDefault - the container + runtime default profile should be used. Unconfined + - no profile should be applied." + type: string + required: + - type + type: object + windowsOptions: + description: The Windows specific settings applied to + all containers. If unspecified, the options from the + PodSecurityContext will be used. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set + when spec.os.name is linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA + admission webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec + named by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name + of the GMSA credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container + should be run as a 'Host Process' container. This + field is alpha-level and will only be honored + by components that enable the WindowsHostProcessContainers + feature flag. Setting this field without the feature + flag will result in errors when validating the + Pod. All of a Pod's containers must have the same + effective HostProcess value (it is not allowed + to have a mix of HostProcess containers and non-HostProcess + containers). In addition, if HostProcess is true + then HostNetwork must also be set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the + entrypoint of the container process. Defaults + to the user specified in image metadata if unspecified. + May also be set in PodSecurityContext. If set + in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + type: string + type: object + type: object + startupProbe: + description: 'StartupProbe indicates that the Pod has successfully + initialized. If specified, no other probes are executed + until this completes successfully. If this probe fails, + the Pod will be restarted, just as if the livenessProbe + failed. This can be used to provide different probe parameters + at the beginning of a Pod''s lifecycle, when it might + take a long time to load data or warm a cache, than during + steady-state operation. This cannot be updated. More info: + https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to execute + inside the container, the working directory for + the command is root ('/') in the container's + filesystem. The command is simply exec'd, it is + not run inside a shell, so traditional shell instructions + ('|', etc) won't work. To use a shell, you need + to explicitly call out to that shell. Exit status + of 0 is treated as live/healthy and non-zero is + unhealthy. + items: + type: string + type: array + type: object + failureThreshold: + description: Minimum consecutive failures for the probe + to be considered failed after having succeeded. Defaults + to 3. Minimum value is 1. + format: int32 + type: integer + grpc: + description: GRPC specifies an action involving a GRPC + port. This is a beta field and requires enabling GRPCContainerProbe + feature gate. + properties: + port: + description: Port number of the gRPC service. Number + must be in the range 1 to 65535. + format: int32 + type: integer + service: + description: "Service is the name of the service + to place in the gRPC HealthCheckRequest (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + \n If this is not specified, the default behavior + is defined by gRPC." + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies the http request to perform. + properties: + host: + description: Host name to connect to, defaults to + the pod IP. You probably want to set "Host" in + httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the request. + HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom header + to be used in HTTP probes + properties: + name: + description: The header field name + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to the + host. Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: 'Number of seconds after the container + has started before liveness probes are initiated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + periodSeconds: + description: How often (in seconds) to perform the probe. + Default to 10 seconds. Minimum value is 1. + format: int32 + type: integer + successThreshold: + description: Minimum consecutive successes for the probe + to be considered successful after having failed. Defaults + to 1. Must be 1 for liveness and startup. Minimum + value is 1. + format: int32 + type: integer + tcpSocket: + description: TCPSocket specifies an action involving + a TCP port. + properties: + host: + description: 'Optional: Host name to connect to, + defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: Optional duration in seconds the pod needs + to terminate gracefully upon probe failure. The grace + period is the duration in seconds after the processes + running in the pod are sent a termination signal and + the time when the processes are forcibly halted with + a kill signal. Set this value longer than the expected + cleanup time for your process. If this value is nil, + the pod's terminationGracePeriodSeconds will be used. + Otherwise, this value overrides the value provided + by the pod spec. Value must be non-negative integer. + The value zero indicates stop immediately via the + kill signal (no opportunity to shut down). This is + a beta field and requires enabling ProbeTerminationGracePeriod + feature gate. Minimum value is 1. spec.terminationGracePeriodSeconds + is used if unset. + format: int64 + type: integer + timeoutSeconds: + description: 'Number of seconds after which the probe + times out. Defaults to 1 second. Minimum value is + 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + type: object + stdin: + description: Whether this container should allocate a buffer + for stdin in the container runtime. If this is not set, + reads from stdin in the container will always result in + EOF. Default is false. + type: boolean + stdinOnce: + description: Whether the container runtime should close + the stdin channel after it has been opened by a single + attach. When stdin is true the stdin stream will remain + open across multiple attach sessions. If stdinOnce is + set to true, stdin is opened on container start, is empty + until the first client attaches to stdin, and then remains + open and accepts data until the client disconnects, at + which time stdin is closed and remains closed until the + container is restarted. If this flag is false, a container + processes that reads from stdin will never receive an + EOF. Default is false + type: boolean + terminationMessagePath: + description: 'Optional: Path at which the file to which + the container''s termination message will be written is + mounted into the container''s filesystem. Message written + is intended to be brief final status, such as an assertion + failure message. Will be truncated by the node if greater + than 4096 bytes. The total message length across all containers + will be limited to 12kb. Defaults to /dev/termination-log. + Cannot be updated.' + type: string + terminationMessagePolicy: + description: Indicate how the termination message should + be populated. File will use the contents of terminationMessagePath + to populate the container status message on both success + and failure. FallbackToLogsOnError will use the last chunk + of container log output if the termination message file + is empty and the container exited with an error. The log + output is limited to 2048 bytes or 80 lines, whichever + is smaller. Defaults to File. Cannot be updated. + type: string + tty: + description: Whether this container should allocate a TTY + for itself, also requires 'stdin' to be true. Default + is false. + type: boolean + volumeDevices: + description: volumeDevices is the list of block devices + to be used by the container. + items: + description: volumeDevice describes a mapping of a raw + block device within a container. + properties: + devicePath: + description: devicePath is the path inside of the + container that the device will be mapped to. + type: string + name: + description: name must match the name of a persistentVolumeClaim + in the pod + type: string + required: + - devicePath + - name + type: object + type: array + volumeMounts: + description: Pod volumes to mount into the container's filesystem. + Cannot be updated. + items: + description: VolumeMount describes a mounting of a Volume + within a container. + properties: + mountPath: + description: Path within the container at which the + volume should be mounted. Must not contain ':'. + type: string + mountPropagation: + description: mountPropagation determines how mounts + are propagated from the host to container and the + other way around. When not set, MountPropagationNone + is used. This field is beta in 1.10. + type: string + name: + description: This must match the Name of a Volume. + type: string + readOnly: + description: Mounted read-only if true, read-write + otherwise (false or unspecified). Defaults to false. + type: boolean + subPath: + description: Path within the volume from which the + container's volume should be mounted. Defaults to + "" (volume's root). + type: string + subPathExpr: + description: Expanded path within the volume from + which the container's volume should be mounted. + Behaves similarly to SubPath but environment variable + references $(VAR_NAME) are expanded using the container's + environment. Defaults to "" (volume's root). SubPathExpr + and SubPath are mutually exclusive. + type: string + required: + - mountPath + - name + type: object + type: array + workingDir: + description: Container's working directory. If not specified, + the container runtime's default will be used, which might + be configured in the container image. Cannot be updated. + type: string + required: + - name + type: object + type: array + extraVolumeMounts: + items: + description: VolumeMount describes a mounting of a Volume within + a container. + properties: + mountPath: + description: Path within the container at which the volume + should be mounted. Must not contain ':'. + type: string + mountPropagation: + description: mountPropagation determines how mounts are + propagated from the host to container and the other way + around. When not set, MountPropagationNone is used. This + field is beta in 1.10. + type: string + name: + description: This must match the Name of a Volume. + type: string + readOnly: + description: Mounted read-only if true, read-write otherwise + (false or unspecified). Defaults to false. + type: boolean + subPath: + description: Path within the volume from which the container's + volume should be mounted. Defaults to "" (volume's root). + type: string + subPathExpr: + description: Expanded path within the volume from which + the container's volume should be mounted. Behaves similarly + to SubPath but environment variable references $(VAR_NAME) + are expanded using the container's environment. Defaults + to "" (volume's root). SubPathExpr and SubPath are mutually + exclusive. + type: string + required: + - mountPath + - name + type: object + type: array + extraVolumes: + items: + description: Volume represents a named volume in a pod that + may be accessed by any container in the pod. + properties: + awsElasticBlockStore: + description: 'awsElasticBlockStore represents an AWS Disk + resource that is attached to a kubelet''s host machine + and then exposed to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' + properties: + fsType: + description: 'fsType is the filesystem type of the volume + that you want to mount. Tip: Ensure that the filesystem + type is supported by the host operating system. Examples: + "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" + if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore + TODO: how do we prevent errors in the filesystem from + compromising the machine' + type: string + partition: + description: 'partition is the partition in the volume + that you want to mount. If omitted, the default is + to mount by volume name. Examples: For volume /dev/sda1, + you specify the partition as "1". Similarly, the volume + partition for /dev/sda is "0" (or you can leave the + property empty).' + format: int32 + type: integer + readOnly: + description: 'readOnly value true will force the readOnly + setting in VolumeMounts. More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' + type: boolean + volumeID: + description: 'volumeID is unique ID of the persistent + disk resource in AWS (Amazon EBS volume). More info: + https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' + type: string + required: + - volumeID + type: object + azureDisk: + description: azureDisk represents an Azure Data Disk mount + on the host and bind mount to the pod. + properties: + cachingMode: + description: 'cachingMode is the Host Caching mode: + None, Read Only, Read Write.' + type: string + diskName: + description: diskName is the Name of the data disk in + the blob storage + type: string + diskURI: + description: diskURI is the URI of data disk in the + blob storage + type: string + fsType: + description: fsType is Filesystem type to mount. Must + be a filesystem type supported by the host operating + system. Ex. "ext4", "xfs", "ntfs". Implicitly inferred + to be "ext4" if unspecified. + type: string + kind: + description: 'kind expected values are Shared: multiple + blob disks per storage account Dedicated: single + blob disk per storage account Managed: azure managed + data disk (only in managed availability set). defaults + to shared' + type: string + readOnly: + description: readOnly Defaults to false (read/write). + ReadOnly here will force the ReadOnly setting in VolumeMounts. + type: boolean + required: + - diskName + - diskURI + type: object + azureFile: + description: azureFile represents an Azure File Service + mount on the host and bind mount to the pod. + properties: + readOnly: + description: readOnly defaults to false (read/write). + ReadOnly here will force the ReadOnly setting in VolumeMounts. + type: boolean + secretName: + description: secretName is the name of secret that + contains Azure Storage Account Name and Key + type: string + shareName: + description: shareName is the azure share Name + type: string + required: + - secretName + - shareName + type: object + cephfs: + description: cephFS represents a Ceph FS mount on the host + that shares a pod's lifetime + properties: + monitors: + description: 'monitors is Required: Monitors is a collection + of Ceph monitors More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + items: + type: string + type: array + path: + description: 'path is Optional: Used as the mounted + root, rather than the full Ceph tree, default is /' + type: string + readOnly: + description: 'readOnly is Optional: Defaults to false + (read/write). ReadOnly here will force the ReadOnly + setting in VolumeMounts. More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + type: boolean + secretFile: + description: 'secretFile is Optional: SecretFile is + the path to key ring for User, default is /etc/ceph/user.secret + More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + type: string + secretRef: + description: 'secretRef is Optional: SecretRef is reference + to the authentication secret for User, default is + empty. More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + type: object + user: + description: 'user is optional: User is the rados user + name, default is admin More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + type: string + required: + - monitors + type: object + cinder: + description: 'cinder represents a cinder volume attached + and mounted on kubelets host machine. More info: https://examples.k8s.io/mysql-cinder-pd/README.md' + properties: + fsType: + description: 'fsType is the filesystem type to mount. + Must be a filesystem type supported by the host operating + system. Examples: "ext4", "xfs", "ntfs". Implicitly + inferred to be "ext4" if unspecified. More info: https://examples.k8s.io/mysql-cinder-pd/README.md' + type: string + readOnly: + description: 'readOnly defaults to false (read/write). + ReadOnly here will force the ReadOnly setting in VolumeMounts. + More info: https://examples.k8s.io/mysql-cinder-pd/README.md' + type: boolean + secretRef: + description: 'secretRef is optional: points to a secret + object containing parameters used to connect to OpenStack.' + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + type: object + volumeID: + description: 'volumeID used to identify the volume in + cinder. More info: https://examples.k8s.io/mysql-cinder-pd/README.md' + type: string + required: + - volumeID + type: object + configMap: + description: configMap represents a configMap that should + populate this volume + properties: + defaultMode: + description: 'defaultMode is optional: mode bits used + to set permissions on created files by default. Must + be an octal value between 0000 and 0777 or a decimal + value between 0 and 511. YAML accepts both octal and + decimal values, JSON requires decimal values for mode + bits. Defaults to 0644. Directories within the path + are not affected by this setting. This might be in + conflict with other options that affect the file mode, + like fsGroup, and the result can be other mode bits + set.' + format: int32 + type: integer + items: + description: items if unspecified, each key-value pair + in the Data field of the referenced ConfigMap will + be projected into the volume as a file whose name + is the key and content is the value. If specified, + the listed keys will be projected into the specified + paths, and unlisted keys will not be present. If a + key is specified which is not present in the ConfigMap, + the volume setup will error unless it is marked optional. + Paths must be relative and may not contain the '..' + path or start with '..'. + items: + description: Maps a string key to a path within a + volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: mode bits used + to set permissions on this file. Must be an + octal value between 0000 and 0777 or a decimal + value between 0 and 511. YAML accepts both octal + and decimal values, JSON requires decimal values + for mode bits. If not specified, the volume + defaultMode will be used. This might be in conflict + with other options that affect the file mode, + like fsGroup, and the result can be other mode + bits set.' + format: int32 + type: integer + path: + description: path is the relative path of the + file to map the key to. May not be an absolute + path. May not contain the path element '..'. + May not start with the string '..'. + type: string + required: + - key + - path + type: object + type: array + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + optional: + description: optional specify whether the ConfigMap + or its keys must be defined + type: boolean + type: object + csi: + description: csi (Container Storage Interface) represents + ephemeral storage that is handled by certain external + CSI drivers (Beta feature). + properties: + driver: + description: driver is the name of the CSI driver that + handles this volume. Consult with your admin for the + correct name as registered in the cluster. + type: string + fsType: + description: fsType to mount. Ex. "ext4", "xfs", "ntfs". + If not provided, the empty value is passed to the + associated CSI driver which will determine the default + filesystem to apply. + type: string + nodePublishSecretRef: + description: nodePublishSecretRef is a reference to + the secret object containing sensitive information + to pass to the CSI driver to complete the CSI NodePublishVolume + and NodeUnpublishVolume calls. This field is optional, + and may be empty if no secret is required. If the + secret object contains more than one secret, all secret + references are passed. + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + type: object + readOnly: + description: readOnly specifies a read-only configuration + for the volume. Defaults to false (read/write). + type: boolean + volumeAttributes: + additionalProperties: + type: string + description: volumeAttributes stores driver-specific + properties that are passed to the CSI driver. Consult + your driver's documentation for supported values. + type: object + required: + - driver + type: object + downwardAPI: + description: downwardAPI represents downward API about the + pod that should populate this volume + properties: + defaultMode: + description: 'Optional: mode bits to use on created + files by default. Must be a Optional: mode bits used + to set permissions on created files by default. Must + be an octal value between 0000 and 0777 or a decimal + value between 0 and 511. YAML accepts both octal and + decimal values, JSON requires decimal values for mode + bits. Defaults to 0644. Directories within the path + are not affected by this setting. This might be in + conflict with other options that affect the file mode, + like fsGroup, and the result can be other mode bits + set.' + format: int32 + type: integer + items: + description: Items is a list of downward API volume + file + items: + description: DownwardAPIVolumeFile represents information + to create the file containing the pod field + properties: + fieldRef: + description: 'Required: Selects a field of the + pod: only annotations, labels, name and namespace + are supported.' + 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 + mode: + description: 'Optional: mode bits used to set + permissions on this file, must be an octal value + between 0000 and 0777 or a decimal value between + 0 and 511. YAML accepts both octal and decimal + values, JSON requires decimal values for mode + bits. If not specified, the volume defaultMode + will be used. This might be in conflict with + other options that affect the file mode, like + fsGroup, and the result can be other mode bits + set.' + format: int32 + type: integer + path: + description: 'Required: Path is the relative + path name of the file to be created. Must not + be absolute or contain the ''..'' path. Must + be utf-8 encoded. The first item of the relative + path must not start with ''..''' + type: string + resourceFieldRef: + description: 'Selects a resource of the container: + only resources limits and requests (limits.cpu, + limits.memory, requests.cpu and requests.memory) + 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 + required: + - path + type: object + type: array + type: object + emptyDir: + description: 'emptyDir represents a temporary directory + that shares a pod''s lifetime. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' + properties: + medium: + description: 'medium represents what type of storage + medium should back this directory. The default is + "" which means to use the node''s default medium. + Must be an empty string (default) or Memory. More + info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' + type: string + sizeLimit: + anyOf: + - type: integer + - type: string + description: 'sizeLimit is the total amount of local + storage required for this EmptyDir volume. The size + limit is also applicable for memory medium. The maximum + usage on memory medium EmptyDir would be the minimum + value between the SizeLimit specified here and the + sum of memory limits of all containers in a pod. The + default is nil which means that the limit is undefined. + More info: http://kubernetes.io/docs/user-guide/volumes#emptydir' + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + ephemeral: + description: "ephemeral represents a volume that is handled + by a cluster storage driver. The volume's lifecycle is + tied to the pod that defines it - it will be created before + the pod starts, and deleted when the pod is removed. \n + Use this if: a) the volume is only needed while the pod + runs, b) features of normal volumes like restoring from + snapshot or capacity tracking are needed, c) the storage + driver is specified through a storage class, and d) the + storage driver supports dynamic volume provisioning through + \ a PersistentVolumeClaim (see EphemeralVolumeSource + for more information on the connection between this + volume type and PersistentVolumeClaim). \n Use PersistentVolumeClaim + or one of the vendor-specific APIs for volumes that persist + for longer than the lifecycle of an individual pod. \n + Use CSI for light-weight local ephemeral volumes if the + CSI driver is meant to be used that way - see the documentation + of the driver for more information. \n A pod can use both + types of ephemeral volumes and persistent volumes at the + same time." + properties: + volumeClaimTemplate: + description: "Will be used to create a stand-alone PVC + to provision the volume. The pod in which this EphemeralVolumeSource + is embedded will be the owner of the PVC, i.e. the + PVC will be deleted together with the pod. The name + of the PVC will be `-` where + `` is the name from the `PodSpec.Volumes` + array entry. Pod validation will reject the pod if + the concatenated name is not valid for a PVC (for + example, too long). \n An existing PVC with that name + that is not owned by the pod will *not* be used for + the pod to avoid using an unrelated volume by mistake. + Starting the pod is then blocked until the unrelated + PVC is removed. If such a pre-created PVC is meant + to be used by the pod, the PVC has to updated with + an owner reference to the pod once the pod exists. + Normally this should not be necessary, but it may + be useful when manually reconstructing a broken cluster. + \n This field is read-only and no changes will be + made by Kubernetes to the PVC after it has been created. + \n Required, must not be nil." + properties: + metadata: + description: May contain labels and annotations + that will be copied into the PVC when creating + it. No other fields are allowed and will be rejected + during validation. + type: object + spec: + description: The specification for the PersistentVolumeClaim. + The entire content is copied unchanged into the + PVC that gets created from this template. The + same fields as in a PersistentVolumeClaim are + also valid here. + properties: + accessModes: + description: 'accessModes contains the desired + access modes the volume should have. More + info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' + items: + type: string + type: array + dataSource: + description: 'dataSource field can be used to + specify either: * An existing VolumeSnapshot + object (snapshot.storage.k8s.io/VolumeSnapshot) + * An existing PVC (PersistentVolumeClaim) + If the provisioner or an external controller + can support the specified data source, it + will create a new volume based on the contents + of the specified data source. If the AnyVolumeDataSource + feature gate is enabled, this field will always + have the same contents as the DataSourceRef + field.' + properties: + apiGroup: + description: APIGroup is the group for the + resource being referenced. If APIGroup + is not specified, the specified Kind must + be in the core API group. For any other + third-party types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource + being referenced + type: string + name: + description: Name is the name of resource + being referenced + type: string + required: + - kind + - name + type: object + dataSourceRef: + description: 'dataSourceRef specifies the object + from which to populate the volume with data, + if a non-empty volume is desired. This may + be any local object from a non-empty API group + (non core object) or a PersistentVolumeClaim + object. When this field is specified, volume + binding will only succeed if the type of the + specified object matches some installed volume + populator or dynamic provisioner. This field + will replace the functionality of the DataSource + field and as such if both fields are non-empty, + they must have the same value. For backwards + compatibility, both fields (DataSource and + DataSourceRef) will be set to the same value + automatically if one of them is empty and + the other is non-empty. There are two important + differences between DataSource and DataSourceRef: + * While DataSource only allows two specific + types of objects, DataSourceRef allows any + non-core object, as well as PersistentVolumeClaim + objects. * While DataSource ignores disallowed + values (dropping them), DataSourceRef preserves + all values, and generates an error if a disallowed + value is specified. (Beta) Using this field + requires the AnyVolumeDataSource feature gate + to be enabled.' + properties: + apiGroup: + description: APIGroup is the group for the + resource being referenced. If APIGroup + is not specified, the specified Kind must + be in the core API group. For any other + third-party types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource + being referenced + type: string + name: + description: Name is the name of resource + being referenced + type: string + required: + - kind + - name + type: object + resources: + description: 'resources represents the minimum + resources the volume should have. If RecoverVolumeExpansionFailure + feature is enabled users are allowed to specify + resource requirements that are lower than + previous value but must still be higher than + capacity recorded in the status field of the + claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' + properties: + 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. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + selector: + description: selector is a label query over + volumes to consider for binding. + 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 + required: + - key + - operator + type: object + type: array + 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 + storageClassName: + description: 'storageClassName is the name of + the StorageClass required by the claim. More + info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' + type: string + volumeMode: + description: volumeMode defines what type of + volume is required by the claim. Value of + Filesystem is implied when not included in + claim spec. + type: string + volumeName: + description: volumeName is the binding reference + to the PersistentVolume backing this claim. + type: string + type: object + required: + - spec + type: object + type: object + fc: + description: fc represents a Fibre Channel resource that + is attached to a kubelet's host machine and then exposed + to the pod. + properties: + fsType: + description: 'fsType is the filesystem type to mount. + Must be a filesystem type supported by the host operating + system. Ex. "ext4", "xfs", "ntfs". Implicitly inferred + to be "ext4" if unspecified. TODO: how do we prevent + errors in the filesystem from compromising the machine' + type: string + lun: + description: 'lun is Optional: FC target lun number' + format: int32 + type: integer + readOnly: + description: 'readOnly is Optional: Defaults to false + (read/write). ReadOnly here will force the ReadOnly + setting in VolumeMounts.' + type: boolean + targetWWNs: + description: 'targetWWNs is Optional: FC target worldwide + names (WWNs)' + items: + type: string + type: array + wwids: + description: 'wwids Optional: FC volume world wide identifiers + (wwids) Either wwids or combination of targetWWNs + and lun must be set, but not both simultaneously.' + items: + type: string + type: array + type: object + flexVolume: + description: flexVolume represents a generic volume resource + that is provisioned/attached using an exec based plugin. + properties: + driver: + description: driver is the name of the driver to use + for this volume. + type: string + fsType: + description: fsType is the filesystem type to mount. + Must be a filesystem type supported by the host operating + system. Ex. "ext4", "xfs", "ntfs". The default filesystem + depends on FlexVolume script. + type: string + options: + additionalProperties: + type: string + description: 'options is Optional: this field holds + extra command options if any.' + type: object + readOnly: + description: 'readOnly is Optional: defaults to false + (read/write). ReadOnly here will force the ReadOnly + setting in VolumeMounts.' + type: boolean + secretRef: + description: 'secretRef is Optional: secretRef is reference + to the secret object containing sensitive information + to pass to the plugin scripts. This may be empty if + no secret object is specified. If the secret object + contains more than one secret, all secrets are passed + to the plugin scripts.' + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + type: object + required: + - driver + type: object + flocker: + description: flocker represents a Flocker volume attached + to a kubelet's host machine. This depends on the Flocker + control service being running + properties: + datasetName: + description: datasetName is Name of the dataset stored + as metadata -> name on the dataset for Flocker should + be considered as deprecated + type: string + datasetUUID: + description: datasetUUID is the UUID of the dataset. + This is unique identifier of a Flocker dataset + type: string + type: object + gcePersistentDisk: + description: 'gcePersistentDisk represents a GCE Disk resource + that is attached to a kubelet''s host machine and then + exposed to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' + properties: + fsType: + description: 'fsType is filesystem type of the volume + that you want to mount. Tip: Ensure that the filesystem + type is supported by the host operating system. Examples: + "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" + if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk + TODO: how do we prevent errors in the filesystem from + compromising the machine' + type: string + partition: + description: 'partition is the partition in the volume + that you want to mount. If omitted, the default is + to mount by volume name. Examples: For volume /dev/sda1, + you specify the partition as "1". Similarly, the volume + partition for /dev/sda is "0" (or you can leave the + property empty). More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' + format: int32 + type: integer + pdName: + description: 'pdName is unique name of the PD resource + in GCE. Used to identify the disk in GCE. More info: + https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' + type: string + readOnly: + description: 'readOnly here will force the ReadOnly + setting in VolumeMounts. Defaults to false. More info: + https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' + type: boolean + required: + - pdName + type: object + gitRepo: + description: 'gitRepo represents a git repository at a particular + revision. DEPRECATED: GitRepo is deprecated. To provision + a container with a git repo, mount an EmptyDir into an + InitContainer that clones the repo using git, then mount + the EmptyDir into the Pod''s container.' + properties: + directory: + description: directory is the target directory name. + Must not contain or start with '..'. If '.' is supplied, + the volume directory will be the git repository. Otherwise, + if specified, the volume will contain the git repository + in the subdirectory with the given name. + type: string + repository: + description: repository is the URL + type: string + revision: + description: revision is the commit hash for the specified + revision. + type: string + required: + - repository + type: object + glusterfs: + description: 'glusterfs represents a Glusterfs mount on + the host that shares a pod''s lifetime. More info: https://examples.k8s.io/volumes/glusterfs/README.md' + properties: + endpoints: + description: 'endpoints is the endpoint name that details + Glusterfs topology. More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' + type: string + path: + description: 'path is the Glusterfs volume path. More + info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' + type: string + readOnly: + description: 'readOnly here will force the Glusterfs + volume to be mounted with read-only permissions. Defaults + to false. More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' + type: boolean + required: + - endpoints + - path + type: object + hostPath: + description: 'hostPath represents a pre-existing file or + directory on the host machine that is directly exposed + to the container. This is generally used for system agents + or other privileged things that are allowed to see the + host machine. Most containers will NOT need this. More + info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath + --- TODO(jonesdl) We need to restrict who can use host + directory mounts and who can/can not mount host directories + as read/write.' + properties: + path: + description: 'path of the directory on the host. If + the path is a symlink, it will follow the link to + the real path. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath' + type: string + type: + description: 'type for HostPath Volume Defaults to "" + More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath' + type: string + required: + - path + type: object + iscsi: + description: 'iscsi represents an ISCSI Disk resource that + is attached to a kubelet''s host machine and then exposed + to the pod. More info: https://examples.k8s.io/volumes/iscsi/README.md' + properties: + chapAuthDiscovery: + description: chapAuthDiscovery defines whether support + iSCSI Discovery CHAP authentication + type: boolean + chapAuthSession: + description: chapAuthSession defines whether support + iSCSI Session CHAP authentication + type: boolean + fsType: + description: 'fsType is the filesystem type of the volume + that you want to mount. Tip: Ensure that the filesystem + type is supported by the host operating system. Examples: + "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" + if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#iscsi + TODO: how do we prevent errors in the filesystem from + compromising the machine' + type: string + initiatorName: + description: initiatorName is the custom iSCSI Initiator + Name. If initiatorName is specified with iscsiInterface + simultaneously, new iSCSI interface : will be created for the connection. + type: string + iqn: + description: iqn is the target iSCSI Qualified Name. + type: string + iscsiInterface: + description: iscsiInterface is the interface Name that + uses an iSCSI transport. Defaults to 'default' (tcp). + type: string + lun: + description: lun represents iSCSI Target Lun number. + format: int32 + type: integer + portals: + description: portals is the iSCSI Target Portal List. + The portal is either an IP or ip_addr:port if the + port is other than default (typically TCP ports 860 + and 3260). + items: + type: string + type: array + readOnly: + description: readOnly here will force the ReadOnly setting + in VolumeMounts. Defaults to false. + type: boolean + secretRef: + description: secretRef is the CHAP Secret for iSCSI + target and initiator authentication + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + type: object + targetPortal: + description: targetPortal is iSCSI Target Portal. The + Portal is either an IP or ip_addr:port if the port + is other than default (typically TCP ports 860 and + 3260). + type: string + required: + - iqn + - lun + - targetPortal + type: object + name: + description: 'name of the volume. Must be a DNS_LABEL and + unique within the pod. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + nfs: + description: 'nfs represents an NFS mount on the host that + shares a pod''s lifetime More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' + properties: + path: + description: 'path that is exported by the NFS server. + More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' + type: string + readOnly: + description: 'readOnly here will force the NFS export + to be mounted with read-only permissions. Defaults + to false. More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' + type: boolean + server: + description: 'server is the hostname or IP address of + the NFS server. More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' + type: string + required: + - path + - server + type: object + persistentVolumeClaim: + description: 'persistentVolumeClaimVolumeSource represents + a reference to a PersistentVolumeClaim in the same namespace. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' + properties: + claimName: + description: 'claimName is the name of a PersistentVolumeClaim + in the same namespace as the pod using this volume. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' + type: string + readOnly: + description: readOnly Will force the ReadOnly setting + in VolumeMounts. Default false. + type: boolean + required: + - claimName + type: object + photonPersistentDisk: + description: photonPersistentDisk represents a PhotonController + persistent disk attached and mounted on kubelets host + machine + properties: + fsType: + description: fsType is the filesystem type to mount. + Must be a filesystem type supported by the host operating + system. Ex. "ext4", "xfs", "ntfs". Implicitly inferred + to be "ext4" if unspecified. + type: string + pdID: + description: pdID is the ID that identifies Photon Controller + persistent disk + type: string + required: + - pdID + type: object + portworxVolume: + description: portworxVolume represents a portworx volume + attached and mounted on kubelets host machine + properties: + fsType: + description: fSType represents the filesystem type to + mount Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs". Implicitly inferred + to be "ext4" if unspecified. + type: string + readOnly: + description: readOnly defaults to false (read/write). + ReadOnly here will force the ReadOnly setting in VolumeMounts. + type: boolean + volumeID: + description: volumeID uniquely identifies a Portworx + volume + type: string + required: + - volumeID + type: object + projected: + description: projected items for all in one resources secrets, + configmaps, and downward API + properties: + defaultMode: + description: defaultMode are the mode bits used to set + permissions on created files by default. Must be an + octal value between 0000 and 0777 or a decimal value + between 0 and 511. YAML accepts both octal and decimal + values, JSON requires decimal values for mode bits. + Directories within the path are not affected by this + setting. This might be in conflict with other options + that affect the file mode, like fsGroup, and the result + can be other mode bits set. + format: int32 + type: integer + sources: + description: sources is the list of volume projections + items: + description: Projection that may be projected along + with other supported volume types + properties: + configMap: + description: configMap information about the configMap + data to project + properties: + items: + description: items if unspecified, each key-value + pair in the Data field of the referenced + ConfigMap will be projected into the volume + as a file whose name is the key and content + is the value. If specified, the listed keys + will be projected into the specified paths, + and unlisted keys will not be present. If + a key is specified which is not present + in the ConfigMap, the volume setup will + error unless it is marked optional. Paths + must be relative and may not contain the + '..' path or start with '..'. + items: + description: Maps a string key to a path + within a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: mode + bits used to set permissions on this + file. Must be an octal value between + 0000 and 0777 or a decimal value between + 0 and 511. YAML accepts both octal + and decimal values, JSON requires + decimal values for mode bits. If not + specified, the volume defaultMode + will be used. This might be in conflict + with other options that affect the + file mode, like fsGroup, and the result + can be other mode bits set.' + format: int32 + type: integer + path: + description: path is the relative path + of the file to map the key to. May + not be an absolute path. May not contain + the path element '..'. May not start + with the string '..'. + type: string + required: + - key + - path + type: object + type: array + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + optional: + description: optional specify whether the + ConfigMap or its keys must be defined + type: boolean + type: object + downwardAPI: + description: downwardAPI information about the + downwardAPI data to project + properties: + items: + description: Items is a list of DownwardAPIVolume + file + items: + description: DownwardAPIVolumeFile represents + information to create the file containing + the pod field + properties: + fieldRef: + description: 'Required: Selects a field + of the pod: only annotations, labels, + name and namespace are supported.' + 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 + mode: + description: 'Optional: mode bits used + to set permissions on this file, must + be an octal value between 0000 and + 0777 or a decimal value between 0 + and 511. YAML accepts both octal and + decimal values, JSON requires decimal + values for mode bits. If not specified, + the volume defaultMode will be used. + This might be in conflict with other + options that affect the file mode, + like fsGroup, and the result can be + other mode bits set.' + format: int32 + type: integer + path: + description: 'Required: Path is the + relative path name of the file to + be created. Must not be absolute or + contain the ''..'' path. Must be utf-8 + encoded. The first item of the relative + path must not start with ''..''' + type: string + resourceFieldRef: + description: 'Selects a resource of + the container: only resources limits + and requests (limits.cpu, limits.memory, + requests.cpu and requests.memory) + 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 + required: + - path + type: object + type: array + type: object + secret: + description: secret information about the secret + data to project + properties: + items: + description: items if unspecified, each key-value + pair in the Data field of the referenced + Secret will be projected into the volume + as a file whose name is the key and content + is the value. If specified, the listed keys + will be projected into the specified paths, + and unlisted keys will not be present. If + a key is specified which is not present + in the Secret, the volume setup will error + unless it is marked optional. Paths must + be relative and may not contain the '..' + path or start with '..'. + items: + description: Maps a string key to a path + within a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: mode + bits used to set permissions on this + file. Must be an octal value between + 0000 and 0777 or a decimal value between + 0 and 511. YAML accepts both octal + and decimal values, JSON requires + decimal values for mode bits. If not + specified, the volume defaultMode + will be used. This might be in conflict + with other options that affect the + file mode, like fsGroup, and the result + can be other mode bits set.' + format: int32 + type: integer + path: + description: path is the relative path + of the file to map the key to. May + not be an absolute path. May not contain + the path element '..'. May not start + with the string '..'. + type: string + required: + - key + - path + type: object + type: array + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + optional: + description: optional field specify whether + the Secret or its key must be defined + type: boolean + type: object + serviceAccountToken: + description: serviceAccountToken is information + about the serviceAccountToken data to project + properties: + audience: + description: audience is the intended audience + of the token. A recipient of a token must + identify itself with an identifier specified + in the audience of the token, and otherwise + should reject the token. The audience defaults + to the identifier of the apiserver. + type: string + expirationSeconds: + description: expirationSeconds is the requested + duration of validity of the service account + token. As the token approaches expiration, + the kubelet volume plugin will proactively + rotate the service account token. The kubelet + will start trying to rotate the token if + the token is older than 80 percent of its + time to live or if the token is older than + 24 hours.Defaults to 1 hour and must be + at least 10 minutes. + format: int64 + type: integer + path: + description: path is the path relative to + the mount point of the file to project the + token into. + type: string + required: + - path + type: object + type: object + type: array + type: object + quobyte: + description: quobyte represents a Quobyte mount on the host + that shares a pod's lifetime + properties: + group: + description: group to map volume access to Default is + no group + type: string + readOnly: + description: readOnly here will force the Quobyte volume + to be mounted with read-only permissions. Defaults + to false. + type: boolean + registry: + description: registry represents a single or multiple + Quobyte Registry services specified as a string as + host:port pair (multiple entries are separated with + commas) which acts as the central registry for volumes + type: string + tenant: + description: tenant owning the given Quobyte volume + in the Backend Used with dynamically provisioned Quobyte + volumes, value is set by the plugin + type: string + user: + description: user to map volume access to Defaults to + serivceaccount user + type: string + volume: + description: volume is a string that references an already + created Quobyte volume by name. + type: string + required: + - registry + - volume + type: object + rbd: + description: 'rbd represents a Rados Block Device mount + on the host that shares a pod''s lifetime. More info: + https://examples.k8s.io/volumes/rbd/README.md' + properties: + fsType: + description: 'fsType is the filesystem type of the volume + that you want to mount. Tip: Ensure that the filesystem + type is supported by the host operating system. Examples: + "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" + if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#rbd + TODO: how do we prevent errors in the filesystem from + compromising the machine' + type: string + image: + description: 'image is the rados image name. More info: + https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: string + keyring: + description: 'keyring is the path to key ring for RBDUser. + Default is /etc/ceph/keyring. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: string + monitors: + description: 'monitors is a collection of Ceph monitors. + More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + items: + type: string + type: array + pool: + description: 'pool is the rados pool name. Default is + rbd. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: string + readOnly: + description: 'readOnly here will force the ReadOnly + setting in VolumeMounts. Defaults to false. More info: + https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: boolean + secretRef: + description: 'secretRef is name of the authentication + secret for RBDUser. If provided overrides keyring. + Default is nil. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + type: object + user: + description: 'user is the rados user name. Default is + admin. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: string + required: + - image + - monitors + type: object + scaleIO: + description: scaleIO represents a ScaleIO persistent volume + attached and mounted on Kubernetes nodes. + properties: + fsType: + description: fsType is the filesystem type to mount. + Must be a filesystem type supported by the host operating + system. Ex. "ext4", "xfs", "ntfs". Default is "xfs". + type: string + gateway: + description: gateway is the host address of the ScaleIO + API Gateway. + type: string + protectionDomain: + description: protectionDomain is the name of the ScaleIO + Protection Domain for the configured storage. + type: string + readOnly: + description: readOnly Defaults to false (read/write). + ReadOnly here will force the ReadOnly setting in VolumeMounts. + type: boolean + secretRef: + description: secretRef references to the secret for + ScaleIO user and other sensitive information. If this + is not provided, Login operation will fail. + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + type: object + sslEnabled: + description: sslEnabled Flag enable/disable SSL communication + with Gateway, default false + type: boolean + storageMode: + description: storageMode indicates whether the storage + for a volume should be ThickProvisioned or ThinProvisioned. + Default is ThinProvisioned. + type: string + storagePool: + description: storagePool is the ScaleIO Storage Pool + associated with the protection domain. + type: string + system: + description: system is the name of the storage system + as configured in ScaleIO. + type: string + volumeName: + description: volumeName is the name of a volume already + created in the ScaleIO system that is associated with + this volume source. + type: string + required: + - gateway + - secretRef + - system + type: object + secret: + description: 'secret represents a secret that should populate + this volume. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' + properties: + defaultMode: + description: 'defaultMode is Optional: mode bits used + to set permissions on created files by default. Must + be an octal value between 0000 and 0777 or a decimal + value between 0 and 511. YAML accepts both octal and + decimal values, JSON requires decimal values for mode + bits. Defaults to 0644. Directories within the path + are not affected by this setting. This might be in + conflict with other options that affect the file mode, + like fsGroup, and the result can be other mode bits + set.' + format: int32 + type: integer + items: + description: items If unspecified, each key-value pair + in the Data field of the referenced Secret will be + projected into the volume as a file whose name is + the key and content is the value. If specified, the + listed keys will be projected into the specified paths, + and unlisted keys will not be present. If a key is + specified which is not present in the Secret, the + volume setup will error unless it is marked optional. + Paths must be relative and may not contain the '..' + path or start with '..'. + items: + description: Maps a string key to a path within a + volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: mode bits used + to set permissions on this file. Must be an + octal value between 0000 and 0777 or a decimal + value between 0 and 511. YAML accepts both octal + and decimal values, JSON requires decimal values + for mode bits. If not specified, the volume + defaultMode will be used. This might be in conflict + with other options that affect the file mode, + like fsGroup, and the result can be other mode + bits set.' + format: int32 + type: integer + path: + description: path is the relative path of the + file to map the key to. May not be an absolute + path. May not contain the path element '..'. + May not start with the string '..'. + type: string + required: + - key + - path + type: object + type: array + optional: + description: optional field specify whether the Secret + or its keys must be defined + type: boolean + secretName: + description: 'secretName is the name of the secret in + the pod''s namespace to use. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' + type: string + type: object + storageos: + description: storageOS represents a StorageOS volume attached + and mounted on Kubernetes nodes. + properties: + fsType: + description: fsType is the filesystem type to mount. + Must be a filesystem type supported by the host operating + system. Ex. "ext4", "xfs", "ntfs". Implicitly inferred + to be "ext4" if unspecified. + type: string + readOnly: + description: readOnly defaults to false (read/write). + ReadOnly here will force the ReadOnly setting in VolumeMounts. + type: boolean + secretRef: + description: secretRef specifies the secret to use for + obtaining the StorageOS API credentials. If not specified, + default values will be attempted. + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + type: object + volumeName: + description: volumeName is the human-readable name of + the StorageOS volume. Volume names are only unique + within a namespace. + type: string + volumeNamespace: + description: volumeNamespace specifies the scope of + the volume within StorageOS. If no namespace is specified + then the Pod's namespace will be used. This allows + the Kubernetes name scoping to be mirrored within + StorageOS for tighter integration. Set VolumeName + to any name to override the default behaviour. Set + to "default" if you are not using namespaces within + StorageOS. Namespaces that do not pre-exist within + StorageOS will be created. + type: string + type: object + vsphereVolume: + description: vsphereVolume represents a vSphere volume attached + and mounted on kubelets host machine + properties: + fsType: + description: fsType is filesystem type to mount. Must + be a filesystem type supported by the host operating + system. Ex. "ext4", "xfs", "ntfs". Implicitly inferred + to be "ext4" if unspecified. + type: string + storagePolicyID: + description: storagePolicyID is the storage Policy Based + Management (SPBM) profile ID associated with the StoragePolicyName. + type: string + storagePolicyName: + description: storagePolicyName is the storage Policy + Based Management (SPBM) profile name. + type: string + volumePath: + description: volumePath is the path that identifies + vSphere volume vmdk + type: string + required: + - volumePath + type: object + required: + - name + type: object + type: array + hostNetwork: + type: boolean + image: + type: string + imagePullPolicy: + description: PullPolicy describes a policy for if/when to pull + a container image + type: string + imagePullSecrets: + items: + description: LocalObjectReference contains enough information + to let you locate the referenced object inside the same namespace. + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + type: array + initContainers: + items: + description: A single application container that you want to + run within a pod. + properties: + args: + description: 'Arguments to the entrypoint. The container + image''s CMD is used if this is not provided. Variable + references $(VAR_NAME) are expanded using the container''s + environment. 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. Cannot + be updated. More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell' + items: + type: string + type: array + command: + description: 'Entrypoint array. Not executed within a shell. + The container image''s ENTRYPOINT is used if this is not + provided. Variable references $(VAR_NAME) are expanded + using the container''s environment. 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. Cannot be updated. More info: + https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell' + items: + type: string + type: array + env: + description: List of environment variables to set in the + container. Cannot be updated. + 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: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + optional: + description: Specify whether the ConfigMap + or its key must be defined + type: boolean + required: + - key + type: object + 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 + 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 + 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: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + optional: + description: Specify whether the Secret or + its key must be defined + type: boolean + required: + - key + type: object + type: object + required: + - name + type: object + type: array + envFrom: + description: List of sources to populate environment variables + in the container. The keys defined within a source must + be a C_IDENTIFIER. All invalid keys will be reported as + an event when the container is starting. 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. Cannot be updated. + items: + description: EnvFromSource represents the source of a + set of ConfigMaps + properties: + configMapRef: + description: The ConfigMap to select from + properties: + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the ConfigMap must + be defined + type: boolean + type: object + prefix: + description: An optional identifier to prepend to + each key in the ConfigMap. Must be a C_IDENTIFIER. + type: string + secretRef: + description: The Secret to select from + properties: + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the Secret must be + defined + type: boolean + type: object + type: object + type: array + image: + description: 'Container image name. More info: https://kubernetes.io/docs/concepts/containers/images + This field is optional to allow higher level config management + to default or override container images in workload controllers + like Deployments and StatefulSets.' + type: string + imagePullPolicy: + description: 'Image pull policy. One of Always, Never, IfNotPresent. + Defaults to Always if :latest tag is specified, or IfNotPresent + otherwise. Cannot be updated. More info: https://kubernetes.io/docs/concepts/containers/images#updating-images' + type: string + lifecycle: + description: Actions that the management system should take + in response to container lifecycle events. Cannot be updated. + properties: + postStart: + description: 'PostStart is called immediately after + a container is created. If the handler fails, the + container is terminated and restarted according to + its restart policy. Other management of the container + blocks until the hook completes. More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks' + properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to + execute inside the container, the working + directory for the command is root ('/') in + the container's filesystem. The command is + simply exec'd, it is not run inside a shell, + so traditional shell instructions ('|', etc) + won't work. To use a shell, you need to explicitly + call out to that shell. Exit status of 0 is + treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + type: object + httpGet: + description: HTTPGet specifies the http request + to perform. + properties: + host: + description: Host name to connect to, defaults + to the pod IP. You probably want to set "Host" + in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the request. + HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom + header to be used in HTTP probes + properties: + name: + description: The header field name + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to + the host. Defaults to HTTP. + type: string + required: + - port + type: object + tcpSocket: + description: Deprecated. TCPSocket is NOT supported + as a LifecycleHandler and kept for the backward + compatibility. There are no validation of this + field and lifecycle hooks will fail in runtime + when tcp handler is specified. + properties: + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + preStop: + description: 'PreStop is called immediately before a + container is terminated due to an API request or management + event such as liveness/startup probe failure, preemption, + resource contention, etc. The handler is not called + if the container crashes or exits. The Pod''s termination + grace period countdown begins before the PreStop hook + is executed. Regardless of the outcome of the handler, + the container will eventually terminate within the + Pod''s termination grace period (unless delayed by + finalizers). Other management of the container blocks + until the hook completes or until the termination + grace period is reached. More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks' + properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to + execute inside the container, the working + directory for the command is root ('/') in + the container's filesystem. The command is + simply exec'd, it is not run inside a shell, + so traditional shell instructions ('|', etc) + won't work. To use a shell, you need to explicitly + call out to that shell. Exit status of 0 is + treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + type: object + httpGet: + description: HTTPGet specifies the http request + to perform. + properties: + host: + description: Host name to connect to, defaults + to the pod IP. You probably want to set "Host" + in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the request. + HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom + header to be used in HTTP probes + properties: + name: + description: The header field name + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to + the host. Defaults to HTTP. + type: string + required: + - port + type: object + tcpSocket: + description: Deprecated. TCPSocket is NOT supported + as a LifecycleHandler and kept for the backward + compatibility. There are no validation of this + field and lifecycle hooks will fail in runtime + when tcp handler is specified. + properties: + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + type: object + livenessProbe: + description: 'Periodic probe of container liveness. Container + will be restarted if the probe fails. Cannot be updated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to execute + inside the container, the working directory for + the command is root ('/') in the container's + filesystem. The command is simply exec'd, it is + not run inside a shell, so traditional shell instructions + ('|', etc) won't work. To use a shell, you need + to explicitly call out to that shell. Exit status + of 0 is treated as live/healthy and non-zero is + unhealthy. + items: + type: string + type: array + type: object + failureThreshold: + description: Minimum consecutive failures for the probe + to be considered failed after having succeeded. Defaults + to 3. Minimum value is 1. + format: int32 + type: integer + grpc: + description: GRPC specifies an action involving a GRPC + port. This is a beta field and requires enabling GRPCContainerProbe + feature gate. + properties: + port: + description: Port number of the gRPC service. Number + must be in the range 1 to 65535. + format: int32 + type: integer + service: + description: "Service is the name of the service + to place in the gRPC HealthCheckRequest (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + \n If this is not specified, the default behavior + is defined by gRPC." + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies the http request to perform. + properties: + host: + description: Host name to connect to, defaults to + the pod IP. You probably want to set "Host" in + httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the request. + HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom header + to be used in HTTP probes + properties: + name: + description: The header field name + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to the + host. Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: 'Number of seconds after the container + has started before liveness probes are initiated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + periodSeconds: + description: How often (in seconds) to perform the probe. + Default to 10 seconds. Minimum value is 1. + format: int32 + type: integer + successThreshold: + description: Minimum consecutive successes for the probe + to be considered successful after having failed. Defaults + to 1. Must be 1 for liveness and startup. Minimum + value is 1. + format: int32 + type: integer + tcpSocket: + description: TCPSocket specifies an action involving + a TCP port. + properties: + host: + description: 'Optional: Host name to connect to, + defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: Optional duration in seconds the pod needs + to terminate gracefully upon probe failure. The grace + period is the duration in seconds after the processes + running in the pod are sent a termination signal and + the time when the processes are forcibly halted with + a kill signal. Set this value longer than the expected + cleanup time for your process. If this value is nil, + the pod's terminationGracePeriodSeconds will be used. + Otherwise, this value overrides the value provided + by the pod spec. Value must be non-negative integer. + The value zero indicates stop immediately via the + kill signal (no opportunity to shut down). This is + a beta field and requires enabling ProbeTerminationGracePeriod + feature gate. Minimum value is 1. spec.terminationGracePeriodSeconds + is used if unset. + format: int64 + type: integer + timeoutSeconds: + description: 'Number of seconds after which the probe + times out. Defaults to 1 second. Minimum value is + 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + type: object + name: + description: Name of the container specified as a DNS_LABEL. + Each container in a pod must have a unique name (DNS_LABEL). + Cannot be updated. + type: string + ports: + description: List of ports to expose from the container. + Exposing a port here gives the system additional information + about the network connections a container uses, but is + primarily informational. Not specifying a port here DOES + NOT prevent that port from being exposed. Any port which + is listening on the default "0.0.0.0" address inside a + container will be accessible from the network. Cannot + be updated. + items: + description: ContainerPort represents a network port in + a single container. + properties: + containerPort: + description: Number of port to expose on the pod's + IP address. This must be a valid port number, 0 + < x < 65536. + format: int32 + type: integer + hostIP: + description: What host IP to bind the external port + to. + type: string + hostPort: + description: Number of port to expose on the host. + If specified, this must be a valid port number, + 0 < x < 65536. If HostNetwork is specified, this + must match ContainerPort. Most containers do not + need this. + format: int32 + type: integer + name: + description: If specified, this must be an IANA_SVC_NAME + and unique within the pod. Each named port in a + pod must have a unique name. Name for the port that + can be referred to by services. + type: string + protocol: + default: TCP + description: Protocol for port. Must be UDP, TCP, + or SCTP. Defaults to "TCP". + type: string + required: + - containerPort + type: object + type: array + x-kubernetes-list-map-keys: + - containerPort + - protocol + x-kubernetes-list-type: map + readinessProbe: + description: 'Periodic probe of container service readiness. + Container will be removed from service endpoints if the + probe fails. Cannot be updated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to execute + inside the container, the working directory for + the command is root ('/') in the container's + filesystem. The command is simply exec'd, it is + not run inside a shell, so traditional shell instructions + ('|', etc) won't work. To use a shell, you need + to explicitly call out to that shell. Exit status + of 0 is treated as live/healthy and non-zero is + unhealthy. + items: + type: string + type: array + type: object + failureThreshold: + description: Minimum consecutive failures for the probe + to be considered failed after having succeeded. Defaults + to 3. Minimum value is 1. + format: int32 + type: integer + grpc: + description: GRPC specifies an action involving a GRPC + port. This is a beta field and requires enabling GRPCContainerProbe + feature gate. + properties: + port: + description: Port number of the gRPC service. Number + must be in the range 1 to 65535. + format: int32 + type: integer + service: + description: "Service is the name of the service + to place in the gRPC HealthCheckRequest (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + \n If this is not specified, the default behavior + is defined by gRPC." + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies the http request to perform. + properties: + host: + description: Host name to connect to, defaults to + the pod IP. You probably want to set "Host" in + httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the request. + HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom header + to be used in HTTP probes + properties: + name: + description: The header field name + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to the + host. Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: 'Number of seconds after the container + has started before liveness probes are initiated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + periodSeconds: + description: How often (in seconds) to perform the probe. + Default to 10 seconds. Minimum value is 1. + format: int32 + type: integer + successThreshold: + description: Minimum consecutive successes for the probe + to be considered successful after having failed. Defaults + to 1. Must be 1 for liveness and startup. Minimum + value is 1. + format: int32 + type: integer + tcpSocket: + description: TCPSocket specifies an action involving + a TCP port. + properties: + host: + description: 'Optional: Host name to connect to, + defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: Optional duration in seconds the pod needs + to terminate gracefully upon probe failure. The grace + period is the duration in seconds after the processes + running in the pod are sent a termination signal and + the time when the processes are forcibly halted with + a kill signal. Set this value longer than the expected + cleanup time for your process. If this value is nil, + the pod's terminationGracePeriodSeconds will be used. + Otherwise, this value overrides the value provided + by the pod spec. Value must be non-negative integer. + The value zero indicates stop immediately via the + kill signal (no opportunity to shut down). This is + a beta field and requires enabling ProbeTerminationGracePeriod + feature gate. Minimum value is 1. spec.terminationGracePeriodSeconds + is used if unset. + format: int64 + type: integer + timeoutSeconds: + description: 'Number of seconds after which the probe + times out. Defaults to 1 second. Minimum value is + 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + type: object + resources: + description: 'Compute Resources required by this container. + Cannot be updated. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + properties: + 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. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + securityContext: + description: 'SecurityContext defines the security options + the container should be run with. If set, the fields of + SecurityContext override the equivalent fields of PodSecurityContext. + More info: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/' + properties: + allowPrivilegeEscalation: + description: 'AllowPrivilegeEscalation controls whether + a process can gain more privileges than its parent + process. This bool directly controls if the no_new_privs + flag will be set on the container process. AllowPrivilegeEscalation + is true always when the container is: 1) run as Privileged + 2) has CAP_SYS_ADMIN Note that this field cannot be + set when spec.os.name is windows.' + type: boolean + capabilities: + description: The capabilities to add/drop when running + containers. Defaults to the default set of capabilities + granted by the container runtime. Note that this field + cannot be set when spec.os.name is windows. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + type: object + privileged: + description: Run container in privileged mode. Processes + in privileged containers are essentially equivalent + to root on the host. Defaults to false. Note that + this field cannot be set when spec.os.name is windows. + type: boolean + procMount: + description: procMount denotes the type of proc mount + to use for the containers. The default is DefaultProcMount + which uses the container runtime defaults for readonly + paths and masked paths. This requires the ProcMountType + feature flag to be enabled. Note that this field cannot + be set when spec.os.name is windows. + type: string + readOnlyRootFilesystem: + description: Whether this container has a read-only + root filesystem. Default is false. Note that this + field cannot be set when spec.os.name is windows. + type: boolean + runAsGroup: + description: The GID to run the entrypoint of the container + process. Uses runtime default if unset. May also be + set in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set + when spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as + a non-root user. If true, the Kubelet will validate + the image at runtime to ensure that it does not run + as UID 0 (root) and fail to start the container if + it does. If unset or false, no such validation will + be performed. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container + process. Defaults to user specified in image metadata + if unspecified. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name + is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to the + container. If unspecified, the container runtime will + allocate a random SELinux context for each container. May + also be set in PodSecurityContext. If set in both + SecurityContext and PodSecurityContext, the value + specified in SecurityContext takes precedence. Note + that this field cannot be set when spec.os.name is + windows. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by this container. + If seccomp options are provided at both the pod & + container level, the container options override the + pod options. Note that this field cannot be set when + spec.os.name is windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile + defined in a file on the node should be used. + The profile must be preconfigured on the node + to work. Must be a descending path, relative to + the kubelet's configured seccomp profile location. + Must only be set if type is "Localhost". + type: string + type: + description: "type indicates which kind of seccomp + profile will be applied. Valid options are: \n + Localhost - a profile defined in a file on the + node should be used. RuntimeDefault - the container + runtime default profile should be used. Unconfined + - no profile should be applied." + type: string + required: + - type + type: object + windowsOptions: + description: The Windows specific settings applied to + all containers. If unspecified, the options from the + PodSecurityContext will be used. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set + when spec.os.name is linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA + admission webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec + named by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name + of the GMSA credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container + should be run as a 'Host Process' container. This + field is alpha-level and will only be honored + by components that enable the WindowsHostProcessContainers + feature flag. Setting this field without the feature + flag will result in errors when validating the + Pod. All of a Pod's containers must have the same + effective HostProcess value (it is not allowed + to have a mix of HostProcess containers and non-HostProcess + containers). In addition, if HostProcess is true + then HostNetwork must also be set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the + entrypoint of the container process. Defaults + to the user specified in image metadata if unspecified. + May also be set in PodSecurityContext. If set + in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + type: string + type: object + type: object + startupProbe: + description: 'StartupProbe indicates that the Pod has successfully + initialized. If specified, no other probes are executed + until this completes successfully. If this probe fails, + the Pod will be restarted, just as if the livenessProbe + failed. This can be used to provide different probe parameters + at the beginning of a Pod''s lifecycle, when it might + take a long time to load data or warm a cache, than during + steady-state operation. This cannot be updated. More info: + https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to execute + inside the container, the working directory for + the command is root ('/') in the container's + filesystem. The command is simply exec'd, it is + not run inside a shell, so traditional shell instructions + ('|', etc) won't work. To use a shell, you need + to explicitly call out to that shell. Exit status + of 0 is treated as live/healthy and non-zero is + unhealthy. + items: + type: string + type: array + type: object + failureThreshold: + description: Minimum consecutive failures for the probe + to be considered failed after having succeeded. Defaults + to 3. Minimum value is 1. + format: int32 + type: integer + grpc: + description: GRPC specifies an action involving a GRPC + port. This is a beta field and requires enabling GRPCContainerProbe + feature gate. + properties: + port: + description: Port number of the gRPC service. Number + must be in the range 1 to 65535. + format: int32 + type: integer + service: + description: "Service is the name of the service + to place in the gRPC HealthCheckRequest (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + \n If this is not specified, the default behavior + is defined by gRPC." + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies the http request to perform. + properties: + host: + description: Host name to connect to, defaults to + the pod IP. You probably want to set "Host" in + httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the request. + HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom header + to be used in HTTP probes + properties: + name: + description: The header field name + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to the + host. Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: 'Number of seconds after the container + has started before liveness probes are initiated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + periodSeconds: + description: How often (in seconds) to perform the probe. + Default to 10 seconds. Minimum value is 1. + format: int32 + type: integer + successThreshold: + description: Minimum consecutive successes for the probe + to be considered successful after having failed. Defaults + to 1. Must be 1 for liveness and startup. Minimum + value is 1. + format: int32 + type: integer + tcpSocket: + description: TCPSocket specifies an action involving + a TCP port. + properties: + host: + description: 'Optional: Host name to connect to, + defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: Optional duration in seconds the pod needs + to terminate gracefully upon probe failure. The grace + period is the duration in seconds after the processes + running in the pod are sent a termination signal and + the time when the processes are forcibly halted with + a kill signal. Set this value longer than the expected + cleanup time for your process. If this value is nil, + the pod's terminationGracePeriodSeconds will be used. + Otherwise, this value overrides the value provided + by the pod spec. Value must be non-negative integer. + The value zero indicates stop immediately via the + kill signal (no opportunity to shut down). This is + a beta field and requires enabling ProbeTerminationGracePeriod + feature gate. Minimum value is 1. spec.terminationGracePeriodSeconds + is used if unset. + format: int64 + type: integer + timeoutSeconds: + description: 'Number of seconds after which the probe + times out. Defaults to 1 second. Minimum value is + 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + type: object + stdin: + description: Whether this container should allocate a buffer + for stdin in the container runtime. If this is not set, + reads from stdin in the container will always result in + EOF. Default is false. + type: boolean + stdinOnce: + description: Whether the container runtime should close + the stdin channel after it has been opened by a single + attach. When stdin is true the stdin stream will remain + open across multiple attach sessions. If stdinOnce is + set to true, stdin is opened on container start, is empty + until the first client attaches to stdin, and then remains + open and accepts data until the client disconnects, at + which time stdin is closed and remains closed until the + container is restarted. If this flag is false, a container + processes that reads from stdin will never receive an + EOF. Default is false + type: boolean + terminationMessagePath: + description: 'Optional: Path at which the file to which + the container''s termination message will be written is + mounted into the container''s filesystem. Message written + is intended to be brief final status, such as an assertion + failure message. Will be truncated by the node if greater + than 4096 bytes. The total message length across all containers + will be limited to 12kb. Defaults to /dev/termination-log. + Cannot be updated.' + type: string + terminationMessagePolicy: + description: Indicate how the termination message should + be populated. File will use the contents of terminationMessagePath + to populate the container status message on both success + and failure. FallbackToLogsOnError will use the last chunk + of container log output if the termination message file + is empty and the container exited with an error. The log + output is limited to 2048 bytes or 80 lines, whichever + is smaller. Defaults to File. Cannot be updated. + type: string + tty: + description: Whether this container should allocate a TTY + for itself, also requires 'stdin' to be true. Default + is false. + type: boolean + volumeDevices: + description: volumeDevices is the list of block devices + to be used by the container. + items: + description: volumeDevice describes a mapping of a raw + block device within a container. + properties: + devicePath: + description: devicePath is the path inside of the + container that the device will be mapped to. + type: string + name: + description: name must match the name of a persistentVolumeClaim + in the pod + type: string + required: + - devicePath + - name + type: object + type: array + volumeMounts: + description: Pod volumes to mount into the container's filesystem. + Cannot be updated. + items: + description: VolumeMount describes a mounting of a Volume + within a container. + properties: + mountPath: + description: Path within the container at which the + volume should be mounted. Must not contain ':'. + type: string + mountPropagation: + description: mountPropagation determines how mounts + are propagated from the host to container and the + other way around. When not set, MountPropagationNone + is used. This field is beta in 1.10. + type: string + name: + description: This must match the Name of a Volume. + type: string + readOnly: + description: Mounted read-only if true, read-write + otherwise (false or unspecified). Defaults to false. + type: boolean + subPath: + description: Path within the volume from which the + container's volume should be mounted. Defaults to + "" (volume's root). + type: string + subPathExpr: + description: Expanded path within the volume from + which the container's volume should be mounted. + Behaves similarly to SubPath but environment variable + references $(VAR_NAME) are expanded using the container's + environment. Defaults to "" (volume's root). SubPathExpr + and SubPath are mutually exclusive. + type: string + required: + - mountPath + - name + type: object + type: array + workingDir: + description: Container's working directory. If not specified, + the container runtime's default will be used, which might + be configured in the container image. Cannot be updated. + type: string + required: + - name + type: object + type: array + nodeSelector: + additionalProperties: + type: string + type: object + podAnnotations: + additionalProperties: + type: string + type: object + priorityClassName: + type: string + replicas: + format: int32 + type: integer + resources: + description: ResourceRequirements describes the compute resource + requirements. + properties: + 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. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + securityContext: + description: PodSecurityContext holds pod-level security attributes + and common container settings. Some fields are also present + in container.securityContext. Field values of container.securityContext + take precedence over field values of PodSecurityContext. + properties: + fsGroup: + description: "A special supplemental group that applies to + all containers in a pod. Some volume types allow the Kubelet + to change the ownership of that volume to be owned by the + pod: \n 1. The owning GID will be the FSGroup 2. The setgid + bit is set (new files created in the volume will be owned + by FSGroup) 3. The permission bits are OR'd with rw-rw---- + \n If unset, the Kubelet will not modify the ownership and + permissions of any volume. Note that this field cannot be + set when spec.os.name is windows." + format: int64 + type: integer + fsGroupChangePolicy: + description: 'fsGroupChangePolicy defines behavior of changing + ownership and permission of the volume before being exposed + inside Pod. This field will only apply to volume types which + support fsGroup based ownership(and permissions). It will + have no effect on ephemeral volume types such as: secret, + configmaps and emptydir. Valid values are "OnRootMismatch" + and "Always". If not specified, "Always" is used. Note that + this field cannot be set when spec.os.name is windows.' + type: string + runAsGroup: + description: The GID to run the entrypoint of the container + process. Uses runtime default if unset. May also be set + in SecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence for that container. Note that this field + cannot be set when spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as a non-root + user. If true, the Kubelet will validate the image at runtime + to ensure that it does not run as UID 0 (root) and fail + to start the container if it does. If unset or false, no + such validation will be performed. May also be set in SecurityContext. If + set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container + process. Defaults to user specified in image metadata if + unspecified. May also be set in SecurityContext. If set + in both SecurityContext and PodSecurityContext, the value + specified in SecurityContext takes precedence for that container. + Note that this field cannot be set when spec.os.name is + windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to all containers. + If unspecified, the container runtime will allocate a random + SELinux context for each container. May also be set in + SecurityContext. If set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence + for that container. Note that this field cannot be set when + spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by the containers + in this pod. Note that this field cannot be set when spec.os.name + is windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile defined + in a file on the node should be used. The profile must + be preconfigured on the node to work. Must be a descending + path, relative to the kubelet's configured seccomp profile + location. Must only be set if type is "Localhost". + type: string + type: + description: "type indicates which kind of seccomp profile + will be applied. Valid options are: \n Localhost - a + profile defined in a file on the node should be used. + RuntimeDefault - the container runtime default profile + should be used. Unconfined - no profile should be applied." + type: string + required: + - type + type: object + supplementalGroups: + description: A list of groups applied to the first process + run in each container, in addition to the container's primary + GID. If unspecified, no groups will be added to any container. + Note that this field cannot be set when spec.os.name is + windows. + items: + format: int64 + type: integer + type: array + sysctls: + description: Sysctls hold a list of namespaced sysctls used + for the pod. Pods with unsupported sysctls (by the container + runtime) might fail to launch. Note that this field cannot + be set when spec.os.name is windows. + items: + description: Sysctl defines a kernel parameter to be set + properties: + name: + description: Name of a property to set + type: string + value: + description: Value of a property to set + type: string + required: + - name + - value + type: object + type: array + windowsOptions: + description: The Windows specific settings applied to all + containers. If unspecified, the options within a container's + SecurityContext will be used. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA admission + webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec named + by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of the + GMSA credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container should + be run as a 'Host Process' container. This field is + alpha-level and will only be honored by components that + enable the WindowsHostProcessContainers feature flag. + Setting this field without the feature flag will result + in errors when validating the Pod. All of a Pod's containers + must have the same effective HostProcess value (it is + not allowed to have a mix of HostProcess containers + and non-HostProcess containers). In addition, if HostProcess + is true then HostNetwork must also be set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set in + PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. + type: string + type: object + type: object + serviceAccountName: + type: string + serviceAnnotations: + additionalProperties: + type: string + type: object + tolerations: + 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: + 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 + required: + - key + - operator + type: object + type: array + 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 + 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. For example, in a 3-zone + cluster, MaxSkew is set to 1, and pods with the same labelSelector + spread as 2/2/1: In this case, the global minimum is 1. + | zone1 | zone2 | zone3 | | P P | P P | P | - + if MaxSkew is 1, incoming pod can only be scheduled to + zone3 to become 2/2/2; scheduling it onto zone1(zone2) + would make the ActualSkew(3-1) on zone1(zone2) violate + MaxSkew(1). - if MaxSkew is 2, incoming pod can be scheduled + onto any zone. When `whenUnsatisfiable=ScheduleAnyway`, + it is used to give higher precedence to topologies that + satisfy it. It''s a required field. Default value is 1 + and 0 is not allowed.' + 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. + As a result, when the number of eligible domains is less + than minDomains, scheduler won't schedule more than maxSkew + Pods to those domains. If value is nil, the constraint + behaves as if MinDomains is equal to 1. Valid values are + integers greater than 0. When value is not nil, WhenUnsatisfiable + must be DoNotSchedule. \n For example, in a 3-zone cluster, + MaxSkew is set to 2, MinDomains is set to 5 and pods with + the same labelSelector spread as 2/2/2: | zone1 | zone2 + | zone3 | | P P | P P | P P | The number of domains + is less than 5(MinDomains), so \"global minimum\" is treated + as 0. In this situation, new pod with the same labelSelector + cannot be scheduled, because computed skew will be 3(3 + - 0) if new Pod is scheduled to any of the three zones, + it will violate MaxSkew. \n This is an alpha field and + requires enabling MinDomainsInPodTopologySpread feature + gate." + format: int32 + type: integer + 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 match the node selector. e.g. + If TopologyKey is "kubernetes.io/hostname", each Node + is a domain of that topology. And, if TopologyKey is "topology.kubernetes.io/zone", + each zone is a domain of that topology. It's a required + field. + 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. For example, in a + 3-zone cluster, MaxSkew is set to 1, and pods with the + same labelSelector spread as 3/1/1: | zone1 | zone2 | + zone3 | | P P P | P | P | If WhenUnsatisfiable + is set to DoNotSchedule, incoming pod can only be scheduled + to zone2(zone3) to become 3/2/1(3/1/2) as ActualSkew(2-1) + on zone2(zone3) satisfies MaxSkew(1). In other words, + the cluster can still be imbalanced, but scheduler won''t + make it *more* imbalanced. It''s a required field.' + type: string + required: + - maxSkew + - topologyKey + - whenUnsatisfiable + type: object + type: array + type: object + type: object + required: + - spec + type: object + served: true + storage: true + subresources: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/packages/system/redis-operator/charts/redis-operator/templates/_helpers.tpl b/packages/system/redis-operator/charts/redis-operator/templates/_helpers.tpl new file mode 100644 index 00000000..1fbfb51d --- /dev/null +++ b/packages/system/redis-operator/charts/redis-operator/templates/_helpers.tpl @@ -0,0 +1,85 @@ + +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "chart.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | 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 "chart.fullname" -}} +{{- if .Values.fullnameOverride -}} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- if contains $name .Release.Name -}} +{{- .Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "chart.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + + +{{/* +Common labels +timestamp: {{ now | date "2006-01-02_15-04-05" | quote }} +*/}} +{{- define "chart.labels" -}} +helm.sh/chart: {{ include "chart.chart" . }} +{{ include "chart.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +app.kubernetes.io/part-of: {{ include "chart.name" . }} +{{- if .Values.labels}} +{{ toYaml .Values.labels }} +{{- end }} +{{- end -}} + +{{/* +Selector labels +*/}} +{{- define "chart.selectorLabels" -}} +app.kubernetes.io/name: {{ include "chart.name" . }}{{- if .name -}}-{{- .name -}}{{- end }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end -}} + + +{{/* +Create the name of the service account to use +*/}} +{{- define "chart.serviceAccountName" -}} + {{- if .Values.serviceAccount.create -}} + {{ default (include "chart.fullname" .) .Values.serviceAccount.name }} + {{- else -}} + {{ default "default" .Values.serviceAccount.name }} + {{- end -}} +{{- end -}} + +{{/* Expands data for image pull secret. */}} +{{- define "imagePullSecret" }} +{{- with .Values.imageCredentials }} +{{- printf "{\"auths\":{\"%s\":{\"username\":\"%s\",\"password\":\"%s\",\"email\":\"%s\",\"auth\":\"%s\"}}}" .registry .username .password .email (printf "%s:%s" .username .password | b64enc) | b64enc }} +{{- end }} +{{- end }} + +{{/* +Create the name of the namespace +*/}} +{{- define "chart.namespaceName" -}} +{{- default .Release.Namespace .Values.namespace }} +{{- end }} diff --git a/packages/system/redis-operator/charts/redis-operator/templates/_versions.tpl b/packages/system/redis-operator/charts/redis-operator/templates/_versions.tpl new file mode 100644 index 00000000..ee2f1392 --- /dev/null +++ b/packages/system/redis-operator/charts/redis-operator/templates/_versions.tpl @@ -0,0 +1,20 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Return the appropriate apiVersion for deployment. +*/}} +{{- define "common.capabilities.deployment.apiVersion" -}} +{{- print "apps/v1" -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for ingress. +*/}} +{{- define "common.capabilities.ingress.apiVersion" -}} +{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}} +{{- print "networking.k8s.io/v1" -}} +{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} +{{- print "extensions/v1beta1" -}} +{{- else -}} +{{- print "networking.k8s.io/v1beta1" -}} +{{- end -}} +{{- end -}} diff --git a/packages/system/redis-operator/charts/redis-operator/templates/deployment.yaml b/packages/system/redis-operator/charts/redis-operator/templates/deployment.yaml new file mode 100644 index 00000000..604a44e1 --- /dev/null +++ b/packages/system/redis-operator/charts/redis-operator/templates/deployment.yaml @@ -0,0 +1,85 @@ +{{- $fullName := include "chart.fullname" . -}} +{{ $name := "registry" }} +{{- $data := dict "Chart" .Chart "Release" .Release "Values" .Values -}} +apiVersion: {{ template "common.capabilities.deployment.apiVersion" . }} +kind: Deployment +metadata: + name: {{ $fullName }} + namespace: {{ include "chart.namespaceName" . }} + labels: + {{- include "chart.labels" $data | nindent 4 }} + {{- if .Values.annotations }} + annotations: +{{ toYaml .Values.annotations | indent 4 }} + {{- end }} +spec: + replicas: {{ .Values.replicas }} + selector: + matchLabels: + {{- include "chart.selectorLabels" $data | nindent 6 }} + strategy: + type: {{ .Values.updateStrategy.type }} + template: + metadata: + {{- with .Values.annotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "chart.selectorLabels" $data | nindent 8 }} + spec: + serviceAccountName: {{ template "chart.serviceAccountName" . }} + {{- if (and .Values.imageCredentials.create (not .Values.imageCredentials.existsSecrets)) }} + imagePullSecrets: + - name: {{ $fullName }}-{{ $name }} + {{- else if (and .Values.imageCredentials.create .Values.imageCredentials.existsSecrets) }} + {{- range .Values.imageCredentials.existsSecrets }} + imagePullSecrets: + {{ printf "- name: %s" . }} + {{- end }} + {{- end }} + containers: + - name: {{ .Chart.Name }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion}}" + {{- if .Values.image.cli_args }} + args: + - {{ quote .Values.image.cli_args }} + {{- end }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + ports: + - name: metrics + containerPort: {{ .Values.container.port }} + protocol: TCP + readinessProbe: + tcpSocket: + port: {{ .Values.container.port }} + initialDelaySeconds: 10 + periodSeconds: 3 + timeoutSeconds: 3 + livenessProbe: + tcpSocket: + port: {{ .Values.container.port }} + initialDelaySeconds: 30 + periodSeconds: 5 + timeoutSeconds: 5 + failureThreshold: 6 + successThreshold: 1 + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + resources: + {{- toYaml .Values.resources | nindent 12 }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if .Values.priorityClassName }} + priorityClassName: {{ .Values.priorityClassName }} + {{- end }} diff --git a/packages/system/redis-operator/charts/redis-operator/templates/monitoring.yaml b/packages/system/redis-operator/charts/redis-operator/templates/monitoring.yaml new file mode 100644 index 00000000..8cf9e249 --- /dev/null +++ b/packages/system/redis-operator/charts/redis-operator/templates/monitoring.yaml @@ -0,0 +1,48 @@ +{{- if .Values.monitoring.enabled -}} +{{- $fullName := include "chart.fullname" . -}} +{{- $svcPort := .Values.service.port -}} +{{- $data := dict "Chart" .Chart "Release" .Release "Values" .Values -}} +apiVersion: v1 +kind: Service +metadata: + name: {{ $fullName }}-prometheus + namespace: {{ include "chart.namespaceName" . }} + labels: + prometheus: {{ .Values.monitoring.prometheus.name }} + {{- include "chart.labels" $data | nindent 4 }} +{{- if .Values.monitoring.serviceAnnotations }} + annotations: +{{ toYaml .Values.monitoring.serviceAnnotations | indent 4 }} +{{- end }} +spec: + ports: + - port: {{ $svcPort }} + protocol: TCP + name: metrics + targetPort: metrics + selector: +{{- include "chart.selectorLabels" $data | nindent 4 }} + +--- +{{- if .Values.monitoring.serviceMonitor -}} +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ $fullName }} + namespace: {{ include "chart.namespaceName" . }} + labels: + prometheus: {{ .Values.monitoring.prometheus.name }} + {{- include "chart.labels" $data | nindent 4 }} +spec: + selector: + matchLabels: + prometheus: {{ .Values.monitoring.prometheus.name }} + {{- include "chart.selectorLabels" $data | nindent 6 }} + namespaceSelector: + matchNames: + - {{ include "chart.namespaceName" . }} + endpoints: + - port: metrics + interval: 15s +{{- end -}} +{{- end -}} \ No newline at end of file diff --git a/packages/system/redis-operator/charts/redis-operator/templates/private-registry.yaml b/packages/system/redis-operator/charts/redis-operator/templates/private-registry.yaml new file mode 100644 index 00000000..0df3a1b1 --- /dev/null +++ b/packages/system/redis-operator/charts/redis-operator/templates/private-registry.yaml @@ -0,0 +1,19 @@ +{{- if (and .Values.imageCredentials.create (not .Values.imageCredentials.existsSecrets)) -}} +{{- $fullName := include "chart.fullname" . -}} +{{- $name := "registry" -}} +{{- $data := dict "name" $name "Chart" .Chart "Release" .Release "Values" .Values -}} +apiVersion: v1 +kind: Secret +metadata: + name: {{ $fullName }}-{{ $name }} + namespace: {{ include "chart.namespaceName" . }} + labels: + {{- include "chart.labels" $data | nindent 4 }} + {{- if .Values.annotations }} + annotations: +{{ toYaml .Values.annotations | indent 4 }} + {{- end }} +type: kubernetes.io/dockerconfigjson +data: + .dockerconfigjson: {{ template "imagePullSecret" . }} +{{- end }} \ No newline at end of file diff --git a/packages/system/redis-operator/charts/redis-operator/templates/service-account.yaml b/packages/system/redis-operator/charts/redis-operator/templates/service-account.yaml new file mode 100644 index 00000000..fc9805b8 --- /dev/null +++ b/packages/system/redis-operator/charts/redis-operator/templates/service-account.yaml @@ -0,0 +1,115 @@ +{{ if .Values.serviceAccount.create }} +{{- $fullName := include "chart.fullname" . -}} +{{- $data := dict "Chart" .Chart "Release" .Release "Values" .Values -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ $fullName }} + namespace: {{ include "chart.namespaceName" . }} + labels: + {{- include "chart.labels" $data | nindent 4 }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ $fullName }} + labels: + {{- include "chart.labels" $data | nindent 4 }} +rules: + - apiGroups: + - databases.spotahome.com + resources: + - redisfailovers + - redisfailovers/finalizers + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: + - apiextensions.k8s.io + resources: + - customresourcedefinitions + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: + - coordination.k8s.io + resources: + - leases + verbs: + - create + - get + - list + - update + - apiGroups: + - "" + resources: + - pods + - services + - endpoints + - events + - configmaps + - persistentvolumeclaims + - persistentvolumeclaims/finalizers + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: + - "" + resources: + - secrets + verbs: + - "get" + - apiGroups: + - apps + resources: + - deployments + - statefulsets + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: + - policy + resources: + - poddisruptionbudgets + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +--- +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ $fullName }} +subjects: + - kind: ServiceAccount + name: {{ $fullName }} + namespace: {{ include "chart.namespaceName" . }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ $fullName }} +{{- end }} diff --git a/packages/system/redis-operator/charts/redis-operator/templates/service.yaml b/packages/system/redis-operator/charts/redis-operator/templates/service.yaml new file mode 100644 index 00000000..9291a266 --- /dev/null +++ b/packages/system/redis-operator/charts/redis-operator/templates/service.yaml @@ -0,0 +1,23 @@ +{{- $fullName := include "chart.fullname" . -}} +{{- $svcPort := .Values.service.port -}} +{{- $data := dict "Chart" .Chart "Release" .Release "Values" .Values -}} +apiVersion: v1 +kind: Service +metadata: + name: {{ $fullName }} + namespace: {{ include "chart.namespaceName" . }} + labels: + {{- include "chart.labels" $data | nindent 4 }} + {{- if .Values.annotations }} + annotations: +{{ toYaml .Values.annotations | indent 4 }} + {{- end }} +spec: + type: {{ .Values.service.type}} + ports: + - name: metrics + port: {{ $svcPort }} + protocol: TCP + selector: + {{- include "chart.selectorLabels" $data | nindent 4 }} + diff --git a/packages/system/redis-operator/charts/redis-operator/values.yaml b/packages/system/redis-operator/charts/redis-operator/values.yaml new file mode 100644 index 00000000..0460a54e --- /dev/null +++ b/packages/system/redis-operator/charts/redis-operator/values.yaml @@ -0,0 +1,98 @@ +# Default values for redis-operator. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +# Name of the image repository to pull the container image from. +image: + repository: quay.io/spotahome/redis-operator + pullPolicy: IfNotPresent + tag: v1.3.0 + cli_args: "" + +imageCredentials: + create: false + registry: url.private.registry + username: someone + password: somepassword + email: someone@example.com + # Use exists secrets in namespace + existsSecrets: + - registrysecret + +updateStrategy: + type: RollingUpdate + +replicas: 1 + +# A name in place of the chart name for `app:` labels. +nameOverride: "" + +# A name to substitute for the full names of resources. +fullnameOverride: "" + +# The name of the Namespace to deploy +# If not set, `.Release.Namespace` is used +namespace: null + +serviceAccount: + # Enable service account creation. + create: true + # Annotations to be added to the service account. + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template. + name: "" + +service: + type: ClusterIP + port: 9710 + +container: + port: 9710 + +# Container [security context](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container). +# See the [API reference](https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/#security-context-1) for details. +securityContext: + readOnlyRootFilesystem: true + runAsNonRoot: true + runAsUser: 1000 + +# Container resource [requests and limits](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/). +# See the [API reference](https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/#resources) for details. +# @default -- No requests or limits. +resources: {} +# requests: +# cpu: 100m +# memory: 128Mi +# limits: +# cpu: 100m +# memory: 128Mi + +### Monitoring +############### +monitoring: + # Enable Prometheus PodMonitor to monitor the operator. + enabled: false + serviceMonitor: false + serviceAnnotations: {} + prometheus: + name: unknown + +# Annotations to be added to pods and deployments. +annotations: {} + +nodeSelector: {} + +tolerations: [] + +affinity: {} + +# CRDs configuration +crds: + # -- Additional CRDs annotations + annotations: {} + # argocd.argoproj.io/sync-options: Replace=true + # strategy.spinnaker.io/replace: 'true' + +priorityClassName: "" + diff --git a/packages/system/redis-operator/values.yaml b/packages/system/redis-operator/values.yaml new file mode 100644 index 00000000..eb8c61a9 --- /dev/null +++ b/packages/system/redis-operator/values.yaml @@ -0,0 +1,3 @@ +redis-operator: + image: + tag: v1.3.0-rc1 diff --git a/packages/system/telepresence/Chart.yaml b/packages/system/telepresence/Chart.yaml new file mode 100644 index 00000000..812bc7fa --- /dev/null +++ b/packages/system/telepresence/Chart.yaml @@ -0,0 +1,2 @@ +name: cozy-telepresence +version: 1.0.0 diff --git a/packages/system/telepresence/Makefile b/packages/system/telepresence/Makefile new file mode 100644 index 00000000..d2311d0d --- /dev/null +++ b/packages/system/telepresence/Makefile @@ -0,0 +1,17 @@ +NAME=traffic-manager +NAMESPACE=cozy-telepresence + +show: + helm template --dry-run=server -n $(NAMESPACE) $(NAME) . + +apply: + helm upgrade -i -n $(NAMESPACE) $(NAME) . + +diff: + helm diff upgrade --allow-unreleased --normalize-manifests -n $(NAMESPACE) $(NAME) . + +update: + rm -rf charts + helm repo add datawire https://app.getambassador.io + helm repo update datawire + helm pull datawire/telepresence --untar --untardir charts diff --git a/packages/system/telepresence/charts/telepresence/.gitignore b/packages/system/telepresence/charts/telepresence/.gitignore new file mode 100644 index 00000000..122e89c0 --- /dev/null +++ b/packages/system/telepresence/charts/telepresence/.gitignore @@ -0,0 +1,4 @@ +# Dependencies are copied to charts when the client is built. We don't want them +# checked in. +/charts + diff --git a/packages/system/telepresence/charts/telepresence/.helmignore b/packages/system/telepresence/charts/telepresence/.helmignore new file mode 100644 index 00000000..0e8a0eb3 --- /dev/null +++ b/packages/system/telepresence/charts/telepresence/.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/packages/system/telepresence/charts/telepresence/CHANGELOG.md b/packages/system/telepresence/charts/telepresence/CHANGELOG.md new file mode 100644 index 00000000..f9d7d2ad --- /dev/null +++ b/packages/system/telepresence/charts/telepresence/CHANGELOG.md @@ -0,0 +1,24 @@ +# Change Log + +### 2.6.8 (TBD) + +- Feature: The helm-chart now supports settings resources, securityContext and podSecurityContext for use with chart hooks. + +### v2.3.3-rc.0 + +- Feature: Add AgentInjectorWebhook yaml files, newly introduced in 2.3.1. +- Feature: Include service account + ClusterRole + ClusterRoleBinding for the traffic-manager, since it now communicates directly with the cluster. +- Feature: add `priorityClassName` value. +- Feature: add `nodeSelector`, `affinity` and `tolerations` values to post-upgrade-hook and pre-delete-hook jobs. +- Change: image.repository has been split into image.registry and image.name since the registry is now used in another field. +- Change: the `rbac` value has been changed to be `clientRbac`. +- Change: `service.ports` has been removed since those values are not able to be changed. + +### v0.2.0 + +- Feature: Create RBAC resources from helm chart +- Feature: Update to the 2.3.0 image of Telepresence + +### v0.1.0 + +- Feature: Add support for installing the Traffic Manager with Helm diff --git a/packages/system/telepresence/charts/telepresence/Chart.yaml b/packages/system/telepresence/charts/telepresence/Chart.yaml new file mode 100644 index 00000000..97926d24 --- /dev/null +++ b/packages/system/telepresence/charts/telepresence/Chart.yaml @@ -0,0 +1,12 @@ +apiVersion: v2 +appVersion: 2.16.1 +dependencies: +- condition: ambassador-agent.enabled + name: ambassador-agent + repository: https://app.getambassador.io/ + version: ~1.0.0 +description: A chart for deploying the server-side components of Telepresence +icon: https://www.getambassador.io/images/logo.png +name: telepresence +type: application +version: 2.16.1 diff --git a/packages/system/telepresence/charts/telepresence/README.md b/packages/system/telepresence/charts/telepresence/README.md new file mode 100644 index 00000000..65899cd9 --- /dev/null +++ b/packages/system/telepresence/charts/telepresence/README.md @@ -0,0 +1,48 @@ +## Configuration + +The following tables lists the configurable parameters of the Telepresence Pro chart and their default values. + +| Parameter | Description | Default | +|-----------------------------|---------------------------------------------------------------------------------------------------------------------------|----------------------------| +| agent.envoy.logLevel | The logging level for the traffic-agent Envoy server | defaults to agent.logLevel | +| agent.envoy.serverPort | The server port for the traffic-agent Envoy server | 18000 | +| agent.envoy.adminPort | The admin port for the traffic-agent Envoy server | 19000 | +| agent.envoy.httpIdleTimeout | The time an Envoy http connection can be idle before it is closed. | 70s | +| httpsProxy.rootCATLSSecret | The TLS Secret to use when the traffic manager is behind a proxy. Should contain the root CA for the proxy | `""` | +| licenseKey.create | Create the license key `volume` and `volumeMount`. **Only required for clusters without access to the internet.** | `false` | +| licenseKey.value | The value of the license key. | `""` | +| licenseKey.secret.create | Define whether you want the license key `Secret` to be managed by the release or not. | `true` | +| licenseKey.secret.name | The name of the `Secret` that Traffic Manager will look for. | `systema-license` | +| intercept.disableGlobal | If set to `true`, the traffic-manager will only allow intercepts that use mechanism `http`. | `false` | +| systemaHost | Host to be used for features requiring extensions (formerly the SYSTEMA_HOST environment variable) | `app.getambassador.io` | +| systemaPort | Port to be used with the `systemaHost` for features requiring extensions (formerly the SYSTEMA_HOST environment variable) | `443` | + +## License Key + +Telepresence can create TCP intercepts without a license key. Creating +intercepts based on HTTP headers requires a license key from the Ambassador +Cloud. + +In normal environments that have access to the public internet, the Traffic +Manager will automatically connect to the Ambassador Cloud to retrieve a license +key. If you are working in one of these environments, you can safely ignore +these settings in the chart. + +If you are running in +an [air gapped cluster](https://www.getambassador.io/docs/telepresence/latest/reference/cluster-config/#air-gapped-cluster), +you will need to configure the Traffic Manager to use a license key you manually +deploy to the cluster. + +These notes should help clarify your options for enabling this. + +- `licenseKey.create` will **always** create the `volume` and `volumeMount` for + mounting the `Secret` in the Traffic Managed + +- `licenseKey.secret.name` will define the name of the `Secret` that is + mounted in the Traffic Manager, regardless of it it is created by the chart + +- `licenseKey.secret.create` will create a `Secret` with + ``` + data: + license: {{.licenseKey.value}} + ``` diff --git a/packages/system/telepresence/charts/telepresence/templates/NOTES.txt b/packages/system/telepresence/charts/telepresence/templates/NOTES.txt new file mode 100644 index 00000000..a636e741 --- /dev/null +++ b/packages/system/telepresence/charts/telepresence/templates/NOTES.txt @@ -0,0 +1,19 @@ +-------------------------------------------------------------------------------- +Congratulations! + + +You have successfully installed the Traffic Manager component of Telepresence! +Now your users will be able to `telepresence connect` to this Cluster and create +intercepts for their services! + +-------------------------------------------------------------------------------- +Next Steps +-------------------------------------------------------------------------------- + +- Take a look at our RBAC documentation for setting up the minimal required RBAC +roles for your users at +https://www.getambassador.io/docs/telepresence/latest/reference/rbac/ + +- Ensure that you are keeping up to date with Telepresence releases +https://github.com/telepresenceio/telepresence/releases so that your Traffic +Manager is the same version as the telepresence client your users are running! diff --git a/packages/system/telepresence/charts/telepresence/templates/_helpers.tpl b/packages/system/telepresence/charts/telepresence/templates/_helpers.tpl new file mode 100644 index 00000000..d142de18 --- /dev/null +++ b/packages/system/telepresence/charts/telepresence/templates/_helpers.tpl @@ -0,0 +1,116 @@ +{{- define "clientRbac-ruleExtras" -}} +- apiGroups: ["getambassador.io"] + resources: ["ispecs"] + verbs: ["get"] +{{- end }} +{{/* +Expand the name of the chart. +*/}} +{{- define "telepresence.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{- define "traffic-manager.name" -}} +{{- $name := default "traffic-manager" }} +{{- if .Values.isCI }} +{{- print $name }} +{{- else }} +{{- if ne $name .Release.Name }} +{{- fail "The name of the release MUST BE traffic-manager" }} +{{- end }} +{{- printf "%s" .Release.Name }} +{{- end -}} +{{- end -}} + +{{- /* +Traffic Manager Namespace +*/}} +{{- define "traffic-manager.namespace" -}} +{{- if .Values.isCI }} +{{- print "ambassador" }} +{{- else }} +{{- printf "%s" .Release.Namespace }} +{{- end }} +{{- end -}} + +{{- /* +Create chart name and version as used by the chart label. +*/}} +{{- define "telepresence.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{- /* +Common labels +*/}} +{{- define "telepresence.labels" -}} +{{ include "telepresence.selectorLabels" . }} +helm.sh/chart: {{ include "telepresence.chart" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- /* This value is intentionally undocumented -- it's used by the telepresence binary to determine ownership of the release */}} +{{- if .Values.createdBy }} +app.kubernetes.io/created-by: {{ .Values.createdBy }} +{{- else }} +app.kubernetes.io/created-by: {{ .Release.Service }} +{{- end }} +{{- end }} + +{{- /* +Selector labels +*/}} +{{- define "telepresence.selectorLabels" -}} +app: traffic-manager +telepresence: manager +{{- end }} + +{{- /* +Client RBAC name suffix +*/}} +{{- define "telepresence.clientRbacName" -}} +{{ printf "%s-%s" (default (include "telepresence.name" .) .Values.rbac.nameOverride) (include "traffic-manager.namespace" .) }} +{{- end -}} + +{{- /* +RBAC rules required to create an intercept in a namespace; excludes any rules that are always cluster wide. +*/}} +{{- define "telepresence.clientRbacInterceptRules" -}} +- apiGroups: [""] + resources: ["pods/log"] + verbs: ["get"] +- apiGroups: [""] + resources: ["pods"] + verbs: ["list", "get"] +- apiGroups: [""] + resources: ["services"] + verbs: ["list", "watch"] +# Needed for the gather-traces command +- apiGroups: [""] + resources: ["pods/portforward"] + verbs: ["create"] +- apiGroups: ["apps"] + resources: ["deployments", "replicasets", "statefulsets"] + verbs: ["get", "watch", "list"] +- apiGroups: [""] + resources: ["configmaps"] + resourceNames: ["telepresence-agents"] + verbs: ["get", "watch", "list"] +{{- if and .Values.clientRbac .Values.clientRbac.ruleExtras }} +{{ template "clientRbac-ruleExtras" . }} +{{- end }} +{{- end }} + +{{/* +Kubernetes version +*/}} +{{- define "kube.version.major" }} +{{- $version := regexFind "^[0-9]+" .Capabilities.KubeVersion.Major -}} +{{- printf "%s" $version -}} +{{- end -}} + +{{- define "kube.version.minor" }} +{{- $version := regexFind "^[0-9]+" .Capabilities.KubeVersion.Minor -}} +{{- printf "%s" $version -}} +{{- end -}} diff --git a/packages/system/telepresence/charts/telepresence/templates/agent-configmap.yaml b/packages/system/telepresence/charts/telepresence/templates/agent-configmap.yaml new file mode 100644 index 00000000..8f516c2d --- /dev/null +++ b/packages/system/telepresence/charts/telepresence/templates/agent-configmap.yaml @@ -0,0 +1,7 @@ +{{- if not .Values.rbac.only }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: telepresence-agents + namespace: {{ include "traffic-manager.namespace" . }} +{{- end }} diff --git a/packages/system/telepresence/charts/telepresence/templates/agentInjectorWebhook.yaml b/packages/system/telepresence/charts/telepresence/templates/agentInjectorWebhook.yaml new file mode 100644 index 00000000..42c45623 --- /dev/null +++ b/packages/system/telepresence/charts/telepresence/templates/agentInjectorWebhook.yaml @@ -0,0 +1,78 @@ +{{- if not .Values.rbac.only }} +{{- $altNames := list ( printf "agent-injector.%s" (include "traffic-manager.namespace" .)) ( printf "agent-injector.%s.svc" (include "traffic-manager.namespace" .)) -}} +{{- $genCA := genCA "agent-injector-ca" 365 -}} +{{- $genCert := genSignedCert "agent-injector" nil $altNames 365 $genCA -}} +{{- $secretData := (lookup "v1" "Secret" (include "traffic-manager.namespace" .) .Values.agentInjector.secret.name).data -}} +apiVersion: admissionregistration.k8s.io/v1 +kind: MutatingWebhookConfiguration +metadata: + name: {{ .Values.agentInjector.webhook.name }}-{{ include "traffic-manager.namespace" . }} + labels: + {{- include "telepresence.labels" . | nindent 4 }} +webhooks: +{{- with .Values.agentInjector.webhook.admissionReviewVersions }} +- admissionReviewVersions: + {{- toYaml . | nindent 2 }} +{{- end }} + clientConfig: +{{- if and ($secretData) (not .Values.agentInjector.certificate.regenerate) }} + caBundle: {{ or (get $secretData "ca.crt") (get $secretData "ca.pem") }} +{{- else }} + caBundle: {{ $genCA.Cert | b64enc }} +{{- end }} + service: + name: {{ .Values.agentInjector.name }} + namespace: {{ include "traffic-manager.namespace" . }} + path: {{ .Values.agentInjector.webhook.servicePath }} + port: {{ .Values.agentInjector.webhook.port }} + rules: + - apiGroups: + - "" + apiVersions: + - v1 + operations: + - CREATE + - DELETE + resources: + - pods + scope: '*' + failurePolicy: {{ .Values.agentInjector.webhook.failurePolicy }} + reinvocationPolicy: {{ .Values.agentInjector.webhook.reinvocationPolicy }} + name: agent-injector-{{ include "traffic-manager.namespace" . }}.getambassador.io + sideEffects: {{ .Values.agentInjector.webhook.sideEffects }} + timeoutSeconds: {{ .Values.agentInjector.webhook.timeoutSeconds }} + namespaceSelector: +{{- if .Values.managerRbac.namespaced }} + matchExpressions: +{{- if and (eq (int (include "kube.version.major" .)) 1) (lt (int (include "kube.version.minor" .)) 21) }} + - key: app.kubernetes.io/name +{{- else }} + - key: kubernetes.io/metadata.name +{{- end }} + operator: In + values: +{{- range .Values.managerRbac.namespaces }} + - {{ . }} +{{- end }} +{{- else }} +{{ toYaml .Values.agentInjector.webhook.namespaceSelector | nindent 4 }} +{{- end }} +--- +apiVersion: v1 +kind: Secret +metadata: + name: {{ .Values.agentInjector.secret.name }} + namespace: {{ include "traffic-manager.namespace" . }} + labels: + {{- include "telepresence.labels" . | nindent 4 }} +data: +{{- if and ($secretData) (not .Values.agentInjector.certificate.regenerate) }} + ca.crt: {{ or (get $secretData "ca.crt") (get $secretData "ca.pem") }} + tls.crt: {{ or (get $secretData "tls.crt") (get $secretData "crt.pem") }} + tls.key: {{ or (get $secretData "tls.key") (get $secretData "key.pem") }} +{{- else }} + ca.crt: {{ $genCA.Cert | b64enc }} + tls.crt: {{ $genCert.Cert | b64enc }} + tls.key: {{ $genCert.Key | b64enc }} +{{- end }} +{{- end }} diff --git a/packages/system/telepresence/charts/telepresence/templates/clientRbac/cluster-scope.yaml b/packages/system/telepresence/charts/telepresence/templates/clientRbac/cluster-scope.yaml new file mode 100644 index 00000000..47916860 --- /dev/null +++ b/packages/system/telepresence/charts/telepresence/templates/clientRbac/cluster-scope.yaml @@ -0,0 +1,47 @@ +{{- /* +These are the cluster-wide rbac roles + bindings that will be used by users +who want to use telepresence once its components have been set +up in the cluster. +*/}} +{{- if not .Values.clientRbac.namespaced }} +{{- if .Values.clientRbac.create }} +{{- if (not .Values.clientRbac.subjects) }} +{{- /* fail comes out really ugly if we just do fail "the message here" */}} +{{- $msg := "You must set clientRbac.subjects to a list of valid rbac subjects. See the kubernetes docs for more: https://kubernetes.io/docs/reference/access-authn-authz/rbac/#referring-to-subjects" }} +{{- fail $msg }} +{{- end }} + +--- +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ include "telepresence.clientRbacName" . }} + labels: + {{- include "telepresence.labels" . | nindent 4 }} +rules: +- apiGroups: + - "" + resources: ["namespaces"] + verbs: ["get", "list", "watch"] +- apiGroups: + - "" + resources: ["services"] + verbs: ["get", "list", "watch"] +{{ include "telepresence.clientRbacInterceptRules" . }} + +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ include "telepresence.clientRbacName" . }} + labels: + {{- include "telepresence.labels" . | nindent 4 }} +subjects: +{{- toYaml .Values.clientRbac.subjects | nindent 0}} +roleRef: + kind: ClusterRole + name: {{ include "telepresence.clientRbacName" . }} + apiGroup: rbac.authorization.k8s.io + +{{- end }} +{{- end }} diff --git a/packages/system/telepresence/charts/telepresence/templates/clientRbac/connect.yaml b/packages/system/telepresence/charts/telepresence/templates/clientRbac/connect.yaml new file mode 100644 index 00000000..e02cbd48 --- /dev/null +++ b/packages/system/telepresence/charts/telepresence/templates/clientRbac/connect.yaml @@ -0,0 +1,42 @@ +{{- if .Values.clientRbac.create }} +{{- /* +Client must have the following RBAC in the traffic-manager.namespace to establish +a port-forward to the traffic-manager pod. +*/}} +kind: Role +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: traffic-manager-connect + namespace: {{ include "traffic-manager.namespace" . }} + labels: + {{- include "telepresence.labels" $ | nindent 4 }} +rules: + - apiGroups: [""] + resources: ["pods"] + verbs: ["get", "list", "watch"] + - apiGroups: [""] + resources: ["services"] + resourceNames: + - {{ include "traffic-manager.name" . }} + verbs: ["get"] + - apiGroups: [""] + resources: ["pods/portforward"] + verbs: ["create"] + +--- + +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: traffic-manager-connect + namespace: {{ include "traffic-manager.namespace" . }} + labels: + {{- include "telepresence.labels" $ | nindent 4 }} +subjects: +{{- toYaml .Values.clientRbac.subjects | nindent 0}} +roleRef: + apiGroup: rbac.authorization.k8s.io + name: traffic-manager-connect + kind: Role + +{{- end }} diff --git a/packages/system/telepresence/charts/telepresence/templates/clientRbac/namespace-scope.yaml b/packages/system/telepresence/charts/telepresence/templates/clientRbac/namespace-scope.yaml new file mode 100644 index 00000000..9337dbc9 --- /dev/null +++ b/packages/system/telepresence/charts/telepresence/templates/clientRbac/namespace-scope.yaml @@ -0,0 +1,42 @@ +{{- /* +These are the namespace-scoped rbac roles + bindings that will be used by users +who want to use telepresence once its components have been set +up in the cluster. +*/}} +{{- if .Values.clientRbac.create }} +{{- if .Values.clientRbac.namespaced }} + +{{- $namespaces := .Values.clientRbac.namespaces }} +{{- $subjects := .Values.clientRbac.subjects }} +{{- range $namespaces }} + +--- +kind: Role +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ include "telepresence.clientRbacName" $ }} + namespace: {{ . }} + labels: + {{- include "telepresence.labels" $ | nindent 4 }} +rules: +{{ include "telepresence.clientRbacInterceptRules" $ }} + +--- + +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ include "telepresence.clientRbacName" $ }} + namespace: {{ . }} + labels: + {{- include "telepresence.labels" $ | nindent 4 }} +subjects: +{{- toYaml $subjects | nindent 0}} +roleRef: + kind: Role + name: {{ include "telepresence.clientRbacName" $ }} + apiGroup: rbac.authorization.k8s.io + +{{- end }} +{{- end }} +{{- end }} diff --git a/packages/system/telepresence/charts/telepresence/templates/deployment.yaml b/packages/system/telepresence/charts/telepresence/templates/deployment.yaml new file mode 100644 index 00000000..9cc2c33c --- /dev/null +++ b/packages/system/telepresence/charts/telepresence/templates/deployment.yaml @@ -0,0 +1,332 @@ +{{- define "traffic-manager-env" }} + - name: SYSTEMA_HOST + value: {{ .systemaHost }} + - name: SYSTEMA_PORT + value: {{ .systemaPort | quote }} + - name: INTERCEPT_DISABLE_GLOBAL + value: {{ quote (default false .intercept.disableGlobal) }} + {{- with .agent.envoy }} + {{- if .logLevel }} + - name: AGENT_ENVOY_LOG_LEVEL + value: {{ .logLevel }} + {{- end }} + {{- if .serverPort }} + - name: AGENT_ENVOY_SERVER_PORT + value: {{ .serverPort | quote }} + {{- end }} + {{- if .adminPort }} + - name: AGENT_ENVOY_ADMIN_PORT + value: {{ .adminPort | quote }} + {{- end }} + {{- if .httpIdleTimeout }} + - name: AGENT_ENVOY_HTTP_IDLE_TIMEOUT + value: {{ .httpIdleTimeout }} + {{- end }} + {{- end }} +{{- end }} +{{- define "traffic-manager-mounts" }} + {{- if .licenseKey.create }} + - name: license + mountPath: /home/telepresence + readOnly: true + {{- end }} + {{- if .httpsProxy.rootCATLSSecret }} + - name: proxy-ca + mountPath: /var/run/secrets/proxy_tls + readOnly: true + {{- end }} +{{- end }} +{{- define "traffic-manager-vols" }} + {{- if .licenseKey.create }} + - name: license + secret: + defaultMode: 420 + secretName: {{ .licenseKey.secret.name }} + {{- end }} + {{- if .httpsProxy.rootCATLSSecret }} + - name: proxy-ca + secret: + defaultMode: 420 + secretName: {{ .httpsProxy.rootCATLSSecret }} + {{- end }} +{{- end }} +{{- /* verify that we either have access to Ambassador Cloud or have a agent.image defined */}} +{{- with .Values }} + {{- if not (or (and .systemaHost .systemaPort) (and .agent.image.name .agent.image.tag) (and .agentInjector.agentImage.name .agentInjector.agentImage.tag)) }} + {{- fail "Either systemaHost and systemaPort or agent.image.name and agent.image.tag must be defined" }} + {{- end }} +{{- end }} +{{- with .Values }} +{{- if not .rbac.only }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "traffic-manager.name" $ }} + namespace: {{ include "traffic-manager.namespace" $ }} + labels: + {{- include "telepresence.labels" $ | nindent 4 }} +spec: + replicas: {{ .replicaCount }} + selector: + matchLabels: + {{- include "telepresence.selectorLabels" $ | nindent 6 }} + template: + metadata: + {{- with .podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "telepresence.selectorLabels" $ | nindent 8 }} + {{- with .podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .image.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + securityContext: + {{- toYaml .podSecurityContext | nindent 8 }} + containers: + - name: {{ include "traffic-manager.name" $ }} + securityContext: + {{- toYaml .securityContext | nindent 12 }} + {{- with .image }} + image: "{{ .registry }}/{{ .name }}:{{ .tag | default $.Chart.AppVersion }}" + imagePullPolicy: {{ .pullPolicy }} + {{- end }} + env: + - name: LOG_LEVEL + value: {{ .logLevel }} + - name: SERVER_PORT + value: {{ .apiPort | quote }} + - name: POD_CIDR_STRATEGY + value: {{ .podCIDRStrategy }} + {{- with .podCIDRs }} + - name: POD_CIDRS + value: "{{ join " " . }}" + {{- end }} + - name: MUTATOR_WEBHOOK_PORT + value: {{ .agentInjector.webhook.port | quote }} + {{- with .tracing }} + {{- if .grpcPort }} + - name: TRACING_GRPC_PORT + value: {{ .grpcPort | quote }} + {{- end }} + {{- end }} + {{- with .telepresenceAPI }} + {{- if .port }} + - name: AGENT_REST_API_PORT + value: {{ .port | quote }} + {{- end }} + {{- end }} + {{- if .grpc }} + {{- if .grpc.maxReceiveSize }} + - name: GRPC_MAX_RECEIVE_SIZE + value: {{ .grpc.maxReceiveSize }} + {{- end }} + {{- end }} + - name: AGENT_ARRIVAL_TIMEOUT + value: {{ quote (default "30s" .timeouts.agentArrival) }} + {{- /* + Traffic agent injector configuration + */}} + {{- with .agentInjector }} + - name: AGENT_INJECT_POLICY + value: {{ .injectPolicy }} + - name: AGENT_INJECTOR_NAME + value: {{ .name | quote }} + {{- end }} + {{- /* + Traffic agent configuration + */}} + {{- if .agent.logLevel }} + - name: AGENT_LOG_LEVEL + value: {{ .agent.logLevel }} + {{- end }} + {{- if .agent.port }} + - name: AGENT_PORT + value: {{ .agent.port | quote }} + {{- end }} + {{- /* replaced by agent.appProtocolStrategy. Retained for backward compatibility */}} + {{- if $.Values.agentInjector.appProtocolStrategy }} + - name: AGENT_APP_PROTO_STRATEGY + value: {{ $.Values.agentInjector.appProtocolStrategy }} + {{- else }} + {{- if .agent.appProtocolStrategy }} + - name: AGENT_APP_PROTO_STRATEGY + value: {{ .agent.appProtocolStrategy }} + {{- end }} + {{- end }} + {{- /* replaced by agent.resources. Retained for backward compatibility */}} + {{- if $.Values.agentInjector.agentImage.resources }} + - name: AGENT_RESOURCES + value: '{{ toJson $.Values.agentInjector.agentImage.resources }}' + {{- else }} + {{- if .agent.resources }} + - name: AGENT_RESOURCES + value: '{{ toJson .agent.resources }}' + {{- end }} + {{- end }} + {{- /* replaced by agent.initResoruces. Retained for backward compatibility */}} + {{- if $.Values.agentInjector.agentImage.initResources }} + - name: AGENT_INIT_RESOURCES + value: '{{ toJson $.Values.agentInjector.agentImage.initResources }}' + {{- else }} + {{- if .agent.initResources }} + - name: AGENT_INIT_RESOURCES + value: '{{ toJson .agent.initResources }}' + {{- end }} + {{- end }} + {{- /* replaced by agent.image.name Retained for backward compatibility */}} + {{- if $.Values.agentInjector.agentImage.name }} + - name: AGENT_IMAGE + value: "{{ $.Values.agentInjector.agentImage.name }}:{{ $.Values.agentInjector.agentImage.tag | default $.Chart.AppVersion }}" + {{- else }} + {{- if .agent.image.name }} + - name: AGENT_IMAGE + value: "{{ .agent.image.name }}:{{ .agent.image.tag | default $.Chart.AppVersion }}" + {{- end }} + {{- end }} + {{- /* replaced by agent.image.registry Retained for backward compatibility */}} + {{- if $.Values.agentInjector.agentImage.registry }} + - name: AGENT_REGISTRY + value: {{ $.Values.agentInjector.agentImage.registry }} + {{- else }} + {{- if .agent.image.registry }} + - name: AGENT_REGISTRY + value: {{ .agent.image.registry }} + {{- end }} + {{- end }} + {{- with .agent.image.pullSecrets }} + - name: AGENT_IMAGE_PULL_SECRETS + value: '{{ toJson . }}' + {{- end }} + - name: AGENT_IMAGE_PULL_POLICY + value: {{ .agent.image.pullPolicy }} + {{- if .prometheus.port }} # 0 is false + - name: PROMETHEUS_PORT + value: "{{ .prometheus.port }}" + {{- end }} + - name: MANAGER_NAMESPACE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + - name: POD_IP + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: status.podIP + {{- if .managerRbac.namespaced }} + {{- with .managerRbac.namespaces }} + - name: MANAGED_NAMESPACES + value: "{{ join " " . }}" + {{- end }} + {{- end }} + {{- /* + Client configuration + */}} + {{- with .client }} + - name: CLIENT_CONNECTION_TTL + value: {{ .connectionTTL }} + {{- /* replaced by client.routing. Retained for backward compatibility */}} + {{- with $.Values.dnsConfig }} + {{- if .alsoProxySubnets }} + - name: CLIENT_ROUTING_ALSO_PROXY_SUBNETS + value: "{{ join " " .alsoProxySubnets }}" + {{- end }} + {{- if .neverProxySubnets }} + - name: CLIENT_ROUTING_NEVER_PROXY_SUBNETS + value: "{{ join " " .neverProxySubnets }}" + {{- end }} + {{- else }} + {{- with .routing }} + {{- if .alsoProxySubnets }} + - name: CLIENT_ROUTING_ALSO_PROXY_SUBNETS + value: "{{ join " " .alsoProxySubnets }}" + {{- end }} + {{- if .neverProxySubnets }} + - name: CLIENT_ROUTING_NEVER_PROXY_SUBNETS + value: "{{ join " " .neverProxySubnets }}" + {{- end }} + {{- if .allowConflictingSubnets }} + - name: CLIENT_ROUTING_ALLOW_CONFLICTING_SUBNETS + value: "{{ join " " .allowConflictingSubnets }}" + {{- end }} + {{- end }} + {{- end }} + {{- with .dns }} + {{- with .excludeSuffixes }} + - name: CLIENT_DNS_EXCLUDE_SUFFIXES + value: "{{ join " " . }}" + {{- end }} + {{- with .includeSuffixes }} + - name: CLIENT_DNS_INCLUDE_SUFFIXES + value: "{{ join " " . }}" + {{- end }} + {{- end }} + {{- end }} + {{- if and .trafficManager .trafficManager.envTemplate }} + {{- template "traffic-manager-env" . }} + {{- end }} + ports: + - name: api + containerPort: {{ .apiPort }} + - name: https + containerPort: {{ .agentInjector.webhook.port }} + {{- if .prometheus.port }} # 0 is false + - name: prometheus + containerPort: {{ .prometheus.port }} + {{- end }} + {{- with .tracing }} + - name: grpc-trace + containerPort: {{ .grpcPort }} + {{- end }} + {{- with .livenessProbe }} + livenessProbe: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .readinessProbe }} + readinessProbe: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + volumeMounts: + - name: tls + mountPath: /var/run/secrets/tls + readOnly: true + {{- if and .trafficManager .trafficManager.mountsTemplate }} + {{- template "traffic-manager-mounts" . }} + {{- end }} + {{- with .nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .priorityClassName }} + priorityClassName: {{ . | quote }} + {{- end }} + volumes: + - name: tls + secret: + defaultMode: 420 + secretName: {{ .agentInjector.secret.name }} + {{- if and .trafficManager .trafficManager.volsTemplate }} + {{- template "traffic-manager-vols" . }} + {{- end }} + serviceAccount: traffic-manager + serviceAccountName: traffic-manager +{{- end }} +{{- end }} diff --git a/packages/system/telepresence/charts/telepresence/templates/intercept-env-configmap.yaml b/packages/system/telepresence/charts/telepresence/templates/intercept-env-configmap.yaml new file mode 100644 index 00000000..7a0eef6b --- /dev/null +++ b/packages/system/telepresence/charts/telepresence/templates/intercept-env-configmap.yaml @@ -0,0 +1,12 @@ +{{- if not .Values.rbac.only }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: telepresence-intercept-env + namespace: {{ include "traffic-manager.namespace" . }} +data: + excluded: | + {{- range .Values.intercept.environment.excluded }} + {{ . }} + {{- end }} +{{- end }} diff --git a/packages/system/telepresence/charts/telepresence/templates/licenseSecret.yaml b/packages/system/telepresence/charts/telepresence/templates/licenseSecret.yaml new file mode 100644 index 00000000..aca98299 --- /dev/null +++ b/packages/system/telepresence/charts/telepresence/templates/licenseSecret.yaml @@ -0,0 +1,14 @@ +{{- if not .Values.rbac.only }} +{{- if and .Values.licenseKey.create .Values.licenseKey.secret.create }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ .Values.licenseKey.secret.name }} + namespace: {{ include "traffic-manager.namespace" . }} + labels: + {{- include "telepresence.labels" . | nindent 4 }} +data: + hostDomain: {{ .Values.licenseKey.hostDomain | default "auth.datawire.io" | b64enc | quote }} + license: {{ .Values.licenseKey.value | b64enc | quote }} +{{- end }} +{{- end }} diff --git a/packages/system/telepresence/charts/telepresence/templates/post-upgrade-hook.yaml b/packages/system/telepresence/charts/telepresence/templates/post-upgrade-hook.yaml new file mode 100644 index 00000000..9c1bbc1a --- /dev/null +++ b/packages/system/telepresence/charts/telepresence/templates/post-upgrade-hook.yaml @@ -0,0 +1,85 @@ +{{- if not .Values.rbac.only }} +apiVersion: batch/v1 +kind: Job +metadata: + name: upgrade-legacy + namespace: {{ include "traffic-manager.namespace" . }} + labels: + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + app.kubernetes.io/version: {{ .Chart.AppVersion }} + helm.sh/chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" + annotations: + "helm.sh/hook": post-upgrade + "helm.sh/hook-weight": "-5" + "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded +spec: + template: + metadata: + name: upgrade-legacy + labels: + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + helm.sh/chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" + spec: + restartPolicy: Never + securityContext: + {{- toYaml .Values.hooks.podSecurityContext | nindent 8 }} + {{- with .Values.hooks.curl.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: upgrade-legacy + securityContext: + {{- if .Values.hooks.securityContext }} + {{- toYaml .Values.hooks.securityContext | nindent 12 }} + {{- else }} + {{- toYaml .Values.securityContext | nindent 12 }} + {{- end }} + image: "{{ .Values.hooks.curl.registry }}/{{ .Values.hooks.curl.image }}:{{ .Values.hooks.curl.tag }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + volumeMounts: + - name: secret-volume + mountPath: /secret + env: + - name: CURL_CA_BUNDLE + value: /secret/ca.crt + resources: + {{- toYaml .Values.hooks.resources | nindent 12 }} + {{- /* + Helm considers applying a deployment a success. It doesn't wait for readinessProbes + unless explicitly told to do so by passing --wait and there's no guarantee that's + been done. Therefore, a retry is needed here to ensure proper upgrade. + */}} + args: + - '--connect-timeout' + - '5' + - '--retry' + - '5' + - '--retry-delay' + - '2' + - '--retry-max-time' + - '20' + - '--retry-all-errors' + - '--fail' + - '--request' + - POST + - 'https://{{ .Values.agentInjector.name }}.{{ include "traffic-manager.namespace" . }}:{{ .Values.agentInjector.webhook.port }}/upgrade-legacy' + volumes: + - name: secret-volume + secret: + secretName: {{ .Values.agentInjector.secret.name }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} +{{- end }} diff --git a/packages/system/telepresence/charts/telepresence/templates/pre-delete-hook.yaml b/packages/system/telepresence/charts/telepresence/templates/pre-delete-hook.yaml new file mode 100644 index 00000000..e6448b4e --- /dev/null +++ b/packages/system/telepresence/charts/telepresence/templates/pre-delete-hook.yaml @@ -0,0 +1,73 @@ +{{- if not .Values.rbac.only }} +apiVersion: batch/v1 +kind: Job +metadata: + name: uninstall-agents + namespace: {{ include "traffic-manager.namespace" . }} + labels: + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + app.kubernetes.io/version: {{ .Chart.AppVersion }} + helm.sh/chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" + 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-weight": "-5" + "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded +spec: + backoffLimit: 1 + template: + metadata: + name: uninstall-agents + labels: + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + helm.sh/chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" + spec: + securityContext: + {{- toYaml .Values.hooks.podSecurityContext | nindent 8 }} + restartPolicy: Never + {{- with .Values.hooks.curl.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: uninstall-agents + securityContext: + {{- if .Values.hooks.securityContext }} + {{- toYaml .Values.hooks.securityContext | nindent 12 }} + {{- else }} + {{- toYaml .Values.securityContext | nindent 12 }} + {{- end }} + image: "{{ .Values.hooks.curl.registry }}/{{ .Values.hooks.curl.image }}:{{ .Values.hooks.curl.tag }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + volumeMounts: + - name: secret-volume + mountPath: /secret + env: + - name: CURL_CA_BUNDLE + value: /secret/ca.crt + resources: + {{- toYaml .Values.hooks.resources | nindent 12 }} + command: + - sh + - -c + args: + - 'curl --fail --connect-timeout 5 --max-time 60 --request DELETE https://{{ .Values.agentInjector.name }}.{{ include "traffic-manager.namespace" . }}:{{ .Values.agentInjector.webhook.port }}/uninstall || exit 0' + volumes: + - name: secret-volume + secret: + secretName: {{ .Values.agentInjector.secret.name }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} +{{- end }} diff --git a/packages/system/telepresence/charts/telepresence/templates/service.yaml b/packages/system/telepresence/charts/telepresence/templates/service.yaml new file mode 100644 index 00000000..02bed570 --- /dev/null +++ b/packages/system/telepresence/charts/telepresence/templates/service.yaml @@ -0,0 +1,60 @@ +{{- if not .Values.rbac.only }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "traffic-manager.name" . }} + namespace: {{ include "traffic-manager.namespace" . }} + labels: + {{- include "telepresence.labels" . | nindent 4 }} +spec: + type: {{ .Values.service.type }} + clusterIP: None + ports: + - name: api + port: {{ .Values.apiPort }} + targetPort: api + {{- with .Values.tracing }} + {{- if .grpcPort }} + - name: grpc-trace + port: {{ .grpcPort }} + targetPort: "grpc-trace" + {{- end }} + {{- end }} + + selector: + {{- include "telepresence.selectorLabels" . | nindent 4 }} +--- +apiVersion: v1 +kind: Service +metadata: + name: {{ .Values.agentInjector.name }} + namespace: {{ include "traffic-manager.namespace" . }} + labels: + {{- include "telepresence.labels" . | nindent 4 }} +spec: + type: {{ .Values.service.type }} + ports: + - name: https + port: {{ .Values.agentInjector.webhook.port }} + targetPort: https + selector: + {{- include "telepresence.selectorLabels" . | nindent 4 }} +{{- if .Values.prometheus.port }} # 0 is false +--- +apiVersion: v1 +kind: Service +metadata: + name: telepresence-prometheus + namespace: {{ include "traffic-manager.namespace" . }} + labels: + name: telepresence-prometheus +spec: + type: {{ .Values.service.type }} + ports: + - name: telepresence-prometheus + port: 80 + targetPort: prometheus + selector: + {{- include "telepresence.selectorLabels" . | nindent 4 }} +{{- end }} +{{- end }} diff --git a/packages/system/telepresence/charts/telepresence/templates/tests/test-connection.yaml b/packages/system/telepresence/charts/telepresence/templates/tests/test-connection.yaml new file mode 100644 index 00000000..a292adee --- /dev/null +++ b/packages/system/telepresence/charts/telepresence/templates/tests/test-connection.yaml @@ -0,0 +1,22 @@ +{{- if not .Values.rbac.only }} +apiVersion: v1 +kind: Pod +metadata: + name: "{{ include "traffic-manager.name" . }}-test-connection" + namespace: {{ include "traffic-manager.namespace" . }} + labels: + {{- include "telepresence.labels" . | nindent 4 }} + annotations: + "helm.sh/hook": test-success +spec: + {{- with .Values.hooks.busybox.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 2 }} + {{- end }} + containers: + - name: wget + image: "{{ .Values.hooks.busybox.registry }}/{{ .Values.hooks.busybox.image }}:{{ .Values.hooks.busybox.tag }}" + command: ['wget'] + args: ['{{ include "traffic-manager.name" . }}:8081'] + restartPolicy: Never +{{- end }} diff --git a/packages/system/telepresence/charts/telepresence/templates/trafficManager-configmap.yaml b/packages/system/telepresence/charts/telepresence/templates/trafficManager-configmap.yaml new file mode 100644 index 00000000..05b8fa3b --- /dev/null +++ b/packages/system/telepresence/charts/telepresence/templates/trafficManager-configmap.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "traffic-manager.name" $ }} + namespace: {{ include "traffic-manager.namespace" . }} +data: +{{- if .Values.client }} + client.yaml: | + {{- toYaml .Values.client | nindent 4 }} +{{- end }} +{{- if .Values.trafficManager }} + traffic-manager.yaml: | + {{- toYaml .Values.trafficManager | nindent 4 }} +{{- end }} diff --git a/packages/system/telepresence/charts/telepresence/templates/trafficManagerRbac/cloud-token.yaml b/packages/system/telepresence/charts/telepresence/templates/trafficManagerRbac/cloud-token.yaml new file mode 100644 index 00000000..fd7aab11 --- /dev/null +++ b/packages/system/telepresence/charts/telepresence/templates/trafficManagerRbac/cloud-token.yaml @@ -0,0 +1,39 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + namespace: {{ include "traffic-manager.namespace" . }} + name: traffic-manager-cloud-token + labels: {{- include "telepresence.labels" . | nindent 4 }} +rules: + - apiGroups: + - "" + resources: + - configmaps + verbs: + - list + - watch + - patch + +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: traffic-manager-cloud-token + namespace: {{ include "traffic-manager.namespace" . }} + labels: {{- include "telepresence.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: traffic-manager-cloud-token +subjects: + - kind: ServiceAccount + name: traffic-manager + namespace: {{ include "traffic-manager.namespace" . }} + +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: traffic-manager-agent-cloud-token + namespace: {{ include "traffic-manager.namespace" . }} + labels: {{- include "telepresence.labels" . | nindent 4 }} \ No newline at end of file diff --git a/packages/system/telepresence/charts/telepresence/templates/trafficManagerRbac/cluster-scope.yaml b/packages/system/telepresence/charts/telepresence/templates/trafficManagerRbac/cluster-scope.yaml new file mode 100644 index 00000000..ee84159b --- /dev/null +++ b/packages/system/telepresence/charts/telepresence/templates/trafficManagerRbac/cluster-scope.yaml @@ -0,0 +1,94 @@ +{{- if .Values.managerRbac.create }} +{{- if (not .Values.managerRbac.namespaced) }} +{{- /* +This file contains all cluster-scoped permissions that the traffic manager needs. +This will be larger if namespaced: false, or smaller if it is true +This will also likely expand over time as we move more things from the clients +domain into the traffic-manager. But the good news there is that it will +require less permissions in clientRbac.yaml +*/}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: traffic-manager-{{ include "traffic-manager.namespace" . }} + labels: + {{- include "telepresence.labels" . | nindent 4 }} +rules: +- apiGroups: + - "" + resources: + - services + verbs: + - update {{/* Only needed for upgrade of older versions */}} +- apiGroups: + - "" + resources: + - nodes + - pods + - services + verbs: + - list + - get + - watch +{{- /* Needed to be able to find the cluster DNS resolver */}} +- apiGroups: + - "" + resources: + - namespaces + verbs: + - get + - list +- apiGroups: + - "" + resources: + - configmaps + verbs: + - create +- apiGroups: + - "" + resources: + - configmaps + verbs: + - list + - get + - watch + - update + - delete + resourceNames: + - telepresence-agents + - telepresence-intercept-env +- apiGroups: + - "apps" + resources: + - deployments + - replicasets + - statefulsets + verbs: + - get + - list + - patch + - update {{/* Only needed for upgrade of older versions */}} +- apiGroups: + - "events.k8s.io" + resources: + - events + verbs: + - get + - watch +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: traffic-manager-{{ include "traffic-manager.namespace" . }} + labels: + {{- include "telepresence.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: traffic-manager-{{ include "traffic-manager.namespace" . }} +subjects: +- kind: ServiceAccount + name: traffic-manager + namespace: {{ include "traffic-manager.namespace" . }} +{{- end }} +{{- end }} diff --git a/packages/system/telepresence/charts/telepresence/templates/trafficManagerRbac/namespace-claim.yaml b/packages/system/telepresence/charts/telepresence/templates/trafficManagerRbac/namespace-claim.yaml new file mode 100644 index 00000000..711d7639 --- /dev/null +++ b/packages/system/telepresence/charts/telepresence/templates/trafficManagerRbac/namespace-claim.yaml @@ -0,0 +1,23 @@ +{{- if .Values.managerRbac.create }} +{{- if .Values.managerRbac.namespaced }} +{{- /* +These configmaps will ensure that only one traffic manager can be installed +to manage any given namespace. +This only works provided traffic managers are being managed through the helm chart, and are all namespaced. +*/}} +{{- range .Values.managerRbac.namespaces }} +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: traffic-manager-claim + namespace: {{ . }} + labels: + {{- include "telepresence.labels" $ | nindent 4 }} +data: + owned-by: {{ include "traffic-manager.namespace" $ }} + +{{- end }} + +{{- end }} +{{- end }} diff --git a/packages/system/telepresence/charts/telepresence/templates/trafficManagerRbac/namespace-scope.yaml b/packages/system/telepresence/charts/telepresence/templates/trafficManagerRbac/namespace-scope.yaml new file mode 100644 index 00000000..8c4fa5d5 --- /dev/null +++ b/packages/system/telepresence/charts/telepresence/templates/trafficManagerRbac/namespace-scope.yaml @@ -0,0 +1,150 @@ +{{- if .Values.managerRbac.create }} +{{- /* +This file contains the various namespace-scoped roles + bindings that the traffic-manager needs. +This will likely expand over time as we move more things from the clients +domain into the traffic-manager. But the good news there is that it will +require less permissions in clientRbac.yaml +*/}} +{{- if .Values.managerRbac.namespaced }} + +{{- if not (has (include "traffic-manager.namespace" .) .Values.managerRbac.namespaces) }} +{{- fail (printf "Namespace %s must be included in managerRbac.namespaces (managerRbac.namespaces contains: %s)" (include "traffic-manager.namespace" .) (join "," .Values.managerRbac.namespaces)) }} +{{- end }} + +{{- range .Values.managerRbac.namespaces }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: traffic-manager + namespace: {{ . }} + labels: + {{- include "telepresence.labels" $ | nindent 4 }} +rules: +- apiGroups: + - "" + resources: + - services + verbs: + - update {{/* Only needed for upgrade of older versions */}} +- apiGroups: + - "" + resources: + - pods + - services + verbs: + - list + - get + - watch +- apiGroups: + - "" + resources: + - configmaps + verbs: + - create +- apiGroups: + - "" + resources: + - configmaps + verbs: + - list + - get + - watch + - update + - delete + resourceNames: + - telepresence-agents + - telepresence-intercept-env +- apiGroups: + - "apps" + resources: + - deployments + - replicasets + - statefulsets + verbs: + - get + - list + - patch + - update {{/* Only needed for upgrade of older versions */}} +- apiGroups: + - "events.k8s.io" + resources: + - events + verbs: + - get + - watch +{{- if eq . (include "traffic-manager.namespace" $) }} +{{- /* Must be able to get the manager namespace in order to get the cluster-id */}} +- apiGroups: + - "" + resources: + - namespaces + resourceNames: + - {{ . }} + verbs: + - get +{{- /* +Must be able to make an unsuccessful attempt to create a dummy service in order to receive +the error message containing correct service CIDR +*/}} +- apiGroups: + - "" + resources: + - services + verbs: + - create +{{- end }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: traffic-manager + namespace: {{ . }} + labels: + {{- include "telepresence.labels" $ | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: traffic-manager +subjects: +- kind: ServiceAccount + name: traffic-manager + namespace: {{ include "traffic-manager.namespace" $ }} +{{- end }} + +{{- else }} + +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + namespace: {{ include "traffic-manager.namespace" . }} + name: traffic-manager + labels: + {{- include "telepresence.labels" . | nindent 4 }} +rules: +- apiGroups: + - "" + resources: + - services + verbs: + - create + +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: traffic-manager + namespace: {{ include "traffic-manager.namespace" . }} + labels: + {{- include "telepresence.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: traffic-manager +subjects: +- kind: ServiceAccount + name: traffic-manager + namespace: {{ include "traffic-manager.namespace" . }} +{{- end }} +{{- end }} diff --git a/packages/system/telepresence/charts/telepresence/templates/trafficManagerRbac/service-account.yaml b/packages/system/telepresence/charts/telepresence/templates/trafficManagerRbac/service-account.yaml new file mode 100644 index 00000000..32fa4dc6 --- /dev/null +++ b/packages/system/telepresence/charts/telepresence/templates/trafficManagerRbac/service-account.yaml @@ -0,0 +1,11 @@ +{{- if .Values.managerRbac.create }} +{{- /* This file contains the serviceAccount used for the traffic-manager deployment. */}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: traffic-manager + namespace: {{ include "traffic-manager.namespace" . }} + labels: + {{- include "telepresence.labels" . | nindent 4 }} + +{{- end }} diff --git a/packages/system/telepresence/charts/telepresence/values.yaml b/packages/system/telepresence/charts/telepresence/values.yaml new file mode 100644 index 00000000..081bac7f --- /dev/null +++ b/packages/system/telepresence/charts/telepresence/values.yaml @@ -0,0 +1,145 @@ +affinity: {} +agent: + appProtocolStrategy: http2Probe + envoy: + adminPort: 19000 + httpIdleTimeout: 70s + logLevel: warning + serverPort: 18000 + image: + name: null + pullPolicy: IfNotPresent + pullSecrets: [] + registry: docker.io/datawire + tag: null + initResources: {} + logLevel: null + port: 9900 + resources: {} +agentInjector: + agentImage: {} + certificate: + regenerate: false + injectPolicy: OnDemand + name: agent-injector + secret: + name: mutator-webhook-tls + webhook: + admissionReviewVersions: + - v1 + failurePolicy: Ignore + name: agent-injector-webhook + namespaceSelector: + matchExpressions: + - key: kubernetes.io/metadata.name + operator: NotIn + values: + - kube-system + - kube-node-lease + port: 443 + reinvocationPolicy: IfNeeded + servicePath: /traffic-agent + sideEffects: None + timeoutSeconds: 5 +ambassador-agent: + enabled: true + securityContext: + readOnlyRootFilesystem: true + runAsNonRoot: true + runAsUser: 1000 +apiPort: 8081 +client: + connectionTTL: 24h + dns: + excludeSuffixes: + - .com + - .io + - .net + - .org + - .ru + includeSuffixes: [] + routing: + allowConflictingSubnets: [] + alsoProxySubnets: [] + neverProxySubnets: [] +clientRbac: + create: false + namespaced: false + namespaces: + - ambassador + ruleExtras: true + subjects: [] +grpc: + maxReceiveSize: 4Mi +hooks: + busybox: + image: busybox + imagePullSecrets: [] + registry: docker.io + tag: latest + curl: + image: curlimages/curl + imagePullSecrets: [] + registry: docker.io + tag: 8.1.1 + podSecurityContext: {} + resources: {} + securityContext: {} +httpsProxy: + rootCATLSSecret: "" +image: + imagePullSecrets: [] + name: ambassador-telepresence-manager + pullPolicy: IfNotPresent + registry: docker.io/datawire + tag: "" +intercept: + disableGlobal: false + environment: + excluded: [] +isCI: false +licenseKey: + create: false + secret: + create: true + name: systema-license + value: "" +livenessProbe: {} +logLevel: info +managerRbac: + create: true + namespaced: false + namespaces: [] +nodeSelector: {} +podAnnotations: {} +podCIDRStrategy: auto +podCIDRs: [] +podLabels: {} +podSecurityContext: {} +priorityClassName: "" +prometheus: + port: 0 +rbac: + only: false +readinessProbe: {} +replicaCount: 1 +resources: {} +securityContext: + readOnlyRootFilesystem: true + runAsNonRoot: true + runAsUser: 1000 +service: + type: ClusterIP +systemaHost: app.getambassador.io +systemaPort: 443 +telepresenceAPI: + port: 0 +timeouts: + agentArrival: 30s +tolerations: [] +tracing: + grpcPort: 15766 +trafficManager: + envTemplate: true + mountsTemplate: true + volsTemplate: true diff --git a/packages/system/telepresence/values.yaml b/packages/system/telepresence/values.yaml new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/packages/system/telepresence/values.yaml @@ -0,0 +1 @@ + diff --git a/packages/system/victoria-metrics-operator/Chart.yaml b/packages/system/victoria-metrics-operator/Chart.yaml new file mode 100644 index 00000000..3a841775 --- /dev/null +++ b/packages/system/victoria-metrics-operator/Chart.yaml @@ -0,0 +1,2 @@ +name: cozy-victoria-metrics-operator +version: 1.0.0 diff --git a/packages/system/victoria-metrics-operator/Makefile b/packages/system/victoria-metrics-operator/Makefile new file mode 100644 index 00000000..a2f89f86 --- /dev/null +++ b/packages/system/victoria-metrics-operator/Makefile @@ -0,0 +1,23 @@ +NAME=victoria-metrics-operator +NAMESPACE=cozy-victoria-metrics-operator + +show: + helm template --dry-run=server -n $(NAMESPACE) $(NAME) . + +apply: + helm upgrade -i -n $(NAMESPACE) $(NAME) . + +diff: + helm diff upgrade --allow-unreleased --normalize-manifests -n $(NAMESPACE) $(NAME) . + +update: + rm -rf charts + # VictoriaMetrics operator + helm repo add vm https://victoriametrics.github.io/helm-charts/ + helm repo update vm + helm pull vm/victoria-metrics-operator --untar --untardir charts + # Prometheus CRDs + helm repo add prometheus-community https://prometheus-community.github.io/helm-charts + helm repo update prometheus-community + helm pull prometheus-community/prometheus-operator-crds --untar --untardir charts + rm -f -- `find charts/prometheus-operator-crds/templates -maxdepth 1 -mindepth 1 | grep -v 'servicemonitor\|podmonitor\|prometheusrule\|probe'` diff --git a/packages/system/victoria-metrics-operator/charts/prometheus-operator-crds/.helmignore b/packages/system/victoria-metrics-operator/charts/prometheus-operator-crds/.helmignore new file mode 100644 index 00000000..0e8a0eb3 --- /dev/null +++ b/packages/system/victoria-metrics-operator/charts/prometheus-operator-crds/.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/packages/system/victoria-metrics-operator/charts/prometheus-operator-crds/Chart.yaml b/packages/system/victoria-metrics-operator/charts/prometheus-operator-crds/Chart.yaml new file mode 100644 index 00000000..b63b117d --- /dev/null +++ b/packages/system/victoria-metrics-operator/charts/prometheus-operator-crds/Chart.yaml @@ -0,0 +1,34 @@ +annotations: + artifacthub.io/links: | + - name: Chart Source + url: https://github.com/prometheus-community/helm-charts + artifacthub.io/maintainers: | + - name: dacamposol + email: dacamposol@gmail.com + - name: desaintmartin + email: cedric@desaintmartin.fr + - name: QuentinBisson + email: quentin.bisson@gmail.com +apiVersion: v2 +appVersion: 0.67.0 +description: 'A Helm chart that collects custom resource definitions (CRDs) from the + Prometheus Operator, allowing for seamless integration with GitOps tools ' +icon: https://raw.githubusercontent.com/prometheus/prometheus.github.io/master/assets/prometheus_logo-cb55bb5c346.png +keywords: +- prometheus +- crds +kubeVersion: '>=1.16.0-0' +maintainers: +- email: dacamposol@gmail.com + name: dacamposol +- email: cedric@desaintmartin.fr + name: desaintmartin +- email: quentin.bisson@gmail.com + name: QuentinBisson +- email: github@jkroepke.de + name: jkroepke +name: prometheus-operator-crds +sources: +- https://github.com/prometheus-community/helm-charts +type: application +version: 5.1.0 diff --git a/packages/system/victoria-metrics-operator/charts/prometheus-operator-crds/README.md b/packages/system/victoria-metrics-operator/charts/prometheus-operator-crds/README.md new file mode 100644 index 00000000..4bf1f35a --- /dev/null +++ b/packages/system/victoria-metrics-operator/charts/prometheus-operator-crds/README.md @@ -0,0 +1,57 @@ +# Prometheus Operator CRDs + +This chart brings Custom Resource Definitions (CRD) used by Prometheus Operator introducing the API group `monitoring.coreos.com`. The Prometheus Operator uses Kubernetes custom resources to simplify the deployment and configuration of Prometheus, Alertmanager and related monitoring components. + +For more information on Prometheus Operator and CRDs, please, see [documentation](https://prometheus-operator.dev/docs/operator/design/). + +## Prerequisites + +- Kubernetes >= 1.16.0 +- Helm 3 + +## Get Repository Info + +```console +helm repo add prometheus-community https://prometheus-community.github.io/helm-charts +helm repo update +``` + +_See [`helm repo`](https://helm.sh/docs/helm/helm_repo/) for command documentation._ + + +## Install Chart + +```console +helm install [RELEASE_NAME] prometheus-community/prometheus-operator-crds +``` + +_See [configuration](#configuring) below._ + +_See [helm install](https://helm.sh/docs/helm/helm_install/) for command documentation._ + +## Uninstall Chart + +```console +helm uninstall [RELEASE_NAME] +``` + +This removes all the Kubernetes components associated with the chart and deletes the release +_including_ resources of Kind `Prometheus`, `Alertmanager`, `ServiceMonitor`, etc. + +_See [helm uninstall](https://helm.sh/docs/helm/helm_uninstall/) for command documentation._ + +## Upgrading Chart + +```console +helm upgrade [RELEASE_NAME] [CHART] --install +``` + +_See [helm upgrade](https://helm.sh/docs/helm/helm_upgrade/) for command documentation._ + +## Configuring + +See [Customizing the Chart Before Installing](https://helm.sh/docs/intro/using_helm/#customizing-the-chart-before-installing). To see all configurable options with detailed comments, visit the chart's [values.yaml](./values.yaml), or run these configuration commands: + +```console +helm show values prometheus-community/prometheus-operator-crds +``` diff --git a/packages/system/victoria-metrics-operator/charts/prometheus-operator-crds/hack/update_crds.sh b/packages/system/victoria-metrics-operator/charts/prometheus-operator-crds/hack/update_crds.sh new file mode 100644 index 00000000..545fa469 --- /dev/null +++ b/packages/system/victoria-metrics-operator/charts/prometheus-operator-crds/hack/update_crds.sh @@ -0,0 +1,44 @@ +#!/bin/bash + +if [[ $(uname -s) = "Darwin" ]]; then + VERSION="$(grep ^appVersion ../Chart.yaml | sed 's/appVersion: /v/g')" +else + VERSION="$(grep ^appVersion ../Chart.yaml | sed 's/appVersion:\s/v/g')" +fi + +FILES=( + "crd-alertmanagerconfigs.yaml : monitoring.coreos.com_alertmanagerconfigs.yaml" + "crd-alertmanagers.yaml : monitoring.coreos.com_alertmanagers.yaml" + "crd-podmonitors.yaml : monitoring.coreos.com_podmonitors.yaml" + "crd-probes.yaml : monitoring.coreos.com_probes.yaml" + "crd-prometheusagents.yaml : monitoring.coreos.com_prometheusagents.yaml" + "crd-prometheuses.yaml : monitoring.coreos.com_prometheuses.yaml" + "crd-prometheusrules.yaml : monitoring.coreos.com_prometheusrules.yaml" + "crd-servicemonitors.yaml : monitoring.coreos.com_servicemonitors.yaml" + "crd-scrapeconfigs.yaml : monitoring.coreos.com_scrapeconfigs.yaml" + "crd-thanosrulers.yaml : monitoring.coreos.com_thanosrulers.yaml" +) + +for line in "${FILES[@]}"; do + DESTINATION=$(echo "${line%%:*}" | xargs) + SOURCE=$(echo "${line##*:}" | xargs) + + URL="https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/$VERSION/example/prometheus-operator-crd/$SOURCE" + + echo -e "Downloading Prometheus Operator CRD with Version ${VERSION}:\n${URL}\n" + + echo "# ${URL}" > ../templates/"${DESTINATION}" + + if ! curl --silent --retry-all-errors --fail --location "${URL}" >> ../templates/"${DESTINATION}"; then + echo -e "Failed to download ${URL}!" + exit 1 + fi + # Update or insert annotations block + if yq -e '.metadata.annotations' ../templates/"${DESTINATION}" >/dev/null; then + sed -i '/^ annotations:$/a {{- with .Values.annotations }}\n{{- toYaml . | nindent 4 }}\n{{- end }}' ../templates/"${DESTINATION}" + else + sed -i '/^metadata:$/a {{- with .Values.annotations }}\n annotations:\n{{- toYaml . | nindent 4 }}\n{{- end }}' ../templates/"${DESTINATION}" + fi +done + +exit diff --git a/packages/system/victoria-metrics-operator/charts/prometheus-operator-crds/templates/crd-podmonitors.yaml b/packages/system/victoria-metrics-operator/charts/prometheus-operator-crds/templates/crd-podmonitors.yaml new file mode 100644 index 00000000..b4bd16a6 --- /dev/null +++ b/packages/system/victoria-metrics-operator/charts/prometheus-operator-crds/templates/crd-podmonitors.yaml @@ -0,0 +1,688 @@ +# https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.67.0/example/prometheus-operator-crd/monitoring.coreos.com_podmonitors.yaml +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: +{{- with .Values.annotations }} +{{- toYaml . | nindent 4 }} +{{- end }} + controller-gen.kubebuilder.io/version: v0.11.1 + creationTimestamp: null + name: podmonitors.monitoring.coreos.com +spec: + group: monitoring.coreos.com + names: + categories: + - prometheus-operator + kind: PodMonitor + listKind: PodMonitorList + plural: podmonitors + shortNames: + - pmon + singular: podmonitor + scope: Namespaced + versions: + - name: v1 + schema: + openAPIV3Schema: + description: PodMonitor defines monitoring for a set of pods. + 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: Specification of desired Pod selection for target discovery + by Prometheus. + properties: + attachMetadata: + description: Attaches node metadata to discovered targets. Requires + Prometheus v2.35.0 and above. + properties: + node: + description: When set to true, Prometheus must have permissions + to get Nodes. + type: boolean + type: object + jobLabel: + description: The label to use to retrieve the job name from. + type: string + labelLimit: + description: Per-scrape limit on number of labels that will be accepted + for a sample. Only valid in Prometheus versions 2.27.0 and newer. + format: int64 + type: integer + labelNameLengthLimit: + description: Per-scrape limit on length of labels name that will be + accepted for a sample. Only valid in Prometheus versions 2.27.0 + and newer. + format: int64 + type: integer + labelValueLengthLimit: + description: Per-scrape limit on length of labels value that will + be accepted for a sample. Only valid in Prometheus versions 2.27.0 + and newer. + format: int64 + type: integer + namespaceSelector: + description: Selector to select which namespaces the Endpoints objects + are discovered from. + properties: + any: + description: Boolean describing whether all namespaces are selected + in contrast to a list restricting them. + type: boolean + matchNames: + description: List of namespace names to select from. + items: + type: string + type: array + type: object + podMetricsEndpoints: + description: A list of endpoints allowed as part of this PodMonitor. + items: + description: PodMetricsEndpoint defines a scrapeable endpoint of + a Kubernetes Pod serving Prometheus metrics. + properties: + authorization: + description: Authorization section for this endpoint + properties: + credentials: + description: Selects a key of a Secret in the namespace + that contains the credentials for authentication. + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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: + description: "Defines the authentication type. The value + is case-insensitive. \n \"Basic\" is not a supported value. + \n Default: \"Bearer\"" + type: string + type: object + basicAuth: + description: 'BasicAuth allow an endpoint to authenticate over + basic authentication. More info: https://prometheus.io/docs/operating/configuration/#endpoint' + properties: + password: + description: The secret in the service monitor namespace + that contains the password for authentication. + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + username: + description: The secret in the service monitor namespace + that contains the username for authentication. + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + bearerTokenSecret: + description: Secret to mount to read bearer token for scraping + targets. The secret needs to be in the same namespace as the + pod monitor and accessible by the Prometheus Operator. + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + enableHttp2: + description: Whether to enable HTTP2. + type: boolean + filterRunning: + description: 'Drop pods that are not running. (Failed, Succeeded). + Enabled by default. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#pod-phase' + type: boolean + followRedirects: + description: FollowRedirects configures whether scrape requests + follow HTTP 3xx redirects. + type: boolean + honorLabels: + description: HonorLabels chooses the metric's labels on collisions + with target labels. + type: boolean + honorTimestamps: + description: HonorTimestamps controls whether Prometheus respects + the timestamps present in scraped data. + type: boolean + interval: + description: Interval at which metrics should be scraped If + not specified Prometheus' global scrape interval is used. + pattern: ^(0|(([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?(([0-9]+)ms)?)$ + type: string + metricRelabelings: + description: MetricRelabelConfigs to apply to samples before + ingestion. + items: + description: "RelabelConfig allows dynamic rewriting of the + label set for targets, alerts, scraped samples and remote + write samples. \n More info: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#relabel_config" + properties: + action: + default: replace + description: "Action to perform based on the regex matching. + \n `Uppercase` and `Lowercase` actions require Prometheus + >= v2.36.0. `DropEqual` and `KeepEqual` actions require + Prometheus >= v2.41.0. \n Default: \"Replace\"" + enum: + - replace + - Replace + - keep + - Keep + - drop + - Drop + - hashmod + - HashMod + - labelmap + - LabelMap + - labeldrop + - LabelDrop + - labelkeep + - LabelKeep + - lowercase + - Lowercase + - uppercase + - Uppercase + - keepequal + - KeepEqual + - dropequal + - DropEqual + type: string + modulus: + description: "Modulus to take of the hash of the source + label values. \n Only applicable when the action is + `HashMod`." + format: int64 + type: integer + regex: + description: Regular expression against which the extracted + value is matched. + type: string + replacement: + description: "Replacement value against which a Replace + action is performed if the regular expression matches. + \n Regex capture groups are available." + type: string + separator: + description: Separator is the string between concatenated + SourceLabels. + type: string + sourceLabels: + description: The source labels select values from existing + labels. Their content is concatenated using the configured + Separator and matched against the configured regular + expression. + items: + description: LabelName is a valid Prometheus label name + which may only contain ASCII letters, numbers, as + well as underscores. + pattern: ^[a-zA-Z_][a-zA-Z0-9_]*$ + type: string + type: array + targetLabel: + description: "Label to which the resulting string is written + in a replacement. \n It is mandatory for `Replace`, + `HashMod`, `Lowercase`, `Uppercase`, `KeepEqual` and + `DropEqual` actions. \n Regex capture groups are available." + type: string + type: object + type: array + oauth2: + description: OAuth2 for the URL. Only valid in Prometheus versions + 2.27.0 and newer. + properties: + clientId: + description: The secret or configmap containing the OAuth2 + client id + properties: + configMap: + description: ConfigMap containing data to use for the + targets. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + 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 + secret: + description: Secret containing data to use for the targets. + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + 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 + clientSecret: + description: The secret containing the OAuth2 client secret + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + endpointParams: + additionalProperties: + type: string + description: Parameters to append to the token URL + type: object + scopes: + description: OAuth2 scopes used for the token request + items: + type: string + type: array + tokenUrl: + description: The URL to fetch the token from + minLength: 1 + type: string + required: + - clientId + - clientSecret + - tokenUrl + type: object + params: + additionalProperties: + items: + type: string + type: array + description: Optional HTTP URL parameters + type: object + path: + description: HTTP path to scrape for metrics. If empty, Prometheus + uses the default value (e.g. `/metrics`). + type: string + port: + description: Name of the pod port this endpoint refers to. Mutually + exclusive with targetPort. + type: string + proxyUrl: + description: ProxyURL eg http://proxyserver:2195 Directs scrapes + to proxy through this endpoint. + type: string + relabelings: + description: 'RelabelConfigs to apply to samples before scraping. + Prometheus Operator automatically adds relabelings for a few + standard Kubernetes fields. The original scrape job''s name + is available via the `__tmp_prometheus_job_name` label. More + info: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#relabel_config' + items: + description: "RelabelConfig allows dynamic rewriting of the + label set for targets, alerts, scraped samples and remote + write samples. \n More info: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#relabel_config" + properties: + action: + default: replace + description: "Action to perform based on the regex matching. + \n `Uppercase` and `Lowercase` actions require Prometheus + >= v2.36.0. `DropEqual` and `KeepEqual` actions require + Prometheus >= v2.41.0. \n Default: \"Replace\"" + enum: + - replace + - Replace + - keep + - Keep + - drop + - Drop + - hashmod + - HashMod + - labelmap + - LabelMap + - labeldrop + - LabelDrop + - labelkeep + - LabelKeep + - lowercase + - Lowercase + - uppercase + - Uppercase + - keepequal + - KeepEqual + - dropequal + - DropEqual + type: string + modulus: + description: "Modulus to take of the hash of the source + label values. \n Only applicable when the action is + `HashMod`." + format: int64 + type: integer + regex: + description: Regular expression against which the extracted + value is matched. + type: string + replacement: + description: "Replacement value against which a Replace + action is performed if the regular expression matches. + \n Regex capture groups are available." + type: string + separator: + description: Separator is the string between concatenated + SourceLabels. + type: string + sourceLabels: + description: The source labels select values from existing + labels. Their content is concatenated using the configured + Separator and matched against the configured regular + expression. + items: + description: LabelName is a valid Prometheus label name + which may only contain ASCII letters, numbers, as + well as underscores. + pattern: ^[a-zA-Z_][a-zA-Z0-9_]*$ + type: string + type: array + targetLabel: + description: "Label to which the resulting string is written + in a replacement. \n It is mandatory for `Replace`, + `HashMod`, `Lowercase`, `Uppercase`, `KeepEqual` and + `DropEqual` actions. \n Regex capture groups are available." + type: string + type: object + type: array + scheme: + description: HTTP scheme to use for scraping. `http` and `https` + are the expected values unless you rewrite the `__scheme__` + label via relabeling. If empty, Prometheus uses the default + value `http`. + enum: + - http + - https + type: string + scrapeTimeout: + description: Timeout after which the scrape is ended If not + specified, the Prometheus global scrape interval is used. + pattern: ^(0|(([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?(([0-9]+)ms)?)$ + type: string + targetPort: + anyOf: + - type: integer + - type: string + description: 'Deprecated: Use ''port'' instead.' + x-kubernetes-int-or-string: true + tlsConfig: + description: TLS configuration to use when scraping the endpoint. + properties: + ca: + description: Certificate authority used when verifying server + certificates. + properties: + configMap: + description: ConfigMap containing data to use for the + targets. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + 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 + secret: + description: Secret containing data to use for the targets. + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + 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 + cert: + description: Client certificate to present when doing client-authentication. + properties: + configMap: + description: ConfigMap containing data to use for the + targets. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + 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 + secret: + description: Secret containing data to use for the targets. + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + 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 + insecureSkipVerify: + description: Disable target certificate validation. + type: boolean + keySecret: + description: Secret containing the client key file for the + targets. + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + serverName: + description: Used to verify the hostname for the targets. + type: string + type: object + type: object + type: array + podTargetLabels: + description: PodTargetLabels transfers labels on the Kubernetes Pod + onto the target. + items: + type: string + type: array + sampleLimit: + description: SampleLimit defines per-scrape limit on number of scraped + samples that will be accepted. + format: int64 + type: integer + selector: + description: Selector to select Pod objects. + 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 + required: + - key + - operator + type: object + type: array + 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 + targetLimit: + description: TargetLimit defines a limit on the number of scraped + targets that will be accepted. + format: int64 + type: integer + required: + - podMetricsEndpoints + - selector + type: object + required: + - spec + type: object + served: true + storage: true diff --git a/packages/system/victoria-metrics-operator/charts/prometheus-operator-crds/templates/crd-probes.yaml b/packages/system/victoria-metrics-operator/charts/prometheus-operator-crds/templates/crd-probes.yaml new file mode 100644 index 00000000..a10b0c8d --- /dev/null +++ b/packages/system/victoria-metrics-operator/charts/prometheus-operator-crds/templates/crd-probes.yaml @@ -0,0 +1,730 @@ +# https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.67.0/example/prometheus-operator-crd/monitoring.coreos.com_probes.yaml +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: +{{- with .Values.annotations }} +{{- toYaml . | nindent 4 }} +{{- end }} + controller-gen.kubebuilder.io/version: v0.11.1 + creationTimestamp: null + name: probes.monitoring.coreos.com +spec: + group: monitoring.coreos.com + names: + categories: + - prometheus-operator + kind: Probe + listKind: ProbeList + plural: probes + shortNames: + - prb + singular: probe + scope: Namespaced + versions: + - name: v1 + schema: + openAPIV3Schema: + description: Probe defines monitoring for a set of static targets or ingresses. + 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: Specification of desired Ingress selection for target discovery + by Prometheus. + properties: + authorization: + description: Authorization section for this endpoint + properties: + credentials: + description: Selects a key of a Secret in the namespace that contains + the credentials for authentication. + properties: + key: + description: The key of the secret to select from. Must be + a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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: + description: "Defines the authentication type. The value is case-insensitive. + \n \"Basic\" is not a supported value. \n Default: \"Bearer\"" + type: string + type: object + basicAuth: + description: 'BasicAuth allow an endpoint to authenticate over basic + authentication. More info: https://prometheus.io/docs/operating/configuration/#endpoint' + properties: + password: + description: The secret in the service monitor namespace that + contains the password for authentication. + properties: + key: + description: The key of the secret to select from. Must be + a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + username: + description: The secret in the service monitor namespace that + contains the username for authentication. + properties: + key: + description: The key of the secret to select from. Must be + a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + bearerTokenSecret: + description: Secret to mount to read bearer token for scraping targets. + The secret needs to be in the same namespace as the probe and accessible + by the Prometheus Operator. + properties: + key: + description: The key of the secret to select from. Must be a + valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + interval: + description: Interval at which targets are probed using the configured + prober. If not specified Prometheus' global scrape interval is used. + pattern: ^(0|(([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?(([0-9]+)ms)?)$ + type: string + jobName: + description: The job name assigned to scraped metrics by default. + type: string + labelLimit: + description: Per-scrape limit on number of labels that will be accepted + for a sample. Only valid in Prometheus versions 2.27.0 and newer. + format: int64 + type: integer + labelNameLengthLimit: + description: Per-scrape limit on length of labels name that will be + accepted for a sample. Only valid in Prometheus versions 2.27.0 + and newer. + format: int64 + type: integer + labelValueLengthLimit: + description: Per-scrape limit on length of labels value that will + be accepted for a sample. Only valid in Prometheus versions 2.27.0 + and newer. + format: int64 + type: integer + metricRelabelings: + description: MetricRelabelConfigs to apply to samples before ingestion. + items: + description: "RelabelConfig allows dynamic rewriting of the label + set for targets, alerts, scraped samples and remote write samples. + \n More info: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#relabel_config" + properties: + action: + default: replace + description: "Action to perform based on the regex matching. + \n `Uppercase` and `Lowercase` actions require Prometheus + >= v2.36.0. `DropEqual` and `KeepEqual` actions require Prometheus + >= v2.41.0. \n Default: \"Replace\"" + enum: + - replace + - Replace + - keep + - Keep + - drop + - Drop + - hashmod + - HashMod + - labelmap + - LabelMap + - labeldrop + - LabelDrop + - labelkeep + - LabelKeep + - lowercase + - Lowercase + - uppercase + - Uppercase + - keepequal + - KeepEqual + - dropequal + - DropEqual + type: string + modulus: + description: "Modulus to take of the hash of the source label + values. \n Only applicable when the action is `HashMod`." + format: int64 + type: integer + regex: + description: Regular expression against which the extracted + value is matched. + type: string + replacement: + description: "Replacement value against which a Replace action + is performed if the regular expression matches. \n Regex capture + groups are available." + type: string + separator: + description: Separator is the string between concatenated SourceLabels. + type: string + sourceLabels: + description: The source labels select values from existing labels. + Their content is concatenated using the configured Separator + and matched against the configured regular expression. + items: + description: LabelName is a valid Prometheus label name which + may only contain ASCII letters, numbers, as well as underscores. + pattern: ^[a-zA-Z_][a-zA-Z0-9_]*$ + type: string + type: array + targetLabel: + description: "Label to which the resulting string is written + in a replacement. \n It is mandatory for `Replace`, `HashMod`, + `Lowercase`, `Uppercase`, `KeepEqual` and `DropEqual` actions. + \n Regex capture groups are available." + type: string + type: object + type: array + module: + description: 'The module to use for probing specifying how to probe + the target. Example module configuring in the blackbox exporter: + https://github.com/prometheus/blackbox_exporter/blob/master/example.yml' + type: string + oauth2: + description: OAuth2 for the URL. Only valid in Prometheus versions + 2.27.0 and newer. + properties: + clientId: + description: The secret or configmap containing the OAuth2 client + id + properties: + configMap: + description: ConfigMap containing data to use for the targets. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + secret: + description: Secret containing data to use for the targets. + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + clientSecret: + description: The secret containing the OAuth2 client secret + properties: + key: + description: The key of the secret to select from. Must be + a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + endpointParams: + additionalProperties: + type: string + description: Parameters to append to the token URL + type: object + scopes: + description: OAuth2 scopes used for the token request + items: + type: string + type: array + tokenUrl: + description: The URL to fetch the token from + minLength: 1 + type: string + required: + - clientId + - clientSecret + - tokenUrl + type: object + prober: + description: Specification for the prober to use for probing targets. + The prober.URL parameter is required. Targets cannot be probed if + left empty. + properties: + path: + default: /probe + description: Path to collect metrics from. Defaults to `/probe`. + type: string + proxyUrl: + description: Optional ProxyURL. + type: string + scheme: + description: HTTP scheme to use for scraping. `http` and `https` + are the expected values unless you rewrite the `__scheme__` + label via relabeling. If empty, Prometheus uses the default + value `http`. + enum: + - http + - https + type: string + url: + description: Mandatory URL of the prober. + type: string + required: + - url + type: object + sampleLimit: + description: SampleLimit defines per-scrape limit on number of scraped + samples that will be accepted. + format: int64 + type: integer + scrapeTimeout: + description: Timeout for scraping metrics from the Prometheus exporter. + If not specified, the Prometheus global scrape timeout is used. + pattern: ^(0|(([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?(([0-9]+)ms)?)$ + type: string + targetLimit: + description: TargetLimit defines a limit on the number of scraped + targets that will be accepted. + format: int64 + type: integer + targets: + description: Targets defines a set of static or dynamically discovered + targets to probe. + properties: + ingress: + description: ingress defines the Ingress objects to probe and + the relabeling configuration. If `staticConfig` is also defined, + `staticConfig` takes precedence. + properties: + namespaceSelector: + description: From which namespaces to select Ingress objects. + properties: + any: + description: Boolean describing whether all namespaces + are selected in contrast to a list restricting them. + type: boolean + matchNames: + description: List of namespace names to select from. + items: + type: string + type: array + type: object + relabelingConfigs: + description: 'RelabelConfigs to apply to the label set of + the target before it gets scraped. The original ingress + address is available via the `__tmp_prometheus_ingress_address` + label. It can be used to customize the probed URL. The original + scrape job''s name is available via the `__tmp_prometheus_job_name` + label. More info: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#relabel_config' + items: + description: "RelabelConfig allows dynamic rewriting of + the label set for targets, alerts, scraped samples and + remote write samples. \n More info: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#relabel_config" + properties: + action: + default: replace + description: "Action to perform based on the regex matching. + \n `Uppercase` and `Lowercase` actions require Prometheus + >= v2.36.0. `DropEqual` and `KeepEqual` actions require + Prometheus >= v2.41.0. \n Default: \"Replace\"" + enum: + - replace + - Replace + - keep + - Keep + - drop + - Drop + - hashmod + - HashMod + - labelmap + - LabelMap + - labeldrop + - LabelDrop + - labelkeep + - LabelKeep + - lowercase + - Lowercase + - uppercase + - Uppercase + - keepequal + - KeepEqual + - dropequal + - DropEqual + type: string + modulus: + description: "Modulus to take of the hash of the source + label values. \n Only applicable when the action is + `HashMod`." + format: int64 + type: integer + regex: + description: Regular expression against which the extracted + value is matched. + type: string + replacement: + description: "Replacement value against which a Replace + action is performed if the regular expression matches. + \n Regex capture groups are available." + type: string + separator: + description: Separator is the string between concatenated + SourceLabels. + type: string + sourceLabels: + description: The source labels select values from existing + labels. Their content is concatenated using the configured + Separator and matched against the configured regular + expression. + items: + description: LabelName is a valid Prometheus label + name which may only contain ASCII letters, numbers, + as well as underscores. + pattern: ^[a-zA-Z_][a-zA-Z0-9_]*$ + type: string + type: array + targetLabel: + description: "Label to which the resulting string is + written in a replacement. \n It is mandatory for `Replace`, + `HashMod`, `Lowercase`, `Uppercase`, `KeepEqual` and + `DropEqual` actions. \n Regex capture groups are available." + type: string + type: object + type: array + selector: + description: Selector to select the Ingress objects. + 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 + required: + - key + - operator + type: object + type: array + 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 + type: object + staticConfig: + description: 'staticConfig defines the static list of targets + to probe and the relabeling configuration. If `ingress` is also + defined, `staticConfig` takes precedence. More info: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#static_config.' + properties: + labels: + additionalProperties: + type: string + description: Labels assigned to all metrics scraped from the + targets. + type: object + relabelingConfigs: + description: 'RelabelConfigs to apply to the label set of + the targets before it gets scraped. More info: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#relabel_config' + items: + description: "RelabelConfig allows dynamic rewriting of + the label set for targets, alerts, scraped samples and + remote write samples. \n More info: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#relabel_config" + properties: + action: + default: replace + description: "Action to perform based on the regex matching. + \n `Uppercase` and `Lowercase` actions require Prometheus + >= v2.36.0. `DropEqual` and `KeepEqual` actions require + Prometheus >= v2.41.0. \n Default: \"Replace\"" + enum: + - replace + - Replace + - keep + - Keep + - drop + - Drop + - hashmod + - HashMod + - labelmap + - LabelMap + - labeldrop + - LabelDrop + - labelkeep + - LabelKeep + - lowercase + - Lowercase + - uppercase + - Uppercase + - keepequal + - KeepEqual + - dropequal + - DropEqual + type: string + modulus: + description: "Modulus to take of the hash of the source + label values. \n Only applicable when the action is + `HashMod`." + format: int64 + type: integer + regex: + description: Regular expression against which the extracted + value is matched. + type: string + replacement: + description: "Replacement value against which a Replace + action is performed if the regular expression matches. + \n Regex capture groups are available." + type: string + separator: + description: Separator is the string between concatenated + SourceLabels. + type: string + sourceLabels: + description: The source labels select values from existing + labels. Their content is concatenated using the configured + Separator and matched against the configured regular + expression. + items: + description: LabelName is a valid Prometheus label + name which may only contain ASCII letters, numbers, + as well as underscores. + pattern: ^[a-zA-Z_][a-zA-Z0-9_]*$ + type: string + type: array + targetLabel: + description: "Label to which the resulting string is + written in a replacement. \n It is mandatory for `Replace`, + `HashMod`, `Lowercase`, `Uppercase`, `KeepEqual` and + `DropEqual` actions. \n Regex capture groups are available." + type: string + type: object + type: array + static: + description: The list of hosts to probe. + items: + type: string + type: array + type: object + type: object + tlsConfig: + description: TLS configuration to use when scraping the endpoint. + properties: + ca: + description: Certificate authority used when verifying server + certificates. + properties: + configMap: + description: ConfigMap containing data to use for the targets. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + secret: + description: Secret containing data to use for the targets. + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + cert: + description: Client certificate to present when doing client-authentication. + properties: + configMap: + description: ConfigMap containing data to use for the targets. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + secret: + description: Secret containing data to use for the targets. + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + insecureSkipVerify: + description: Disable target certificate validation. + type: boolean + keySecret: + description: Secret containing the client key file for the targets. + properties: + key: + description: The key of the secret to select from. Must be + a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + serverName: + description: Used to verify the hostname for the targets. + type: string + type: object + type: object + required: + - spec + type: object + served: true + storage: true diff --git a/packages/system/victoria-metrics-operator/charts/prometheus-operator-crds/templates/crd-prometheusrules.yaml b/packages/system/victoria-metrics-operator/charts/prometheus-operator-crds/templates/crd-prometheusrules.yaml new file mode 100644 index 00000000..0fa43e3e --- /dev/null +++ b/packages/system/victoria-metrics-operator/charts/prometheus-operator-crds/templates/crd-prometheusrules.yaml @@ -0,0 +1,134 @@ +# https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.67.0/example/prometheus-operator-crd/monitoring.coreos.com_prometheusrules.yaml +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: +{{- with .Values.annotations }} +{{- toYaml . | nindent 4 }} +{{- end }} + controller-gen.kubebuilder.io/version: v0.11.1 + creationTimestamp: null + name: prometheusrules.monitoring.coreos.com +spec: + group: monitoring.coreos.com + names: + categories: + - prometheus-operator + kind: PrometheusRule + listKind: PrometheusRuleList + plural: prometheusrules + shortNames: + - promrule + singular: prometheusrule + scope: Namespaced + versions: + - name: v1 + schema: + openAPIV3Schema: + description: PrometheusRule defines recording and alerting rules for a Prometheus + instance + 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: Specification of desired alerting rule definitions for Prometheus. + properties: + groups: + description: Content of Prometheus rule file + items: + description: RuleGroup is a list of sequentially evaluated recording + and alerting rules. + properties: + interval: + description: Interval determines how often rules in the group + are evaluated. + pattern: ^(0|(([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?(([0-9]+)ms)?)$ + type: string + limit: + description: Limit the number of alerts an alerting rule and + series a recording rule can produce. Limit is supported starting + with Prometheus >= 2.31 and Thanos Ruler >= 0.24. + type: integer + name: + description: Name of the rule group. + minLength: 1 + type: string + partial_response_strategy: + description: 'PartialResponseStrategy is only used by ThanosRuler + and will be ignored by Prometheus instances. More info: https://github.com/thanos-io/thanos/blob/main/docs/components/rule.md#partial-response' + pattern: ^(?i)(abort|warn)?$ + type: string + rules: + description: List of alerting and recording rules. + items: + description: 'Rule describes an alerting or recording rule + See Prometheus documentation: [alerting](https://www.prometheus.io/docs/prometheus/latest/configuration/alerting_rules/) + or [recording](https://www.prometheus.io/docs/prometheus/latest/configuration/recording_rules/#recording-rules) + rule' + properties: + alert: + description: Name of the alert. Must be a valid label + value. Only one of `record` and `alert` must be set. + type: string + annotations: + additionalProperties: + type: string + description: Annotations to add to each alert. Only valid + for alerting rules. + type: object + expr: + anyOf: + - type: integer + - type: string + description: PromQL expression to evaluate. + x-kubernetes-int-or-string: true + for: + description: Alerts are considered firing once they have + been returned for this long. + pattern: ^(0|(([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?(([0-9]+)ms)?)$ + type: string + keep_firing_for: + description: KeepFiringFor defines how long an alert will + continue firing after the condition that triggered it + has cleared. + minLength: 1 + pattern: ^(0|(([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?(([0-9]+)ms)?)$ + type: string + labels: + additionalProperties: + type: string + description: Labels to add or overwrite. + type: object + record: + description: Name of the time series to output to. Must + be a valid metric name. Only one of `record` and `alert` + must be set. + type: string + required: + - expr + type: object + type: array + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + required: + - spec + type: object + served: true + storage: true diff --git a/packages/system/victoria-metrics-operator/charts/prometheus-operator-crds/templates/crd-servicemonitors.yaml b/packages/system/victoria-metrics-operator/charts/prometheus-operator-crds/templates/crd-servicemonitors.yaml new file mode 100644 index 00000000..26223f43 --- /dev/null +++ b/packages/system/victoria-metrics-operator/charts/prometheus-operator-crds/templates/crd-servicemonitors.yaml @@ -0,0 +1,718 @@ +# https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.67.0/example/prometheus-operator-crd/monitoring.coreos.com_servicemonitors.yaml +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: +{{- with .Values.annotations }} +{{- toYaml . | nindent 4 }} +{{- end }} + controller-gen.kubebuilder.io/version: v0.11.1 + creationTimestamp: null + name: servicemonitors.monitoring.coreos.com +spec: + group: monitoring.coreos.com + names: + categories: + - prometheus-operator + kind: ServiceMonitor + listKind: ServiceMonitorList + plural: servicemonitors + shortNames: + - smon + singular: servicemonitor + scope: Namespaced + versions: + - name: v1 + schema: + openAPIV3Schema: + description: ServiceMonitor defines monitoring for a set of services. + 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: Specification of desired Service selection for target discovery + by Prometheus. + properties: + attachMetadata: + description: Attaches node metadata to discovered targets. Requires + Prometheus v2.37.0 and above. + properties: + node: + description: When set to true, Prometheus must have permissions + to get Nodes. + type: boolean + type: object + endpoints: + description: A list of endpoints allowed as part of this ServiceMonitor. + items: + description: Endpoint defines a scrapeable endpoint serving Prometheus + metrics. + properties: + authorization: + description: Authorization section for this endpoint + properties: + credentials: + description: Selects a key of a Secret in the namespace + that contains the credentials for authentication. + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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: + description: "Defines the authentication type. The value + is case-insensitive. \n \"Basic\" is not a supported value. + \n Default: \"Bearer\"" + type: string + type: object + basicAuth: + description: 'BasicAuth allow an endpoint to authenticate over + basic authentication More info: https://prometheus.io/docs/operating/configuration/#endpoints' + properties: + password: + description: The secret in the service monitor namespace + that contains the password for authentication. + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + username: + description: The secret in the service monitor namespace + that contains the username for authentication. + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + bearerTokenFile: + description: File to read bearer token for scraping targets. + type: string + bearerTokenSecret: + description: Secret to mount to read bearer token for scraping + targets. The secret needs to be in the same namespace as the + service monitor and accessible by the Prometheus Operator. + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + enableHttp2: + description: Whether to enable HTTP2. + type: boolean + filterRunning: + description: 'Drop pods that are not running. (Failed, Succeeded). + Enabled by default. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#pod-phase' + type: boolean + followRedirects: + description: FollowRedirects configures whether scrape requests + follow HTTP 3xx redirects. + type: boolean + honorLabels: + description: HonorLabels chooses the metric's labels on collisions + with target labels. + type: boolean + honorTimestamps: + description: HonorTimestamps controls whether Prometheus respects + the timestamps present in scraped data. + type: boolean + interval: + description: Interval at which metrics should be scraped If + not specified Prometheus' global scrape interval is used. + pattern: ^(0|(([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?(([0-9]+)ms)?)$ + type: string + metricRelabelings: + description: MetricRelabelConfigs to apply to samples before + ingestion. + items: + description: "RelabelConfig allows dynamic rewriting of the + label set for targets, alerts, scraped samples and remote + write samples. \n More info: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#relabel_config" + properties: + action: + default: replace + description: "Action to perform based on the regex matching. + \n `Uppercase` and `Lowercase` actions require Prometheus + >= v2.36.0. `DropEqual` and `KeepEqual` actions require + Prometheus >= v2.41.0. \n Default: \"Replace\"" + enum: + - replace + - Replace + - keep + - Keep + - drop + - Drop + - hashmod + - HashMod + - labelmap + - LabelMap + - labeldrop + - LabelDrop + - labelkeep + - LabelKeep + - lowercase + - Lowercase + - uppercase + - Uppercase + - keepequal + - KeepEqual + - dropequal + - DropEqual + type: string + modulus: + description: "Modulus to take of the hash of the source + label values. \n Only applicable when the action is + `HashMod`." + format: int64 + type: integer + regex: + description: Regular expression against which the extracted + value is matched. + type: string + replacement: + description: "Replacement value against which a Replace + action is performed if the regular expression matches. + \n Regex capture groups are available." + type: string + separator: + description: Separator is the string between concatenated + SourceLabels. + type: string + sourceLabels: + description: The source labels select values from existing + labels. Their content is concatenated using the configured + Separator and matched against the configured regular + expression. + items: + description: LabelName is a valid Prometheus label name + which may only contain ASCII letters, numbers, as + well as underscores. + pattern: ^[a-zA-Z_][a-zA-Z0-9_]*$ + type: string + type: array + targetLabel: + description: "Label to which the resulting string is written + in a replacement. \n It is mandatory for `Replace`, + `HashMod`, `Lowercase`, `Uppercase`, `KeepEqual` and + `DropEqual` actions. \n Regex capture groups are available." + type: string + type: object + type: array + oauth2: + description: OAuth2 for the URL. Only valid in Prometheus versions + 2.27.0 and newer. + properties: + clientId: + description: The secret or configmap containing the OAuth2 + client id + properties: + configMap: + description: ConfigMap containing data to use for the + targets. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + 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 + secret: + description: Secret containing data to use for the targets. + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + 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 + clientSecret: + description: The secret containing the OAuth2 client secret + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + endpointParams: + additionalProperties: + type: string + description: Parameters to append to the token URL + type: object + scopes: + description: OAuth2 scopes used for the token request + items: + type: string + type: array + tokenUrl: + description: The URL to fetch the token from + minLength: 1 + type: string + required: + - clientId + - clientSecret + - tokenUrl + type: object + params: + additionalProperties: + items: + type: string + type: array + description: Optional HTTP URL parameters + type: object + path: + description: HTTP path to scrape for metrics. If empty, Prometheus + uses the default value (e.g. `/metrics`). + type: string + port: + description: Name of the service port this endpoint refers to. + Mutually exclusive with targetPort. + type: string + proxyUrl: + description: ProxyURL eg http://proxyserver:2195 Directs scrapes + to proxy through this endpoint. + type: string + relabelings: + description: 'RelabelConfigs to apply to samples before scraping. + Prometheus Operator automatically adds relabelings for a few + standard Kubernetes fields. The original scrape job''s name + is available via the `__tmp_prometheus_job_name` label. More + info: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#relabel_config' + items: + description: "RelabelConfig allows dynamic rewriting of the + label set for targets, alerts, scraped samples and remote + write samples. \n More info: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#relabel_config" + properties: + action: + default: replace + description: "Action to perform based on the regex matching. + \n `Uppercase` and `Lowercase` actions require Prometheus + >= v2.36.0. `DropEqual` and `KeepEqual` actions require + Prometheus >= v2.41.0. \n Default: \"Replace\"" + enum: + - replace + - Replace + - keep + - Keep + - drop + - Drop + - hashmod + - HashMod + - labelmap + - LabelMap + - labeldrop + - LabelDrop + - labelkeep + - LabelKeep + - lowercase + - Lowercase + - uppercase + - Uppercase + - keepequal + - KeepEqual + - dropequal + - DropEqual + type: string + modulus: + description: "Modulus to take of the hash of the source + label values. \n Only applicable when the action is + `HashMod`." + format: int64 + type: integer + regex: + description: Regular expression against which the extracted + value is matched. + type: string + replacement: + description: "Replacement value against which a Replace + action is performed if the regular expression matches. + \n Regex capture groups are available." + type: string + separator: + description: Separator is the string between concatenated + SourceLabels. + type: string + sourceLabels: + description: The source labels select values from existing + labels. Their content is concatenated using the configured + Separator and matched against the configured regular + expression. + items: + description: LabelName is a valid Prometheus label name + which may only contain ASCII letters, numbers, as + well as underscores. + pattern: ^[a-zA-Z_][a-zA-Z0-9_]*$ + type: string + type: array + targetLabel: + description: "Label to which the resulting string is written + in a replacement. \n It is mandatory for `Replace`, + `HashMod`, `Lowercase`, `Uppercase`, `KeepEqual` and + `DropEqual` actions. \n Regex capture groups are available." + type: string + type: object + type: array + scheme: + description: HTTP scheme to use for scraping. `http` and `https` + are the expected values unless you rewrite the `__scheme__` + label via relabeling. If empty, Prometheus uses the default + value `http`. + enum: + - http + - https + type: string + scrapeTimeout: + description: Timeout after which the scrape is ended If not + specified, the Prometheus global scrape timeout is used unless + it is less than `Interval` in which the latter is used. + pattern: ^(0|(([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?(([0-9]+)ms)?)$ + type: string + targetPort: + anyOf: + - type: integer + - type: string + description: Name or number of the target port of the Pod behind + the Service, the port must be specified with container port + property. Mutually exclusive with port. + x-kubernetes-int-or-string: true + tlsConfig: + description: TLS configuration to use when scraping the endpoint + properties: + ca: + description: Certificate authority used when verifying server + certificates. + properties: + configMap: + description: ConfigMap containing data to use for the + targets. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + 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 + secret: + description: Secret containing data to use for the targets. + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + 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 + caFile: + description: Path to the CA cert in the Prometheus container + to use for the targets. + type: string + cert: + description: Client certificate to present when doing client-authentication. + properties: + configMap: + description: ConfigMap containing data to use for the + targets. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + 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 + secret: + description: Secret containing data to use for the targets. + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + 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 + certFile: + description: Path to the client cert file in the Prometheus + container for the targets. + type: string + insecureSkipVerify: + description: Disable target certificate validation. + type: boolean + keyFile: + description: Path to the client key file in the Prometheus + container for the targets. + type: string + keySecret: + description: Secret containing the client key file for the + targets. + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + serverName: + description: Used to verify the hostname for the targets. + type: string + type: object + type: object + type: array + jobLabel: + description: "JobLabel selects the label from the associated Kubernetes + service which will be used as the `job` label for all metrics. \n + For example: If in `ServiceMonitor.spec.jobLabel: foo` and in `Service.metadata.labels.foo: + bar`, then the `job=\"bar\"` label is added to all metrics. \n If + the value of this field is empty or if the label doesn't exist for + the given Service, the `job` label of the metrics defaults to the + name of the Kubernetes Service." + type: string + labelLimit: + description: Per-scrape limit on number of labels that will be accepted + for a sample. Only valid in Prometheus versions 2.27.0 and newer. + format: int64 + type: integer + labelNameLengthLimit: + description: Per-scrape limit on length of labels name that will be + accepted for a sample. Only valid in Prometheus versions 2.27.0 + and newer. + format: int64 + type: integer + labelValueLengthLimit: + description: Per-scrape limit on length of labels value that will + be accepted for a sample. Only valid in Prometheus versions 2.27.0 + and newer. + format: int64 + type: integer + namespaceSelector: + description: Selector to select which namespaces the Kubernetes Endpoints + objects are discovered from. + properties: + any: + description: Boolean describing whether all namespaces are selected + in contrast to a list restricting them. + type: boolean + matchNames: + description: List of namespace names to select from. + items: + type: string + type: array + type: object + podTargetLabels: + description: PodTargetLabels transfers labels on the Kubernetes `Pod` + onto the created metrics. + items: + type: string + type: array + sampleLimit: + description: SampleLimit defines per-scrape limit on number of scraped + samples that will be accepted. + format: int64 + type: integer + selector: + description: Selector to select Endpoints objects. + 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 + required: + - key + - operator + type: object + type: array + 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 + targetLabels: + description: TargetLabels transfers labels from the Kubernetes `Service` + onto the created metrics. + items: + type: string + type: array + targetLimit: + description: TargetLimit defines a limit on the number of scraped + targets that will be accepted. + format: int64 + type: integer + required: + - endpoints + - selector + type: object + required: + - spec + type: object + served: true + storage: true diff --git a/packages/system/victoria-metrics-operator/charts/prometheus-operator-crds/values.yaml b/packages/system/victoria-metrics-operator/charts/prometheus-operator-crds/values.yaml new file mode 100644 index 00000000..c9d50a61 --- /dev/null +++ b/packages/system/victoria-metrics-operator/charts/prometheus-operator-crds/values.yaml @@ -0,0 +1,3 @@ +## Annotations for CRDs +## +annotations: {} diff --git a/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/.helmignore b/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/.helmignore new file mode 100644 index 00000000..50af0317 --- /dev/null +++ b/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/.helmignore @@ -0,0 +1,22 @@ +# 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 +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/CHANGELOG.md b/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/CHANGELOG.md new file mode 100644 index 00000000..8c10b8f6 --- /dev/null +++ b/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/CHANGELOG.md @@ -0,0 +1,71 @@ +# CHANGELOG for `victoria-metrics-operator` helm-chart + +## Next release + +**Release date:** TBD + +![AppVersion: **APP_VERSION**](https://img.shields.io/static/v1?label=AppVersion&message=**APP_VERSION**&color=success&logo=) +![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +- TODO + +## 0.26.0 + +**Release date:** 2023-08-30 + +![AppVersion: 0.37.0](https://img.shields.io/static/v1?label=AppVersion&message=0.37.0&color=success&logo=) +![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +- Bump operator version to [v0.37.0](https://github.com/VictoriaMetrics/operator/releases/tag/v0.37.0) +- `psp_auto_creation_enabled` for operator is disabled by default + +## 0.25.0 + +**Release date:** 2023-08-24 + +![AppVersion: 0.36.0](https://img.shields.io/static/v1?label=AppVersion&message=0.36.0&color=success&logo=) +![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +* Added `topologySpreadConstraints` for the operator + a small refactoring (#611) +* Fix vm operator appVersion (#589) +* Fixes operator doc description +* Add `cleanupCRD` option to clean up vm cr resources when uninstalling (#593) +* Bump operator version to [v0.36.0](https://github.com/VictoriaMetrics/operator/releases/tag/v0.36.0) + +## 0.24.1 + +**Release date:** 2023-07-13 + +![AppVersion: 0.35.](https://img.shields.io/static/v1?label=AppVersion&message=0.35.&color=success&logo=) +![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +* operator release v0.35.1 + +## 0.24.0 + +**Release date:** 2023-07-03 + +![AppVersion: 0.35.0](https://img.shields.io/static/v1?label=AppVersion&message=0.35.0&color=success&logo=) +![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +* updates operator for v0.35.0 +* updates for v1.91.1 release + +## 0.23.1 + +**Release date:** 2023-05-29 + +![AppVersion: 0.34.1](https://img.shields.io/static/v1?label=AppVersion&message=0.34.1&color=success&logo=) +![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +* updates operator for v0.34.1 version + +## 0.23.0 + +**Release date:** 2023-05-25 + +![AppVersion: 0.34.0](https://img.shields.io/static/v1?label=AppVersion&message=0.34.0&color=success&logo=) +![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +* bump operator version +* feat(operator): add PodDisruptionBudget (#546) diff --git a/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/Chart.yaml b/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/Chart.yaml new file mode 100644 index 00000000..ec7a5c23 --- /dev/null +++ b/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/Chart.yaml @@ -0,0 +1,40 @@ +annotations: + artifacthub.io/category: monitoring-logging + artifacthub.io/changes: |- + **Release date:** 2023-08-30 + + ![AppVersion: 0.37.0](https://img.shields.io/static/v1?label=AppVersion&message=0.37.0&color=success&logo=) + ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + + - Bump operator version to [v0.37.0](https://github.com/VictoriaMetrics/operator/releases/tag/v0.37.0) + - `psp_auto_creation_enabled` for operator is disabled by default + artifacthub.io/license: Apache-2.0 + artifacthub.io/links: | + - name: Sources + url: https://github.com/VictoriaMetrics/helm-charts + - name: Charts repo + url: https://victoriametrics.github.io/helm-charts/ + - name: Docs + url: https://docs.victoriametrics.com/operator + artifacthub.io/operator: "true" +apiVersion: v1 +appVersion: 0.37.0 +description: Victoria Metrics Operator +home: https://github.com/VictoriaMetrics/operator +icon: https://avatars.githubusercontent.com/u/43720803?s=200&v=4 +keywords: +- victoriametrics +- operator +- monitoring +- kubernetes +- observability +- tsdb +- metrics +- metricsql +- timeseries +kubeVersion: '>=1.23.0-0' +name: victoria-metrics-operator +sources: +- https://github.com/VictoriaMetrics/helm-charts +- https://github.com/VictoriaMetrics/operator +version: 0.26.0 diff --git a/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/README.md b/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/README.md new file mode 100644 index 00000000..0be4629c --- /dev/null +++ b/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/README.md @@ -0,0 +1,189 @@ +# Helm Chart For Victoria Metrics Operator. + + ![Version: 0.26.0](https://img.shields.io/badge/Version-0.26.0-informational?style=flat-square) +[![Artifact Hub](https://img.shields.io/endpoint?url=https://artifacthub.io/badge/repository/victoriametrics)](https://artifacthub.io/packages/helm/victoriametrics/victoria-logs-operator) + +Victoria Metrics Operator + +## Prerequisites + +* Install the follow packages: ``git``, ``kubectl``, ``helm``, ``helm-docs``. See this [tutorial](../../REQUIREMENTS.md). +* PV support on underlying infrastructure. + +## Upgrade guide + + During release an issue with helm CRD was discovered. So for upgrade from version less then 0.1.3 you have to two options: + 1) use helm management for CRD, enabled by default. + 2) use own management system, need to add variable: --set createCRD=false. + +If you choose helm management, following steps must be done before upgrade: + +1) define namespace and helm release name variables + +``` +export NAMESPACE=default +export RELEASE_NAME=operator +``` + +execute kubectl commands: + +``` +kubectl get crd | grep victoriametrics.com | awk '{print $1 }' | xargs -i kubectl label crd {} app.kubernetes.io/managed-by=Helm --overwrite +kubectl get crd | grep victoriametrics.com | awk '{print $1 }' | xargs -i kubectl annotate crd {} meta.helm.sh/release-namespace="$NAMESPACE" meta.helm.sh/release-name="$RELEASE_NAME" --overwrite +``` + +run helm upgrade command. + +## Chart Details + +This chart will do the following: + +* Rollout victoria metrics operator + +## How to install + +Access a Kubernetes cluster. + +Add a chart helm repository with follow commands: + +```console +helm repo add vm https://victoriametrics.github.io/helm-charts/ + +helm repo update +``` + +List versions of ``vm/victoria-metrics-operator`` chart available to installation: + +```console +helm search repo vm/victoria-metrics-operator -l +``` + +Export default values of ``victoria-metrics-operator`` chart to file ``values.yaml``: + +```console +helm show values vm/victoria-metrics-operator > values.yaml +``` + +Change the values according to the need of the environment in ``values.yaml`` file. + +Test the installation with command: + +```console +helm install vmoperator vm/victoria-metrics-operator -f values.yaml -n NAMESPACE --debug --dry-run +``` + +Install chart with command: + +```console +helm install vmoperator vm/victoria-metrics-operator -f values.yaml -n NAMESPACE +``` + +Get the pods lists by running this commands: + +```console +kubectl get pods -A | grep 'operator' +``` + +Get the application by running this command: + +```console +helm list -f vmoperator -n NAMESPACE +``` + +See the history of versions of ``vmoperator`` application with command. + +```console +helm history vmoperator -n NAMESPACE +``` + +## How to uninstall + +Remove application with command. + +```console +helm uninstall vmoperator -n NAMESPACE +``` + +## Validation webhook + + Its possible to use validation of created resources with operator. For now, you need cert-manager to easily certificate management https://cert-manager.io/docs/ + +```yaml +admissionWebhooks: + enabled: true + # what to do in case, when operator not available to validate request. + certManager: + # enables cert creation and injection by cert-manager + enabled: true +``` + +## Documentation of Helm Chart + +Install ``helm-docs`` following the instructions on this [tutorial](../../REQUIREMENTS.md). + +Generate docs with ``helm-docs`` command. + +```bash +cd charts/victoria-metrics-operator + +helm-docs +``` + +The markdown generation is entirely go template driven. The tool parses metadata from charts and generates a number of sub-templates that can be referenced in a template file (by default ``README.md.gotmpl``). If no template file is provided, the tool has a default internal template that will generate a reasonably formatted README. + +## Parameters + +The following tables lists the configurable parameters of the chart and their default values. + +Change the values according to the need of the environment in ``victoria-metrics-operator/values.yaml`` file. + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| admissionWebhooks | object | `{"caBundle":"","certManager":{"enabled":false,"issuer":{}},"enabled":false,"enabledCRDValidation":{"vmagent":true,"vmalert":true,"vmalertmanager":true,"vmalertmanagerConfig":true,"vmauth":true,"vmcluster":true,"vmrule":true,"vmsingle":true,"vmuser":true},"policy":"Fail"}` | Configures resource validation | +| admissionWebhooks.caBundle | string | `""` | with keys: tls.key, tls.crt, ca.crt | +| admissionWebhooks.certManager.enabled | bool | `false` | Enables cert creation and injection by cert-manager. | +| admissionWebhooks.certManager.issuer | object | `{}` | If needed, provide own issuer. Operator will create self-signed if empty. | +| admissionWebhooks.enabled | bool | `false` | Enables validation webhook. | +| admissionWebhooks.policy | string | `"Fail"` | What to do in case, when operator not available to validate request. | +| affinity | object | `{}` | Pod affinity | +| annotations | object | `{}` | Annotations to be added to the all resources | +| cleanupCRD | bool | `false` | Tells helm to clean up vm cr resources when uninstalling | +| cleanupImage.pullPolicy | string | `"IfNotPresent"` | | +| cleanupImage.repository | string | `"gcr.io/google_containers/hyperkube"` | | +| cleanupImage.tag | string | `"v1.18.0"` | | +| createCRD | bool | `true` | with this option, if you remove this chart, all crd resources will be deleted with it. | +| env | list | `[]` | extra settings for the operator deployment. full list Ref: [https://github.com/VictoriaMetrics/operator/blob/master/vars.MD](https://github.com/VictoriaMetrics/operator/blob/master/vars.MD) | +| extraArgs | object | `{}` | operator container additional commandline arguments | +| extraContainers | list | `[]` | | +| extraHostPathMounts | list | `[]` | Additional hostPath mounts | +| extraLabels | object | `{}` | Labels to be added to the all resources | +| extraVolumeMounts | list | `[]` | Extra Volume Mounts for the container | +| extraVolumes | list | `[]` | Extra Volumes for the pod | +| fullnameOverride | string | `""` | Overrides the full name of server component | +| image.pullPolicy | string | `"IfNotPresent"` | Image pull policy | +| image.repository | string | `"victoriametrics/operator"` | Image repository | +| image.tag | string | `"v0.37.0"` | Image tag | +| imagePullSecrets | list | `[]` | Secret to pull images | +| logLevel | string | `"info"` | possible values: info and error. | +| nameOverride | string | `""` | VM operatror deployment name override | +| nodeSelector | object | `{}` | Pod's node selector. Ref: [https://kubernetes.io/docs/user-guide/node-selection/](https://kubernetes.io/docs/user-guide/node-selection/ | +| operator.disable_prometheus_converter | bool | `false` | By default, operator converts prometheus-operator objects. | +| operator.enable_converter_ownership | bool | `false` | Enables ownership reference for converted prometheus-operator objects, it will remove corresponding victoria-metrics objects in case of deletion prometheus one. | +| operator.prometheus_converter_add_argocd_ignore_annotations | bool | `false` | Compare-options and sync-options for prometheus objects converted by operator for properly use with ArgoCD | +| operator.psp_auto_creation_enabled | bool | `false` | By default, operator doesn't create psp for its objects. | +| operator.useCustomConfigReloader | bool | `false` | Enables custom config-reloader, bundled with operator. It should reduce vmagent and vmauth config sync-time and make it predictable. | +| podDisruptionBudget.enabled | bool | `false` | | +| podDisruptionBudget.labels | object | `{}` | | +| podLabels | object | `{}` | | +| podSecurityContext | object | `{}` | | +| rbac.create | bool | `true` | Specifies whether the RBAC resources should be created | +| rbac.pspEnabled | bool | `true` | | +| replicaCount | int | `1` | | +| resources | object | `{}` | Resource object | +| securityContext | object | `{}` | | +| serviceAccount.create | bool | `true` | Specifies whether a service account should be created | +| serviceAccount.name | string | `""` | The name of the service account to use. If not set and create is true, a name is generated using the fullname template | +| serviceMonitor | object | `{"annotations":{},"enabled":false,"extraLabels":{},"relabelings":[]}` | configures monitoring with serviceScrape. VMServiceScrape must be pre-installed | +| tolerations | list | `[]` | Array of tolerations object. Ref: [https://kubernetes.io/docs/concepts/configuration/assign-pod-node/](https://kubernetes.io/docs/concepts/configuration/assign-pod-node/) | +| topologySpreadConstraints | list | `[]` | Pod Topology Spread Constraints. Ref: [https://kubernetes.io/docs/concepts/scheduling-eviction/topology-spread-constraints/](https://kubernetes.io/docs/concepts/scheduling-eviction/topology-spread-constraints/) | +| watchNamespace | string | `""` | | \ No newline at end of file diff --git a/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/README.md.gotmpl b/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/README.md.gotmpl new file mode 100644 index 00000000..18c4c9cb --- /dev/null +++ b/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/README.md.gotmpl @@ -0,0 +1,140 @@ +# Helm Chart For Victoria Metrics Operator. + +{{ template "chart.typeBadge" . }} {{ template "chart.versionBadge" . }} +[![Artifact Hub](https://img.shields.io/endpoint?url=https://artifacthub.io/badge/repository/victoriametrics)](https://artifacthub.io/packages/helm/victoriametrics/victoria-logs-operator) + +{{ template "chart.description" . }} + +## Prerequisites + +* Install the follow packages: ``git``, ``kubectl``, ``helm``, ``helm-docs``. See this [tutorial](../../REQUIREMENTS.md). +* PV support on underlying infrastructure. + +## Upgrade guide + + During release an issue with helm CRD was discovered. So for upgrade from version less then 0.1.3 you have to two options: + 1) use helm management for CRD, enabled by default. + 2) use own management system, need to add variable: --set createCRD=false. + +If you choose helm management, following steps must be done before upgrade: + +1) define namespace and helm release name variables + +``` +export NAMESPACE=default +export RELEASE_NAME=operator +``` + +execute kubectl commands: + +``` +kubectl get crd | grep victoriametrics.com | awk '{print $1 }' | xargs -i kubectl label crd {} app.kubernetes.io/managed-by=Helm --overwrite +kubectl get crd | grep victoriametrics.com | awk '{print $1 }' | xargs -i kubectl annotate crd {} meta.helm.sh/release-namespace="$NAMESPACE" meta.helm.sh/release-name="$RELEASE_NAME" --overwrite +``` + +run helm upgrade command. + +## Chart Details + +This chart will do the following: + +* Rollout victoria metrics operator + +## How to install + +Access a Kubernetes cluster. + +Add a chart helm repository with follow commands: + +```console +helm repo add vm https://victoriametrics.github.io/helm-charts/ + +helm repo update +``` + +List versions of ``vm/victoria-metrics-operator`` chart available to installation: + +```console +helm search repo vm/victoria-metrics-operator -l +``` + +Export default values of ``victoria-metrics-operator`` chart to file ``values.yaml``: + +```console +helm show values vm/victoria-metrics-operator > values.yaml +``` + +Change the values according to the need of the environment in ``values.yaml`` file. + +Test the installation with command: + +```console +helm install vmoperator vm/victoria-metrics-operator -f values.yaml -n NAMESPACE --debug --dry-run +``` + +Install chart with command: + +```console +helm install vmoperator vm/victoria-metrics-operator -f values.yaml -n NAMESPACE +``` + +Get the pods lists by running this commands: + +```console +kubectl get pods -A | grep 'operator' +``` + +Get the application by running this command: + +```console +helm list -f vmoperator -n NAMESPACE +``` + +See the history of versions of ``vmoperator`` application with command. + +```console +helm history vmoperator -n NAMESPACE +``` + +## How to uninstall + +Remove application with command. + +```console +helm uninstall vmoperator -n NAMESPACE +``` + +## Validation webhook + + Its possible to use validation of created resources with operator. For now, you need cert-manager to easily certificate management https://cert-manager.io/docs/ + +```yaml +admissionWebhooks: + enabled: true + # what to do in case, when operator not available to validate request. + certManager: + # enables cert creation and injection by cert-manager + enabled: true +``` + +## Documentation of Helm Chart + +Install ``helm-docs`` following the instructions on this [tutorial](../../REQUIREMENTS.md). + +Generate docs with ``helm-docs`` command. + +```bash +cd charts/victoria-metrics-operator + +helm-docs +``` + +The markdown generation is entirely go template driven. The tool parses metadata from charts and generates a number of sub-templates that can be referenced in a template file (by default ``README.md.gotmpl``). If no template file is provided, the tool has a default internal template that will generate a reasonably formatted README. + +## Parameters + +The following tables lists the configurable parameters of the chart and their default values. + +Change the values according to the need of the environment in ``victoria-metrics-operator/values.yaml`` file. + +{{ template "chart.valuesTable" . }} \ No newline at end of file diff --git a/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/RELEASE_NOTES.md b/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/RELEASE_NOTES.md new file mode 100644 index 00000000..7ac9b795 --- /dev/null +++ b/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/RELEASE_NOTES.md @@ -0,0 +1,10 @@ +# Release notes for version 0.26.0 + +**Release date:** 2023-08-30 + +![AppVersion: 0.37.0](https://img.shields.io/static/v1?label=AppVersion&message=0.37.0&color=success&logo=) +![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +- Bump operator version to [v0.37.0](https://github.com/VictoriaMetrics/operator/releases/tag/v0.37.0) +- `psp_auto_creation_enabled` for operator is disabled by default + diff --git a/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/templates/NOTES.txt b/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/templates/NOTES.txt new file mode 100644 index 00000000..25e909b2 --- /dev/null +++ b/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/templates/NOTES.txt @@ -0,0 +1,5 @@ +{{ $.Chart.Name }} has been installed. Check its status by running: + kubectl --namespace {{ .Release.Namespace }} get pods -l "app.kubernetes.io/instance={{ $.Release.Name }}" + +Get more information on https://github.com/VictoriaMetrics/helm-charts/tree/master/charts/victoria-metrics-operator. +See "Getting started guide for VM Operator" on https://docs.victoriametrics.com/guides/getting-started-with-vm-operator.html . diff --git a/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/templates/_helpers.tpl b/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/templates/_helpers.tpl new file mode 100644 index 00000000..9cb7e4fc --- /dev/null +++ b/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/templates/_helpers.tpl @@ -0,0 +1,67 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "vm-operator.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | 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 "vm-operator.fullname" -}} +{{- if .Values.fullnameOverride -}} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- if contains $name .Release.Name -}} +{{- .Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "vm-operator.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create the name of the service account +*/}} +{{- define "vm-operator.serviceAccountName" -}} +{{- if .Values.serviceAccount.create -}} + {{ default (include "vm-operator.fullname" .) .Values.serviceAccount.name }} +{{- else -}} + {{ default "default" .Values.serviceAccount.name }} +{{- end -}} +{{- end -}} + +{{/* +Selector labels +*/}} +{{- define "vm-operator.selectorLabels" -}} +app.kubernetes.io/name: {{ include "vm-operator.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end -}} + +{{/* +Create unified labels for vm-operator components +*/}} +{{- define "vm-operator.labels" -}} +{{- include "vm-operator.selectorLabels" . }} +helm.sh/chart: {{ include "vm-operator.chart" . }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end -}} + +{{/* +Create the name of service account and clusterRole for cleanup-hook +*/}} +{{- define "vm-operator.cleanupHookName" -}} +{{- printf "%s-%s" (include "vm-operator.fullname" .) "cleanup-hook" | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} diff --git a/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/templates/certmanager.yaml b/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/templates/certmanager.yaml new file mode 100644 index 00000000..1e26aee3 --- /dev/null +++ b/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/templates/certmanager.yaml @@ -0,0 +1,57 @@ +{{- if .Values.admissionWebhooks.certManager.enabled -}} +{{- if not .Values.admissionWebhooks.certManager.issuer -}} +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + name: {{ template "vm-operator.fullname" . }}-root + namespace: {{ .Release.Namespace }} +spec: + selfSigned: {} +--- +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: {{ template "vm-operator.fullname" . }}-root-ca + namespace: {{ .Release.Namespace }} +spec: + secretName: {{ template "vm-operator.fullname" . }}-root-ca + duration: 63800h0m0s + issuerRef: + name: {{ template "vm-operator.fullname" . }}-root + commonName: "ca.validation.victoriametrics" + isCA: true +--- +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + name: {{ template "vm-operator.fullname" . }}-issuer + namespace: {{ .Release.Namespace }} +spec: + ca: + secretName: {{ template "vm-operator.fullname" . }}-root-ca +{{- end }} +--- +# actual cert part for operator +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: {{ template "vm-operator.fullname" . }}-validation + namespace: {{ .Release.Namespace }} +spec: + secretName: {{ template "vm-operator.fullname" . }}-validation + duration: 45800h0m0s + issuerRef: + {{- if .Values.admissionWebhooks.certManager.issuer }} + {{- range $k, $v := .Values.admissionWebhooks.certManager.issuer }} + {{ $k}}: {{ $v}} + {{- end }} + {{- else }} + name: {{ template "vm-operator.fullname" . }}-issuer + {{- end }} + dnsNames: + - {{ template "vm-operator.fullname" . }} + - {{ template "vm-operator.fullname" . }}.{{ .Release.Namespace }} + - {{ template "vm-operator.fullname" . }}.{{ .Release.Namespace }}.svc +{{- end -}} + + diff --git a/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/templates/cluster_role.yaml b/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/templates/cluster_role.yaml new file mode 100644 index 00000000..24722266 --- /dev/null +++ b/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/templates/cluster_role.yaml @@ -0,0 +1,499 @@ +{{- if and .Values.rbac.create (not .Values.watchNamespace) -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ template "vm-operator.fullname" . }} + labels: +{{ include "vm-operator.labels" . | indent 4 }} +rules: +- apiGroups: + - "" + resources: + - configmaps + - configmaps/finalizers + verbs: + - '*' +- apiGroups: + - "" + resources: + - endpoints + verbs: + - '*' +- apiGroups: + - "" + resources: + - events + verbs: + - '*' +- apiGroups: + - "" + resources: + - namespaces + verbs: + - get + - list + - watch +- apiGroups: + - "" + resources: + - persistentvolumeclaims + - persistentvolumeclaims/finalizers + verbs: + - '*' +- apiGroups: + - "" + resources: + - pods + verbs: + - '*' +- apiGroups: + - "" + resources: + - secrets + - secrets/finalizers + verbs: + - '*' +- apiGroups: + - "" + resources: + - services + verbs: + - '*' +- apiGroups: + - "" + resources: + - services/finalizers + verbs: + - '*' +- apiGroups: + - apps + resources: + - deployments + - deployments/finalizers + verbs: + - '*' +- apiGroups: + - apps + resources: + - replicasets + verbs: + - '*' +- apiGroups: + - apps + resources: + - statefulsets + - statefulsets/finalizers + - statefulsets/status + verbs: + - '*' +- apiGroups: + - monitoring.coreos.com + resources: + - '*' + verbs: + - '*' +- apiGroups: + - operator.victoriametrics.com + resources: + - vmagents + - vmagents/finalizers + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - operator.victoriametrics.com + resources: + - vmagents/status + verbs: + - get + - patch + - update +- apiGroups: + - operator.victoriametrics.com + resources: + - vmalertmanagers + - vmalertmanagers/finalizers + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - operator.victoriametrics.com + resources: + - vmalertmanagers/status + verbs: + - get + - patch + - update +- apiGroups: + - operator.victoriametrics.com + resources: + - vmalertmanagerconfigs + - vmalertmanagerconfigs/finalizers + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - operator.victoriametrics.com + resources: + - vmalertmanagerconfigss/status + verbs: + - get + - patch + - update +- apiGroups: + - operator.victoriametrics.com + resources: + - vmalerts + - vmalerts/finalizers + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - operator.victoriametrics.com + resources: + - vmalerts/status + verbs: + - get + - patch + - update +- apiGroups: + - operator.victoriametrics.com + resources: + - vmclusters + - vmclusters/finalizers + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - operator.victoriametrics.com + resources: + - vmclusters/status + verbs: + - get + - patch + - update +- apiGroups: + - operator.victoriametrics.com + resources: + - vmpodscrapes + - vmprobscrapes/finalizers + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - operator.victoriametrics.com + resources: + - vmpodscrapes/status + verbs: + - get + - patch + - update +- apiGroups: + - operator.victoriametrics.com + resources: + - vmrules + - vmrules/finalizers + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - operator.victoriametrics.com + resources: + - vmrules/status + verbs: + - get + - patch + - update +- apiGroups: + - operator.victoriametrics.com + resources: + - vmservicescrapes + - vmservicescrapes/finalizers + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - operator.victoriametrics.com + resources: + - vmservicescrapes/status + verbs: + - get + - patch + - update +- apiGroups: + - operator.victoriametrics.com + resources: + - vmprobes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - operator.victoriametrics.com + resources: + - vmprobes/status + verbs: + - get + - patch + - update +- apiGroups: + - operator.victoriametrics.com + resources: + - vmsingles + - vmsingles/finalizers + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - operator.victoriametrics.com + resources: + - vmsingles/status + verbs: + - get + - patch + - update +- apiGroups: + - "" + resources: + - nodes + - nodes/proxy + - services + - endpoints + - pods + - endpointslices + - configmaps + - nodes/metrics + - namespaces + verbs: + - get + - list + - watch +- apiGroups: + - "extensions" + - "networking.k8s.io" + resources: + - ingresses + verbs: + - get + - list + - watch +- nonResourceURLs: + - "/metrics" + - "/metrics/resources" + verbs: + - get + - watch + - list +- apiGroups: + - "rbac.authorization.k8s.io" + resources: + - clusterrolebindings + - clusterrolebindings/finalizers + - clusterroles + - clusterroles/finalizers + - roles + - rolebindings + verbs: + - get + - list + - create + - patch + - update + - watch + - delete +- apiGroups: + - "policy" + resources: + - podsecuritypolicies + - podsecuritypolicies/finalizers + verbs: + - get + - list + - create + - patch + - update + - use + - watch + - delete +- apiGroups: + - "" + resources: + - serviceaccounts + - serviceaccounts/finalizers + verbs: + - get + - list + - create + - watch + - update + - delete +- apiGroups: + - operator.victoriametrics.com + resources: + - vmnodescrapes + - vmnodescrapes/finalizers + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - operator.victoriametrics.com + resources: + - vmnodescrapes/status + verbs: + - get + - patch + - update +- apiGroups: + - operator.victoriametrics.com + resources: + - vmstaticscrapes + - vmstaticscrapes/finalizers + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - operator.victoriametrics.com + resources: + - vmstaticscrapes/status + verbs: + - get + - patch + - update +- apiGroups: + - operator.victoriametrics.com + resources: + - vmauths + - vmauths/finalizers + - vmusers + - vmusers/finalizers + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - operator.victoriametrics.com + resources: + - vmusers/status + - vmauths/status + verbs: + - get + - patch + - update +- apiGroups: + - storage.k8s.io + resources: + - storageclasses + verbs: + - list + - get + - watch +- apiGroups: + - policy + resources: + - poddisruptionbudgets + - poddisruptionbudgets/finalizers + verbs: + - '*' +- apiGroups: + - route.openshift.io + - image.openshift.io + resources: + - routers/metrics + - registry/metrics + verbs: + - get +- apiGroups: + - autoscaling + verbs: + - list + - get + - delete + - create + - update + - watch + resources: + - horizontalpodautoscalers +- apiGroups: + - networking.k8s.io + - extensions + resources: + - ingresses + - ingresses/finalizers + verbs: + - create + - delete + - get + - patch + - update + - watch +- apiGroups: + - apiextensions.k8s.io + resources: + - customresourcedefinitions + verbs: + - get + - list +{{- end -}} diff --git a/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/templates/clusterrole_binding.yaml b/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/templates/clusterrole_binding.yaml new file mode 100644 index 00000000..cd0e55d7 --- /dev/null +++ b/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/templates/clusterrole_binding.yaml @@ -0,0 +1,23 @@ +{{- if and .Values.rbac.create (not .Values.watchNamespace) -}} +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ include "vm-operator.fullname" . }} + labels: +{{ include "vm-operator.labels" . | indent 4 }} +{{- with .Values.extraLabels }} +{{ toYaml . | indent 4 }} +{{- end }} +{{- with .Values.annotations }} + annotations: +{{ toYaml . | indent 4 }} +{{- end }} +subjects: +- kind: ServiceAccount + name: {{ template "vm-operator.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} +roleRef: + kind: ClusterRole + name: {{ include "vm-operator.fullname" . }} + apiGroup: rbac.authorization.k8s.io +{{- end -}} diff --git a/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/templates/crd.yaml b/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/templates/crd.yaml new file mode 100644 index 00000000..39f8456b --- /dev/null +++ b/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/templates/crd.yaml @@ -0,0 +1,18228 @@ +{{- if .Values.createCRD }} +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.12.1 + name: vmagents.operator.victoriametrics.com +spec: + group: operator.victoriametrics.com + names: + kind: VMAgent + listKind: VMAgentList + plural: vmagents + singular: vmagent + scope: Namespaced + versions: + - additionalPrinterColumns: + - description: current number of shards + jsonPath: .status.shards + name: Shards Count + type: integer + - description: current number of replicas + jsonPath: .status.replicas + name: Replica Count + type: integer + name: v1beta1 + schema: + openAPIV3Schema: + description: VMAgent - is a tiny but brave agent, which helps you collect + metrics from various sources and stores them in VictoriaMetrics or any other + Prometheus-compatible storage system that supports the remote_write protocol. + 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: VMAgentSpec defines the desired state of VMAgent + properties: + '-': + description: ParsingError contents error with context if operator + was failed to parse json object from kubernetes api server + type: string + aPIServerConfig: + description: APIServerConfig allows specifying a host and auth methods + to access apiserver. If left empty, VMAgent is assumed to run inside + of the cluster and will discover API servers automatically and use + the pod's CA certificate and bearer token file at /var/run/secrets/kubernetes.io/serviceaccount/. + properties: + authorization: + description: Authorization configures generic authorization params + properties: + credentials: + description: Reference to the secret with value for authorization + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + credentialsFile: + description: File with value for authorization + type: string + type: + description: Type of authorization, default to bearer + type: string + type: object + basicAuth: + description: BasicAuth allow an endpoint to authenticate over + basic authentication + properties: + password: + description: The secret in the service scrape namespace that + contains the password for authentication. It must be at + them same namespace as CRD + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + password_file: + description: PasswordFile defines path to password file at + disk + type: string + username: + description: The secret in the service scrape namespace that + contains the username for authentication. It must be at + them same namespace as CRD + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + bearerToken: + description: Bearer token for accessing apiserver. + type: string + bearerTokenFile: + description: File to read bearer token for accessing apiserver. + type: string + host: + description: Host of apiserver. A valid string consisting of a + hostname or IP followed by an optional port number + type: string + tlsConfig: + description: TLSConfig Config to use for accessing apiserver. + properties: + ca: + description: Stuct containing the CA cert to use for the targets. + properties: + configMap: + description: ConfigMap containing data to use for the + targets. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + 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 + secret: + description: Secret containing data to use for the targets. + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + 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 + caFile: + description: Path to the CA cert in the container to use for + the targets. + type: string + cert: + description: Struct containing the client cert file for the + targets. + properties: + configMap: + description: ConfigMap containing data to use for the + targets. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + 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 + secret: + description: Secret containing data to use for the targets. + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + 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 + certFile: + description: Path to the client cert file in the container + for the targets. + type: string + insecureSkipVerify: + description: Disable target certificate validation. + type: boolean + keyFile: + description: Path to the client key file in the container + for the targets. + type: string + keySecret: + description: Secret containing the client key file for the + targets. + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + serverName: + description: Used to verify the hostname for the targets. + type: string + type: object + required: + - host + type: object + additionalScrapeConfigs: + description: AdditionalScrapeConfigs As scrape configs are appended, + the user is responsible to make sure it is valid. Note that using + this feature may expose the possibility to break upgrades of VMAgent. + It is advised to review VMAgent release notes to ensure that no + incompatible scrape configs are going to break VMAgent after the + upgrade. + properties: + key: + description: The key of the secret to select from. Must be a + valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + affinity: + description: Affinity If specified, the pod's scheduling constraints. + type: object + x-kubernetes-preserve-unknown-fields: true + arbitraryFSAccessThroughSMs: + description: ArbitraryFSAccessThroughSMs configures whether configuration + based on a service scrape can access arbitrary files on the file + system of the VMAgent container e.g. bearer token files. + properties: + deny: + type: boolean + type: object + claimTemplates: + description: ClaimTemplates allows adding additional VolumeClaimTemplates + for VMAgent in StatefulMode + items: + description: PersistentVolumeClaim is a user's request for and claim + to a persistent volume + 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: + description: 'Standard object''s metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata' + type: object + x-kubernetes-preserve-unknown-fields: true + spec: + description: 'spec defines the desired characteristics of a + volume requested by a pod author. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' + properties: + accessModes: + description: 'accessModes contains the desired access modes + the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' + items: + type: string + type: array + dataSource: + description: 'dataSource field can be used to specify either: + * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) + * An existing PVC (PersistentVolumeClaim) If the provisioner + or an external controller can support the specified data + source, it will create a new volume based on the contents + of the specified data source. If the AnyVolumeDataSource + feature gate is enabled, this field will always have the + same contents as the DataSourceRef field.' + properties: + apiGroup: + description: APIGroup is the group for the resource + being referenced. If APIGroup is not specified, the + specified Kind must be in the core API group. For + any other third-party types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource being referenced + type: string + name: + description: Name is the name of resource being referenced + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + description: 'dataSourceRef specifies the object from which + to populate the volume with data, if a non-empty volume + is desired. This may be any local object from a non-empty + API group (non core object) or a PersistentVolumeClaim + object. When this field is specified, volume binding will + only succeed if the type of the specified object matches + some installed volume populator or dynamic provisioner. + This field will replace the functionality of the DataSource + field and as such if both fields are non-empty, they must + have the same value. For backwards compatibility, both + fields (DataSource and DataSourceRef) will be set to the + same value automatically if one of them is empty and the + other is non-empty. There are two important differences + between DataSource and DataSourceRef: * While DataSource + only allows two specific types of objects, DataSourceRef + allows any non-core object, as well as PersistentVolumeClaim + objects. * While DataSource ignores disallowed values + (dropping them), DataSourceRef preserves all values, and + generates an error if a disallowed value is specified. + (Beta) Using this field requires the AnyVolumeDataSource + feature gate to be enabled.' + properties: + apiGroup: + description: APIGroup is the group for the resource + being referenced. If APIGroup is not specified, the + specified Kind must be in the core API group. For + any other third-party types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource being referenced + type: string + name: + description: Name is the name of resource being referenced + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + resources: + description: 'resources represents the minimum resources + the volume should have. If RecoverVolumeExpansionFailure + feature is enabled users are allowed to specify resource + requirements that are lower than previous value but must + still be higher than capacity recorded in the status field + of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' + properties: + 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. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + selector: + description: selector is a label query over volumes to consider + for binding. + 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 + required: + - key + - operator + type: object + type: array + 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 + storageClassName: + description: 'storageClassName is the name of the StorageClass + required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' + type: string + volumeMode: + description: volumeMode defines what type of volume is required + by the claim. Value of Filesystem is implied when not + included in claim spec. + type: string + volumeName: + description: volumeName is the binding reference to the + PersistentVolume backing this claim. + type: string + type: object + status: + description: 'status represents the current information/status + of a persistent volume claim. Read-only. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' + properties: + accessModes: + description: 'accessModes contains the actual access modes + the volume backing the PVC has. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' + items: + type: string + type: array + allocatedResources: + 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: allocatedResources is the storage resource + within AllocatedResources tracks the capacity allocated + to a PVC. It may be larger than the actual capacity when + a volume expansion operation is requested. For storage + quota, the larger value from allocatedResources and PVC.spec.resources + is used. If allocatedResources is not set, PVC.spec.resources + alone is used for quota calculation. If a volume expansion + capacity request is lowered, allocatedResources is only + lowered if there are no expansion operations in progress + and if the actual volume capacity is equal or lower than + the requested capacity. This is an alpha field and requires + enabling RecoverVolumeExpansionFailure feature. + type: object + capacity: + 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: capacity represents the actual resources of + the underlying volume. + type: object + conditions: + description: conditions is the current Condition of persistent + volume claim. If underlying persistent volume is being + resized then the Condition will be set to 'ResizeStarted'. + items: + description: PersistentVolumeClaimCondition contails details + about state of pvc + properties: + lastProbeTime: + description: lastProbeTime is the time we probed the + condition. + format: date-time + type: string + lastTransitionTime: + description: lastTransitionTime is the time the condition + transitioned from one status to another. + format: date-time + type: string + message: + description: message is the human-readable message + indicating details about last transition. + type: string + reason: + description: reason is a unique, this should be a + short, machine understandable string that gives + the reason for condition's last transition. If it + reports "ResizeStarted" that means the underlying + persistent volume is being resized. + type: string + status: + type: string + type: + description: PersistentVolumeClaimConditionType is + a valid value of PersistentVolumeClaimCondition.Type + type: string + required: + - status + - type + type: object + type: array + phase: + description: phase represents the current phase of PersistentVolumeClaim. + type: string + resizeStatus: + description: resizeStatus stores status of resize operation. + ResizeStatus is not set by default but when expansion + is complete resizeStatus is set to empty string by resize + controller or kubelet. This is an alpha field and requires + enabling RecoverVolumeExpansionFailure feature. + type: string + type: object + type: object + type: array + configMaps: + description: ConfigMaps is a list of ConfigMaps in the same namespace + as the vmagent object, which shall be mounted into the vmagent Pods. + will be mounted at path /etc/vm/configs + items: + type: string + type: array + containers: + description: Containers property allows to inject additions sidecars + or to patch existing containers. It can be useful for proxies, backup, + etc. + items: + description: A single application container that you want to run + within a pod. + required: + - name + type: object + x-kubernetes-preserve-unknown-fields: true + type: array + dnsConfig: + description: Specifies the DNS parameters of a pod. Parameters specified + here will be merged to the generated DNS configuration based on + DNSPolicy. + items: + x-kubernetes-preserve-unknown-fields: true + properties: + nameservers: + description: A list of DNS name server IP addresses. This will + be appended to the base nameservers generated from DNSPolicy. + Duplicated nameservers will be removed. + items: + type: string + type: array + options: + description: A list of DNS resolver options. This will be merged + with the base options generated from DNSPolicy. Duplicated entries + will be removed. Resolution options given in Options will override + those that appear in the base DNSPolicy. + items: + description: PodDNSConfigOption defines DNS resolver options + of a pod. + properties: + name: + description: Required. + type: string + value: + type: string + type: object + type: array + searches: + description: A list of DNS search domains for host-name lookup. + This will be appended to the base search paths generated from + DNSPolicy. Duplicated search paths will be removed. + items: + type: string + type: array + type: object + dnsPolicy: + description: DNSPolicy set DNS policy for the pod + type: string + enforcedNamespaceLabel: + description: EnforcedNamespaceLabel enforces adding a namespace label + of origin for each alert and metric that is user created. The label + value will always be the namespace of the object that is being created. + type: string + externalLabels: + additionalProperties: + type: string + description: ExternalLabels The labels to add to any time series scraped + by vmagent. it doesn't affect metrics ingested directly by push + API's + type: object + extraArgs: + additionalProperties: + type: string + description: 'ExtraArgs that will be passed to VMAgent pod for example + remoteWrite.tmpDataPath: /tmp it would be converted to flag --remoteWrite.tmpDataPath=/tmp' + type: object + extraEnvs: + description: ExtraEnvs that will be added to VMAgent pod + 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 + required: + - name + type: object + x-kubernetes-preserve-unknown-fields: true + type: array + host_aliases: + description: HostAliases provides mapping between ip and hostnames, + that would be propagated to pod, cannot be used with HostNetwork. + items: + description: HostAlias holds the mapping between IP and hostnames + that will be injected as an entry in the pod's hosts file. + properties: + hostnames: + description: Hostnames for the above IP address. + items: + type: string + type: array + ip: + description: IP address of the host file entry. + type: string + type: object + type: array + hostNetwork: + description: HostNetwork controls whether the pod may use the node + network namespace + type: boolean + ignoreNamespaceSelectors: + description: IgnoreNamespaceSelectors if set to true will ignore NamespaceSelector + settings from the podscrape and vmservicescrape configs, and they + will only discover endpoints within their current namespace. Defaults + to false. + type: boolean + image: + description: Image - docker image settings for VMAgent if no specified + operator uses default config version + properties: + pullPolicy: + description: PullPolicy describes how to pull docker image + type: string + repository: + description: Repository contains name of docker image + it's repository + if needed + type: string + tag: + description: Tag contains desired docker image version + type: string + type: object + imagePullSecrets: + description: ImagePullSecrets An optional list of references to secrets + in the same namespace to use for pulling images from registries + see https://kubernetes.io/docs/concepts/containers/images/#referring-to-an-imagepullsecrets-on-a-pod + items: + description: LocalObjectReference contains enough information to + let you locate the referenced object inside the same namespace. + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + x-kubernetes-map-type: atomic + type: array + initContainers: + description: 'InitContainers allows adding initContainers to the pod + definition. Those can be used to e.g. fetch secrets for injection + into the vmagent configuration from external sources. Any errors + during the execution of an initContainer will lead to a restart + of the Pod. More info: https://kubernetes.io/docs/concepts/workloads/pods/init-containers/ + Using initContainers for any use case other then secret fetching + is entirely outside the scope of what the maintainers will support + and by doing so, you accept that this behaviour may break at any + time without notice.' + items: + description: A single application container that you want to run + within a pod. + required: + - name + type: object + x-kubernetes-preserve-unknown-fields: true + type: array + inlineRelabelConfig: + description: InlineRelabelConfig - defines GlobalRelabelConfig for + vmagent, can be defined directly at CRD. + items: + description: 'RelabelConfig allows dynamic rewriting of the label + set, being applied to samples before ingestion. It defines ``-section + of configuration. More info: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#metric_relabel_configs' + properties: + action: + description: Action to perform based on regex matching. Default + is 'replace' + type: string + if: + description: 'If represents metricsQL match expression: ''{__name__=~"foo_.*"}''' + type: string + labels: + additionalProperties: + type: string + description: 'Labels is used together with Match for `action: + graphite`' + type: object + match: + description: 'Match is used together with Labels for `action: + graphite`' + type: string + modulus: + description: Modulus to take of the hash of the source label + values. + format: int64 + type: integer + regex: + description: Regular expression against which the extracted + value is matched. Default is '(.*)' + type: string + replacement: + description: Replacement value against which a regex replace + is performed if the regular expression matches. Regex capture + groups are available. Default is '$1' + type: string + separator: + description: Separator placed between concatenated source label + values. default is ';'. + type: string + source_labels: + description: UnderScoreSourceLabels - additional form of source + labels source_labels for compatibility with original relabel + config. if set both sourceLabels and source_labels, sourceLabels + has priority. for details https://github.com/VictoriaMetrics/operator/issues/131 + items: + type: string + type: array + sourceLabels: + description: The source labels select values from existing labels. + Their content is concatenated using the configured separator + and matched against the configured regular expression for + the replace, keep, and drop actions. + items: + type: string + type: array + target_label: + description: UnderScoreTargetLabel - additional form of target + label - target_label for compatibility with original relabel + config. if set both targetLabel and target_label, targetLabel + has priority. for details https://github.com/VictoriaMetrics/operator/issues/131 + type: string + targetLabel: + description: Label to which the resulting value is written in + a replace action. It is mandatory for replace actions. Regex + capture groups are available. + type: string + type: object + type: array + inlineScrapeConfig: + description: 'InlineScrapeConfig As scrape configs are appended, the + user is responsible to make sure it is valid. Note that using this + feature may expose the possibility to break upgrades of VMAgent. + It is advised to review VMAgent release notes to ensure that no + incompatible scrape configs are going to break VMAgent after the + upgrade. it should be defined as single yaml file. inlineScrapeConfig: + | - job_name: "prometheus" static_configs: - targets: ["localhost:9090"]' + type: string + insertPorts: + description: InsertPorts - additional listen ports for data ingestion. + properties: + graphitePort: + description: GraphitePort listen port + type: string + influxPort: + description: InfluxPort listen port + type: string + openTSDBHTTPPort: + description: OpenTSDBHTTPPort for http connections. + type: string + openTSDBPort: + description: OpenTSDBPort for tcp and udp listen + type: string + type: object + livenessProbe: + description: LivenessProbe that will be added CRD pod + type: object + x-kubernetes-preserve-unknown-fields: true + logFormat: + description: LogFormat for VMAgent to be configured with. + enum: + - default + - json + type: string + logLevel: + description: LogLevel for VMAgent to be configured with. INFO, WARN, + ERROR, FATAL, PANIC + enum: + - INFO + - WARN + - ERROR + - FATAL + - PANIC + type: string + maxScrapeInterval: + description: MaxScrapeInterval allows limiting maximum scrape interval + for VMServiceScrape, VMPodScrape and other scrapes If interval is + higher than defined limit, `maxScrapeInterval` will be used. + type: string + minScrapeInterval: + description: MinScrapeInterval allows limiting minimal scrape interval + for VMServiceScrape, VMPodScrape and other scrapes If interval is + lower than defined limit, `minScrapeInterval` will be used. + type: string + nodeScrapeNamespaceSelector: + description: NodeScrapeNamespaceSelector defines Namespaces to be + selected for VMNodeScrape discovery. Works in combination with Selector. + NamespaceSelector nil - only objects at VMAgent namespace. Selector + nil - only objects at NamespaceSelector namespaces. If both nil + - behaviour controlled by selectAllByDefault + 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 + required: + - key + - operator + type: object + type: array + 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 + nodeScrapeRelabelTemplate: + description: NodeScrapeRelabelTemplate defines relabel config, that + will be added to each VMNodeScrape. it's useful for adding specific + labels to all targets + items: + description: 'RelabelConfig allows dynamic rewriting of the label + set, being applied to samples before ingestion. It defines ``-section + of configuration. More info: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#metric_relabel_configs' + properties: + action: + description: Action to perform based on regex matching. Default + is 'replace' + type: string + if: + description: 'If represents metricsQL match expression: ''{__name__=~"foo_.*"}''' + type: string + labels: + additionalProperties: + type: string + description: 'Labels is used together with Match for `action: + graphite`' + type: object + match: + description: 'Match is used together with Labels for `action: + graphite`' + type: string + modulus: + description: Modulus to take of the hash of the source label + values. + format: int64 + type: integer + regex: + description: Regular expression against which the extracted + value is matched. Default is '(.*)' + type: string + replacement: + description: Replacement value against which a regex replace + is performed if the regular expression matches. Regex capture + groups are available. Default is '$1' + type: string + separator: + description: Separator placed between concatenated source label + values. default is ';'. + type: string + source_labels: + description: UnderScoreSourceLabels - additional form of source + labels source_labels for compatibility with original relabel + config. if set both sourceLabels and source_labels, sourceLabels + has priority. for details https://github.com/VictoriaMetrics/operator/issues/131 + items: + type: string + type: array + sourceLabels: + description: The source labels select values from existing labels. + Their content is concatenated using the configured separator + and matched against the configured regular expression for + the replace, keep, and drop actions. + items: + type: string + type: array + target_label: + description: UnderScoreTargetLabel - additional form of target + label - target_label for compatibility with original relabel + config. if set both targetLabel and target_label, targetLabel + has priority. for details https://github.com/VictoriaMetrics/operator/issues/131 + type: string + targetLabel: + description: Label to which the resulting value is written in + a replace action. It is mandatory for replace actions. Regex + capture groups are available. + type: string + type: object + type: array + nodeScrapeSelector: + description: NodeScrapeSelector defines VMNodeScrape to be selected + for scraping. Works in combination with NamespaceSelector. NamespaceSelector + nil - only objects at VMAgent namespace. Selector nil - only objects + at NamespaceSelector namespaces. If both nil - behaviour controlled + by selectAllByDefault + 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 + required: + - key + - operator + type: object + type: array + 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: NodeSelector Define which Nodes the Pods are scheduled + on. + type: object + overrideHonorLabels: + description: OverrideHonorLabels if set to true overrides all user + configured honor_labels. If HonorLabels is set in ServiceScrape + or PodScrape to true, this overrides honor_labels to false. + type: boolean + overrideHonorTimestamps: + description: OverrideHonorTimestamps allows to globally enforce honoring + timestamps in all scrape configs. + type: boolean + podDisruptionBudget: + description: PodDisruptionBudget created by operator + properties: + maxUnavailable: + anyOf: + - type: integer + - type: string + description: An eviction is allowed if at most "maxUnavailable" + pods selected by "selector" are unavailable after the eviction, + i.e. even in absence of the evicted pod. For example, one can + prevent all voluntary evictions by specifying 0. This is a mutually + exclusive setting with "minAvailable". + x-kubernetes-int-or-string: true + minAvailable: + anyOf: + - type: integer + - type: string + description: An eviction is allowed if at least "minAvailable" + pods selected by "selector" will still be available after the + eviction, i.e. even in the absence of the evicted pod. So for + example you can prevent all voluntary evictions by specifying + "100%". + x-kubernetes-int-or-string: true + selectorLabels: + additionalProperties: + type: string + description: replaces default labels selector generated by operator + it's useful when you need to create custom budget + type: object + type: object + podMetadata: + description: PodMetadata configures Labels and Annotations which are + propagated to the vmagent pods. + properties: + annotations: + additionalProperties: + type: string + description: 'Annotations is an unstructured key value map stored + with a resource that may be set by external tools to store and + retrieve arbitrary metadata. They are not queryable and should + be preserved when modifying objects. More info: http://kubernetes.io/docs/user-guide/annotations' + type: object + labels: + additionalProperties: + type: string + description: 'Labels Map of string keys and values that can be + used to organize and categorize (scope and select) objects. + May match selectors of replication controllers and services. + More info: http://kubernetes.io/docs/user-guide/labels' + type: object + name: + description: 'Name must be unique within a namespace. Is required + when creating resources, although some resources may allow a + client to request the generation of an appropriate name automatically. + Name is primarily intended for creation idempotence and configuration + definition. Cannot be updated. More info: http://kubernetes.io/docs/user-guide/identifiers#names' + type: string + type: object + podScrapeNamespaceSelector: + description: PodScrapeNamespaceSelector defines Namespaces to be selected + for VMPodScrape discovery. Works in combination with Selector. NamespaceSelector + nil - only objects at VMAgent namespace. Selector nil - only objects + at NamespaceSelector namespaces. If both nil - behaviour controlled + by selectAllByDefault + 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 + required: + - key + - operator + type: object + type: array + 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 + podScrapeRelabelTemplate: + description: PodScrapeRelabelTemplate defines relabel config, that + will be added to each VMPodScrape. it's useful for adding specific + labels to all targets + items: + description: 'RelabelConfig allows dynamic rewriting of the label + set, being applied to samples before ingestion. It defines ``-section + of configuration. More info: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#metric_relabel_configs' + properties: + action: + description: Action to perform based on regex matching. Default + is 'replace' + type: string + if: + description: 'If represents metricsQL match expression: ''{__name__=~"foo_.*"}''' + type: string + labels: + additionalProperties: + type: string + description: 'Labels is used together with Match for `action: + graphite`' + type: object + match: + description: 'Match is used together with Labels for `action: + graphite`' + type: string + modulus: + description: Modulus to take of the hash of the source label + values. + format: int64 + type: integer + regex: + description: Regular expression against which the extracted + value is matched. Default is '(.*)' + type: string + replacement: + description: Replacement value against which a regex replace + is performed if the regular expression matches. Regex capture + groups are available. Default is '$1' + type: string + separator: + description: Separator placed between concatenated source label + values. default is ';'. + type: string + source_labels: + description: UnderScoreSourceLabels - additional form of source + labels source_labels for compatibility with original relabel + config. if set both sourceLabels and source_labels, sourceLabels + has priority. for details https://github.com/VictoriaMetrics/operator/issues/131 + items: + type: string + type: array + sourceLabels: + description: The source labels select values from existing labels. + Their content is concatenated using the configured separator + and matched against the configured regular expression for + the replace, keep, and drop actions. + items: + type: string + type: array + target_label: + description: UnderScoreTargetLabel - additional form of target + label - target_label for compatibility with original relabel + config. if set both targetLabel and target_label, targetLabel + has priority. for details https://github.com/VictoriaMetrics/operator/issues/131 + type: string + targetLabel: + description: Label to which the resulting value is written in + a replace action. It is mandatory for replace actions. Regex + capture groups are available. + type: string + type: object + type: array + podScrapeSelector: + description: PodScrapeSelector defines PodScrapes to be selected for + target discovery. Works in combination with NamespaceSelector. NamespaceSelector + nil - only objects at VMAgent namespace. Selector nil - only objects + at NamespaceSelector namespaces. If both nil - behaviour controlled + by selectAllByDefault + 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 + required: + - key + - operator + type: object + type: array + 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 + podSecurityPolicyName: + description: PodSecurityPolicyName - defines name for podSecurityPolicy + in case of empty value, prefixedName will be used. + type: string + port: + description: Port listen address + type: string + priorityClassName: + description: PriorityClassName assigned to the Pods + type: string + probeNamespaceSelector: + description: ProbeNamespaceSelector defines Namespaces to be selected + for VMProbe discovery. Works in combination with Selector. NamespaceSelector + nil - only objects at VMAgent namespace. Selector nil - only objects + at NamespaceSelector namespaces. If both nil - behaviour controlled + by selectAllByDefault + 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 + required: + - key + - operator + type: object + type: array + 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 + probeScrapeRelabelTemplate: + description: ProbeScrapeRelabelTemplate defines relabel config, that + will be added to each VMProbeScrape. it's useful for adding specific + labels to all targets + items: + description: 'RelabelConfig allows dynamic rewriting of the label + set, being applied to samples before ingestion. It defines ``-section + of configuration. More info: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#metric_relabel_configs' + properties: + action: + description: Action to perform based on regex matching. Default + is 'replace' + type: string + if: + description: 'If represents metricsQL match expression: ''{__name__=~"foo_.*"}''' + type: string + labels: + additionalProperties: + type: string + description: 'Labels is used together with Match for `action: + graphite`' + type: object + match: + description: 'Match is used together with Labels for `action: + graphite`' + type: string + modulus: + description: Modulus to take of the hash of the source label + values. + format: int64 + type: integer + regex: + description: Regular expression against which the extracted + value is matched. Default is '(.*)' + type: string + replacement: + description: Replacement value against which a regex replace + is performed if the regular expression matches. Regex capture + groups are available. Default is '$1' + type: string + separator: + description: Separator placed between concatenated source label + values. default is ';'. + type: string + source_labels: + description: UnderScoreSourceLabels - additional form of source + labels source_labels for compatibility with original relabel + config. if set both sourceLabels and source_labels, sourceLabels + has priority. for details https://github.com/VictoriaMetrics/operator/issues/131 + items: + type: string + type: array + sourceLabels: + description: The source labels select values from existing labels. + Their content is concatenated using the configured separator + and matched against the configured regular expression for + the replace, keep, and drop actions. + items: + type: string + type: array + target_label: + description: UnderScoreTargetLabel - additional form of target + label - target_label for compatibility with original relabel + config. if set both targetLabel and target_label, targetLabel + has priority. for details https://github.com/VictoriaMetrics/operator/issues/131 + type: string + targetLabel: + description: Label to which the resulting value is written in + a replace action. It is mandatory for replace actions. Regex + capture groups are available. + type: string + type: object + type: array + probeSelector: + description: ProbeSelector defines VMProbe to be selected for target + probing. Works in combination with NamespaceSelector. NamespaceSelector + nil - only objects at VMAgent namespace. Selector nil - only objects + at NamespaceSelector namespaces. If both nil - behaviour controlled + by selectAllByDefault + 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 + required: + - key + - operator + type: object + type: array + 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 + readinessGates: + description: ReadinessGates defines pod readiness gates + items: + description: PodReadinessGate contains the reference to a pod condition + properties: + conditionType: + description: ConditionType refers to a condition in the pod's + condition list with matching type. + type: string + required: + - conditionType + type: object + type: array + readinessProbe: + description: ReadinessProbe that will be added CRD pod + type: object + x-kubernetes-preserve-unknown-fields: true + relabelConfig: + description: RelabelConfig ConfigMap with global relabel config -remoteWrite.relabelConfig + This relabeling is applied to all the collected metrics before sending + them to remote storage. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + remoteWrite: + description: 'RemoteWrite list of victoria metrics /some other remote + write system for vm it must looks like: http://victoria-metrics-single:8429/api/v1/write + or for cluster different url https://github.com/VictoriaMetrics/VictoriaMetrics/tree/master/app/vmagent#splitting-data-streams-among-multiple-systems' + items: + description: VMAgentRemoteWriteSpec defines the remote storage configuration + for VmAgent + properties: + basicAuth: + description: BasicAuth allow an endpoint to authenticate over + basic authentication + properties: + password: + description: The secret in the service scrape namespace + that contains the password for authentication. It must + be at them same namespace as CRD + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + password_file: + description: PasswordFile defines path to password file + at disk + type: string + username: + description: The secret in the service scrape namespace + that contains the username for authentication. It must + be at them same namespace as CRD + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + bearerTokenSecret: + description: Optional bearer auth token to use for -remoteWrite.url + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + headers: + description: 'Headers allow configuring custom http headers + Must be in form of semicolon separated header with value e.g. + headerName: headerValue vmagent supports since 1.79.0 version' + items: + type: string + type: array + inlineUrlRelabelConfig: + description: InlineUrlRelabelConfig defines relabeling config + for remoteWriteURL, it can be defined at crd spec. + items: + description: 'RelabelConfig allows dynamic rewriting of the + label set, being applied to samples before ingestion. It + defines ``-section of configuration. + More info: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#metric_relabel_configs' + properties: + action: + description: Action to perform based on regex matching. + Default is 'replace' + type: string + if: + description: 'If represents metricsQL match expression: + ''{__name__=~"foo_.*"}''' + type: string + labels: + additionalProperties: + type: string + description: 'Labels is used together with Match for `action: + graphite`' + type: object + match: + description: 'Match is used together with Labels for `action: + graphite`' + type: string + modulus: + description: Modulus to take of the hash of the source + label values. + format: int64 + type: integer + regex: + description: Regular expression against which the extracted + value is matched. Default is '(.*)' + type: string + replacement: + description: Replacement value against which a regex replace + is performed if the regular expression matches. Regex + capture groups are available. Default is '$1' + type: string + separator: + description: Separator placed between concatenated source + label values. default is ';'. + type: string + source_labels: + description: UnderScoreSourceLabels - additional form + of source labels source_labels for compatibility with + original relabel config. if set both sourceLabels and + source_labels, sourceLabels has priority. for details + https://github.com/VictoriaMetrics/operator/issues/131 + items: + type: string + type: array + sourceLabels: + description: The source labels select values from existing + labels. Their content is concatenated using the configured + separator and matched against the configured regular + expression for the replace, keep, and drop actions. + items: + type: string + type: array + target_label: + description: UnderScoreTargetLabel - additional form of + target label - target_label for compatibility with original + relabel config. if set both targetLabel and target_label, + targetLabel has priority. for details https://github.com/VictoriaMetrics/operator/issues/131 + type: string + targetLabel: + description: Label to which the resulting value is written + in a replace action. It is mandatory for replace actions. + Regex capture groups are available. + type: string + type: object + type: array + oauth2: + description: OAuth2 defines auth configuration + properties: + client_id: + description: The secret or configmap containing the OAuth2 + client id + properties: + configMap: + description: ConfigMap containing data to use for the + targets. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + 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 + secret: + description: Secret containing data to use for the targets. + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + 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 + client_secret: + description: The secret containing the OAuth2 client secret + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + client_secret_file: + description: ClientSecretFile defines path for client secret + file. + type: string + endpoint_params: + additionalProperties: + type: string + description: Parameters to append to the token URL + type: object + scopes: + description: OAuth2 scopes used for the token request + items: + type: string + type: array + token_url: + description: The URL to fetch the token from + minLength: 1 + type: string + required: + - client_id + - token_url + type: object + sendTimeout: + description: Timeout for sending a single block of data to -remoteWrite.url + (default 1m0s) + pattern: '[0-9]+(ms|s|m|h)' + type: string + streamAggrConfig: + description: StreamAggrConfig defines stream aggregation configuration + for VMAgent for -remoteWrite.url + properties: + dedupInterval: + description: Allows setting different de-duplication intervals + per each configured remote storage + type: string + dropInput: + description: Allow drop all the input samples after the + aggregation + type: boolean + keepInput: + description: Allows writing both raw and aggregate data + type: boolean + rules: + description: Stream aggregation rules + items: + description: StreamAggrRule defines the rule in stream + aggregation config + properties: + by: + description: "By is an optional list of labels for + grouping input series. \n See also Without. \n If + neither By nor Without are set, then the Outputs + are calculated individually per each input time + series." + items: + type: string + type: array + input_relabel_configs: + description: InputRelabelConfigs is an optional relabeling + rules, which are applied on the input before aggregation. + items: + description: 'RelabelConfig allows dynamic rewriting + of the label set, being applied to samples before + ingestion. It defines ``-section + of configuration. More info: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#metric_relabel_configs' + properties: + action: + description: Action to perform based on regex + matching. Default is 'replace' + type: string + if: + description: 'If represents metricsQL match + expression: ''{__name__=~"foo_.*"}''' + type: string + labels: + additionalProperties: + type: string + description: 'Labels is used together with Match + for `action: graphite`' + type: object + match: + description: 'Match is used together with Labels + for `action: graphite`' + type: string + modulus: + description: Modulus to take of the hash of + the source label values. + format: int64 + type: integer + regex: + description: Regular expression against which + the extracted value is matched. Default is + '(.*)' + type: string + replacement: + description: Replacement value against which + a regex replace is performed if the regular + expression matches. Regex capture groups are + available. Default is '$1' + type: string + separator: + description: Separator placed between concatenated + source label values. default is ';'. + type: string + source_labels: + description: UnderScoreSourceLabels - additional + form of source labels source_labels for compatibility + with original relabel config. if set both + sourceLabels and source_labels, sourceLabels + has priority. for details https://github.com/VictoriaMetrics/operator/issues/131 + items: + type: string + type: array + sourceLabels: + description: The source labels select values + from existing labels. Their content is concatenated + using the configured separator and matched + against the configured regular expression + for the replace, keep, and drop actions. + items: + type: string + type: array + target_label: + description: UnderScoreTargetLabel - additional + form of target label - target_label for compatibility + with original relabel config. if set both + targetLabel and target_label, targetLabel + has priority. for details https://github.com/VictoriaMetrics/operator/issues/131 + type: string + targetLabel: + description: Label to which the resulting value + is written in a replace action. It is mandatory + for replace actions. Regex capture groups + are available. + type: string + type: object + type: array + interval: + description: Interval is the interval between aggregations. + type: string + match: + description: "Match is a label selector for filtering + time series for the given selector. \n If the match + isn't set, then all the input time series are processed." + items: + type: string + type: array + output_relabel_configs: + description: OutputRelabelConfigs is an optional relabeling + rules, which are applied on the aggregated output + before being sent to remote storage. + items: + description: 'RelabelConfig allows dynamic rewriting + of the label set, being applied to samples before + ingestion. It defines ``-section + of configuration. More info: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#metric_relabel_configs' + properties: + action: + description: Action to perform based on regex + matching. Default is 'replace' + type: string + if: + description: 'If represents metricsQL match + expression: ''{__name__=~"foo_.*"}''' + type: string + labels: + additionalProperties: + type: string + description: 'Labels is used together with Match + for `action: graphite`' + type: object + match: + description: 'Match is used together with Labels + for `action: graphite`' + type: string + modulus: + description: Modulus to take of the hash of + the source label values. + format: int64 + type: integer + regex: + description: Regular expression against which + the extracted value is matched. Default is + '(.*)' + type: string + replacement: + description: Replacement value against which + a regex replace is performed if the regular + expression matches. Regex capture groups are + available. Default is '$1' + type: string + separator: + description: Separator placed between concatenated + source label values. default is ';'. + type: string + source_labels: + description: UnderScoreSourceLabels - additional + form of source labels source_labels for compatibility + with original relabel config. if set both + sourceLabels and source_labels, sourceLabels + has priority. for details https://github.com/VictoriaMetrics/operator/issues/131 + items: + type: string + type: array + sourceLabels: + description: The source labels select values + from existing labels. Their content is concatenated + using the configured separator and matched + against the configured regular expression + for the replace, keep, and drop actions. + items: + type: string + type: array + target_label: + description: UnderScoreTargetLabel - additional + form of target label - target_label for compatibility + with original relabel config. if set both + targetLabel and target_label, targetLabel + has priority. for details https://github.com/VictoriaMetrics/operator/issues/131 + type: string + targetLabel: + description: Label to which the resulting value + is written in a replace action. It is mandatory + for replace actions. Regex capture groups + are available. + type: string + type: object + type: array + outputs: + description: "Outputs is a list of output aggregate + functions to produce. \n The following names are + allowed: \n - total - aggregates input counters + - increase - counts the increase over input counters + - count_series - counts the input series - count_samples + - counts the input samples - sum_samples - sums + the input samples - last - the last biggest sample + value - min - the minimum sample value - max - the + maximum sample value - avg - the average value across + all the samples - stddev - standard deviation across + all the samples - stdvar - standard variance across + all the samples - histogram_bucket - creates VictoriaMetrics + histogram for input samples - quantiles(phi1, ..., + phiN) - quantiles' estimation for phi in the range + [0..1] \n The output time series will have the following + names: \n input_name:aggr__" + items: + type: string + type: array + staleness_interval: + description: StalenessInterval defines an interval + after which the series state will be reset if no + samples have been sent during it. + type: string + without: + description: "Without is an optional list of labels, + which must be excluded when grouping input series. + \n See also By. \n If neither By nor Without are + set, then the Outputs are calculated individually + per each input time series." + items: + type: string + type: array + required: + - interval + - outputs + type: object + type: array + required: + - rules + type: object + tlsConfig: + description: TLSConfig describes tls configuration for remote + write target + properties: + ca: + description: Stuct containing the CA cert to use for the + targets. + properties: + configMap: + description: ConfigMap containing data to use for the + targets. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + 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 + secret: + description: Secret containing data to use for the targets. + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + 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 + caFile: + description: Path to the CA cert in the container to use + for the targets. + type: string + cert: + description: Struct containing the client cert file for + the targets. + properties: + configMap: + description: ConfigMap containing data to use for the + targets. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + 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 + secret: + description: Secret containing data to use for the targets. + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + 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 + certFile: + description: Path to the client cert file in the container + for the targets. + type: string + insecureSkipVerify: + description: Disable target certificate validation. + type: boolean + keyFile: + description: Path to the client key file in the container + for the targets. + type: string + keySecret: + description: Secret containing the client key file for the + targets. + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + serverName: + description: Used to verify the hostname for the targets. + type: string + type: object + url: + description: URL of the endpoint to send samples to. + type: string + urlRelabelConfig: + description: ConfigMap with relabeling config which is applied + to metrics before sending them to the corresponding -remoteWrite.url + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + required: + - url + type: object + type: array + remoteWriteSettings: + description: RemoteWriteSettings defines global settings for all remoteWrite + urls. + properties: + flushInterval: + description: Interval for flushing the data to remote storage. + (default 1s) + pattern: '[0-9]+(ms|s|m|h)' + type: string + label: + additionalProperties: + type: string + description: Optional labels in the form 'name=value' to add to + all the metrics before sending them + type: object + maxBlockSize: + description: The maximum size in bytes of unpacked request to + send to remote storage + format: int32 + type: integer + maxDiskUsagePerURL: + description: The maximum file-based buffer size in bytes at -remoteWrite.tmpDataPath + format: int64 + type: integer + queues: + description: The number of concurrent queues + format: int32 + type: integer + showURL: + description: Whether to show -remoteWrite.url in the exported + metrics. It is hidden by default, since it can contain sensitive + auth info + type: boolean + tmpDataPath: + description: Path to directory where temporary data for remote + write component is stored (default vmagent-remotewrite-data) + type: string + useMultiTenantMode: + description: Configures vmagent in multi-tenant mode with direct + cluster support docs https://docs.victoriametrics.com/vmagent.html#multitenancy + it's global setting and affects all remote storage configurations + type: boolean + type: object + replicaCount: + description: ReplicaCount is the expected size of the VMAgent cluster. + The controller will eventually make the size of the running cluster + equal to the expected size. NOTE enable VMSingle deduplication for + replica usage + format: int32 + type: integer + resources: + description: Resources container resource request and limits, https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + if not specified - default setting will be used + properties: + 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. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + rollingUpdate: + description: RollingUpdate - overrides deployment update params. + properties: + maxSurge: + anyOf: + - type: integer + - type: string + description: 'The maximum number of pods that can be scheduled + above the desired number of pods. Value can be an absolute number + (ex: 5) or a percentage of desired pods (ex: 10%). This can + not be 0 if MaxUnavailable is 0. Absolute number is calculated + from percentage by rounding up. Defaults to 25%. Example: when + this is set to 30%, the new ReplicaSet can be scaled up immediately + when the rolling update starts, such that the total number of + old and new pods do not exceed 130% of desired pods. Once old + pods have been killed, new ReplicaSet can be scaled up further, + ensuring that total number of pods running at any time during + the update is at most 130% of desired pods.' + x-kubernetes-int-or-string: true + maxUnavailable: + anyOf: + - type: integer + - type: string + description: 'The maximum number of pods that can be unavailable + during the update. Value can be an absolute number (ex: 5) or + a percentage of desired pods (ex: 10%). Absolute number is calculated + from percentage by rounding down. This can not be 0 if MaxSurge + is 0. Defaults to 25%. Example: when this is set to 30%, the + old ReplicaSet can be scaled down to 70% of desired pods immediately + when the rolling update starts. Once new pods are ready, old + ReplicaSet can be scaled down further, followed by scaling up + the new ReplicaSet, ensuring that the total number of pods available + at all times during the update is at least 70% of desired pods.' + x-kubernetes-int-or-string: true + type: object + runtimeClassName: + description: RuntimeClassName - defines runtime class for kubernetes + pod. https://kubernetes.io/docs/concepts/containers/runtime-class/ + type: string + schedulerName: + description: SchedulerName - defines kubernetes scheduler name + type: string + scrapeInterval: + description: ScrapeInterval defines how often scrape targets by default + pattern: '[0-9]+(ms|s|m|h)' + type: string + scrapeTimeout: + description: ScrapeTimeout defines global timeout for targets scrape + pattern: '[0-9]+(ms|s|m|h)' + type: string + secrets: + description: Secrets is a list of Secrets in the same namespace as + the vmagent object, which shall be mounted into the vmagent Pods. + will be mounted at path /etc/vm/secrets + items: + type: string + type: array + securityContext: + description: SecurityContext holds pod-level security attributes and + common container settings. This defaults to the default PodSecurityContext. + type: object + x-kubernetes-preserve-unknown-fields: true + selectAllByDefault: + description: 'SelectAllByDefault changes default behavior for empty + CRD selectors, such ServiceScrapeSelector. with selectAllScrapes: + true and empty serviceScrapeSelector and ServiceScrapeNamespaceSelector + Operator selects all exist serviceScrapes with selectAllScrapes: + false - selects nothing' + type: boolean + serviceAccountName: + description: ServiceAccountName is the name of the ServiceAccount + to use to run the VMAgent Pods. + type: string + serviceScrapeNamespaceSelector: + description: ServiceScrapeNamespaceSelector Namespaces to be selected + for VMServiceScrape discovery. Works in combination with Selector. + NamespaceSelector nil - only objects at VMAgent namespace. Selector + nil - only objects at NamespaceSelector namespaces. If both nil + - behaviour controlled by selectAllByDefault + 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 + required: + - key + - operator + type: object + type: array + 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 + serviceScrapeRelabelTemplate: + description: ServiceScrapeRelabelTemplate defines relabel config, + that will be added to each VMServiceScrape. it's useful for adding + specific labels to all targets + items: + description: 'RelabelConfig allows dynamic rewriting of the label + set, being applied to samples before ingestion. It defines ``-section + of configuration. More info: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#metric_relabel_configs' + properties: + action: + description: Action to perform based on regex matching. Default + is 'replace' + type: string + if: + description: 'If represents metricsQL match expression: ''{__name__=~"foo_.*"}''' + type: string + labels: + additionalProperties: + type: string + description: 'Labels is used together with Match for `action: + graphite`' + type: object + match: + description: 'Match is used together with Labels for `action: + graphite`' + type: string + modulus: + description: Modulus to take of the hash of the source label + values. + format: int64 + type: integer + regex: + description: Regular expression against which the extracted + value is matched. Default is '(.*)' + type: string + replacement: + description: Replacement value against which a regex replace + is performed if the regular expression matches. Regex capture + groups are available. Default is '$1' + type: string + separator: + description: Separator placed between concatenated source label + values. default is ';'. + type: string + source_labels: + description: UnderScoreSourceLabels - additional form of source + labels source_labels for compatibility with original relabel + config. if set both sourceLabels and source_labels, sourceLabels + has priority. for details https://github.com/VictoriaMetrics/operator/issues/131 + items: + type: string + type: array + sourceLabels: + description: The source labels select values from existing labels. + Their content is concatenated using the configured separator + and matched against the configured regular expression for + the replace, keep, and drop actions. + items: + type: string + type: array + target_label: + description: UnderScoreTargetLabel - additional form of target + label - target_label for compatibility with original relabel + config. if set both targetLabel and target_label, targetLabel + has priority. for details https://github.com/VictoriaMetrics/operator/issues/131 + type: string + targetLabel: + description: Label to which the resulting value is written in + a replace action. It is mandatory for replace actions. Regex + capture groups are available. + type: string + type: object + type: array + serviceScrapeSelector: + description: ServiceScrapeSelector defines ServiceScrapes to be selected + for target discovery. Works in combination with NamespaceSelector. + NamespaceSelector nil - only objects at VMAgent namespace. Selector + nil - only objects at NamespaceSelector namespaces. If both nil + - behaviour controlled by selectAllByDefault + 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 + required: + - key + - operator + type: object + type: array + 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 + serviceScrapeSpec: + description: ServiceScrapeSpec that will be added to vmagent VMServiceScrape + spec + required: + - endpoints + type: object + x-kubernetes-preserve-unknown-fields: true + serviceSpec: + description: ServiceSpec that will be added to vmagent service spec + properties: + metadata: + description: EmbeddedObjectMetadata defines objectMeta for additional + service. + properties: + annotations: + additionalProperties: + type: string + description: 'Annotations is an unstructured key value map + stored with a resource that may be set by external tools + to store and retrieve arbitrary metadata. They are not queryable + and should be preserved when modifying objects. More info: + http://kubernetes.io/docs/user-guide/annotations' + type: object + labels: + additionalProperties: + type: string + description: 'Labels Map of string keys and values that can + be used to organize and categorize (scope and select) objects. + May match selectors of replication controllers and services. + More info: http://kubernetes.io/docs/user-guide/labels' + type: object + name: + description: 'Name must be unique within a namespace. Is required + when creating resources, although some resources may allow + a client to request the generation of an appropriate name + automatically. Name is primarily intended for creation idempotence + and configuration definition. Cannot be updated. More info: + http://kubernetes.io/docs/user-guide/identifiers#names' + type: string + type: object + spec: + description: 'ServiceSpec describes the attributes that a user + creates on a service. More info: https://kubernetes.io/docs/concepts/services-networking/service/' + type: object + x-kubernetes-preserve-unknown-fields: true + required: + - spec + type: object + shardCount: + description: ShardCount - numbers of shards of VMAgent in this case + operator will use 1 deployment/sts per shard with replicas count + according to spec.replicas https://victoriametrics.github.io/vmagent.html#scraping-big-number-of-targets + type: integer + startupProbe: + description: StartupProbe that will be added to CRD pod + type: object + x-kubernetes-preserve-unknown-fields: true + statefulMode: + description: StatefulMode enables StatefulSet for `VMAgent` instead + of Deployment it allows using persistent storage for vmagent's persistentQueue + type: boolean + statefulRollingUpdateStrategy: + description: StatefulRollingUpdateStrategy allows configuration for + strategyType set it to RollingUpdate for disabling operator statefulSet + rollingUpdate + type: string + statefulStorage: + description: StatefulStorage configures storage for StatefulSet + properties: + disableMountSubPath: + description: 'Deprecated: subPath usage will be disabled by default + in a future release, this option will become unnecessary. DisableMountSubPath + allows to remove any subPath usage in volume mounts.' + type: boolean + emptyDir: + description: 'EmptyDirVolumeSource to be used by the Prometheus + StatefulSets. If specified, used in place of any volumeClaimTemplate. + More info: https://kubernetes.io/docs/concepts/storage/volumes/#emptydir' + properties: + medium: + description: 'medium represents what type of storage medium + should back this directory. The default is "" which means + to use the node''s default medium. Must be an empty string + (default) or Memory. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' + type: string + sizeLimit: + anyOf: + - type: integer + - type: string + description: 'sizeLimit is the total amount of local storage + required for this EmptyDir volume. The size limit is also + applicable for memory medium. The maximum usage on memory + medium EmptyDir would be the minimum value between the SizeLimit + specified here and the sum of memory limits of all containers + in a pod. The default is nil which means that the limit + is undefined. More info: http://kubernetes.io/docs/user-guide/volumes#emptydir' + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + volumeClaimTemplate: + description: A PVC spec to be used by the VMAlertManager StatefulSets. + 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: + description: EmbeddedMetadata contains metadata relevant to + an EmbeddedResource. + properties: + annotations: + additionalProperties: + type: string + description: 'Annotations is an unstructured key value + map stored with a resource that may be set by external + tools to store and retrieve arbitrary metadata. They + are not queryable and should be preserved when modifying + objects. More info: http://kubernetes.io/docs/user-guide/annotations' + type: object + labels: + additionalProperties: + type: string + description: 'Labels Map of string keys and values that + can be used to organize and categorize (scope and select) + objects. May match selectors of replication controllers + and services. More info: http://kubernetes.io/docs/user-guide/labels' + type: object + name: + description: 'Name must be unique within a namespace. + Is required when creating resources, although some resources + may allow a client to request the generation of an appropriate + name automatically. Name is primarily intended for creation + idempotence and configuration definition. Cannot be + updated. More info: http://kubernetes.io/docs/user-guide/identifiers#names' + type: string + type: object + spec: + description: 'Spec defines the desired characteristics of + a volume requested by a pod author. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' + properties: + accessModes: + description: 'accessModes contains the desired access + modes the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' + items: + type: string + type: array + dataSource: + description: 'dataSource field can be used to specify + either: * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) + * An existing PVC (PersistentVolumeClaim) If the provisioner + or an external controller can support the specified + data source, it will create a new volume based on the + contents of the specified data source. If the AnyVolumeDataSource + feature gate is enabled, this field will always have + the same contents as the DataSourceRef field.' + properties: + apiGroup: + description: APIGroup is the group for the resource + being referenced. If APIGroup is not specified, + the specified Kind must be in the core API group. + For any other third-party types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource being referenced + type: string + name: + description: Name is the name of resource being referenced + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + description: 'dataSourceRef specifies the object from + which to populate the volume with data, if a non-empty + volume is desired. This may be any local object from + a non-empty API group (non core object) or a PersistentVolumeClaim + object. When this field is specified, volume binding + will only succeed if the type of the specified object + matches some installed volume populator or dynamic provisioner. + This field will replace the functionality of the DataSource + field and as such if both fields are non-empty, they + must have the same value. For backwards compatibility, + both fields (DataSource and DataSourceRef) will be set + to the same value automatically if one of them is empty + and the other is non-empty. There are two important + differences between DataSource and DataSourceRef: * + While DataSource only allows two specific types of objects, + DataSourceRef allows any non-core object, as well as + PersistentVolumeClaim objects. * While DataSource ignores + disallowed values (dropping them), DataSourceRef preserves + all values, and generates an error if a disallowed value + is specified. (Beta) Using this field requires the AnyVolumeDataSource + feature gate to be enabled.' + properties: + apiGroup: + description: APIGroup is the group for the resource + being referenced. If APIGroup is not specified, + the specified Kind must be in the core API group. + For any other third-party types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource being referenced + type: string + name: + description: Name is the name of resource being referenced + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + resources: + description: 'resources represents the minimum resources + the volume should have. If RecoverVolumeExpansionFailure + feature is enabled users are allowed to specify resource + requirements that are lower than previous value but + must still be higher than capacity recorded in the status + field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' + properties: + 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. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + selector: + description: selector is a label query over volumes to + consider for binding. + 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 + required: + - key + - operator + type: object + type: array + 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 + storageClassName: + description: 'storageClassName is the name of the StorageClass + required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' + type: string + volumeMode: + description: volumeMode defines what type of volume is + required by the claim. Value of Filesystem is implied + when not included in claim spec. + type: string + volumeName: + description: volumeName is the binding reference to the + PersistentVolume backing this claim. + type: string + type: object + status: + description: 'Status represents the current information/status + of a persistent volume claim. Read-only. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' + properties: + accessModes: + description: 'accessModes contains the actual access modes + the volume backing the PVC has. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' + items: + type: string + type: array + allocatedResources: + 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: allocatedResources is the storage resource + within AllocatedResources tracks the capacity allocated + to a PVC. It may be larger than the actual capacity + when a volume expansion operation is requested. For + storage quota, the larger value from allocatedResources + and PVC.spec.resources is used. If allocatedResources + is not set, PVC.spec.resources alone is used for quota + calculation. If a volume expansion capacity request + is lowered, allocatedResources is only lowered if there + are no expansion operations in progress and if the actual + volume capacity is equal or lower than the requested + capacity. This is an alpha field and requires enabling + RecoverVolumeExpansionFailure feature. + type: object + capacity: + 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: capacity represents the actual resources + of the underlying volume. + type: object + conditions: + description: conditions is the current Condition of persistent + volume claim. If underlying persistent volume is being + resized then the Condition will be set to 'ResizeStarted'. + items: + description: PersistentVolumeClaimCondition contails + details about state of pvc + properties: + lastProbeTime: + description: lastProbeTime is the time we probed + the condition. + format: date-time + type: string + lastTransitionTime: + description: lastTransitionTime is the time the + condition transitioned from one status to another. + format: date-time + type: string + message: + description: message is the human-readable message + indicating details about last transition. + type: string + reason: + description: reason is a unique, this should be + a short, machine understandable string that gives + the reason for condition's last transition. If + it reports "ResizeStarted" that means the underlying + persistent volume is being resized. + type: string + status: + type: string + type: + description: PersistentVolumeClaimConditionType + is a valid value of PersistentVolumeClaimCondition.Type + type: string + required: + - status + - type + type: object + type: array + phase: + description: phase represents the current phase of PersistentVolumeClaim. + type: string + resizeStatus: + description: resizeStatus stores status of resize operation. + ResizeStatus is not set by default but when expansion + is complete resizeStatus is set to empty string by resize + controller or kubelet. This is an alpha field and requires + enabling RecoverVolumeExpansionFailure feature. + type: string + type: object + type: object + type: object + staticScrapeNamespaceSelector: + description: StaticScrapeNamespaceSelector defines Namespaces to be + selected for VMStaticScrape discovery. Works in combination with + NamespaceSelector. NamespaceSelector nil - only objects at VMAgent + namespace. Selector nil - only objects at NamespaceSelector namespaces. + If both nil - behaviour controlled by selectAllByDefault + 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 + required: + - key + - operator + type: object + type: array + 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 + staticScrapeRelabelTemplate: + description: StaticScrapeRelabelTemplate defines relabel config, that + will be added to each VMStaticScrape. it's useful for adding specific + labels to all targets + items: + description: 'RelabelConfig allows dynamic rewriting of the label + set, being applied to samples before ingestion. It defines ``-section + of configuration. More info: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#metric_relabel_configs' + properties: + action: + description: Action to perform based on regex matching. Default + is 'replace' + type: string + if: + description: 'If represents metricsQL match expression: ''{__name__=~"foo_.*"}''' + type: string + labels: + additionalProperties: + type: string + description: 'Labels is used together with Match for `action: + graphite`' + type: object + match: + description: 'Match is used together with Labels for `action: + graphite`' + type: string + modulus: + description: Modulus to take of the hash of the source label + values. + format: int64 + type: integer + regex: + description: Regular expression against which the extracted + value is matched. Default is '(.*)' + type: string + replacement: + description: Replacement value against which a regex replace + is performed if the regular expression matches. Regex capture + groups are available. Default is '$1' + type: string + separator: + description: Separator placed between concatenated source label + values. default is ';'. + type: string + source_labels: + description: UnderScoreSourceLabels - additional form of source + labels source_labels for compatibility with original relabel + config. if set both sourceLabels and source_labels, sourceLabels + has priority. for details https://github.com/VictoriaMetrics/operator/issues/131 + items: + type: string + type: array + sourceLabels: + description: The source labels select values from existing labels. + Their content is concatenated using the configured separator + and matched against the configured regular expression for + the replace, keep, and drop actions. + items: + type: string + type: array + target_label: + description: UnderScoreTargetLabel - additional form of target + label - target_label for compatibility with original relabel + config. if set both targetLabel and target_label, targetLabel + has priority. for details https://github.com/VictoriaMetrics/operator/issues/131 + type: string + targetLabel: + description: Label to which the resulting value is written in + a replace action. It is mandatory for replace actions. Regex + capture groups are available. + type: string + type: object + type: array + staticScrapeSelector: + description: StaticScrapeSelector defines PodScrapes to be selected + for target discovery. Works in combination with NamespaceSelector. + If both nil - match everything. NamespaceSelector nil - only objects + at VMAgent namespace. Selector nil - only objects at NamespaceSelector + namespaces. + 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 + required: + - key + - operator + type: object + type: array + 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 + terminationGracePeriodSeconds: + description: TerminationGracePeriodSeconds period for container graceful + termination + format: int64 + type: integer + tolerations: + description: Tolerations If specified, the pod's tolerations. + 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: TopologySpreadConstraints embedded kubernetes pod configuration + option, controls how pods are spread across your cluster among failure-domains + such as regions, zones, nodes, and other user-defined topology domains + https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/ + items: + description: TopologySpreadConstraint specifies how to spread matching + pods among the given topology. + required: + - maxSkew + - topologyKey + - whenUnsatisfiable + type: object + x-kubernetes-preserve-unknown-fields: true + type: array + updateStrategy: + description: UpdateStrategy - overrides default update strategy. works + only for deployments, statefulset always use OnDelete. + enum: + - Recreate + - RollingUpdate + type: string + vmAgentExternalLabelName: + description: VMAgentExternalLabelName Name of vmAgent external label + used to denote vmAgent instance name. Defaults to the value of `prometheus`. + External label will _not_ be added when value is set to empty string + (`""`). + type: string + volumeMounts: + description: VolumeMounts allows configuration of additional VolumeMounts + on the output deploy definition. VolumeMounts specified will be + appended to other VolumeMounts in the vmagent container, that are + generated as a result of StorageSpec objects. + items: + description: VolumeMount describes a mounting of a Volume within + a container. + properties: + mountPath: + description: Path within the container at which the volume should + be mounted. Must not contain ':'. + type: string + mountPropagation: + description: mountPropagation determines how mounts are propagated + from the host to container and the other way around. When + not set, MountPropagationNone is used. This field is beta + in 1.10. + type: string + name: + description: This must match the Name of a Volume. + type: string + readOnly: + description: Mounted read-only if true, read-write otherwise + (false or unspecified). Defaults to false. + type: boolean + subPath: + description: Path within the volume from which the container's + volume should be mounted. Defaults to "" (volume's root). + type: string + subPathExpr: + description: Expanded path within the volume from which the + container's volume should be mounted. Behaves similarly to + SubPath but environment variable references $(VAR_NAME) are + expanded using the container's environment. Defaults to "" + (volume's root). SubPathExpr and SubPath are mutually exclusive. + type: string + required: + - mountPath + - name + type: object + type: array + volumes: + description: Volumes allows configuration of additional volumes on + the output deploy definition. Volumes specified will be appended + to other volumes that are generated as a result of StorageSpec objects. + items: + description: Volume represents a named volume in a pod that may + be accessed by any container in the pod. + required: + - name + type: object + x-kubernetes-preserve-unknown-fields: true + type: array + type: object + status: + description: VMAgentStatus defines the observed state of VMAgent + properties: + availableReplicas: + description: AvailableReplicas Total number of available pods (ready + for at least minReadySeconds) targeted by this VMAlert cluster. + format: int32 + type: integer + replicas: + description: ReplicaCount Total number of pods targeted by this VMAgent + format: int32 + type: integer + selector: + description: Selector string form of label value set for autoscaling + type: string + shards: + description: Shards represents total number of vmagent deployments + with uniq scrape targets + format: int32 + type: integer + unavailableReplicas: + description: UnavailableReplicas Total number of unavailable pods + targeted by this VMAgent cluster. + format: int32 + type: integer + updatedReplicas: + description: UpdatedReplicas Total number of non-terminated pods targeted + by this VMAgent cluster that have the desired version spec. + format: int32 + type: integer + required: + - availableReplicas + - replicas + - selector + - shards + - unavailableReplicas + - updatedReplicas + type: object + type: object + served: true + storage: true + subresources: + scale: + labelSelectorPath: .status.selector + specReplicasPath: .spec.shardCount + statusReplicasPath: .status.shards + status: {} +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.12.1 + name: vmalertmanagerconfigs.operator.victoriametrics.com +spec: + group: operator.victoriametrics.com + names: + kind: VMAlertmanagerConfig + listKind: VMAlertmanagerConfigList + plural: vmalertmanagerconfigs + singular: vmalertmanagerconfig + scope: Namespaced + versions: + - name: v1beta1 + schema: + openAPIV3Schema: + description: VMAlertmanagerConfig is the Schema for the vmalertmanagerconfigs + 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: VMAlertmanagerConfigSpec defines configuration for VMAlertmanagerConfig + properties: + '-': + type: string + inhibit_rules: + description: InhibitRules will only apply for alerts matching the + resource's namespace. + items: + description: InhibitRule defines an inhibition rule that allows + to mute alerts when other alerts are already firing. Note, it + doesn't support deprecated alertmanager config options. See https://prometheus.io/docs/alerting/latest/configuration/#inhibit_rule + properties: + equal: + description: Labels that must have an equal value in the source + and target alert for the inhibition to take effect. + items: + type: string + type: array + source_matchers: + description: SourceMatchers defines a list of matchers for which + one or more alerts have to exist for the inhibition to take + effect. + items: + type: string + type: array + target_matchers: + description: TargetMatchers defines a list of matchers that + have to be fulfilled by the target alerts to be muted. + items: + type: string + type: array + type: object + type: array + mute_time_intervals: + description: MuteTimeInterval - global mute time See https://prometheus.io/docs/alerting/latest/configuration/#mute_time_interval + items: + description: MuteTimeInterval for alerts + properties: + name: + description: Name of interval + type: string + time_intervals: + description: TimeIntervals interval configuration + items: + description: TimeInterval defines intervals of time + properties: + days_of_month: + description: DayOfMonth defines list of numerical days + in the month. Days begin at 1. Negative values are also + accepted. for example, ['1:5', '-3:-1'] + items: + type: string + type: array + location: + description: Location in golang time location form, e.g. + UTC + type: string + months: + description: Months defines list of calendar months identified + by a case-insentive name (e.g. ‘January’) or numeric + 1. For example, ['1:3', 'may:august', 'december'] + items: + type: string + type: array + times: + description: Times defines time range for mute + items: + description: TimeRange ranges inclusive of the starting + time and exclusive of the end time + properties: + end_time: + description: EndTime for example HH:MM + type: string + start_time: + description: StartTime for example HH:MM + type: string + required: + - end_time + - start_time + type: object + type: array + weekdays: + description: Weekdays defines list of days of the week, + where the week begins on Sunday and ends on Saturday. + items: + type: string + type: array + years: + description: Years defines numerical list of years, ranges + are accepted. For example, ['2020:2022', '2030'] + items: + type: string + type: array + type: object + type: array + required: + - time_intervals + type: object + type: array + receivers: + description: Receivers defines alert receivers. without defined Route, + receivers will be skipped. + items: + description: Receiver defines one or more notification integrations. + properties: + email_configs: + description: EmailConfigs defines email notification configurations. + items: + description: EmailConfig configures notifications via Email. + properties: + auth_identity: + description: The identity to use for authentication. + type: string + auth_password: + description: AuthPassword defines secret name and key + at CRD namespace. + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + 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 + auth_secret: + description: AuthSecret defines secrent name and key at + CRD namespace. It must contain the CRAM-MD5 secret. + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + 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 + auth_username: + description: The username to use for authentication. + type: string + from: + description: The sender address. + type: string + headers: + additionalProperties: + type: string + description: Further headers email header key/value pairs. + Overrides any headers previously set by the notification + implementation. + type: object + hello: + description: The hostname to identify to the SMTP server. + type: string + html: + description: The HTML body of the email notification. + type: string + require_tls: + description: The SMTP TLS requirement. Note that Go does + not support unencrypted connections to remote SMTP endpoints. + type: boolean + send_resolved: + description: SendResolved controls notify about resolved + alerts. + type: boolean + smarthost: + description: The SMTP host through which emails are sent. + type: string + text: + description: The text body of the email notification. + type: string + tls_config: + description: TLS configuration + properties: + ca: + description: Stuct containing the CA cert to use for + the targets. + properties: + configMap: + description: ConfigMap containing data to use + for the targets. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + 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 + secret: + description: Secret containing data to use for + the targets. + properties: + key: + description: The key of the secret to select + from. Must be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + 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 + caFile: + description: Path to the CA cert in the container + to use for the targets. + type: string + cert: + description: Struct containing the client cert file + for the targets. + properties: + configMap: + description: ConfigMap containing data to use + for the targets. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + 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 + secret: + description: Secret containing data to use for + the targets. + properties: + key: + description: The key of the secret to select + from. Must be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + 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 + certFile: + description: Path to the client cert file in the container + for the targets. + type: string + insecureSkipVerify: + description: Disable target certificate validation. + type: boolean + keyFile: + description: Path to the client key file in the container + for the targets. + type: string + keySecret: + description: Secret containing the client key file + for the targets. + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + 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 + serverName: + description: Used to verify the hostname for the targets. + type: string + type: object + to: + description: The email address to send notifications to. + type: string + type: object + type: array + name: + description: Name of the receiver. Must be unique across all + items from the list. + minLength: 1 + type: string + opsgenie_configs: + description: OpsGenieConfigs defines ops genie notification + configurations. + items: + description: OpsGenieConfig configures notifications via OpsGenie. + See https://prometheus.io/docs/alerting/latest/configuration/#opsgenie_config + properties: + api_key: + description: The secret's key that contains the OpsGenie + API key. It must be at them same namespace as CRD + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + 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 + apiURL: + description: The URL to send OpsGenie API requests to. + type: string + description: + description: Description of the incident. + type: string + details: + additionalProperties: + type: string + description: A set of arbitrary key/value pairs that provide + further detail about the incident. + type: object + http_config: + description: HTTP client configuration. + type: object + x-kubernetes-preserve-unknown-fields: true + message: + description: Alert text limited to 130 characters. + type: string + note: + description: Additional alert note. + type: string + priority: + description: Priority level of alert. Possible values + are P1, P2, P3, P4, and P5. + type: string + responders: + description: List of responders responsible for notifications. + items: + description: OpsGenieConfigResponder defines a responder + to an incident. One of `id`, `name` or `username` + has to be defined. + properties: + id: + description: ID of the responder. + type: string + name: + description: Name of the responder. + type: string + type: + description: Type of responder. + minLength: 1 + type: string + username: + description: Username of the responder. + type: string + required: + - type + type: object + type: array + send_resolved: + description: SendResolved controls notify about resolved + alerts. + type: boolean + source: + description: Backlink to the sender of the notification. + type: string + tags: + description: Comma separated list of tags attached to + the notifications. + type: string + type: object + type: array + pagerduty_configs: + description: PagerDutyConfigs defines pager duty notification + configurations. + items: + description: PagerDutyConfig configures notifications via + PagerDuty. See https://prometheus.io/docs/alerting/latest/configuration/#pagerduty_config + properties: + class: + description: The class/type of the event. + type: string + client: + description: Client identification. + type: string + client_url: + description: Backlink to the sender of notification. + type: string + component: + description: The part or component of the affected system + that is broken. + type: string + description: + description: Description of the incident. + type: string + details: + additionalProperties: + type: string + description: Arbitrary key/value pairs that provide further + detail about the incident. + type: object + group: + description: A cluster or grouping of sources. + type: string + http_config: + description: HTTP client configuration. + type: object + x-kubernetes-preserve-unknown-fields: true + images: + description: Images to attach to the incident. + items: + description: ImageConfig is used to attach images to + the incident. See https://developer.pagerduty.com/docs/ZG9jOjExMDI5NTgx-send-an-alert-event#the-images-property + for more information. + properties: + alt: + type: string + href: + type: string + source: + type: string + required: + - source + type: object + type: array + links: + description: Links to attach to the incident. + items: + description: LinkConfig is used to attach text links + to the incident. See https://developer.pagerduty.com/docs/ZG9jOjExMDI5NTgx-send-an-alert-event#the-links-property + for more information. + properties: + href: + type: string + text: + type: string + required: + - href + type: object + type: array + routing_key: + description: The secret's key that contains the PagerDuty + integration key (when using Events API v2). Either this + field or `serviceKey` needs to be defined. It must be + at them same namespace as CRD + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + 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 + send_resolved: + description: SendResolved controls notify about resolved + alerts. + type: boolean + service_key: + description: The secret's key that contains the PagerDuty + service key (when using integration type "Prometheus"). + Either this field or `routingKey` needs to be defined. + It must be at them same namespace as CRD + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + 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 + severity: + description: Severity of the incident. + type: string + url: + description: The URL to send requests to. + type: string + type: object + type: array + pushover_configs: + description: PushoverConfigs defines push over notification + configurations. + items: + description: PushoverConfig configures notifications via Pushover. + See https://prometheus.io/docs/alerting/latest/configuration/#pushover_config + properties: + expire: + description: How long your notification will continue + to be retried for, unless the user acknowledges the + notification. + type: string + html: + description: Whether notification message is HTML or plain + text. + type: boolean + http_config: + description: HTTP client configuration. + type: object + x-kubernetes-preserve-unknown-fields: true + message: + description: Notification message. + type: string + priority: + description: Priority, see https://pushover.net/api#priority + type: string + retry: + description: How often the Pushover servers will send + the same notification to the user. Must be at least + 30 seconds. + type: string + send_resolved: + description: SendResolved controls notify about resolved + alerts. + type: boolean + sound: + description: The name of one of the sounds supported by + device clients to override the user's default sound + choice + type: string + title: + description: Notification title. + type: string + token: + description: The secret's key that contains the registered + application’s API token, see https://pushover.net/apps. + It must be at them same namespace as CRD + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + 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 + url: + description: A supplementary URL shown alongside the message. + type: string + url_title: + description: A title for supplementary URL, otherwise + just the URL is shown + type: string + user_key: + description: The secret's key that contains the recipient + user’s user key. It must be at them same namespace as + CRD + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + 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 + type: array + slack_configs: + description: SlackConfigs defines slack notification configurations. + items: + description: SlackConfig configures notifications via Slack. + See https://prometheus.io/docs/alerting/latest/configuration/#slack_config + properties: + actions: + description: A list of Slack actions that are sent with + each notification. + items: + description: SlackAction configures a single Slack action + that is sent with each notification. See https://api.slack.com/docs/message-attachments#action_fields + and https://api.slack.com/docs/message-buttons for + more information. + properties: + confirm: + description: SlackConfirmationField protect users + from destructive actions or particularly distinguished + decisions by asking them to confirm their button + click one more time. See https://api.slack.com/docs/interactive-message-field-guide#confirmation_fields + for more information. + properties: + dismiss_text: + type: string + ok_text: + type: string + text: + minLength: 1 + type: string + title: + type: string + required: + - text + type: object + name: + type: string + style: + type: string + text: + minLength: 1 + type: string + type: + minLength: 1 + type: string + url: + type: string + value: + type: string + required: + - text + - type + type: object + type: array + api_url: + description: The secret's key that contains the Slack + webhook URL. It must be at them same namespace as CRD + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + 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 + callback_id: + type: string + channel: + description: The channel or user to send notifications + to. + type: string + color: + type: string + fallback: + type: string + fields: + description: A list of Slack fields that are sent with + each notification. + items: + description: SlackField configures a single Slack field + that is sent with each notification. See https://api.slack.com/docs/message-attachments#fields + for more information. + properties: + short: + type: boolean + title: + minLength: 1 + type: string + value: + minLength: 1 + type: string + required: + - title + - value + type: object + type: array + footer: + type: string + http_config: + description: HTTP client configuration. + type: object + x-kubernetes-preserve-unknown-fields: true + icon_emoji: + type: string + icon_url: + type: string + image_url: + type: string + link_names: + type: boolean + mrkdwn_in: + items: + type: string + type: array + pretext: + type: string + send_resolved: + description: SendResolved controls notify about resolved + alerts. + type: boolean + short_fields: + type: boolean + text: + type: string + thumb_url: + type: string + title: + type: string + title_link: + type: string + username: + type: string + type: object + type: array + telegram_configs: + items: + properties: + api_url: + description: APIUrl the Telegram API URL i.e. https://api.telegram.org. + type: string + bot_token: + description: BotToken token for the bot https://core.telegram.org/bots/api + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + 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 + chat_id: + description: ChatID is ID of the chat where to send the + messages. + type: integer + disable_notifications: + description: DisableNotifications + type: boolean + http_config: + description: HTTP client configuration. + type: object + x-kubernetes-preserve-unknown-fields: true + message: + description: Message is templated message + type: string + parse_mode: + description: ParseMode for telegram message, supported + values are MarkdownV2, Markdown, Markdown and empty + string for plain text. + type: string + send_resolved: + description: SendResolved controls notify about resolved + alerts. + type: boolean + required: + - bot_token + - chat_id + type: object + type: array + victorops_configs: + description: VictorOpsConfigs defines victor ops notification + configurations. + items: + description: VictorOpsConfig configures notifications via + VictorOps. See https://prometheus.io/docs/alerting/latest/configuration/#victorops_config + properties: + api_key: + description: The secret's key that contains the API key + to use when talking to the VictorOps API. It must be + at them same namespace as CRD + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + 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 + api_url: + description: The VictorOps API URL. + type: string + custom_fields: + additionalProperties: + type: string + description: Adds optional custom fields https://github.com/prometheus/alertmanager/blob/v0.24.0/config/notifiers.go#L537 + type: object + entity_display_name: + description: Contains summary of the alerted problem. + type: string + http_config: + description: The HTTP client's configuration. + properties: + basic_auth: + description: TODO oAuth2 support BasicAuth for the + client. + properties: + password: + description: The secret in the service scrape + namespace that contains the password for authentication. + It must be at them same namespace as CRD + properties: + key: + description: The key of the secret to select + from. Must be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + 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 + password_file: + description: PasswordFile defines path to password + file at disk + type: string + username: + description: The secret in the service scrape + namespace that contains the username for authentication. + It must be at them same namespace as CRD + properties: + key: + description: The key of the secret to select + from. Must be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + 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 + bearer_token_file: + description: BearerTokenFile defines filename for + bearer token, it must be mounted to pod. + type: string + bearer_token_secret: + description: The secret's key that contains the bearer + token It must be at them same namespace as CRD + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + 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 + proxyURL: + description: Optional proxy URL. + type: string + tls_config: + description: TLS configuration for the client. + properties: + ca: + description: Stuct containing the CA cert to use + for the targets. + properties: + configMap: + description: ConfigMap containing data to + use for the targets. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + 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 + secret: + description: Secret containing data to use + for the targets. + properties: + key: + description: The key of the secret to + select from. Must be a valid secret + key. + type: string + name: + description: 'Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + 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 + caFile: + description: Path to the CA cert in the container + to use for the targets. + type: string + cert: + description: Struct containing the client cert + file for the targets. + properties: + configMap: + description: ConfigMap containing data to + use for the targets. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + 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 + secret: + description: Secret containing data to use + for the targets. + properties: + key: + description: The key of the secret to + select from. Must be a valid secret + key. + type: string + name: + description: 'Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + 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 + certFile: + description: Path to the client cert file in the + container for the targets. + type: string + insecureSkipVerify: + description: Disable target certificate validation. + type: boolean + keyFile: + description: Path to the client key file in the + container for the targets. + type: string + keySecret: + description: Secret containing the client key + file for the targets. + properties: + key: + description: The key of the secret to select + from. Must be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + 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 + serverName: + description: Used to verify the hostname for the + targets. + type: string + type: object + type: object + message_type: + description: Describes the behavior of the alert (CRITICAL, + WARNING, INFO). + type: string + monitoring_tool: + description: The monitoring tool the state message is + from. + type: string + routing_key: + description: A key used to map the alert to a team. + type: string + send_resolved: + description: SendResolved controls notify about resolved + alerts. + type: boolean + state_message: + description: Contains long explanation of the alerted + problem. + type: string + type: object + type: array + webhook_configs: + description: WebhookConfigs defines webhook notification configurations. + items: + description: WebhookConfig configures notifications via a + generic receiver supporting the webhook payload. See https://prometheus.io/docs/alerting/latest/configuration/#webhook_config + properties: + http_config: + description: HTTP client configuration. + type: object + x-kubernetes-preserve-unknown-fields: true + max_alerts: + description: Maximum number of alerts to be sent per webhook + message. When 0, all alerts are included. + format: int32 + minimum: 0 + type: integer + send_resolved: + description: SendResolved controls notify about resolved + alerts. + type: boolean + url: + description: URL to send requests to, one of `urlSecret` + and `url` must be defined. + type: string + url_secret: + description: URLSecret defines secret name and key at + the CRD namespace. It must contain the webhook URL. + one of `urlSecret` and `url` must be defined. + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + 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 + type: array + wechat_configs: + description: WeChatConfigs defines wechat notification configurations. + items: + description: WeChatConfig configures notifications via WeChat. + See https://prometheus.io/docs/alerting/latest/configuration/#wechat_config + properties: + agent_id: + type: string + api_secret: + description: The secret's key that contains the WeChat + API key. The secret needs to be in the same namespace + as the AlertmanagerConfig object and accessible by the + Prometheus Operator. + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + 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 + api_url: + description: The WeChat API URL. + type: string + corp_id: + description: The corp id for authentication. + type: string + http_config: + description: HTTP client configuration. + properties: + basic_auth: + description: TODO oAuth2 support BasicAuth for the + client. + properties: + password: + description: The secret in the service scrape + namespace that contains the password for authentication. + It must be at them same namespace as CRD + properties: + key: + description: The key of the secret to select + from. Must be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + 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 + password_file: + description: PasswordFile defines path to password + file at disk + type: string + username: + description: The secret in the service scrape + namespace that contains the username for authentication. + It must be at them same namespace as CRD + properties: + key: + description: The key of the secret to select + from. Must be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + 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 + bearer_token_file: + description: BearerTokenFile defines filename for + bearer token, it must be mounted to pod. + type: string + bearer_token_secret: + description: The secret's key that contains the bearer + token It must be at them same namespace as CRD + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + 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 + proxyURL: + description: Optional proxy URL. + type: string + tls_config: + description: TLS configuration for the client. + properties: + ca: + description: Stuct containing the CA cert to use + for the targets. + properties: + configMap: + description: ConfigMap containing data to + use for the targets. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + 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 + secret: + description: Secret containing data to use + for the targets. + properties: + key: + description: The key of the secret to + select from. Must be a valid secret + key. + type: string + name: + description: 'Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + 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 + caFile: + description: Path to the CA cert in the container + to use for the targets. + type: string + cert: + description: Struct containing the client cert + file for the targets. + properties: + configMap: + description: ConfigMap containing data to + use for the targets. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + 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 + secret: + description: Secret containing data to use + for the targets. + properties: + key: + description: The key of the secret to + select from. Must be a valid secret + key. + type: string + name: + description: 'Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + 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 + certFile: + description: Path to the client cert file in the + container for the targets. + type: string + insecureSkipVerify: + description: Disable target certificate validation. + type: boolean + keyFile: + description: Path to the client key file in the + container for the targets. + type: string + keySecret: + description: Secret containing the client key + file for the targets. + properties: + key: + description: The key of the secret to select + from. Must be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + 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 + serverName: + description: Used to verify the hostname for the + targets. + type: string + type: object + type: object + message: + description: API request data as defined by the WeChat + API. + type: string + message_type: + type: string + send_resolved: + description: SendResolved controls notify about resolved + alerts. + type: boolean + to_party: + type: string + to_tag: + type: string + to_user: + type: string + type: object + type: array + required: + - name + type: object + type: array + route: + description: Route definition for alertmanager, may include nested + routes. + properties: + active_time_intervals: + description: ActiveTimeIntervals Times when the route should be + active These must match the name at time_intervals + items: + type: string + type: array + continue: + description: Continue indicating whether an alert should continue + matching subsequent sibling nodes. It will always be true for + the first-level route if disableRouteContinueEnforce for vmalertmanager + not set. + type: boolean + group_by: + description: List of labels to group by. + items: + type: string + type: array + group_interval: + description: How long to wait before sending an updated notification. + pattern: '[0-9]+(ms|s|m|h)' + type: string + group_wait: + description: How long to wait before sending the initial notification. + pattern: '[0-9]+(ms|s|m|h)' + type: string + matchers: + description: 'List of matchers that the alert’s labels should + match. For the first level route, the operator adds a namespace: + "CRD_NS" matcher. https://prometheus.io/docs/alerting/latest/configuration/#matcher' + items: + type: string + type: array + mute_time_intervals: + description: MuteTimeIntervals for alerts + items: + type: string + type: array + receiver: + description: Name of the receiver for this route. + type: string + repeat_interval: + description: How long to wait before repeating the last notification. + pattern: '[0-9]+(ms|s|m|h)' + type: string + routes: + description: Child routes. https://prometheus.io/docs/alerting/latest/configuration/#route + items: + x-kubernetes-preserve-unknown-fields: true + type: array + required: + - receiver + type: object + time_intervals: + description: ParsingError contents error with context if operator + was failed to parse json object from kubernetes api server TimeIntervals + modern config option, use it instead of mute_time_intervals + items: + description: MuteTimeInterval for alerts + properties: + name: + description: Name of interval + type: string + time_intervals: + description: TimeIntervals interval configuration + items: + description: TimeInterval defines intervals of time + properties: + days_of_month: + description: DayOfMonth defines list of numerical days + in the month. Days begin at 1. Negative values are also + accepted. for example, ['1:5', '-3:-1'] + items: + type: string + type: array + location: + description: Location in golang time location form, e.g. + UTC + type: string + months: + description: Months defines list of calendar months identified + by a case-insentive name (e.g. ‘January’) or numeric + 1. For example, ['1:3', 'may:august', 'december'] + items: + type: string + type: array + times: + description: Times defines time range for mute + items: + description: TimeRange ranges inclusive of the starting + time and exclusive of the end time + properties: + end_time: + description: EndTime for example HH:MM + type: string + start_time: + description: StartTime for example HH:MM + type: string + required: + - end_time + - start_time + type: object + type: array + weekdays: + description: Weekdays defines list of days of the week, + where the week begins on Sunday and ends on Saturday. + items: + type: string + type: array + years: + description: Years defines numerical list of years, ranges + are accepted. For example, ['2020:2022', '2030'] + items: + type: string + type: array + type: object + type: array + required: + - time_intervals + type: object + type: array + type: object + status: + description: VMAlertmanagerConfigStatus defines the observed state of + VMAlertmanagerConfig + properties: + reason: + description: ErrorReason describes validation or any other errors. + 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.12.1 + name: vmalertmanagers.operator.victoriametrics.com +spec: + group: operator.victoriametrics.com + names: + kind: VMAlertmanager + listKind: VMAlertmanagerList + plural: vmalertmanagers + shortNames: + - vma + singular: vmalertmanager + scope: Namespaced + versions: + - additionalPrinterColumns: + - description: The version of VMAlertmanager + jsonPath: .spec.version + name: Version + type: string + - description: The desired replicas number of Alertmanagers + jsonPath: .spec.ReplicaCount + name: ReplicaCount + type: integer + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1beta1 + schema: + openAPIV3Schema: + description: VMAlertmanager represents Victoria-Metrics deployment for Alertmanager. + 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: 'Specification of the desired behavior of the VMAlertmanager + cluster. More info: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#spec-and-status' + properties: + '-': + description: ParsingError contents error with context if operator + was failed to parse json object from kubernetes api server + type: string + additionalPeers: + description: AdditionalPeers allows injecting a set of additional + Alertmanagers to peer with to form a highly available cluster. + items: + type: string + type: array + affinity: + description: Affinity If specified, the pod's scheduling constraints. + type: object + x-kubernetes-preserve-unknown-fields: true + claimTemplates: + description: ClaimTemplates allows adding additional VolumeClaimTemplates + for StatefulSet + items: + description: PersistentVolumeClaim is a user's request for and claim + to a persistent volume + 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: + description: 'Standard object''s metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata' + type: object + x-kubernetes-preserve-unknown-fields: true + spec: + description: 'spec defines the desired characteristics of a + volume requested by a pod author. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' + properties: + accessModes: + description: 'accessModes contains the desired access modes + the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' + items: + type: string + type: array + dataSource: + description: 'dataSource field can be used to specify either: + * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) + * An existing PVC (PersistentVolumeClaim) If the provisioner + or an external controller can support the specified data + source, it will create a new volume based on the contents + of the specified data source. If the AnyVolumeDataSource + feature gate is enabled, this field will always have the + same contents as the DataSourceRef field.' + properties: + apiGroup: + description: APIGroup is the group for the resource + being referenced. If APIGroup is not specified, the + specified Kind must be in the core API group. For + any other third-party types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource being referenced + type: string + name: + description: Name is the name of resource being referenced + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + description: 'dataSourceRef specifies the object from which + to populate the volume with data, if a non-empty volume + is desired. This may be any local object from a non-empty + API group (non core object) or a PersistentVolumeClaim + object. When this field is specified, volume binding will + only succeed if the type of the specified object matches + some installed volume populator or dynamic provisioner. + This field will replace the functionality of the DataSource + field and as such if both fields are non-empty, they must + have the same value. For backwards compatibility, both + fields (DataSource and DataSourceRef) will be set to the + same value automatically if one of them is empty and the + other is non-empty. There are two important differences + between DataSource and DataSourceRef: * While DataSource + only allows two specific types of objects, DataSourceRef + allows any non-core object, as well as PersistentVolumeClaim + objects. * While DataSource ignores disallowed values + (dropping them), DataSourceRef preserves all values, and + generates an error if a disallowed value is specified. + (Beta) Using this field requires the AnyVolumeDataSource + feature gate to be enabled.' + properties: + apiGroup: + description: APIGroup is the group for the resource + being referenced. If APIGroup is not specified, the + specified Kind must be in the core API group. For + any other third-party types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource being referenced + type: string + name: + description: Name is the name of resource being referenced + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + resources: + description: 'resources represents the minimum resources + the volume should have. If RecoverVolumeExpansionFailure + feature is enabled users are allowed to specify resource + requirements that are lower than previous value but must + still be higher than capacity recorded in the status field + of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' + properties: + 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. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + selector: + description: selector is a label query over volumes to consider + for binding. + 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 + required: + - key + - operator + type: object + type: array + 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 + storageClassName: + description: 'storageClassName is the name of the StorageClass + required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' + type: string + volumeMode: + description: volumeMode defines what type of volume is required + by the claim. Value of Filesystem is implied when not + included in claim spec. + type: string + volumeName: + description: volumeName is the binding reference to the + PersistentVolume backing this claim. + type: string + type: object + status: + description: 'status represents the current information/status + of a persistent volume claim. Read-only. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' + properties: + accessModes: + description: 'accessModes contains the actual access modes + the volume backing the PVC has. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' + items: + type: string + type: array + allocatedResources: + 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: allocatedResources is the storage resource + within AllocatedResources tracks the capacity allocated + to a PVC. It may be larger than the actual capacity when + a volume expansion operation is requested. For storage + quota, the larger value from allocatedResources and PVC.spec.resources + is used. If allocatedResources is not set, PVC.spec.resources + alone is used for quota calculation. If a volume expansion + capacity request is lowered, allocatedResources is only + lowered if there are no expansion operations in progress + and if the actual volume capacity is equal or lower than + the requested capacity. This is an alpha field and requires + enabling RecoverVolumeExpansionFailure feature. + type: object + capacity: + 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: capacity represents the actual resources of + the underlying volume. + type: object + conditions: + description: conditions is the current Condition of persistent + volume claim. If underlying persistent volume is being + resized then the Condition will be set to 'ResizeStarted'. + items: + description: PersistentVolumeClaimCondition contails details + about state of pvc + properties: + lastProbeTime: + description: lastProbeTime is the time we probed the + condition. + format: date-time + type: string + lastTransitionTime: + description: lastTransitionTime is the time the condition + transitioned from one status to another. + format: date-time + type: string + message: + description: message is the human-readable message + indicating details about last transition. + type: string + reason: + description: reason is a unique, this should be a + short, machine understandable string that gives + the reason for condition's last transition. If it + reports "ResizeStarted" that means the underlying + persistent volume is being resized. + type: string + status: + type: string + type: + description: PersistentVolumeClaimConditionType is + a valid value of PersistentVolumeClaimCondition.Type + type: string + required: + - status + - type + type: object + type: array + phase: + description: phase represents the current phase of PersistentVolumeClaim. + type: string + resizeStatus: + description: resizeStatus stores status of resize operation. + ResizeStatus is not set by default but when expansion + is complete resizeStatus is set to empty string by resize + controller or kubelet. This is an alpha field and requires + enabling RecoverVolumeExpansionFailure feature. + type: string + type: object + type: object + type: array + clusterAdvertiseAddress: + description: 'ClusterAdvertiseAddress is the explicit address to advertise + in cluster. Needs to be provided for non RFC1918 [1] (public) addresses. + [1] RFC1918: https://tools.ietf.org/html/rfc1918' + type: string + configMaps: + description: ConfigMaps is a list of ConfigMaps in the same namespace + as the VMAlertmanager object, which shall be mounted into the VMAlertmanager + Pods. The ConfigMaps are mounted into /etc/vm/configs/. + items: + type: string + type: array + configNamespaceSelector: + description: ConfigNamespaceSelector defines namespace selector for + VMAlertmanagerConfig. Works in combination with Selector. NamespaceSelector + nil - only objects at VMAlertmanager namespace. Selector nil - only + objects at NamespaceSelector namespaces. If both nil - behaviour + controlled by selectAllByDefault + 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 + required: + - key + - operator + type: object + type: array + 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 + configRawYaml: + description: ConfigRawYaml - raw configuration for alertmanager, it + helps it to start without secret. priority -> hardcoded ConfigRaw + -> ConfigRaw, provided by user -> ConfigSecret. + type: string + configSecret: + description: 'ConfigSecret is the name of a Kubernetes Secret in the + same namespace as the VMAlertmanager object, which contains configuration + for this VMAlertmanager, configuration must be inside secret key: + alertmanager.yaml. It must be created by user. instance. Defaults + to ''vmalertmanager-'' The secret is mounted + into /etc/alertmanager/config.' + type: string + configSelector: + description: ConfigSelector defines selector for VMAlertmanagerConfig, + result config will be merged with with Raw or Secret config. Works + in combination with NamespaceSelector. NamespaceSelector nil - only + objects at VMAlertmanager namespace. Selector nil - only objects + at NamespaceSelector namespaces. If both nil - behaviour controlled + by selectAllByDefault + 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 + required: + - key + - operator + type: object + type: array + 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 + containers: + description: Containers allows injecting additional containers or + patching existing containers. This is meant to allow adding an authentication + proxy to an VMAlertmanager pod. + items: + description: A single application container that you want to run + within a pod. + required: + - name + type: object + x-kubernetes-preserve-unknown-fields: true + type: array + disableNamespaceMatcher: + description: DisableNamespaceMatcher disables namespace label matcher + for VMAlertmanagerConfig It may be useful if alert doesn't have + namespace label for some reason + type: boolean + disableRouteContinueEnforce: + description: DisableRouteContinueEnforce cancel the behavior for VMAlertmanagerConfig + that always enforce first-level route continue to true + type: boolean + dnsConfig: + description: Specifies the DNS parameters of a pod. Parameters specified + here will be merged to the generated DNS configuration based on + DNSPolicy. + items: + x-kubernetes-preserve-unknown-fields: true + properties: + nameservers: + description: A list of DNS name server IP addresses. This will + be appended to the base nameservers generated from DNSPolicy. + Duplicated nameservers will be removed. + items: + type: string + type: array + options: + description: A list of DNS resolver options. This will be merged + with the base options generated from DNSPolicy. Duplicated entries + will be removed. Resolution options given in Options will override + those that appear in the base DNSPolicy. + items: + description: PodDNSConfigOption defines DNS resolver options + of a pod. + properties: + name: + description: Required. + type: string + value: + type: string + type: object + type: array + searches: + description: A list of DNS search domains for host-name lookup. + This will be appended to the base search paths generated from + DNSPolicy. Duplicated search paths will be removed. + items: + type: string + type: array + type: object + dnsPolicy: + description: DNSPolicy sets DNS policy for the pod + type: string + externalURL: + description: ExternalURL the VMAlertmanager instances will be available + under. This is necessary to generate correct URLs. This is necessary + if VMAlertmanager is not served from root of a DNS name. + type: string + extraArgs: + additionalProperties: + type: string + description: 'ExtraArgs that will be passed to VMAlertmanager pod + for example log.level: debug' + type: object + extraEnvs: + description: ExtraEnvs that will be added to VMAlertmanager pod + 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 + required: + - name + type: object + x-kubernetes-preserve-unknown-fields: true + type: array + hostNetwork: + description: HostNetwork controls whether the pod may use the node + network namespace + type: boolean + image: + description: Image - docker image settings for VMAlertmanager if no + specified operator uses default config version + properties: + pullPolicy: + description: PullPolicy describes how to pull docker image + type: string + repository: + description: Repository contains name of docker image + it's repository + if needed + type: string + tag: + description: Tag contains desired docker image version + type: string + type: object + imagePullSecrets: + description: ImagePullSecrets An optional list of references to secrets + in the same namespace to use for pulling images from registries + see https://kubernetes.io/docs/concepts/containers/images/#referring-to-an-imagepullsecrets-on-a-pod + items: + description: LocalObjectReference contains enough information to + let you locate the referenced object inside the same namespace. + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + x-kubernetes-map-type: atomic + type: array + initContainers: + description: 'InitContainers allows adding initContainers to the pod + definition. Those can be used to e.g. fetch secrets for injection + into the VMAlertmanager configuration from external sources. Any + errors during the execution of an initContainer will lead to a restart + of the Pod. More info: https://kubernetes.io/docs/concepts/workloads/pods/init-containers/ + Using initContainers for any use case other then secret fetching + is entirely outside the scope of what the maintainers will support + and by doing so, you accept that this behaviour may break at any + time without notice.' + items: + description: A single application container that you want to run + within a pod. + required: + - name + type: object + x-kubernetes-preserve-unknown-fields: true + type: array + listenLocal: + description: ListenLocal makes the VMAlertmanager server listen on + loopback, so that it does not bind against the Pod IP. Note this + is only for the VMAlertmanager UI, not the gossip communication. + type: boolean + livenessProbe: + description: LivenessProbe that will be added CRD pod + type: object + x-kubernetes-preserve-unknown-fields: true + logFormat: + description: LogFormat for VMAlertmanager to be configured with. + type: string + logLevel: + description: Log level for VMAlertmanager to be configured with. + type: string + nodeSelector: + additionalProperties: + type: string + description: NodeSelector Define which Nodes the Pods are scheduled + on. + type: object + paused: + description: Paused If set to true all actions on the underlaying + managed objects are not goint to be performed, except for delete + actions. + type: boolean + podDisruptionBudget: + description: PodDisruptionBudget created by operator + properties: + maxUnavailable: + anyOf: + - type: integer + - type: string + description: An eviction is allowed if at most "maxUnavailable" + pods selected by "selector" are unavailable after the eviction, + i.e. even in absence of the evicted pod. For example, one can + prevent all voluntary evictions by specifying 0. This is a mutually + exclusive setting with "minAvailable". + x-kubernetes-int-or-string: true + minAvailable: + anyOf: + - type: integer + - type: string + description: An eviction is allowed if at least "minAvailable" + pods selected by "selector" will still be available after the + eviction, i.e. even in the absence of the evicted pod. So for + example you can prevent all voluntary evictions by specifying + "100%". + x-kubernetes-int-or-string: true + selectorLabels: + additionalProperties: + type: string + description: replaces default labels selector generated by operator + it's useful when you need to create custom budget + type: object + type: object + podMetadata: + description: PodMetadata configures Labels and Annotations which are + propagated to the alertmanager pods. + properties: + annotations: + additionalProperties: + type: string + description: 'Annotations is an unstructured key value map stored + with a resource that may be set by external tools to store and + retrieve arbitrary metadata. They are not queryable and should + be preserved when modifying objects. More info: http://kubernetes.io/docs/user-guide/annotations' + type: object + labels: + additionalProperties: + type: string + description: 'Labels Map of string keys and values that can be + used to organize and categorize (scope and select) objects. + May match selectors of replication controllers and services. + More info: http://kubernetes.io/docs/user-guide/labels' + type: object + name: + description: 'Name must be unique within a namespace. Is required + when creating resources, although some resources may allow a + client to request the generation of an appropriate name automatically. + Name is primarily intended for creation idempotence and configuration + definition. Cannot be updated. More info: http://kubernetes.io/docs/user-guide/identifiers#names' + type: string + type: object + podSecurityPolicyName: + description: PodSecurityPolicyName - defines name for podSecurityPolicy + in case of empty value, prefixedName will be used. + type: string + portName: + description: PortName used for the pods and governing service. This + defaults to web + type: string + priorityClassName: + description: PriorityClassName class assigned to the Pods + type: string + readinessGates: + description: ReadinessGates defines pod readiness gates + items: + description: PodReadinessGate contains the reference to a pod condition + properties: + conditionType: + description: ConditionType refers to a condition in the pod's + condition list with matching type. + type: string + required: + - conditionType + type: object + type: array + readinessProbe: + description: ReadinessProbe that will be added CRD pod + type: object + x-kubernetes-preserve-unknown-fields: true + replicaCount: + description: ReplicaCount Size is the expected size of the alertmanager + cluster. The controller will eventually make the size of the running + cluster equal to the expected + format: int32 + minimum: 1 + type: integer + resources: + description: Resources container resource request and limits, https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + properties: + 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. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + retention: + description: Retention Time duration VMAlertmanager shall retain data + for. Default is '120h', and must match the regular expression `[0-9]+(ms|s|m|h)` + (milliseconds seconds minutes hours). + pattern: '[0-9]+(ms|s|m|h)' + type: string + rollingUpdateStrategy: + description: RollingUpdateStrategy defines strategy for application + updates Default is OnDelete, in this case operator handles update + process Can be changed for RollingUpdate + type: string + routePrefix: + description: RoutePrefix VMAlertmanager registers HTTP handlers for. + This is useful, if using ExternalURL and a proxy is rewriting HTTP + routes of a request, and the actual ExternalURL is still true, but + the server serves requests under a different route prefix. For example + for use with `kubectl proxy`. + type: string + runtimeClassName: + description: RuntimeClassName - defines runtime class for kubernetes + pod. https://kubernetes.io/docs/concepts/containers/runtime-class/ + type: string + schedulerName: + description: SchedulerName - defines kubernetes scheduler name + type: string + secrets: + description: Secrets is a list of Secrets in the same namespace as + the VMAlertmanager object, which shall be mounted into the VMAlertmanager + Pods. The Secrets are mounted into /etc/vm/secrets/ + items: + type: string + type: array + securityContext: + description: SecurityContext holds pod-level security attributes and + common container settings. This defaults to the default PodSecurityContext. + type: object + x-kubernetes-preserve-unknown-fields: true + selectAllByDefault: + description: 'SelectAllByDefault changes default behavior for empty + CRD selectors, such ConfigSelector. with selectAllScrapes: true + and undefined ConfigSelector and ConfigNamespaceSelector Operator + selects all exist alertManagerConfigs with selectAllScrapes: false + - selects nothing' + type: boolean + serviceAccountName: + description: ServiceAccountName is the name of the ServiceAccount + to use + type: string + serviceScrapeSpec: + description: ServiceScrapeSpec that will be added to vmalertmanager + VMServiceScrape spec + required: + - endpoints + type: object + x-kubernetes-preserve-unknown-fields: true + serviceSpec: + description: ServiceSpec that will be added to vmalertmanager service + spec + properties: + metadata: + description: EmbeddedObjectMetadata defines objectMeta for additional + service. + properties: + annotations: + additionalProperties: + type: string + description: 'Annotations is an unstructured key value map + stored with a resource that may be set by external tools + to store and retrieve arbitrary metadata. They are not queryable + and should be preserved when modifying objects. More info: + http://kubernetes.io/docs/user-guide/annotations' + type: object + labels: + additionalProperties: + type: string + description: 'Labels Map of string keys and values that can + be used to organize and categorize (scope and select) objects. + May match selectors of replication controllers and services. + More info: http://kubernetes.io/docs/user-guide/labels' + type: object + name: + description: 'Name must be unique within a namespace. Is required + when creating resources, although some resources may allow + a client to request the generation of an appropriate name + automatically. Name is primarily intended for creation idempotence + and configuration definition. Cannot be updated. More info: + http://kubernetes.io/docs/user-guide/identifiers#names' + type: string + type: object + spec: + description: 'ServiceSpec describes the attributes that a user + creates on a service. More info: https://kubernetes.io/docs/concepts/services-networking/service/' + type: object + x-kubernetes-preserve-unknown-fields: true + required: + - spec + type: object + startupProbe: + description: StartupProbe that will be added to CRD pod + type: object + x-kubernetes-preserve-unknown-fields: true + storage: + description: Storage is the definition of how storage will be used + by the VMAlertmanager instances. + properties: + disableMountSubPath: + description: 'Deprecated: subPath usage will be disabled by default + in a future release, this option will become unnecessary. DisableMountSubPath + allows to remove any subPath usage in volume mounts.' + type: boolean + emptyDir: + description: 'EmptyDirVolumeSource to be used by the Prometheus + StatefulSets. If specified, used in place of any volumeClaimTemplate. + More info: https://kubernetes.io/docs/concepts/storage/volumes/#emptydir' + properties: + medium: + description: 'medium represents what type of storage medium + should back this directory. The default is "" which means + to use the node''s default medium. Must be an empty string + (default) or Memory. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' + type: string + sizeLimit: + anyOf: + - type: integer + - type: string + description: 'sizeLimit is the total amount of local storage + required for this EmptyDir volume. The size limit is also + applicable for memory medium. The maximum usage on memory + medium EmptyDir would be the minimum value between the SizeLimit + specified here and the sum of memory limits of all containers + in a pod. The default is nil which means that the limit + is undefined. More info: http://kubernetes.io/docs/user-guide/volumes#emptydir' + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + volumeClaimTemplate: + description: A PVC spec to be used by the VMAlertManager StatefulSets. + 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: + description: EmbeddedMetadata contains metadata relevant to + an EmbeddedResource. + properties: + annotations: + additionalProperties: + type: string + description: 'Annotations is an unstructured key value + map stored with a resource that may be set by external + tools to store and retrieve arbitrary metadata. They + are not queryable and should be preserved when modifying + objects. More info: http://kubernetes.io/docs/user-guide/annotations' + type: object + labels: + additionalProperties: + type: string + description: 'Labels Map of string keys and values that + can be used to organize and categorize (scope and select) + objects. May match selectors of replication controllers + and services. More info: http://kubernetes.io/docs/user-guide/labels' + type: object + name: + description: 'Name must be unique within a namespace. + Is required when creating resources, although some resources + may allow a client to request the generation of an appropriate + name automatically. Name is primarily intended for creation + idempotence and configuration definition. Cannot be + updated. More info: http://kubernetes.io/docs/user-guide/identifiers#names' + type: string + type: object + spec: + description: 'Spec defines the desired characteristics of + a volume requested by a pod author. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' + properties: + accessModes: + description: 'accessModes contains the desired access + modes the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' + items: + type: string + type: array + dataSource: + description: 'dataSource field can be used to specify + either: * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) + * An existing PVC (PersistentVolumeClaim) If the provisioner + or an external controller can support the specified + data source, it will create a new volume based on the + contents of the specified data source. If the AnyVolumeDataSource + feature gate is enabled, this field will always have + the same contents as the DataSourceRef field.' + properties: + apiGroup: + description: APIGroup is the group for the resource + being referenced. If APIGroup is not specified, + the specified Kind must be in the core API group. + For any other third-party types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource being referenced + type: string + name: + description: Name is the name of resource being referenced + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + description: 'dataSourceRef specifies the object from + which to populate the volume with data, if a non-empty + volume is desired. This may be any local object from + a non-empty API group (non core object) or a PersistentVolumeClaim + object. When this field is specified, volume binding + will only succeed if the type of the specified object + matches some installed volume populator or dynamic provisioner. + This field will replace the functionality of the DataSource + field and as such if both fields are non-empty, they + must have the same value. For backwards compatibility, + both fields (DataSource and DataSourceRef) will be set + to the same value automatically if one of them is empty + and the other is non-empty. There are two important + differences between DataSource and DataSourceRef: * + While DataSource only allows two specific types of objects, + DataSourceRef allows any non-core object, as well as + PersistentVolumeClaim objects. * While DataSource ignores + disallowed values (dropping them), DataSourceRef preserves + all values, and generates an error if a disallowed value + is specified. (Beta) Using this field requires the AnyVolumeDataSource + feature gate to be enabled.' + properties: + apiGroup: + description: APIGroup is the group for the resource + being referenced. If APIGroup is not specified, + the specified Kind must be in the core API group. + For any other third-party types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource being referenced + type: string + name: + description: Name is the name of resource being referenced + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + resources: + description: 'resources represents the minimum resources + the volume should have. If RecoverVolumeExpansionFailure + feature is enabled users are allowed to specify resource + requirements that are lower than previous value but + must still be higher than capacity recorded in the status + field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' + properties: + 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. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + selector: + description: selector is a label query over volumes to + consider for binding. + 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 + required: + - key + - operator + type: object + type: array + 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 + storageClassName: + description: 'storageClassName is the name of the StorageClass + required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' + type: string + volumeMode: + description: volumeMode defines what type of volume is + required by the claim. Value of Filesystem is implied + when not included in claim spec. + type: string + volumeName: + description: volumeName is the binding reference to the + PersistentVolume backing this claim. + type: string + type: object + status: + description: 'Status represents the current information/status + of a persistent volume claim. Read-only. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' + properties: + accessModes: + description: 'accessModes contains the actual access modes + the volume backing the PVC has. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' + items: + type: string + type: array + allocatedResources: + 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: allocatedResources is the storage resource + within AllocatedResources tracks the capacity allocated + to a PVC. It may be larger than the actual capacity + when a volume expansion operation is requested. For + storage quota, the larger value from allocatedResources + and PVC.spec.resources is used. If allocatedResources + is not set, PVC.spec.resources alone is used for quota + calculation. If a volume expansion capacity request + is lowered, allocatedResources is only lowered if there + are no expansion operations in progress and if the actual + volume capacity is equal or lower than the requested + capacity. This is an alpha field and requires enabling + RecoverVolumeExpansionFailure feature. + type: object + capacity: + 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: capacity represents the actual resources + of the underlying volume. + type: object + conditions: + description: conditions is the current Condition of persistent + volume claim. If underlying persistent volume is being + resized then the Condition will be set to 'ResizeStarted'. + items: + description: PersistentVolumeClaimCondition contails + details about state of pvc + properties: + lastProbeTime: + description: lastProbeTime is the time we probed + the condition. + format: date-time + type: string + lastTransitionTime: + description: lastTransitionTime is the time the + condition transitioned from one status to another. + format: date-time + type: string + message: + description: message is the human-readable message + indicating details about last transition. + type: string + reason: + description: reason is a unique, this should be + a short, machine understandable string that gives + the reason for condition's last transition. If + it reports "ResizeStarted" that means the underlying + persistent volume is being resized. + type: string + status: + type: string + type: + description: PersistentVolumeClaimConditionType + is a valid value of PersistentVolumeClaimCondition.Type + type: string + required: + - status + - type + type: object + type: array + phase: + description: phase represents the current phase of PersistentVolumeClaim. + type: string + resizeStatus: + description: resizeStatus stores status of resize operation. + ResizeStatus is not set by default but when expansion + is complete resizeStatus is set to empty string by resize + controller or kubelet. This is an alpha field and requires + enabling RecoverVolumeExpansionFailure feature. + type: string + type: object + type: object + type: object + templates: + description: Templates is a list of ConfigMap key references for ConfigMaps + in the same namespace as the VMAlertmanager object, which shall + be mounted into the VMAlertmanager Pods. The Templates are mounted + into /etc/vm/templates//. + items: + description: ConfigMapKeyReference refers to a key in a ConfigMap. + properties: + key: + description: The ConfigMap key to refer to. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + required: + - key + type: object + x-kubernetes-map-type: atomic + type: array + terminationGracePeriodSeconds: + description: TerminationGracePeriodSeconds period for container graceful + termination + format: int64 + type: integer + tolerations: + description: Tolerations If specified, the pod's tolerations. + 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: TopologySpreadConstraints embedded kubernetes pod configuration + option, controls how pods are spread across your cluster among failure-domains + such as regions, zones, nodes, and other user-defined topology domains + https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/ + items: + description: TopologySpreadConstraint specifies how to spread matching + pods among the given topology. + required: + - maxSkew + - topologyKey + - whenUnsatisfiable + type: object + x-kubernetes-preserve-unknown-fields: true + type: array + volumeMounts: + description: VolumeMounts allows configuration of additional VolumeMounts + on the output StatefulSet definition. VolumeMounts specified will + be appended to other VolumeMounts in the alertmanager container, + that are generated as a result of StorageSpec objects. + items: + description: VolumeMount describes a mounting of a Volume within + a container. + properties: + mountPath: + description: Path within the container at which the volume should + be mounted. Must not contain ':'. + type: string + mountPropagation: + description: mountPropagation determines how mounts are propagated + from the host to container and the other way around. When + not set, MountPropagationNone is used. This field is beta + in 1.10. + type: string + name: + description: This must match the Name of a Volume. + type: string + readOnly: + description: Mounted read-only if true, read-write otherwise + (false or unspecified). Defaults to false. + type: boolean + subPath: + description: Path within the volume from which the container's + volume should be mounted. Defaults to "" (volume's root). + type: string + subPathExpr: + description: Expanded path within the volume from which the + container's volume should be mounted. Behaves similarly to + SubPath but environment variable references $(VAR_NAME) are + expanded using the container's environment. Defaults to "" + (volume's root). SubPathExpr and SubPath are mutually exclusive. + type: string + required: + - mountPath + - name + type: object + type: array + volumes: + description: Volumes allows configuration of additional volumes on + the output StatefulSet definition. Volumes specified will be appended + to other volumes that are generated as a result of StorageSpec objects. + items: + description: Volume represents a named volume in a pod that may + be accessed by any container in the pod. + required: + - name + type: object + x-kubernetes-preserve-unknown-fields: true + type: array + type: object + status: + description: 'Most recent observed status of the VMAlertmanager cluster. + Operator API itself. More info: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#spec-and-status' + properties: + availableReplicas: + description: AvailableReplicas Total number of available pods (ready + for at least minReadySeconds) targeted by this VMAlertmanager cluster. + format: int32 + type: integer + paused: + description: Paused Represents whether any actions on the underlaying + managed objects are being performed. Only delete actions will be + performed. + type: boolean + replicas: + description: ReplicaCount Total number of non-terminated pods targeted + by this VMAlertmanager cluster (their labels match the selector). + format: int32 + type: integer + unavailableReplicas: + description: UnavailableReplicas Total number of unavailable pods + targeted by this VMAlertmanager cluster. + format: int32 + type: integer + updatedReplicas: + description: UpdatedReplicas Total number of non-terminated pods targeted + by this VMAlertmanager cluster that have the desired version spec. + format: int32 + type: integer + required: + - availableReplicas + - paused + - replicas + - unavailableReplicas + - updatedReplicas + type: object + required: + - spec + type: object + served: true + storage: true + subresources: {} +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.12.1 + name: vmalerts.operator.victoriametrics.com +spec: + group: operator.victoriametrics.com + names: + kind: VMAlert + listKind: VMAlertList + plural: vmalerts + singular: vmalert + scope: Namespaced + versions: + - name: v1beta1 + schema: + openAPIV3Schema: + description: VMAlert executes a list of given alerting or recording rules + against configured address. + 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: VMAlertSpec defines the desired state of VMAlert + properties: + '-': + description: ParsingError contents error with context if operator + was failed to parse json object from kubernetes api server + type: string + affinity: + description: Affinity If specified, the pod's scheduling constraints. + type: object + x-kubernetes-preserve-unknown-fields: true + configMaps: + description: ConfigMaps is a list of ConfigMaps in the same namespace + as the VMAlert object, which shall be mounted into the VMAlert Pods. + The ConfigMaps are mounted into /etc/vm/configs/. + items: + type: string + type: array + containers: + description: Containers property allows to inject additions sidecars + or to patch existing containers. It can be useful for proxies, backup, + etc. + items: + description: A single application container that you want to run + within a pod. + required: + - name + type: object + x-kubernetes-preserve-unknown-fields: true + type: array + datasource: + description: Datasource Victoria Metrics or VMSelect url. Required + parameter. e.g. http://127.0.0.1:8428 + properties: + OAuth2: + x-kubernetes-preserve-unknown-fields: true + basicAuth: + description: BasicAuth allow an endpoint to authenticate over + basic authentication + properties: + password: + description: The secret in the service scrape namespace that + contains the password for authentication. It must be at + them same namespace as CRD + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + password_file: + description: PasswordFile defines path to password file at + disk + type: string + username: + description: The secret in the service scrape namespace that + contains the username for authentication. It must be at + them same namespace as CRD + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + bearerTokenFile: + description: Path to bearer token file + type: string + bearerTokenSecret: + description: Optional bearer auth token to use for -remoteWrite.url + properties: + key: + description: The key of the secret to select from. Must be + a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + headers: + description: Headers allow configuring custom http headers Must + be in form of semicolon separated header with value e.g. headerName:headerValue + vmalert supports it since 1.79.0 version + items: + type: string + type: array + oauth2: + description: OAuth2 defines OAuth2 configuration + properties: + client_id: + description: The secret or configmap containing the OAuth2 + client id + properties: + configMap: + description: ConfigMap containing data to use for the + targets. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + 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 + secret: + description: Secret containing data to use for the targets. + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + 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 + client_secret: + description: The secret containing the OAuth2 client secret + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + client_secret_file: + description: ClientSecretFile defines path for client secret + file. + type: string + endpoint_params: + additionalProperties: + type: string + description: Parameters to append to the token URL + type: object + scopes: + description: OAuth2 scopes used for the token request + items: + type: string + type: array + token_url: + description: The URL to fetch the token from + minLength: 1 + type: string + required: + - client_id + - token_url + type: object + tlsConfig: + description: TLSConfig specifies TLSConfig configuration parameters. + type: object + x-kubernetes-preserve-unknown-fields: true + url: + description: Victoria Metrics or VMSelect url. Required parameter. + E.g. http://127.0.0.1:8428 + type: string + required: + - url + type: object + dnsConfig: + description: Specifies the DNS parameters of a pod. Parameters specified + here will be merged to the generated DNS configuration based on + DNSPolicy. + items: + x-kubernetes-preserve-unknown-fields: true + properties: + nameservers: + description: A list of DNS name server IP addresses. This will + be appended to the base nameservers generated from DNSPolicy. + Duplicated nameservers will be removed. + items: + type: string + type: array + options: + description: A list of DNS resolver options. This will be merged + with the base options generated from DNSPolicy. Duplicated entries + will be removed. Resolution options given in Options will override + those that appear in the base DNSPolicy. + items: + description: PodDNSConfigOption defines DNS resolver options + of a pod. + properties: + name: + description: Required. + type: string + value: + type: string + type: object + type: array + searches: + description: A list of DNS search domains for host-name lookup. + This will be appended to the base search paths generated from + DNSPolicy. Duplicated search paths will be removed. + items: + type: string + type: array + type: object + dnsPolicy: + description: DNSPolicy sets DNS policy for the pod + type: string + enforcedNamespaceLabel: + description: EnforcedNamespaceLabel enforces adding a namespace label + of origin for each alert and metric that is user created. The label + value will always be the namespace of the object that is being created. + type: string + evaluationInterval: + description: EvaluationInterval defines how often to evaluate rules + by default + pattern: '[0-9]+(ms|s|m|h)' + type: string + externalLabels: + additionalProperties: + type: string + description: 'ExternalLabels in the form ''name: value'' to add to + all generated recording rules and alerts.' + type: object + extraArgs: + additionalProperties: + type: string + description: ExtraArgs that will be passed to VMAlert pod for example + -remoteWrite.tmpDataPath=/tmp + type: object + extraEnvs: + description: ExtraEnvs that will be added to VMAlert pod + 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 + required: + - name + type: object + x-kubernetes-preserve-unknown-fields: true + type: array + hostNetwork: + description: HostNetwork controls whether the pod may use the node + network namespace + type: boolean + image: + description: Image - docker image settings for VMAlert if no specified + operator uses default config version + properties: + pullPolicy: + description: PullPolicy describes how to pull docker image + type: string + repository: + description: Repository contains name of docker image + it's repository + if needed + type: string + tag: + description: Tag contains desired docker image version + type: string + type: object + imagePullSecrets: + description: ImagePullSecrets An optional list of references to secrets + in the same namespace to use for pulling images from registries + see https://kubernetes.io/docs/concepts/containers/images/#referring-to-an-imagepullsecrets-on-a-pod + items: + description: LocalObjectReference contains enough information to + let you locate the referenced object inside the same namespace. + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + x-kubernetes-map-type: atomic + type: array + initContainers: + description: 'InitContainers allows adding initContainers to the pod + definition. Those can be used to e.g. fetch secrets for injection + into the VMAlert configuration from external sources. Any errors + during the execution of an initContainer will lead to a restart + of the Pod. More info: https://kubernetes.io/docs/concepts/workloads/pods/init-containers/ + Using initContainers for any use case other then secret fetching + is entirely outside the scope of what the maintainers will support + and by doing so, you accept that this behaviour may break at any + time without notice.' + items: + description: A single application container that you want to run + within a pod. + required: + - name + type: object + x-kubernetes-preserve-unknown-fields: true + type: array + livenessProbe: + description: LivenessProbe that will be added CRD pod + type: object + x-kubernetes-preserve-unknown-fields: true + logFormat: + description: LogFormat for VMAlert to be configured with. default + or json + enum: + - default + - json + type: string + logLevel: + description: LogLevel for VMAlert to be configured with. + enum: + - INFO + - WARN + - ERROR + - FATAL + - PANIC + type: string + nodeSelector: + additionalProperties: + type: string + description: NodeSelector Define which Nodes the Pods are scheduled + on. + type: object + notifier: + description: 'Notifier prometheus alertmanager endpoint spec. Required + at least one of notifier or notifiers. e.g. http://127.0.0.1:9093 + If specified both notifier and notifiers, notifier will be added + as last element to notifiers. only one of notifier options could + be chosen: notifierConfigRef or notifiers + notifier' + properties: + OAuth2: + x-kubernetes-preserve-unknown-fields: true + basicAuth: + description: BasicAuth allow an endpoint to authenticate over + basic authentication + properties: + password: + description: The secret in the service scrape namespace that + contains the password for authentication. It must be at + them same namespace as CRD + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + password_file: + description: PasswordFile defines path to password file at + disk + type: string + username: + description: The secret in the service scrape namespace that + contains the username for authentication. It must be at + them same namespace as CRD + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + bearerTokenFile: + description: Path to bearer token file + type: string + bearerTokenSecret: + description: Optional bearer auth token to use for -remoteWrite.url + properties: + key: + description: The key of the secret to select from. Must be + a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + headers: + description: Headers allow configuring custom http headers Must + be in form of semicolon separated header with value e.g. headerName:headerValue + vmalert supports it since 1.79.0 version + items: + type: string + type: array + oauth2: + description: OAuth2 defines OAuth2 configuration + properties: + client_id: + description: The secret or configmap containing the OAuth2 + client id + properties: + configMap: + description: ConfigMap containing data to use for the + targets. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + 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 + secret: + description: Secret containing data to use for the targets. + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + 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 + client_secret: + description: The secret containing the OAuth2 client secret + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + client_secret_file: + description: ClientSecretFile defines path for client secret + file. + type: string + endpoint_params: + additionalProperties: + type: string + description: Parameters to append to the token URL + type: object + scopes: + description: OAuth2 scopes used for the token request + items: + type: string + type: array + token_url: + description: The URL to fetch the token from + minLength: 1 + type: string + required: + - client_id + - token_url + type: object + selector: + description: Selector allows service discovery for alertmanager + in this case all matched vmalertmanager replicas will be added + into vmalert notifier.url as statefulset pod.fqdn + properties: + labelSelector: + description: A label selector is a label query over a set + of resources. The result of matchLabels and matchExpressions + are ANDed. An empty label selector matches all objects. + A null label selector matches no objects. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: NamespaceSelector is a selector for selecting + either all namespaces or a list of namespaces. + properties: + any: + description: Boolean describing whether all namespaces + are selected in contrast to a list restricting them. + type: boolean + matchNames: + description: List of namespace names. + items: + type: string + type: array + type: object + type: object + tlsConfig: + description: TLSConfig specifies TLSConfig configuration parameters. + type: object + x-kubernetes-preserve-unknown-fields: true + url: + description: AlertManager url. E.g. http://127.0.0.1:9093 + type: string + type: object + notifierConfigRef: + description: 'NotifierConfigRef reference for secret with notifier + configuration for vmalert only one of notifier options could be + chosen: notifierConfigRef or notifiers + notifier' + properties: + key: + description: The key of the secret to select from. Must be a + valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + notifiers: + description: 'Notifiers prometheus alertmanager endpoints. Required + at least one of notifier or notifiers. e.g. http://127.0.0.1:9093 + If specified both notifier and notifiers, notifier will be added + as last element to notifiers. only one of notifier options could + be chosen: notifierConfigRef or notifiers + notifier' + items: + description: VMAlertNotifierSpec defines the notifier url for sending + information about alerts + properties: + OAuth2: + x-kubernetes-preserve-unknown-fields: true + basicAuth: + description: BasicAuth allow an endpoint to authenticate over + basic authentication + properties: + password: + description: The secret in the service scrape namespace + that contains the password for authentication. It must + be at them same namespace as CRD + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + password_file: + description: PasswordFile defines path to password file + at disk + type: string + username: + description: The secret in the service scrape namespace + that contains the username for authentication. It must + be at them same namespace as CRD + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + bearerTokenFile: + description: Path to bearer token file + type: string + bearerTokenSecret: + description: Optional bearer auth token to use for -remoteWrite.url + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + headers: + description: Headers allow configuring custom http headers Must + be in form of semicolon separated header with value e.g. headerName:headerValue + vmalert supports it since 1.79.0 version + items: + type: string + type: array + oauth2: + description: OAuth2 defines OAuth2 configuration + properties: + client_id: + description: The secret or configmap containing the OAuth2 + client id + properties: + configMap: + description: ConfigMap containing data to use for the + targets. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + 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 + secret: + description: Secret containing data to use for the targets. + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + 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 + client_secret: + description: The secret containing the OAuth2 client secret + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + client_secret_file: + description: ClientSecretFile defines path for client secret + file. + type: string + endpoint_params: + additionalProperties: + type: string + description: Parameters to append to the token URL + type: object + scopes: + description: OAuth2 scopes used for the token request + items: + type: string + type: array + token_url: + description: The URL to fetch the token from + minLength: 1 + type: string + required: + - client_id + - token_url + type: object + selector: + description: Selector allows service discovery for alertmanager + in this case all matched vmalertmanager replicas will be added + into vmalert notifier.url as statefulset pod.fqdn + properties: + labelSelector: + description: A label selector is a label query over a set + of resources. The result of matchLabels and matchExpressions + are ANDed. An empty label selector matches all objects. + A null label selector matches no objects. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: NamespaceSelector is a selector for selecting + either all namespaces or a list of namespaces. + properties: + any: + description: Boolean describing whether all namespaces + are selected in contrast to a list restricting them. + type: boolean + matchNames: + description: List of namespace names. + items: + type: string + type: array + type: object + type: object + tlsConfig: + description: TLSConfig specifies TLSConfig configuration parameters. + type: object + x-kubernetes-preserve-unknown-fields: true + url: + description: AlertManager url. E.g. http://127.0.0.1:9093 + type: string + type: object + type: array + podDisruptionBudget: + description: PodDisruptionBudget created by operator + properties: + maxUnavailable: + anyOf: + - type: integer + - type: string + description: An eviction is allowed if at most "maxUnavailable" + pods selected by "selector" are unavailable after the eviction, + i.e. even in absence of the evicted pod. For example, one can + prevent all voluntary evictions by specifying 0. This is a mutually + exclusive setting with "minAvailable". + x-kubernetes-int-or-string: true + minAvailable: + anyOf: + - type: integer + - type: string + description: An eviction is allowed if at least "minAvailable" + pods selected by "selector" will still be available after the + eviction, i.e. even in the absence of the evicted pod. So for + example you can prevent all voluntary evictions by specifying + "100%". + x-kubernetes-int-or-string: true + selectorLabels: + additionalProperties: + type: string + description: replaces default labels selector generated by operator + it's useful when you need to create custom budget + type: object + type: object + podMetadata: + description: PodMetadata configures Labels and Annotations which are + propagated to the VMAlert pods. + properties: + annotations: + additionalProperties: + type: string + description: 'Annotations is an unstructured key value map stored + with a resource that may be set by external tools to store and + retrieve arbitrary metadata. They are not queryable and should + be preserved when modifying objects. More info: http://kubernetes.io/docs/user-guide/annotations' + type: object + labels: + additionalProperties: + type: string + description: 'Labels Map of string keys and values that can be + used to organize and categorize (scope and select) objects. + May match selectors of replication controllers and services. + More info: http://kubernetes.io/docs/user-guide/labels' + type: object + name: + description: 'Name must be unique within a namespace. Is required + when creating resources, although some resources may allow a + client to request the generation of an appropriate name automatically. + Name is primarily intended for creation idempotence and configuration + definition. Cannot be updated. More info: http://kubernetes.io/docs/user-guide/identifiers#names' + type: string + type: object + podSecurityPolicyName: + description: PodSecurityPolicyName - defines name for podSecurityPolicy + in case of empty value, prefixedName will be used. + type: string + port: + description: Port for listen + type: string + priorityClassName: + description: Priority class assigned to the Pods + type: string + readinessGates: + description: ReadinessGates defines pod readiness gates + items: + description: PodReadinessGate contains the reference to a pod condition + properties: + conditionType: + description: ConditionType refers to a condition in the pod's + condition list with matching type. + type: string + required: + - conditionType + type: object + type: array + readinessProbe: + description: ReadinessProbe that will be added CRD pod + type: object + x-kubernetes-preserve-unknown-fields: true + remoteRead: + description: RemoteRead Optional URL to read vmalert state (persisted + via RemoteWrite) This configuration only makes sense if alerts state + has been successfully persisted (via RemoteWrite) before. see -remoteRead.url + docs in vmalerts for details. E.g. http://127.0.0.1:8428 + properties: + OAuth2: + x-kubernetes-preserve-unknown-fields: true + basicAuth: + description: BasicAuth allow an endpoint to authenticate over + basic authentication + properties: + password: + description: The secret in the service scrape namespace that + contains the password for authentication. It must be at + them same namespace as CRD + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + password_file: + description: PasswordFile defines path to password file at + disk + type: string + username: + description: The secret in the service scrape namespace that + contains the username for authentication. It must be at + them same namespace as CRD + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + bearerTokenFile: + description: Path to bearer token file + type: string + bearerTokenSecret: + description: Optional bearer auth token to use for -remoteWrite.url + properties: + key: + description: The key of the secret to select from. Must be + a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + headers: + description: Headers allow configuring custom http headers Must + be in form of semicolon separated header with value e.g. headerName:headerValue + vmalert supports it since 1.79.0 version + items: + type: string + type: array + lookback: + description: Lookback defines how far to look into past for alerts + timeseries. For example, if lookback=1h then range from now() + to now()-1h will be scanned. (default 1h0m0s) Applied only to + RemoteReadSpec + type: string + oauth2: + description: OAuth2 defines OAuth2 configuration + properties: + client_id: + description: The secret or configmap containing the OAuth2 + client id + properties: + configMap: + description: ConfigMap containing data to use for the + targets. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + 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 + secret: + description: Secret containing data to use for the targets. + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + 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 + client_secret: + description: The secret containing the OAuth2 client secret + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + client_secret_file: + description: ClientSecretFile defines path for client secret + file. + type: string + endpoint_params: + additionalProperties: + type: string + description: Parameters to append to the token URL + type: object + scopes: + description: OAuth2 scopes used for the token request + items: + type: string + type: array + token_url: + description: The URL to fetch the token from + minLength: 1 + type: string + required: + - client_id + - token_url + type: object + tlsConfig: + description: TLSConfig specifies TLSConfig configuration parameters. + type: object + x-kubernetes-preserve-unknown-fields: true + url: + description: URL of the endpoint to send samples to. + type: string + required: + - url + type: object + remoteWrite: + description: RemoteWrite Optional URL to remote-write compatible storage + to persist vmalert state and rule results to. Rule results will + be persisted according to each rule. Alerts state will be persisted + in the form of time series named ALERTS and ALERTS_FOR_STATE see + -remoteWrite.url docs in vmalerts for details. E.g. http://127.0.0.1:8428 + properties: + OAuth2: + x-kubernetes-preserve-unknown-fields: true + basicAuth: + description: BasicAuth allow an endpoint to authenticate over + basic authentication + properties: + password: + description: The secret in the service scrape namespace that + contains the password for authentication. It must be at + them same namespace as CRD + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + password_file: + description: PasswordFile defines path to password file at + disk + type: string + username: + description: The secret in the service scrape namespace that + contains the username for authentication. It must be at + them same namespace as CRD + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + bearerTokenFile: + description: Path to bearer token file + type: string + bearerTokenSecret: + description: Optional bearer auth token to use for -remoteWrite.url + properties: + key: + description: The key of the secret to select from. Must be + a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + concurrency: + description: Defines number of readers that concurrently write + into remote storage (default 1) + format: int32 + type: integer + flushInterval: + description: Defines interval of flushes to remote write endpoint + (default 5s) + pattern: '[0-9]+(ms|s|m|h)' + type: string + headers: + description: Headers allow configuring custom http headers Must + be in form of semicolon separated header with value e.g. headerName:headerValue + vmalert supports it since 1.79.0 version + items: + type: string + type: array + maxBatchSize: + description: Defines defines max number of timeseries to be flushed + at once (default 1000) + format: int32 + type: integer + maxQueueSize: + description: Defines the max number of pending datapoints to remote + write endpoint (default 100000) + format: int32 + type: integer + oauth2: + description: OAuth2 defines OAuth2 configuration + properties: + client_id: + description: The secret or configmap containing the OAuth2 + client id + properties: + configMap: + description: ConfigMap containing data to use for the + targets. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + 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 + secret: + description: Secret containing data to use for the targets. + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + 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 + client_secret: + description: The secret containing the OAuth2 client secret + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + client_secret_file: + description: ClientSecretFile defines path for client secret + file. + type: string + endpoint_params: + additionalProperties: + type: string + description: Parameters to append to the token URL + type: object + scopes: + description: OAuth2 scopes used for the token request + items: + type: string + type: array + token_url: + description: The URL to fetch the token from + minLength: 1 + type: string + required: + - client_id + - token_url + type: object + tlsConfig: + description: TLSConfig specifies TLSConfig configuration parameters. + type: object + x-kubernetes-preserve-unknown-fields: true + url: + description: URL of the endpoint to send samples to. + type: string + required: + - url + type: object + replicaCount: + description: ReplicaCount is the expected size of the VMAlert cluster. + The controller will eventually make the size of the running cluster + equal to the expected size. + format: int32 + type: integer + resources: + description: Resources container resource request and limits, https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + properties: + 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. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + rollingUpdate: + description: RollingUpdate - overrides deployment update params. + properties: + maxSurge: + anyOf: + - type: integer + - type: string + description: 'The maximum number of pods that can be scheduled + above the desired number of pods. Value can be an absolute number + (ex: 5) or a percentage of desired pods (ex: 10%). This can + not be 0 if MaxUnavailable is 0. Absolute number is calculated + from percentage by rounding up. Defaults to 25%. Example: when + this is set to 30%, the new ReplicaSet can be scaled up immediately + when the rolling update starts, such that the total number of + old and new pods do not exceed 130% of desired pods. Once old + pods have been killed, new ReplicaSet can be scaled up further, + ensuring that total number of pods running at any time during + the update is at most 130% of desired pods.' + x-kubernetes-int-or-string: true + maxUnavailable: + anyOf: + - type: integer + - type: string + description: 'The maximum number of pods that can be unavailable + during the update. Value can be an absolute number (ex: 5) or + a percentage of desired pods (ex: 10%). Absolute number is calculated + from percentage by rounding down. This can not be 0 if MaxSurge + is 0. Defaults to 25%. Example: when this is set to 30%, the + old ReplicaSet can be scaled down to 70% of desired pods immediately + when the rolling update starts. Once new pods are ready, old + ReplicaSet can be scaled down further, followed by scaling up + the new ReplicaSet, ensuring that the total number of pods available + at all times during the update is at least 70% of desired pods.' + x-kubernetes-int-or-string: true + type: object + ruleNamespaceSelector: + description: RuleNamespaceSelector to be selected for VMRules discovery. + Works in combination with Selector. If both nil - behaviour controlled + by selectAllByDefault NamespaceSelector nil - only objects at VMAlert + namespace. + 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 + required: + - key + - operator + type: object + type: array + 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 + rulePath: + description: 'RulePath to the file with alert rules. Supports patterns. + Flag can be specified multiple times. Examples: -rule /path/to/file. + Path to a single file with alerting rules -rule dir/*.yaml -rule + /*.yaml. Relative path to all .yaml files in folder, absolute path + to all .yaml files in root. by default operator adds /etc/vmalert/configs/base/vmalert.yaml' + items: + type: string + type: array + ruleSelector: + description: RuleSelector selector to select which VMRules to mount + for loading alerting rules from. Works in combination with NamespaceSelector. + If both nil - behaviour controlled by selectAllByDefault NamespaceSelector + nil - only objects at VMAlert namespace. + 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 + required: + - key + - operator + type: object + type: array + 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 + runtimeClassName: + description: RuntimeClassName - defines runtime class for kubernetes + pod. https://kubernetes.io/docs/concepts/containers/runtime-class/ + type: string + schedulerName: + description: SchedulerName - defines kubernetes scheduler name + type: string + secrets: + description: Secrets is a list of Secrets in the same namespace as + the VMAlert object, which shall be mounted into the VMAlert Pods. + The Secrets are mounted into /etc/vm/secrets/. + items: + type: string + type: array + securityContext: + description: SecurityContext holds pod-level security attributes and + common container settings. This defaults to the default PodSecurityContext. + type: object + x-kubernetes-preserve-unknown-fields: true + selectAllByDefault: + description: 'SelectAllByDefault changes default behavior for empty + CRD selectors, such RuleSelector. with selectAllByDefault: true + and empty serviceScrapeSelector and RuleNamespaceSelector Operator + selects all exist serviceScrapes with selectAllByDefault: false + - selects nothing' + type: boolean + serviceAccountName: + description: ServiceAccountName is the name of the ServiceAccount + to use to run the VMAlert Pods. + type: string + serviceScrapeSpec: + description: ServiceScrapeSpec that will be added to vmalert VMServiceScrape + spec + required: + - endpoints + type: object + x-kubernetes-preserve-unknown-fields: true + serviceSpec: + description: ServiceSpec that will be added to vmalert service spec + properties: + metadata: + description: EmbeddedObjectMetadata defines objectMeta for additional + service. + properties: + annotations: + additionalProperties: + type: string + description: 'Annotations is an unstructured key value map + stored with a resource that may be set by external tools + to store and retrieve arbitrary metadata. They are not queryable + and should be preserved when modifying objects. More info: + http://kubernetes.io/docs/user-guide/annotations' + type: object + labels: + additionalProperties: + type: string + description: 'Labels Map of string keys and values that can + be used to organize and categorize (scope and select) objects. + May match selectors of replication controllers and services. + More info: http://kubernetes.io/docs/user-guide/labels' + type: object + name: + description: 'Name must be unique within a namespace. Is required + when creating resources, although some resources may allow + a client to request the generation of an appropriate name + automatically. Name is primarily intended for creation idempotence + and configuration definition. Cannot be updated. More info: + http://kubernetes.io/docs/user-guide/identifiers#names' + type: string + type: object + spec: + description: 'ServiceSpec describes the attributes that a user + creates on a service. More info: https://kubernetes.io/docs/concepts/services-networking/service/' + type: object + x-kubernetes-preserve-unknown-fields: true + required: + - spec + type: object + startupProbe: + description: StartupProbe that will be added to CRD pod + type: object + x-kubernetes-preserve-unknown-fields: true + terminationGracePeriodSeconds: + description: TerminationGracePeriodSeconds period for container graceful + termination + format: int64 + type: integer + tolerations: + description: Tolerations If specified, the pod's tolerations. + 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: TopologySpreadConstraints embedded kubernetes pod configuration + option, controls how pods are spread across your cluster among failure-domains + such as regions, zones, nodes, and other user-defined topology domains + https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/ + items: + description: TopologySpreadConstraint specifies how to spread matching + pods among the given topology. + required: + - maxSkew + - topologyKey + - whenUnsatisfiable + type: object + x-kubernetes-preserve-unknown-fields: true + type: array + updateStrategy: + description: UpdateStrategy - overrides default update strategy. + enum: + - Recreate + - RollingUpdate + type: string + volumeMounts: + description: VolumeMounts allows configuration of additional VolumeMounts + on the output Deployment definition. VolumeMounts specified will + be appended to other VolumeMounts in the VMAlert container, that + are generated as a result of StorageSpec objects. + items: + description: VolumeMount describes a mounting of a Volume within + a container. + properties: + mountPath: + description: Path within the container at which the volume should + be mounted. Must not contain ':'. + type: string + mountPropagation: + description: mountPropagation determines how mounts are propagated + from the host to container and the other way around. When + not set, MountPropagationNone is used. This field is beta + in 1.10. + type: string + name: + description: This must match the Name of a Volume. + type: string + readOnly: + description: Mounted read-only if true, read-write otherwise + (false or unspecified). Defaults to false. + type: boolean + subPath: + description: Path within the volume from which the container's + volume should be mounted. Defaults to "" (volume's root). + type: string + subPathExpr: + description: Expanded path within the volume from which the + container's volume should be mounted. Behaves similarly to + SubPath but environment variable references $(VAR_NAME) are + expanded using the container's environment. Defaults to "" + (volume's root). SubPathExpr and SubPath are mutually exclusive. + type: string + required: + - mountPath + - name + type: object + type: array + volumes: + description: Volumes allows configuration of additional volumes on + the output Deployment definition. Volumes specified will be appended + to other volumes that are generated as a result of StorageSpec objects. + items: + description: Volume represents a named volume in a pod that may + be accessed by any container in the pod. + required: + - name + type: object + x-kubernetes-preserve-unknown-fields: true + type: array + required: + - datasource + type: object + status: + description: VMAlertStatus defines the observed state of VMAlert + properties: + availableReplicas: + description: AvailableReplicas Total number of available pods (ready + for at least minReadySeconds) targeted by this VMAlert cluster. + format: int32 + type: integer + replicas: + description: ReplicaCount Total number of non-terminated pods targeted + by this VMAlert cluster (their labels match the selector). + format: int32 + type: integer + unavailableReplicas: + description: UnavailableReplicas Total number of unavailable pods + targeted by this VMAlert cluster. + format: int32 + type: integer + updatedReplicas: + description: UpdatedReplicas Total number of non-terminated pods targeted + by this VMAlert cluster that have the desired version spec. + format: int32 + type: integer + required: + - availableReplicas + - replicas + - unavailableReplicas + - updatedReplicas + 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.12.1 + name: vmauths.operator.victoriametrics.com +spec: + group: operator.victoriametrics.com + names: + kind: VMAuth + listKind: VMAuthList + plural: vmauths + singular: vmauth + scope: Namespaced + versions: + - name: v1beta1 + schema: + openAPIV3Schema: + description: VMAuth is the Schema for the vmauths 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: VMAuthSpec defines the desired state of VMAuth + properties: + '-': + description: ParsingError contents error with context if operator + was failed to parse json object from kubernetes api server + type: string + affinity: + description: Affinity If specified, the pod's scheduling constraints. + type: object + x-kubernetes-preserve-unknown-fields: true + configMaps: + description: ConfigMaps is a list of ConfigMaps in the same namespace + as the VMAuth object, which shall be mounted into the VMAuth Pods. + items: + type: string + type: array + containers: + description: Containers property allows to inject additions sidecars + or to patch existing containers. It can be useful for proxies, backup, + etc. + items: + description: A single application container that you want to run + within a pod. + required: + - name + type: object + x-kubernetes-preserve-unknown-fields: true + type: array + dnsConfig: + description: Specifies the DNS parameters of a pod. Parameters specified + here will be merged to the generated DNS configuration based on + DNSPolicy. + items: + x-kubernetes-preserve-unknown-fields: true + properties: + nameservers: + description: A list of DNS name server IP addresses. This will + be appended to the base nameservers generated from DNSPolicy. + Duplicated nameservers will be removed. + items: + type: string + type: array + options: + description: A list of DNS resolver options. This will be merged + with the base options generated from DNSPolicy. Duplicated entries + will be removed. Resolution options given in Options will override + those that appear in the base DNSPolicy. + items: + description: PodDNSConfigOption defines DNS resolver options + of a pod. + properties: + name: + description: Required. + type: string + value: + type: string + type: object + type: array + searches: + description: A list of DNS search domains for host-name lookup. + This will be appended to the base search paths generated from + DNSPolicy. Duplicated search paths will be removed. + items: + type: string + type: array + type: object + dnsPolicy: + description: DNSPolicy sets DNS policy for the pod + type: string + extraArgs: + additionalProperties: + type: string + description: 'ExtraArgs that will be passed to VMAuth pod for example + remoteWrite.tmpDataPath: /tmp' + type: object + extraEnvs: + description: ExtraEnvs that will be added to VMAuth pod + 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 + required: + - name + type: object + x-kubernetes-preserve-unknown-fields: true + type: array + hostAliases: + description: HostAliases provides mapping for ip and hostname, that + would be propagated to pod, cannot be used with HostNetwork. + items: + description: HostAlias holds the mapping between IP and hostnames + that will be injected as an entry in the pod's hosts file. + properties: + hostnames: + description: Hostnames for the above IP address. + items: + type: string + type: array + ip: + description: IP address of the host file entry. + type: string + type: object + type: array + hostNetwork: + description: HostNetwork controls whether the pod may use the node + network namespace + type: boolean + image: + description: Image - docker image settings for VMAuth if no specified + operator uses default config version + properties: + pullPolicy: + description: PullPolicy describes how to pull docker image + type: string + repository: + description: Repository contains name of docker image + it's repository + if needed + type: string + tag: + description: Tag contains desired docker image version + type: string + type: object + imagePullSecrets: + description: ImagePullSecrets An optional list of references to secrets + in the same namespace to use for pulling images from registries + see https://kubernetes.io/docs/concepts/containers/images/#referring-to-an-imagepullsecrets-on-a-pod + items: + description: LocalObjectReference contains enough information to + let you locate the referenced object inside the same namespace. + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + x-kubernetes-map-type: atomic + type: array + ingress: + description: Ingress enables ingress configuration for VMAuth. + properties: + annotations: + additionalProperties: + type: string + description: 'Annotations is an unstructured key value map stored + with a resource that may be set by external tools to store and + retrieve arbitrary metadata. They are not queryable and should + be preserved when modifying objects. More info: http://kubernetes.io/docs/user-guide/annotations' + type: object + class_name: + description: ClassName defines ingress class name for VMAuth + type: string + extraRules: + description: ExtraRules - additional rules for ingress, must be + checked for correctness by user. + items: + description: IngressRule represents the rules mapping the paths + under a specified host to the related backend services. Incoming + requests are first evaluated for a host match, then routed + to the backend associated with the matching IngressRuleValue. + properties: + host: + description: "Host is the fully qualified domain name of + a network host, as defined by RFC 3986. Note the following + deviations from the \"host\" part of the URI as defined + in RFC 3986: 1. IPs are not allowed. Currently an IngressRuleValue + can only apply to the IP in the Spec of the parent Ingress. + 2. The `:` delimiter is not respected because ports are + not allowed. Currently the port of an Ingress is implicitly + :80 for http and :443 for https. Both these may change + in the future. Incoming requests are matched against the + host before the IngressRuleValue. If the host is unspecified, + the Ingress routes all traffic based on the specified + IngressRuleValue. \n Host can be \"precise\" which is + a domain name without the terminating dot of a network + host (e.g. \"foo.bar.com\") or \"wildcard\", which is + a domain name prefixed with a single wildcard label (e.g. + \"*.foo.com\"). The wildcard character '*' must appear + by itself as the first DNS label and matches only a single + label. You cannot have a wildcard label by itself (e.g. + Host == \"*\"). Requests will be matched against the Host + field in the following way: 1. If Host is precise, the + request matches this rule if the http host header is equal + to Host. 2. If Host is a wildcard, then the request matches + this rule if the http host header is to equal to the suffix + (removing the first label) of the wildcard rule." + type: string + http: + description: 'HTTPIngressRuleValue is a list of http selectors + pointing to backends. In the example: http:///? + -> backend where where parts of the url correspond to + RFC 3986, this resource will be used to match against + everything after the last ''/'' and before the first ''?'' + or ''#''.' + properties: + paths: + description: A collection of paths that map requests + to backends. + items: + description: HTTPIngressPath associates a path with + a backend. Incoming urls matching the path are forwarded + to the backend. + properties: + backend: + description: Backend defines the referenced service + endpoint to which the traffic will be forwarded + to. + properties: + resource: + description: Resource is an ObjectRef to another + Kubernetes resource in the namespace of + the Ingress object. If resource is specified, + a service.Name and service.Port must not + be specified. This is a mutually exclusive + setting with "Service". + properties: + apiGroup: + description: APIGroup is the group for + the resource being referenced. If APIGroup + is not specified, the specified Kind + must be in the core API group. For any + other third-party types, APIGroup is + required. + type: string + kind: + description: Kind is the type of resource + being referenced + type: string + name: + description: Name is the name of resource + being referenced + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + service: + description: Service references a Service + as a Backend. This is a mutually exclusive + setting with "Resource". + properties: + name: + description: Name is the referenced service. + The service must exist in the same namespace + as the Ingress object. + type: string + port: + description: Port of the referenced service. + A port name or port number is required + for a IngressServiceBackend. + properties: + name: + description: Name is the name of the + port on the Service. This is a mutually + exclusive setting with "Number". + type: string + number: + description: Number is the numerical + port number (e.g. 80) on the Service. + This is a mutually exclusive setting + with "Name". + format: int32 + type: integer + type: object + required: + - name + type: object + type: object + path: + description: Path is matched against the path + of an incoming request. Currently it can contain + characters disallowed from the conventional + "path" part of a URL as defined by RFC 3986. + Paths must begin with a '/' and must be present + when using PathType with value "Exact" or "Prefix". + type: string + pathType: + description: 'PathType determines the interpretation + of the Path matching. PathType can be one of + the following values: * Exact: Matches the URL + path exactly. * Prefix: Matches based on a URL + path prefix split by ''/''. Matching is done + on a path element by element basis. A path element + refers is the list of labels in the path split + by the ''/'' separator. A request is a match + for path p if every p is an element-wise prefix + of p of the request path. Note that if the last + element of the path is a substring of the last + element in request path, it is not a match (e.g. + /foo/bar matches /foo/bar/baz, but does not + match /foo/barbaz). * ImplementationSpecific: + Interpretation of the Path matching is up to + the IngressClass. Implementations can treat + this as a separate PathType or treat it identically + to Prefix or Exact path types. Implementations + are required to support all path types.' + type: string + required: + - backend + - pathType + type: object + type: array + x-kubernetes-list-type: atomic + required: + - paths + type: object + type: object + type: array + extraTls: + description: ExtraTLS - additional TLS configuration for ingress + must be checked for correctness by user. + items: + description: IngressTLS describes the transport layer security + associated with an Ingress. + properties: + hosts: + description: Hosts are a list of hosts included in the TLS + certificate. The values in this list must match the name/s + used in the tlsSecret. Defaults to the wildcard host setting + for the loadbalancer controller fulfilling this Ingress, + if left unspecified. + items: + type: string + type: array + x-kubernetes-list-type: atomic + secretName: + description: SecretName is the name of the secret used to + terminate TLS traffic on port 443. Field is left optional + to allow TLS routing based on SNI hostname alone. If the + SNI host in a listener conflicts with the "Host" header + field used by an IngressRule, the SNI host is used for + termination and value of the Host header is used for routing. + type: string + type: object + type: array + host: + description: Host defines ingress host parameter for default rule + It will be used, only if TlsHosts is empty + type: string + labels: + additionalProperties: + type: string + description: 'Labels Map of string keys and values that can be + used to organize and categorize (scope and select) objects. + May match selectors of replication controllers and services. + More info: http://kubernetes.io/docs/user-guide/labels' + type: object + name: + description: 'Name must be unique within a namespace. Is required + when creating resources, although some resources may allow a + client to request the generation of an appropriate name automatically. + Name is primarily intended for creation idempotence and configuration + definition. Cannot be updated. More info: http://kubernetes.io/docs/user-guide/identifiers#names' + type: string + tlsHosts: + description: TlsHosts configures TLS access for ingress, tlsSecretName + must be defined for it. + items: + type: string + type: array + tlsSecretName: + description: TlsSecretName defines secretname at the VMAuth namespace + with cert and key https://kubernetes.io/docs/concepts/services-networking/ingress/#tls + type: string + type: object + initContainers: + description: 'InitContainers allows adding initContainers to the pod + definition. Those can be used to e.g. fetch secrets for injection + into the vmSingle configuration from external sources. Any errors + during the execution of an initContainer will lead to a restart + of the Pod. More info: https://kubernetes.io/docs/concepts/workloads/pods/init-containers/ + Using initContainers for any use case other then secret fetching + is entirely outside the scope of what the maintainers will support + and by doing so, you accept that this behaviour may break at any + time without notice.' + items: + description: A single application container that you want to run + within a pod. + required: + - name + type: object + x-kubernetes-preserve-unknown-fields: true + type: array + livenessProbe: + description: LivenessProbe that will be added CRD pod + type: object + x-kubernetes-preserve-unknown-fields: true + logFormat: + description: LogFormat for VMAuth to be configured with. + enum: + - default + - json + type: string + logLevel: + description: LogLevel for victoria metrics single to be configured + with. + enum: + - INFO + - WARN + - ERROR + - FATAL + - PANIC + type: string + nodeSelector: + additionalProperties: + type: string + description: NodeSelector Define which Nodes the Pods are scheduled + on. + type: object + podDisruptionBudget: + description: PodDisruptionBudget created by operator + properties: + maxUnavailable: + anyOf: + - type: integer + - type: string + description: An eviction is allowed if at most "maxUnavailable" + pods selected by "selector" are unavailable after the eviction, + i.e. even in absence of the evicted pod. For example, one can + prevent all voluntary evictions by specifying 0. This is a mutually + exclusive setting with "minAvailable". + x-kubernetes-int-or-string: true + minAvailable: + anyOf: + - type: integer + - type: string + description: An eviction is allowed if at least "minAvailable" + pods selected by "selector" will still be available after the + eviction, i.e. even in the absence of the evicted pod. So for + example you can prevent all voluntary evictions by specifying + "100%". + x-kubernetes-int-or-string: true + selectorLabels: + additionalProperties: + type: string + description: replaces default labels selector generated by operator + it's useful when you need to create custom budget + type: object + type: object + podMetadata: + description: PodMetadata configures Labels and Annotations which are + propagated to the VMAuth pods. + properties: + annotations: + additionalProperties: + type: string + description: 'Annotations is an unstructured key value map stored + with a resource that may be set by external tools to store and + retrieve arbitrary metadata. They are not queryable and should + be preserved when modifying objects. More info: http://kubernetes.io/docs/user-guide/annotations' + type: object + labels: + additionalProperties: + type: string + description: 'Labels Map of string keys and values that can be + used to organize and categorize (scope and select) objects. + May match selectors of replication controllers and services. + More info: http://kubernetes.io/docs/user-guide/labels' + type: object + name: + description: 'Name must be unique within a namespace. Is required + when creating resources, although some resources may allow a + client to request the generation of an appropriate name automatically. + Name is primarily intended for creation idempotence and configuration + definition. Cannot be updated. More info: http://kubernetes.io/docs/user-guide/identifiers#names' + type: string + type: object + podSecurityPolicyName: + description: PodSecurityPolicyName - defines name for podSecurityPolicy + in case of empty value, prefixedName will be used. + type: string + port: + description: Port listen port + type: string + priorityClassName: + description: PriorityClassName assigned to the Pods + type: string + readinessGates: + description: ReadinessGates defines pod readiness gates + items: + description: PodReadinessGate contains the reference to a pod condition + properties: + conditionType: + description: ConditionType refers to a condition in the pod's + condition list with matching type. + type: string + required: + - conditionType + type: object + type: array + readinessProbe: + description: ReadinessProbe that will be added CRD pod + type: object + x-kubernetes-preserve-unknown-fields: true + replicaCount: + description: ReplicaCount is the expected size of the VMAuth + format: int32 + type: integer + resources: + description: Resources container resource request and limits, https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + if not defined default resources from operator config will be used + properties: + 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. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + runtimeClassName: + description: RuntimeClassName - defines runtime class for kubernetes + pod. https://kubernetes.io/docs/concepts/containers/runtime-class/ + type: string + schedulerName: + description: SchedulerName - defines kubernetes scheduler name + type: string + secrets: + description: Secrets is a list of Secrets in the same namespace as + the VMAuth object, which shall be mounted into the VMAuth Pods. + items: + type: string + type: array + securityContext: + description: SecurityContext holds pod-level security attributes and + common container settings. This defaults to the default PodSecurityContext. + type: object + x-kubernetes-preserve-unknown-fields: true + selectAllByDefault: + description: 'SelectAllByDefault changes default behavior for empty + CRD selectors, such userSelector. with selectAllByDefault: true + and empty userSelector and userNamespaceSelector Operator selects + all exist users with selectAllByDefault: false - selects nothing' + type: boolean + serviceAccountName: + description: ServiceAccountName is the name of the ServiceAccount + to use to run the VMAuth Pods. + type: string + serviceScrapeSpec: + description: ServiceScrapeSpec that will be added to vmauth VMServiceScrape + spec + required: + - endpoints + type: object + x-kubernetes-preserve-unknown-fields: true + serviceSpec: + description: ServiceSpec that will be added to vmsingle service spec + properties: + metadata: + description: EmbeddedObjectMetadata defines objectMeta for additional + service. + properties: + annotations: + additionalProperties: + type: string + description: 'Annotations is an unstructured key value map + stored with a resource that may be set by external tools + to store and retrieve arbitrary metadata. They are not queryable + and should be preserved when modifying objects. More info: + http://kubernetes.io/docs/user-guide/annotations' + type: object + labels: + additionalProperties: + type: string + description: 'Labels Map of string keys and values that can + be used to organize and categorize (scope and select) objects. + May match selectors of replication controllers and services. + More info: http://kubernetes.io/docs/user-guide/labels' + type: object + name: + description: 'Name must be unique within a namespace. Is required + when creating resources, although some resources may allow + a client to request the generation of an appropriate name + automatically. Name is primarily intended for creation idempotence + and configuration definition. Cannot be updated. More info: + http://kubernetes.io/docs/user-guide/identifiers#names' + type: string + type: object + spec: + description: 'ServiceSpec describes the attributes that a user + creates on a service. More info: https://kubernetes.io/docs/concepts/services-networking/service/' + type: object + x-kubernetes-preserve-unknown-fields: true + required: + - spec + type: object + startupProbe: + description: StartupProbe that will be added to CRD pod + type: object + x-kubernetes-preserve-unknown-fields: true + terminationGracePeriodSeconds: + description: TerminationGracePeriodSeconds period for container graceful + termination + format: int64 + type: integer + tolerations: + description: Tolerations If specified, the pod's tolerations. + 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: TopologySpreadConstraints embedded kubernetes pod configuration + option, controls how pods are spread across your cluster among failure-domains + such as regions, zones, nodes, and other user-defined topology domains + https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/ + items: + description: TopologySpreadConstraint specifies how to spread matching + pods among the given topology. + required: + - maxSkew + - topologyKey + - whenUnsatisfiable + type: object + x-kubernetes-preserve-unknown-fields: true + type: array + unauthorizedAccessConfig: + description: UnauthorizedAccessConfig configures access for un authorized + users + items: + description: VMAuthUnauthorizedPath defines url_map for unauthorized + access + properties: + ip_filters: + description: IPFilters defines filter for src ip address enterprise + only + properties: + allow_list: + items: + type: string + type: array + deny_list: + items: + type: string + type: array + type: object + src_paths: + description: Paths src request paths + items: + type: string + type: array + url_prefix: + description: URLs defines url_prefix for dst routing + items: + type: string + type: array + type: object + type: array + userNamespaceSelector: + description: UserNamespaceSelector Namespaces to be selected for VMAuth + discovery. Works in combination with Selector. NamespaceSelector + nil - only objects at VMAuth namespace. Selector nil - only objects + at NamespaceSelector namespaces. If both nil - behaviour controlled + by selectAllByDefault + 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 + required: + - key + - operator + type: object + type: array + 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 + userSelector: + description: UserSelector defines VMUser to be selected for config + file generation. Works in combination with NamespaceSelector. NamespaceSelector + nil - only objects at VMAuth namespace. If both nil - behaviour + controlled by selectAllByDefault + 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 + required: + - key + - operator + type: object + type: array + 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 + volumeMounts: + description: VolumeMounts allows configuration of additional VolumeMounts + on the output Deployment definition. VolumeMounts specified will + be appended to other VolumeMounts in the VMAuth container, that + are generated as a result of StorageSpec objects. + items: + description: VolumeMount describes a mounting of a Volume within + a container. + properties: + mountPath: + description: Path within the container at which the volume should + be mounted. Must not contain ':'. + type: string + mountPropagation: + description: mountPropagation determines how mounts are propagated + from the host to container and the other way around. When + not set, MountPropagationNone is used. This field is beta + in 1.10. + type: string + name: + description: This must match the Name of a Volume. + type: string + readOnly: + description: Mounted read-only if true, read-write otherwise + (false or unspecified). Defaults to false. + type: boolean + subPath: + description: Path within the volume from which the container's + volume should be mounted. Defaults to "" (volume's root). + type: string + subPathExpr: + description: Expanded path within the volume from which the + container's volume should be mounted. Behaves similarly to + SubPath but environment variable references $(VAR_NAME) are + expanded using the container's environment. Defaults to "" + (volume's root). SubPathExpr and SubPath are mutually exclusive. + type: string + required: + - mountPath + - name + type: object + type: array + volumes: + description: Volumes allows configuration of additional volumes on + the output deploy definition. Volumes specified will be appended + to other volumes that are generated as a result of StorageSpec objects. + items: + description: Volume represents a named volume in a pod that may + be accessed by any container in the pod. + required: + - name + type: object + x-kubernetes-preserve-unknown-fields: true + type: array + type: object + status: + description: VMAuthStatus defines the observed state of VMAuth + 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.12.1 + name: vmclusters.operator.victoriametrics.com +spec: + group: operator.victoriametrics.com + names: + kind: VMCluster + listKind: VMClusterList + plural: vmclusters + singular: vmcluster + scope: Namespaced + versions: + - additionalPrinterColumns: + - description: replicas of VMInsert + jsonPath: .spec.vminsert.replicaCount + name: Insert Count + type: string + - description: replicas of VMStorage + jsonPath: .spec.vmstorage.replicaCount + name: Storage Count + type: string + - description: replicas of VMSelect + jsonPath: .spec.vmselect.replicaCount + name: Select Count + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + - description: Current status of cluster + jsonPath: .status.clusterStatus + name: Status + type: string + name: v1beta1 + schema: + openAPIV3Schema: + description: VMCluster is fast, cost-effective and scalable time-series database. + Cluster version with + 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: VMClusterSpec defines the desired state of VMCluster + properties: + '-': + description: ParsingError contents error with context if operator + was failed to parse json object from kubernetes api server + type: string + clusterVersion: + description: ClusterVersion defines default images tag for all components. + it can be overwritten with component specific image.tag value. + type: string + imagePullSecrets: + description: ImagePullSecrets An optional list of references to secrets + in the same namespace to use for pulling images from registries + see https://kubernetes.io/docs/concepts/containers/images/#referring-to-an-imagepullsecrets-on-a-pod + items: + description: LocalObjectReference contains enough information to + let you locate the referenced object inside the same namespace. + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + x-kubernetes-map-type: atomic + type: array + podSecurityPolicyName: + description: PodSecurityPolicyName - defines name for podSecurityPolicy + in case of empty value, prefixedName will be used. + type: string + replicationFactor: + description: ReplicationFactor defines how many copies of data make + among distinct storage nodes + format: int32 + type: integer + retentionPeriod: + description: RetentionPeriod for the stored metrics Note VictoriaMetrics + has data/ and indexdb/ folders metrics from data/ removed eventually + as soon as partition leaves retention period reverse index data + at indexdb rotates once at the half of configured retention period + https://docs.victoriametrics.com/Single-server-VictoriaMetrics.html#retention + type: string + serviceAccountName: + description: ServiceAccountName is the name of the ServiceAccount + to use to run the VMSelect, VMStorage and VMInsert Pods. + type: string + vminsert: + properties: + affinity: + description: Affinity If specified, the pod's scheduling constraints. + type: object + x-kubernetes-preserve-unknown-fields: true + clusterNativeListenPort: + description: 'ClusterNativePort for multi-level cluster setup. + More details: https://docs.victoriametrics.com/Cluster-VictoriaMetrics.html#multi-level-cluster-setup' + type: string + configMaps: + description: ConfigMaps is a list of ConfigMaps in the same namespace + as the VMSelect object, which shall be mounted into the VMSelect + Pods. The ConfigMaps are mounted into /etc/vm/configs/. + items: + type: string + type: array + containers: + description: Containers property allows to inject additions sidecars + or to patch existing containers. It can be useful for proxies, + backup, etc. + items: + description: A single application container that you want to + run within a pod. + required: + - name + type: object + x-kubernetes-preserve-unknown-fields: true + type: array + dnsConfig: + description: Specifies the DNS parameters of a pod. Parameters + specified here will be merged to the generated DNS configuration + based on DNSPolicy. + items: + x-kubernetes-preserve-unknown-fields: true + properties: + nameservers: + description: A list of DNS name server IP addresses. This + will be appended to the base nameservers generated from + DNSPolicy. Duplicated nameservers will be removed. + items: + type: string + type: array + options: + description: A list of DNS resolver options. This will be + merged with the base options generated from DNSPolicy. Duplicated + entries will be removed. Resolution options given in Options + will override those that appear in the base DNSPolicy. + items: + description: PodDNSConfigOption defines DNS resolver options + of a pod. + properties: + name: + description: Required. + type: string + value: + type: string + type: object + type: array + searches: + description: A list of DNS search domains for host-name lookup. + This will be appended to the base search paths generated + from DNSPolicy. Duplicated search paths will be removed. + items: + type: string + type: array + type: object + dnsPolicy: + description: DNSPolicy sets DNS policy for the pod + type: string + extraArgs: + additionalProperties: + type: string + type: object + extraEnvs: + description: ExtraEnvs that will be added to VMSelect pod + 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 + required: + - name + type: object + x-kubernetes-preserve-unknown-fields: true + type: array + hostNetwork: + description: HostNetwork controls whether the pod may use the + node network namespace + type: boolean + hpa: + description: HPA defines kubernetes PodAutoScaling configuration + version 2. + type: object + x-kubernetes-preserve-unknown-fields: true + image: + description: Image - docker image settings for VMInsert + properties: + pullPolicy: + description: PullPolicy describes how to pull docker image + type: string + repository: + description: Repository contains name of docker image + it's + repository if needed + type: string + tag: + description: Tag contains desired docker image version + type: string + type: object + initContainers: + description: 'InitContainers allows adding initContainers to the + pod definition. Those can be used to e.g. fetch secrets for + injection into the VMSelect configuration from external sources. + Any errors during the execution of an initContainer will lead + to a restart of the Pod. More info: https://kubernetes.io/docs/concepts/workloads/pods/init-containers/ + Using initContainers for any use case other then secret fetching + is entirely outside the scope of what the maintainers will support + and by doing so, you accept that this behaviour may break at + any time without notice.' + items: + description: A single application container that you want to + run within a pod. + required: + - name + type: object + x-kubernetes-preserve-unknown-fields: true + type: array + insertPorts: + description: InsertPorts - additional listen ports for data ingestion. + properties: + graphitePort: + description: GraphitePort listen port + type: string + influxPort: + description: InfluxPort listen port + type: string + openTSDBHTTPPort: + description: OpenTSDBHTTPPort for http connections. + type: string + openTSDBPort: + description: OpenTSDBPort for tcp and udp listen + type: string + type: object + livenessProbe: + description: LivenessProbe that will be added CRD pod + type: object + x-kubernetes-preserve-unknown-fields: true + logFormat: + description: LogFormat for VMSelect to be configured with. default + or json + enum: + - default + - json + type: string + logLevel: + description: LogLevel for VMSelect to be configured with. + enum: + - INFO + - WARN + - ERROR + - FATAL + - PANIC + type: string + name: + description: Name is deprecated and will be removed at 0.22.0 + release + type: string + nodeSelector: + additionalProperties: + type: string + description: NodeSelector Define which Nodes the Pods are scheduled + on. + type: object + podDisruptionBudget: + description: PodDisruptionBudget created by operator + properties: + maxUnavailable: + anyOf: + - type: integer + - type: string + description: An eviction is allowed if at most "maxUnavailable" + pods selected by "selector" are unavailable after the eviction, + i.e. even in absence of the evicted pod. For example, one + can prevent all voluntary evictions by specifying 0. This + is a mutually exclusive setting with "minAvailable". + x-kubernetes-int-or-string: true + minAvailable: + anyOf: + - type: integer + - type: string + description: An eviction is allowed if at least "minAvailable" + pods selected by "selector" will still be available after + the eviction, i.e. even in the absence of the evicted pod. So + for example you can prevent all voluntary evictions by specifying + "100%". + x-kubernetes-int-or-string: true + selectorLabels: + additionalProperties: + type: string + description: replaces default labels selector generated by + operator it's useful when you need to create custom budget + type: object + type: object + podMetadata: + description: PodMetadata configures Labels and Annotations which + are propagated to the VMSelect pods. + properties: + annotations: + additionalProperties: + type: string + description: 'Annotations is an unstructured key value map + stored with a resource that may be set by external tools + to store and retrieve arbitrary metadata. They are not queryable + and should be preserved when modifying objects. More info: + http://kubernetes.io/docs/user-guide/annotations' + type: object + labels: + additionalProperties: + type: string + description: 'Labels Map of string keys and values that can + be used to organize and categorize (scope and select) objects. + May match selectors of replication controllers and services. + More info: http://kubernetes.io/docs/user-guide/labels' + type: object + name: + description: 'Name must be unique within a namespace. Is required + when creating resources, although some resources may allow + a client to request the generation of an appropriate name + automatically. Name is primarily intended for creation idempotence + and configuration definition. Cannot be updated. More info: + http://kubernetes.io/docs/user-guide/identifiers#names' + type: string + type: object + port: + description: Port listen port + type: string + priorityClassName: + description: Priority class assigned to the Pods + type: string + readinessGates: + description: ReadinessGates defines pod readiness gates + items: + description: PodReadinessGate contains the reference to a pod + condition + properties: + conditionType: + description: ConditionType refers to a condition in the + pod's condition list with matching type. + type: string + required: + - conditionType + type: object + type: array + readinessProbe: + description: ReadinessProbe that will be added CRD pod + type: object + x-kubernetes-preserve-unknown-fields: true + replicaCount: + description: ReplicaCount is the expected size of the VMInsert + cluster. The controller will eventually make the size of the + running cluster equal to the expected size. + format: int32 + type: integer + resources: + description: Resources container resource request and limits, + https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + properties: + 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. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + rollingUpdate: + description: RollingUpdate - overrides deployment update params. + properties: + maxSurge: + anyOf: + - type: integer + - type: string + description: 'The maximum number of pods that can be scheduled + above the desired number of pods. Value can be an absolute + number (ex: 5) or a percentage of desired pods (ex: 10%). + This can not be 0 if MaxUnavailable is 0. Absolute number + is calculated from percentage by rounding up. Defaults to + 25%. Example: when this is set to 30%, the new ReplicaSet + can be scaled up immediately when the rolling update starts, + such that the total number of old and new pods do not exceed + 130% of desired pods. Once old pods have been killed, new + ReplicaSet can be scaled up further, ensuring that total + number of pods running at any time during the update is + at most 130% of desired pods.' + x-kubernetes-int-or-string: true + maxUnavailable: + anyOf: + - type: integer + - type: string + description: 'The maximum number of pods that can be unavailable + during the update. Value can be an absolute number (ex: + 5) or a percentage of desired pods (ex: 10%). Absolute number + is calculated from percentage by rounding down. This can + not be 0 if MaxSurge is 0. Defaults to 25%. Example: when + this is set to 30%, the old ReplicaSet can be scaled down + to 70% of desired pods immediately when the rolling update + starts. Once new pods are ready, old ReplicaSet can be scaled + down further, followed by scaling up the new ReplicaSet, + ensuring that the total number of pods available at all + times during the update is at least 70% of desired pods.' + x-kubernetes-int-or-string: true + type: object + runtimeClassName: + description: RuntimeClassName - defines runtime class for kubernetes + pod. https://kubernetes.io/docs/concepts/containers/runtime-class/ + type: string + schedulerName: + description: SchedulerName - defines kubernetes scheduler name + type: string + secrets: + description: Secrets is a list of Secrets in the same namespace + as the VMSelect object, which shall be mounted into the VMSelect + Pods. The Secrets are mounted into /etc/vm/secrets/. + items: + type: string + type: array + securityContext: + description: SecurityContext holds pod-level security attributes + and common container settings. This defaults to the default + PodSecurityContext. + type: object + x-kubernetes-preserve-unknown-fields: true + serviceScrapeSpec: + description: ServiceScrapeSpec that will be added to vminsert + VMServiceScrape spec + required: + - endpoints + type: object + x-kubernetes-preserve-unknown-fields: true + serviceSpec: + description: ServiceSpec that will be added to vminsert service + spec + properties: + metadata: + description: EmbeddedObjectMetadata defines objectMeta for + additional service. + properties: + annotations: + additionalProperties: + type: string + description: 'Annotations is an unstructured key value + map stored with a resource that may be set by external + tools to store and retrieve arbitrary metadata. They + are not queryable and should be preserved when modifying + objects. More info: http://kubernetes.io/docs/user-guide/annotations' + type: object + labels: + additionalProperties: + type: string + description: 'Labels Map of string keys and values that + can be used to organize and categorize (scope and select) + objects. May match selectors of replication controllers + and services. More info: http://kubernetes.io/docs/user-guide/labels' + type: object + name: + description: 'Name must be unique within a namespace. + Is required when creating resources, although some resources + may allow a client to request the generation of an appropriate + name automatically. Name is primarily intended for creation + idempotence and configuration definition. Cannot be + updated. More info: http://kubernetes.io/docs/user-guide/identifiers#names' + type: string + type: object + spec: + description: 'ServiceSpec describes the attributes that a + user creates on a service. More info: https://kubernetes.io/docs/concepts/services-networking/service/' + type: object + x-kubernetes-preserve-unknown-fields: true + required: + - spec + type: object + startupProbe: + description: StartupProbe that will be added to CRD pod + type: object + x-kubernetes-preserve-unknown-fields: true + terminationGracePeriodSeconds: + description: TerminationGracePeriodSeconds period for container + graceful termination + format: int64 + type: integer + tolerations: + description: Tolerations If specified, the pod's tolerations. + 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: TopologySpreadConstraints embedded kubernetes pod + configuration option, controls how pods are spread across your + cluster among failure-domains such as regions, zones, nodes, + and other user-defined topology domains https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/ + items: + description: TopologySpreadConstraint specifies how to spread + matching pods among the given topology. + required: + - maxSkew + - topologyKey + - whenUnsatisfiable + type: object + x-kubernetes-preserve-unknown-fields: true + type: array + updateStrategy: + description: UpdateStrategy - overrides default update strategy. + enum: + - Recreate + - RollingUpdate + type: string + volumeMounts: + description: VolumeMounts allows configuration of additional VolumeMounts + on the output Deployment definition. VolumeMounts specified + will be appended to other VolumeMounts in the VMSelect container, + that are generated as a result of StorageSpec objects. + items: + description: VolumeMount describes a mounting of a Volume within + a container. + properties: + mountPath: + description: Path within the container at which the volume + should be mounted. Must not contain ':'. + type: string + mountPropagation: + description: mountPropagation determines how mounts are + propagated from the host to container and the other way + around. When not set, MountPropagationNone is used. This + field is beta in 1.10. + type: string + name: + description: This must match the Name of a Volume. + type: string + readOnly: + description: Mounted read-only if true, read-write otherwise + (false or unspecified). Defaults to false. + type: boolean + subPath: + description: Path within the volume from which the container's + volume should be mounted. Defaults to "" (volume's root). + type: string + subPathExpr: + description: Expanded path within the volume from which + the container's volume should be mounted. Behaves similarly + to SubPath but environment variable references $(VAR_NAME) + are expanded using the container's environment. Defaults + to "" (volume's root). SubPathExpr and SubPath are mutually + exclusive. + type: string + required: + - mountPath + - name + type: object + type: array + volumes: + description: Volumes allows configuration of additional volumes + on the output Deployment definition. Volumes specified will + be appended to other volumes that are generated as a result + of StorageSpec objects. + items: + description: Volume represents a named volume in a pod that + may be accessed by any container in the pod. + required: + - name + type: object + x-kubernetes-preserve-unknown-fields: true + type: array + required: + - replicaCount + type: object + vmselect: + properties: + affinity: + description: Affinity If specified, the pod's scheduling constraints. + type: object + x-kubernetes-preserve-unknown-fields: true + cacheMountPath: + description: CacheMountPath allows to add cache persistent for + VMSelect + type: string + claimTemplates: + description: ClaimTemplates allows adding additional VolumeClaimTemplates + for StatefulSet + items: + description: PersistentVolumeClaim is a user's request for and + claim to a persistent volume + 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: + description: 'Standard object''s metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata' + type: object + x-kubernetes-preserve-unknown-fields: true + spec: + description: 'spec defines the desired characteristics of + a volume requested by a pod author. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' + properties: + accessModes: + description: 'accessModes contains the desired access + modes the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' + items: + type: string + type: array + dataSource: + description: 'dataSource field can be used to specify + either: * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) + * An existing PVC (PersistentVolumeClaim) If the provisioner + or an external controller can support the specified + data source, it will create a new volume based on + the contents of the specified data source. If the + AnyVolumeDataSource feature gate is enabled, this + field will always have the same contents as the DataSourceRef + field.' + properties: + apiGroup: + description: APIGroup is the group for the resource + being referenced. If APIGroup is not specified, + the specified Kind must be in the core API group. + For any other third-party types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource being + referenced + type: string + name: + description: Name is the name of resource being + referenced + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + description: 'dataSourceRef specifies the object from + which to populate the volume with data, if a non-empty + volume is desired. This may be any local object from + a non-empty API group (non core object) or a PersistentVolumeClaim + object. When this field is specified, volume binding + will only succeed if the type of the specified object + matches some installed volume populator or dynamic + provisioner. This field will replace the functionality + of the DataSource field and as such if both fields + are non-empty, they must have the same value. For + backwards compatibility, both fields (DataSource and + DataSourceRef) will be set to the same value automatically + if one of them is empty and the other is non-empty. + There are two important differences between DataSource + and DataSourceRef: * While DataSource only allows + two specific types of objects, DataSourceRef allows + any non-core object, as well as PersistentVolumeClaim + objects. * While DataSource ignores disallowed values + (dropping them), DataSourceRef preserves all values, + and generates an error if a disallowed value is specified. + (Beta) Using this field requires the AnyVolumeDataSource + feature gate to be enabled.' + properties: + apiGroup: + description: APIGroup is the group for the resource + being referenced. If APIGroup is not specified, + the specified Kind must be in the core API group. + For any other third-party types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource being + referenced + type: string + name: + description: Name is the name of resource being + referenced + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + resources: + description: 'resources represents the minimum resources + the volume should have. If RecoverVolumeExpansionFailure + feature is enabled users are allowed to specify resource + requirements that are lower than previous value but + must still be higher than capacity recorded in the + status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' + properties: + 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. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + selector: + description: selector is a label query over volumes + to consider for binding. + 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 + required: + - key + - operator + type: object + type: array + 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 + storageClassName: + description: 'storageClassName is the name of the StorageClass + required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' + type: string + volumeMode: + description: volumeMode defines what type of volume + is required by the claim. Value of Filesystem is implied + when not included in claim spec. + type: string + volumeName: + description: volumeName is the binding reference to + the PersistentVolume backing this claim. + type: string + type: object + status: + description: 'status represents the current information/status + of a persistent volume claim. Read-only. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' + properties: + accessModes: + description: 'accessModes contains the actual access + modes the volume backing the PVC has. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' + items: + type: string + type: array + allocatedResources: + 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: allocatedResources is the storage resource + within AllocatedResources tracks the capacity allocated + to a PVC. It may be larger than the actual capacity + when a volume expansion operation is requested. For + storage quota, the larger value from allocatedResources + and PVC.spec.resources is used. If allocatedResources + is not set, PVC.spec.resources alone is used for quota + calculation. If a volume expansion capacity request + is lowered, allocatedResources is only lowered if + there are no expansion operations in progress and + if the actual volume capacity is equal or lower than + the requested capacity. This is an alpha field and + requires enabling RecoverVolumeExpansionFailure feature. + type: object + capacity: + 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: capacity represents the actual resources + of the underlying volume. + type: object + conditions: + description: conditions is the current Condition of + persistent volume claim. If underlying persistent + volume is being resized then the Condition will be + set to 'ResizeStarted'. + items: + description: PersistentVolumeClaimCondition contails + details about state of pvc + properties: + lastProbeTime: + description: lastProbeTime is the time we probed + the condition. + format: date-time + type: string + lastTransitionTime: + description: lastTransitionTime is the time the + condition transitioned from one status to another. + format: date-time + type: string + message: + description: message is the human-readable message + indicating details about last transition. + type: string + reason: + description: reason is a unique, this should be + a short, machine understandable string that + gives the reason for condition's last transition. + If it reports "ResizeStarted" that means the + underlying persistent volume is being resized. + type: string + status: + type: string + type: + description: PersistentVolumeClaimConditionType + is a valid value of PersistentVolumeClaimCondition.Type + type: string + required: + - status + - type + type: object + type: array + phase: + description: phase represents the current phase of PersistentVolumeClaim. + type: string + resizeStatus: + description: resizeStatus stores status of resize operation. + ResizeStatus is not set by default but when expansion + is complete resizeStatus is set to empty string by + resize controller or kubelet. This is an alpha field + and requires enabling RecoverVolumeExpansionFailure + feature. + type: string + type: object + type: object + type: array + clusterNativeListenPort: + description: 'ClusterNativePort for multi-level cluster setup. + More details: https://docs.victoriametrics.com/Cluster-VictoriaMetrics.html#multi-level-cluster-setup' + type: string + configMaps: + description: ConfigMaps is a list of ConfigMaps in the same namespace + as the VMSelect object, which shall be mounted into the VMSelect + Pods. The ConfigMaps are mounted into /etc/vm/configs/. + items: + type: string + type: array + containers: + description: Containers property allows to inject additions sidecars + or to patch existing containers. It can be useful for proxies, + backup, etc. + items: + description: A single application container that you want to + run within a pod. + required: + - name + type: object + x-kubernetes-preserve-unknown-fields: true + type: array + dnsConfig: + description: Specifies the DNS parameters of a pod. Parameters + specified here will be merged to the generated DNS configuration + based on DNSPolicy. + items: + x-kubernetes-preserve-unknown-fields: true + properties: + nameservers: + description: A list of DNS name server IP addresses. This + will be appended to the base nameservers generated from + DNSPolicy. Duplicated nameservers will be removed. + items: + type: string + type: array + options: + description: A list of DNS resolver options. This will be + merged with the base options generated from DNSPolicy. Duplicated + entries will be removed. Resolution options given in Options + will override those that appear in the base DNSPolicy. + items: + description: PodDNSConfigOption defines DNS resolver options + of a pod. + properties: + name: + description: Required. + type: string + value: + type: string + type: object + type: array + searches: + description: A list of DNS search domains for host-name lookup. + This will be appended to the base search paths generated + from DNSPolicy. Duplicated search paths will be removed. + items: + type: string + type: array + type: object + dnsPolicy: + description: DNSPolicy sets DNS policy for the pod + type: string + extraArgs: + additionalProperties: + type: string + type: object + extraEnvs: + description: ExtraEnvs that will be added to VMSelect pod + 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 + required: + - name + type: object + x-kubernetes-preserve-unknown-fields: true + type: array + hostNetwork: + description: HostNetwork controls whether the pod may use the + node network namespace + type: boolean + hpa: + description: Configures horizontal pod autoscaling. Note, enabling + this option disables vmselect to vmselect communication. In + most cases it's not an issue. + type: object + x-kubernetes-preserve-unknown-fields: true + image: + description: Image - docker image settings for VMSelect + properties: + pullPolicy: + description: PullPolicy describes how to pull docker image + type: string + repository: + description: Repository contains name of docker image + it's + repository if needed + type: string + tag: + description: Tag contains desired docker image version + type: string + type: object + initContainers: + description: 'InitContainers allows adding initContainers to the + pod definition. Those can be used to e.g. fetch secrets for + injection into the VMSelect configuration from external sources. + Any errors during the execution of an initContainer will lead + to a restart of the Pod. More info: https://kubernetes.io/docs/concepts/workloads/pods/init-containers/ + Using initContainers for any use case other then secret fetching + is entirely outside the scope of what the maintainers will support + and by doing so, you accept that this behaviour may break at + any time without notice.' + items: + description: A single application container that you want to + run within a pod. + required: + - name + type: object + x-kubernetes-preserve-unknown-fields: true + type: array + livenessProbe: + description: LivenessProbe that will be added CRD pod + type: object + x-kubernetes-preserve-unknown-fields: true + logFormat: + description: LogFormat for VMSelect to be configured with. default + or json + enum: + - default + - json + type: string + logLevel: + description: LogLevel for VMSelect to be configured with. + enum: + - INFO + - WARN + - ERROR + - FATAL + - PANIC + type: string + name: + description: Name is deprecated and will be removed at 0.22.0 + release + type: string + nodeSelector: + additionalProperties: + type: string + description: NodeSelector Define which Nodes the Pods are scheduled + on. + type: object + persistentVolume: + description: Storage - add persistent volume for cacheMounthPath + its useful for persistent cache use storage instead of persistentVolume. + properties: + disableMountSubPath: + description: 'Deprecated: subPath usage will be disabled by + default in a future release, this option will become unnecessary. + DisableMountSubPath allows to remove any subPath usage in + volume mounts.' + type: boolean + emptyDir: + description: 'EmptyDirVolumeSource to be used by the Prometheus + StatefulSets. If specified, used in place of any volumeClaimTemplate. + More info: https://kubernetes.io/docs/concepts/storage/volumes/#emptydir' + properties: + medium: + description: 'medium represents what type of storage medium + should back this directory. The default is "" which + means to use the node''s default medium. Must be an + empty string (default) or Memory. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' + type: string + sizeLimit: + anyOf: + - type: integer + - type: string + description: 'sizeLimit is the total amount of local storage + required for this EmptyDir volume. The size limit is + also applicable for memory medium. The maximum usage + on memory medium EmptyDir would be the minimum value + between the SizeLimit specified here and the sum of + memory limits of all containers in a pod. The default + is nil which means that the limit is undefined. More + info: http://kubernetes.io/docs/user-guide/volumes#emptydir' + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + volumeClaimTemplate: + description: A PVC spec to be used by the VMAlertManager StatefulSets. + type: object + x-kubernetes-preserve-unknown-fields: true + type: object + podDisruptionBudget: + description: PodDisruptionBudget created by operator + properties: + maxUnavailable: + anyOf: + - type: integer + - type: string + description: An eviction is allowed if at most "maxUnavailable" + pods selected by "selector" are unavailable after the eviction, + i.e. even in absence of the evicted pod. For example, one + can prevent all voluntary evictions by specifying 0. This + is a mutually exclusive setting with "minAvailable". + x-kubernetes-int-or-string: true + minAvailable: + anyOf: + - type: integer + - type: string + description: An eviction is allowed if at least "minAvailable" + pods selected by "selector" will still be available after + the eviction, i.e. even in the absence of the evicted pod. So + for example you can prevent all voluntary evictions by specifying + "100%". + x-kubernetes-int-or-string: true + selectorLabels: + additionalProperties: + type: string + description: replaces default labels selector generated by + operator it's useful when you need to create custom budget + type: object + type: object + podMetadata: + description: PodMetadata configures Labels and Annotations which + are propagated to the VMSelect pods. + properties: + annotations: + additionalProperties: + type: string + description: 'Annotations is an unstructured key value map + stored with a resource that may be set by external tools + to store and retrieve arbitrary metadata. They are not queryable + and should be preserved when modifying objects. More info: + http://kubernetes.io/docs/user-guide/annotations' + type: object + labels: + additionalProperties: + type: string + description: 'Labels Map of string keys and values that can + be used to organize and categorize (scope and select) objects. + May match selectors of replication controllers and services. + More info: http://kubernetes.io/docs/user-guide/labels' + type: object + name: + description: 'Name must be unique within a namespace. Is required + when creating resources, although some resources may allow + a client to request the generation of an appropriate name + automatically. Name is primarily intended for creation idempotence + and configuration definition. Cannot be updated. More info: + http://kubernetes.io/docs/user-guide/identifiers#names' + type: string + type: object + port: + description: Port listen port + type: string + priorityClassName: + description: Priority class assigned to the Pods + type: string + readinessGates: + description: ReadinessGates defines pod readiness gates + items: + description: PodReadinessGate contains the reference to a pod + condition + properties: + conditionType: + description: ConditionType refers to a condition in the + pod's condition list with matching type. + type: string + required: + - conditionType + type: object + type: array + readinessProbe: + description: ReadinessProbe that will be added CRD pod + type: object + x-kubernetes-preserve-unknown-fields: true + replicaCount: + description: ReplicaCount is the expected size of the VMSelect + cluster. The controller will eventually make the size of the + running cluster equal to the expected size. + format: int32 + type: integer + resources: + description: Resources container resource request and limits, + https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + properties: + 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. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + rollingUpdateStrategy: + description: RollingUpdateStrategy defines strategy for application + updates Default is OnDelete, in this case operator handles update + process Can be changed for RollingUpdate + type: string + runtimeClassName: + description: RuntimeClassName - defines runtime class for kubernetes + pod. https://kubernetes.io/docs/concepts/containers/runtime-class/ + type: string + schedulerName: + description: SchedulerName - defines kubernetes scheduler name + type: string + secrets: + description: Secrets is a list of Secrets in the same namespace + as the VMSelect object, which shall be mounted into the VMSelect + Pods. The Secrets are mounted into /etc/vm/secrets/. + items: + type: string + type: array + securityContext: + description: SecurityContext holds pod-level security attributes + and common container settings. This defaults to the default + PodSecurityContext. + type: object + x-kubernetes-preserve-unknown-fields: true + serviceScrapeSpec: + description: ServiceScrapeSpec that will be added to vmselect + VMServiceScrape spec + required: + - endpoints + type: object + x-kubernetes-preserve-unknown-fields: true + serviceSpec: + description: ServiceSpec that will be added to vmselect service + spec + properties: + metadata: + description: EmbeddedObjectMetadata defines objectMeta for + additional service. + properties: + annotations: + additionalProperties: + type: string + description: 'Annotations is an unstructured key value + map stored with a resource that may be set by external + tools to store and retrieve arbitrary metadata. They + are not queryable and should be preserved when modifying + objects. More info: http://kubernetes.io/docs/user-guide/annotations' + type: object + labels: + additionalProperties: + type: string + description: 'Labels Map of string keys and values that + can be used to organize and categorize (scope and select) + objects. May match selectors of replication controllers + and services. More info: http://kubernetes.io/docs/user-guide/labels' + type: object + name: + description: 'Name must be unique within a namespace. + Is required when creating resources, although some resources + may allow a client to request the generation of an appropriate + name automatically. Name is primarily intended for creation + idempotence and configuration definition. Cannot be + updated. More info: http://kubernetes.io/docs/user-guide/identifiers#names' + type: string + type: object + spec: + description: 'ServiceSpec describes the attributes that a + user creates on a service. More info: https://kubernetes.io/docs/concepts/services-networking/service/' + type: object + x-kubernetes-preserve-unknown-fields: true + required: + - spec + type: object + startupProbe: + description: StartupProbe that will be added to CRD pod + type: object + x-kubernetes-preserve-unknown-fields: true + storage: + description: StorageSpec - add persistent volume claim for cacheMounthPath + its needed for persistent cache + properties: + disableMountSubPath: + description: 'Deprecated: subPath usage will be disabled by + default in a future release, this option will become unnecessary. + DisableMountSubPath allows to remove any subPath usage in + volume mounts.' + type: boolean + emptyDir: + description: 'EmptyDirVolumeSource to be used by the Prometheus + StatefulSets. If specified, used in place of any volumeClaimTemplate. + More info: https://kubernetes.io/docs/concepts/storage/volumes/#emptydir' + properties: + medium: + description: 'medium represents what type of storage medium + should back this directory. The default is "" which + means to use the node''s default medium. Must be an + empty string (default) or Memory. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' + type: string + sizeLimit: + anyOf: + - type: integer + - type: string + description: 'sizeLimit is the total amount of local storage + required for this EmptyDir volume. The size limit is + also applicable for memory medium. The maximum usage + on memory medium EmptyDir would be the minimum value + between the SizeLimit specified here and the sum of + memory limits of all containers in a pod. The default + is nil which means that the limit is undefined. More + info: http://kubernetes.io/docs/user-guide/volumes#emptydir' + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + volumeClaimTemplate: + description: A PVC spec to be used by the VMAlertManager StatefulSets. + 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: + description: EmbeddedMetadata contains metadata relevant + to an EmbeddedResource. + properties: + annotations: + additionalProperties: + type: string + description: 'Annotations is an unstructured key value + map stored with a resource that may be set by external + tools to store and retrieve arbitrary metadata. + They are not queryable and should be preserved when + modifying objects. More info: http://kubernetes.io/docs/user-guide/annotations' + type: object + labels: + additionalProperties: + type: string + description: 'Labels Map of string keys and values + that can be used to organize and categorize (scope + and select) objects. May match selectors of replication + controllers and services. More info: http://kubernetes.io/docs/user-guide/labels' + type: object + name: + description: 'Name must be unique within a namespace. + Is required when creating resources, although some + resources may allow a client to request the generation + of an appropriate name automatically. Name is primarily + intended for creation idempotence and configuration + definition. Cannot be updated. More info: http://kubernetes.io/docs/user-guide/identifiers#names' + type: string + type: object + spec: + description: 'Spec defines the desired characteristics + of a volume requested by a pod author. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' + properties: + accessModes: + description: 'accessModes contains the desired access + modes the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' + items: + type: string + type: array + dataSource: + description: 'dataSource field can be used to specify + either: * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) + * An existing PVC (PersistentVolumeClaim) If the + provisioner or an external controller can support + the specified data source, it will create a new + volume based on the contents of the specified data + source. If the AnyVolumeDataSource feature gate + is enabled, this field will always have the same + contents as the DataSourceRef field.' + properties: + apiGroup: + description: APIGroup is the group for the resource + being referenced. If APIGroup is not specified, + the specified Kind must be in the core API group. + For any other third-party types, APIGroup is + required. + type: string + kind: + description: Kind is the type of resource being + referenced + type: string + name: + description: Name is the name of resource being + referenced + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + description: 'dataSourceRef specifies the object from + which to populate the volume with data, if a non-empty + volume is desired. This may be any local object + from a non-empty API group (non core object) or + a PersistentVolumeClaim object. When this field + is specified, volume binding will only succeed if + the type of the specified object matches some installed + volume populator or dynamic provisioner. This field + will replace the functionality of the DataSource + field and as such if both fields are non-empty, + they must have the same value. For backwards compatibility, + both fields (DataSource and DataSourceRef) will + be set to the same value automatically if one of + them is empty and the other is non-empty. There + are two important differences between DataSource + and DataSourceRef: * While DataSource only allows + two specific types of objects, DataSourceRef allows + any non-core object, as well as PersistentVolumeClaim + objects. * While DataSource ignores disallowed values + (dropping them), DataSourceRef preserves all values, + and generates an error if a disallowed value is + specified. (Beta) Using this field requires the + AnyVolumeDataSource feature gate to be enabled.' + properties: + apiGroup: + description: APIGroup is the group for the resource + being referenced. If APIGroup is not specified, + the specified Kind must be in the core API group. + For any other third-party types, APIGroup is + required. + type: string + kind: + description: Kind is the type of resource being + referenced + type: string + name: + description: Name is the name of resource being + referenced + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + resources: + description: 'resources represents the minimum resources + the volume should have. If RecoverVolumeExpansionFailure + feature is enabled users are allowed to specify + resource requirements that are lower than previous + value but must still be higher than capacity recorded + in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' + properties: + 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. More info: + https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + selector: + description: selector is a label query over volumes + to consider for binding. + 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 + required: + - key + - operator + type: object + type: array + 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 + storageClassName: + description: 'storageClassName is the name of the + StorageClass required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' + type: string + volumeMode: + description: volumeMode defines what type of volume + is required by the claim. Value of Filesystem is + implied when not included in claim spec. + type: string + volumeName: + description: volumeName is the binding reference to + the PersistentVolume backing this claim. + type: string + type: object + status: + description: 'Status represents the current information/status + of a persistent volume claim. Read-only. More info: + https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' + properties: + accessModes: + description: 'accessModes contains the actual access + modes the volume backing the PVC has. More info: + https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' + items: + type: string + type: array + allocatedResources: + 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: allocatedResources is the storage resource + within AllocatedResources tracks the capacity allocated + to a PVC. It may be larger than the actual capacity + when a volume expansion operation is requested. + For storage quota, the larger value from allocatedResources + and PVC.spec.resources is used. If allocatedResources + is not set, PVC.spec.resources alone is used for + quota calculation. If a volume expansion capacity + request is lowered, allocatedResources is only lowered + if there are no expansion operations in progress + and if the actual volume capacity is equal or lower + than the requested capacity. This is an alpha field + and requires enabling RecoverVolumeExpansionFailure + feature. + type: object + capacity: + 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: capacity represents the actual resources + of the underlying volume. + type: object + conditions: + description: conditions is the current Condition of + persistent volume claim. If underlying persistent + volume is being resized then the Condition will + be set to 'ResizeStarted'. + items: + description: PersistentVolumeClaimCondition contails + details about state of pvc + properties: + lastProbeTime: + description: lastProbeTime is the time we probed + the condition. + format: date-time + type: string + lastTransitionTime: + description: lastTransitionTime is the time + the condition transitioned from one status + to another. + format: date-time + type: string + message: + description: message is the human-readable message + indicating details about last transition. + type: string + reason: + description: reason is a unique, this should + be a short, machine understandable string + that gives the reason for condition's last + transition. If it reports "ResizeStarted" + that means the underlying persistent volume + is being resized. + type: string + status: + type: string + type: + description: PersistentVolumeClaimConditionType + is a valid value of PersistentVolumeClaimCondition.Type + type: string + required: + - status + - type + type: object + type: array + phase: + description: phase represents the current phase of + PersistentVolumeClaim. + type: string + resizeStatus: + description: resizeStatus stores status of resize + operation. ResizeStatus is not set by default but + when expansion is complete resizeStatus is set to + empty string by resize controller or kubelet. This + is an alpha field and requires enabling RecoverVolumeExpansionFailure + feature. + type: string + type: object + type: object + type: object + terminationGracePeriodSeconds: + description: TerminationGracePeriodSeconds period for container + graceful termination + format: int64 + type: integer + tolerations: + description: Tolerations If specified, the pod's tolerations. + 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: TopologySpreadConstraints embedded kubernetes pod + configuration option, controls how pods are spread across your + cluster among failure-domains such as regions, zones, nodes, + and other user-defined topology domains https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/ + items: + description: TopologySpreadConstraint specifies how to spread + matching pods among the given topology. + required: + - maxSkew + - topologyKey + - whenUnsatisfiable + type: object + x-kubernetes-preserve-unknown-fields: true + type: array + volumeMounts: + description: VolumeMounts allows configuration of additional VolumeMounts + on the output Deployment definition. VolumeMounts specified + will be appended to other VolumeMounts in the VMSelect container, + that are generated as a result of StorageSpec objects. + items: + description: VolumeMount describes a mounting of a Volume within + a container. + properties: + mountPath: + description: Path within the container at which the volume + should be mounted. Must not contain ':'. + type: string + mountPropagation: + description: mountPropagation determines how mounts are + propagated from the host to container and the other way + around. When not set, MountPropagationNone is used. This + field is beta in 1.10. + type: string + name: + description: This must match the Name of a Volume. + type: string + readOnly: + description: Mounted read-only if true, read-write otherwise + (false or unspecified). Defaults to false. + type: boolean + subPath: + description: Path within the volume from which the container's + volume should be mounted. Defaults to "" (volume's root). + type: string + subPathExpr: + description: Expanded path within the volume from which + the container's volume should be mounted. Behaves similarly + to SubPath but environment variable references $(VAR_NAME) + are expanded using the container's environment. Defaults + to "" (volume's root). SubPathExpr and SubPath are mutually + exclusive. + type: string + required: + - mountPath + - name + type: object + type: array + volumes: + description: Volumes allows configuration of additional volumes + on the output Deployment definition. Volumes specified will + be appended to other volumes that are generated as a result + of StorageSpec objects. + items: + description: Volume represents a named volume in a pod that + may be accessed by any container in the pod. + required: + - name + type: object + x-kubernetes-preserve-unknown-fields: true + type: array + required: + - replicaCount + type: object + vmstorage: + properties: + affinity: + description: Affinity If specified, the pod's scheduling constraints. + type: object + x-kubernetes-preserve-unknown-fields: true + claimTemplates: + description: ClaimTemplates allows adding additional VolumeClaimTemplates + for StatefulSet + items: + description: PersistentVolumeClaim is a user's request for and + claim to a persistent volume + 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: + description: 'Standard object''s metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata' + type: object + x-kubernetes-preserve-unknown-fields: true + spec: + description: 'spec defines the desired characteristics of + a volume requested by a pod author. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' + properties: + accessModes: + description: 'accessModes contains the desired access + modes the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' + items: + type: string + type: array + dataSource: + description: 'dataSource field can be used to specify + either: * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) + * An existing PVC (PersistentVolumeClaim) If the provisioner + or an external controller can support the specified + data source, it will create a new volume based on + the contents of the specified data source. If the + AnyVolumeDataSource feature gate is enabled, this + field will always have the same contents as the DataSourceRef + field.' + properties: + apiGroup: + description: APIGroup is the group for the resource + being referenced. If APIGroup is not specified, + the specified Kind must be in the core API group. + For any other third-party types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource being + referenced + type: string + name: + description: Name is the name of resource being + referenced + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + description: 'dataSourceRef specifies the object from + which to populate the volume with data, if a non-empty + volume is desired. This may be any local object from + a non-empty API group (non core object) or a PersistentVolumeClaim + object. When this field is specified, volume binding + will only succeed if the type of the specified object + matches some installed volume populator or dynamic + provisioner. This field will replace the functionality + of the DataSource field and as such if both fields + are non-empty, they must have the same value. For + backwards compatibility, both fields (DataSource and + DataSourceRef) will be set to the same value automatically + if one of them is empty and the other is non-empty. + There are two important differences between DataSource + and DataSourceRef: * While DataSource only allows + two specific types of objects, DataSourceRef allows + any non-core object, as well as PersistentVolumeClaim + objects. * While DataSource ignores disallowed values + (dropping them), DataSourceRef preserves all values, + and generates an error if a disallowed value is specified. + (Beta) Using this field requires the AnyVolumeDataSource + feature gate to be enabled.' + properties: + apiGroup: + description: APIGroup is the group for the resource + being referenced. If APIGroup is not specified, + the specified Kind must be in the core API group. + For any other third-party types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource being + referenced + type: string + name: + description: Name is the name of resource being + referenced + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + resources: + description: 'resources represents the minimum resources + the volume should have. If RecoverVolumeExpansionFailure + feature is enabled users are allowed to specify resource + requirements that are lower than previous value but + must still be higher than capacity recorded in the + status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' + properties: + 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. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + selector: + description: selector is a label query over volumes + to consider for binding. + 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 + required: + - key + - operator + type: object + type: array + 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 + storageClassName: + description: 'storageClassName is the name of the StorageClass + required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' + type: string + volumeMode: + description: volumeMode defines what type of volume + is required by the claim. Value of Filesystem is implied + when not included in claim spec. + type: string + volumeName: + description: volumeName is the binding reference to + the PersistentVolume backing this claim. + type: string + type: object + status: + description: 'status represents the current information/status + of a persistent volume claim. Read-only. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' + properties: + accessModes: + description: 'accessModes contains the actual access + modes the volume backing the PVC has. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' + items: + type: string + type: array + allocatedResources: + 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: allocatedResources is the storage resource + within AllocatedResources tracks the capacity allocated + to a PVC. It may be larger than the actual capacity + when a volume expansion operation is requested. For + storage quota, the larger value from allocatedResources + and PVC.spec.resources is used. If allocatedResources + is not set, PVC.spec.resources alone is used for quota + calculation. If a volume expansion capacity request + is lowered, allocatedResources is only lowered if + there are no expansion operations in progress and + if the actual volume capacity is equal or lower than + the requested capacity. This is an alpha field and + requires enabling RecoverVolumeExpansionFailure feature. + type: object + capacity: + 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: capacity represents the actual resources + of the underlying volume. + type: object + conditions: + description: conditions is the current Condition of + persistent volume claim. If underlying persistent + volume is being resized then the Condition will be + set to 'ResizeStarted'. + items: + description: PersistentVolumeClaimCondition contails + details about state of pvc + properties: + lastProbeTime: + description: lastProbeTime is the time we probed + the condition. + format: date-time + type: string + lastTransitionTime: + description: lastTransitionTime is the time the + condition transitioned from one status to another. + format: date-time + type: string + message: + description: message is the human-readable message + indicating details about last transition. + type: string + reason: + description: reason is a unique, this should be + a short, machine understandable string that + gives the reason for condition's last transition. + If it reports "ResizeStarted" that means the + underlying persistent volume is being resized. + type: string + status: + type: string + type: + description: PersistentVolumeClaimConditionType + is a valid value of PersistentVolumeClaimCondition.Type + type: string + required: + - status + - type + type: object + type: array + phase: + description: phase represents the current phase of PersistentVolumeClaim. + type: string + resizeStatus: + description: resizeStatus stores status of resize operation. + ResizeStatus is not set by default but when expansion + is complete resizeStatus is set to empty string by + resize controller or kubelet. This is an alpha field + and requires enabling RecoverVolumeExpansionFailure + feature. + type: string + type: object + type: object + type: array + configMaps: + description: ConfigMaps is a list of ConfigMaps in the same namespace + as the VMSelect object, which shall be mounted into the VMSelect + Pods. The ConfigMaps are mounted into /etc/vm/configs/. + items: + type: string + type: array + containers: + description: Containers property allows to inject additions sidecars + or to patch existing containers. It can be useful for proxies, + backup, etc. + items: + description: A single application container that you want to + run within a pod. + required: + - name + type: object + x-kubernetes-preserve-unknown-fields: true + type: array + dnsConfig: + description: Specifies the DNS parameters of a pod. Parameters + specified here will be merged to the generated DNS configuration + based on DNSPolicy. + items: + x-kubernetes-preserve-unknown-fields: true + properties: + nameservers: + description: A list of DNS name server IP addresses. This + will be appended to the base nameservers generated from + DNSPolicy. Duplicated nameservers will be removed. + items: + type: string + type: array + options: + description: A list of DNS resolver options. This will be + merged with the base options generated from DNSPolicy. Duplicated + entries will be removed. Resolution options given in Options + will override those that appear in the base DNSPolicy. + items: + description: PodDNSConfigOption defines DNS resolver options + of a pod. + properties: + name: + description: Required. + type: string + value: + type: string + type: object + type: array + searches: + description: A list of DNS search domains for host-name lookup. + This will be appended to the base search paths generated + from DNSPolicy. Duplicated search paths will be removed. + items: + type: string + type: array + type: object + dnsPolicy: + description: DNSPolicy sets DNS policy for the pod + type: string + extraArgs: + additionalProperties: + type: string + type: object + extraEnvs: + description: ExtraEnvs that will be added to VMSelect pod + 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 + required: + - name + type: object + x-kubernetes-preserve-unknown-fields: true + type: array + hostNetwork: + description: HostNetwork controls whether the pod may use the + node network namespace + type: boolean + image: + description: Image - docker image settings for VMStorage + properties: + pullPolicy: + description: PullPolicy describes how to pull docker image + type: string + repository: + description: Repository contains name of docker image + it's + repository if needed + type: string + tag: + description: Tag contains desired docker image version + type: string + type: object + initContainers: + description: 'InitContainers allows adding initContainers to the + pod definition. Those can be used to e.g. fetch secrets for + injection into the VMSelect configuration from external sources. + Any errors during the execution of an initContainer will lead + to a restart of the Pod. More info: https://kubernetes.io/docs/concepts/workloads/pods/init-containers/ + Using initContainers for any use case other then secret fetching + is entirely outside the scope of what the maintainers will support + and by doing so, you accept that this behaviour may break at + any time without notice.' + items: + description: A single application container that you want to + run within a pod. + required: + - name + type: object + x-kubernetes-preserve-unknown-fields: true + type: array + livenessProbe: + description: LivenessProbe that will be added CRD pod + type: object + x-kubernetes-preserve-unknown-fields: true + logFormat: + description: LogFormat for VMSelect to be configured with. default + or json + enum: + - default + - json + type: string + logLevel: + description: LogLevel for VMSelect to be configured with. + enum: + - INFO + - WARN + - ERROR + - FATAL + - PANIC + type: string + maintenanceInsertNodeIDs: + description: 'MaintenanceInsertNodeIDs - excludes given node ids + from insert requests routing, must contain pod suffixes - for + pod-0, id will be 0 and etc. lets say, you have pod-0, pod-1, + pod-2, pod-3. to exclude pod-0 and pod-3 from insert routing, + define nodeIDs: [0,3]. Useful at storage expanding, when you + want to rebalance some data at cluster.' + items: + format: int32 + type: integer + type: array + maintenanceSelectNodeIDs: + description: MaintenanceInsertNodeIDs - excludes given node ids + from select requests routing, must contain pod suffixes - for + pod-0, id will be 0 and etc. + items: + format: int32 + type: integer + type: array + name: + description: Name is deprecated and will be removed at 0.22.0 + release + type: string + nodeSelector: + additionalProperties: + type: string + description: NodeSelector Define which Nodes the Pods are scheduled + on. + type: object + podDisruptionBudget: + description: PodDisruptionBudget created by operator + properties: + maxUnavailable: + anyOf: + - type: integer + - type: string + description: An eviction is allowed if at most "maxUnavailable" + pods selected by "selector" are unavailable after the eviction, + i.e. even in absence of the evicted pod. For example, one + can prevent all voluntary evictions by specifying 0. This + is a mutually exclusive setting with "minAvailable". + x-kubernetes-int-or-string: true + minAvailable: + anyOf: + - type: integer + - type: string + description: An eviction is allowed if at least "minAvailable" + pods selected by "selector" will still be available after + the eviction, i.e. even in the absence of the evicted pod. So + for example you can prevent all voluntary evictions by specifying + "100%". + x-kubernetes-int-or-string: true + selectorLabels: + additionalProperties: + type: string + description: replaces default labels selector generated by + operator it's useful when you need to create custom budget + type: object + type: object + podMetadata: + description: PodMetadata configures Labels and Annotations which + are propagated to the VMSelect pods. + properties: + annotations: + additionalProperties: + type: string + description: 'Annotations is an unstructured key value map + stored with a resource that may be set by external tools + to store and retrieve arbitrary metadata. They are not queryable + and should be preserved when modifying objects. More info: + http://kubernetes.io/docs/user-guide/annotations' + type: object + labels: + additionalProperties: + type: string + description: 'Labels Map of string keys and values that can + be used to organize and categorize (scope and select) objects. + May match selectors of replication controllers and services. + More info: http://kubernetes.io/docs/user-guide/labels' + type: object + name: + description: 'Name must be unique within a namespace. Is required + when creating resources, although some resources may allow + a client to request the generation of an appropriate name + automatically. Name is primarily intended for creation idempotence + and configuration definition. Cannot be updated. More info: + http://kubernetes.io/docs/user-guide/identifiers#names' + type: string + type: object + port: + description: Port for health check connetions + type: string + priorityClassName: + description: Priority class assigned to the Pods + type: string + readinessGates: + description: ReadinessGates defines pod readiness gates + items: + description: PodReadinessGate contains the reference to a pod + condition + properties: + conditionType: + description: ConditionType refers to a condition in the + pod's condition list with matching type. + type: string + required: + - conditionType + type: object + type: array + readinessProbe: + description: ReadinessProbe that will be added CRD pod + type: object + x-kubernetes-preserve-unknown-fields: true + replicaCount: + description: ReplicaCount is the expected size of the VMStorage + cluster. The controller will eventually make the size of the + running cluster equal to the expected size. + format: int32 + type: integer + resources: + description: Resources container resource request and limits, + https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + properties: + 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. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + rollingUpdateStrategy: + description: RollingUpdateStrategy defines strategy for application + updates Default is OnDelete, in this case operator handles update + process Can be changed for RollingUpdate + type: string + runtimeClassName: + description: RuntimeClassName - defines runtime class for kubernetes + pod. https://kubernetes.io/docs/concepts/containers/runtime-class/ + type: string + schedulerName: + description: SchedulerName - defines kubernetes scheduler name + type: string + secrets: + description: Secrets is a list of Secrets in the same namespace + as the VMSelect object, which shall be mounted into the VMSelect + Pods. The Secrets are mounted into /etc/vm/secrets/. + items: + type: string + type: array + securityContext: + description: SecurityContext holds pod-level security attributes + and common container settings. This defaults to the default + PodSecurityContext. + type: object + x-kubernetes-preserve-unknown-fields: true + serviceScrapeSpec: + description: ServiceScrapeSpec that will be added to vmstorage + VMServiceScrape spec + required: + - endpoints + type: object + x-kubernetes-preserve-unknown-fields: true + serviceSpec: + description: ServiceSpec that will be create additional service + for vmstorage + properties: + metadata: + description: EmbeddedObjectMetadata defines objectMeta for + additional service. + properties: + annotations: + additionalProperties: + type: string + description: 'Annotations is an unstructured key value + map stored with a resource that may be set by external + tools to store and retrieve arbitrary metadata. They + are not queryable and should be preserved when modifying + objects. More info: http://kubernetes.io/docs/user-guide/annotations' + type: object + labels: + additionalProperties: + type: string + description: 'Labels Map of string keys and values that + can be used to organize and categorize (scope and select) + objects. May match selectors of replication controllers + and services. More info: http://kubernetes.io/docs/user-guide/labels' + type: object + name: + description: 'Name must be unique within a namespace. + Is required when creating resources, although some resources + may allow a client to request the generation of an appropriate + name automatically. Name is primarily intended for creation + idempotence and configuration definition. Cannot be + updated. More info: http://kubernetes.io/docs/user-guide/identifiers#names' + type: string + type: object + spec: + description: 'ServiceSpec describes the attributes that a + user creates on a service. More info: https://kubernetes.io/docs/concepts/services-networking/service/' + type: object + x-kubernetes-preserve-unknown-fields: true + required: + - spec + type: object + startupProbe: + description: StartupProbe that will be added to CRD pod + type: object + x-kubernetes-preserve-unknown-fields: true + storage: + description: Storage - add persistent volume for StorageDataPath + its useful for persistent cache + properties: + disableMountSubPath: + description: 'Deprecated: subPath usage will be disabled by + default in a future release, this option will become unnecessary. + DisableMountSubPath allows to remove any subPath usage in + volume mounts.' + type: boolean + emptyDir: + description: 'EmptyDirVolumeSource to be used by the Prometheus + StatefulSets. If specified, used in place of any volumeClaimTemplate. + More info: https://kubernetes.io/docs/concepts/storage/volumes/#emptydir' + properties: + medium: + description: 'medium represents what type of storage medium + should back this directory. The default is "" which + means to use the node''s default medium. Must be an + empty string (default) or Memory. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' + type: string + sizeLimit: + anyOf: + - type: integer + - type: string + description: 'sizeLimit is the total amount of local storage + required for this EmptyDir volume. The size limit is + also applicable for memory medium. The maximum usage + on memory medium EmptyDir would be the minimum value + between the SizeLimit specified here and the sum of + memory limits of all containers in a pod. The default + is nil which means that the limit is undefined. More + info: http://kubernetes.io/docs/user-guide/volumes#emptydir' + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + volumeClaimTemplate: + description: A PVC spec to be used by the VMAlertManager StatefulSets. + type: object + x-kubernetes-preserve-unknown-fields: true + type: object + storageDataPath: + description: StorageDataPath - path to storage data + type: string + terminationGracePeriodSeconds: + description: TerminationGracePeriodSeconds period for container + graceful termination + format: int64 + type: integer + tolerations: + description: Tolerations If specified, the pod's tolerations. + 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: TopologySpreadConstraints embedded kubernetes pod + configuration option, controls how pods are spread across your + cluster among failure-domains such as regions, zones, nodes, + and other user-defined topology domains https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/ + items: + description: TopologySpreadConstraint specifies how to spread + matching pods among the given topology. + required: + - maxSkew + - topologyKey + - whenUnsatisfiable + type: object + x-kubernetes-preserve-unknown-fields: true + type: array + vmBackup: + description: VMBackup configuration for backup + properties: + acceptEULA: + description: AcceptEULA accepts enterprise feature usage, + must be set to true. otherwise backupmanager cannot be added + to single/cluster version. https://victoriametrics.com/legal/eula/ + type: boolean + concurrency: + description: Defines number of concurrent workers. Higher + concurrency may reduce backup duration (default 10) + format: int32 + type: integer + credentialsSecret: + description: CredentialsSecret is secret in the same namespace + for access to remote storage The secret is mounted into + /etc/vm/creds. + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + customS3Endpoint: + description: Custom S3 endpoint for use with S3-compatible + storages (e.g. MinIO). S3 is used if not set + type: string + destination: + description: Defines destination for backup + type: string + destinationDisableSuffixAdd: + description: DestinationDisableSuffixAdd - disables suffix + adding for cluster version backups each vmstorage backup + must have unique backup folder so operator adds POD_NAME + as suffix for backup destination folder. + type: boolean + disableDaily: + description: Defines if daily backups disabled (default false) + type: boolean + disableHourly: + description: Defines if hourly backups disabled (default false) + type: boolean + disableMonthly: + description: Defines if monthly backups disabled (default + false) + type: boolean + disableWeekly: + description: Defines if weekly backups disabled (default false) + type: boolean + extraArgs: + additionalProperties: + type: string + description: extra args like maxBytesPerSecond default 0 + type: object + extraEnvs: + 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: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + 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: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + 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: Image - docker image settings for VMBackuper + properties: + pullPolicy: + description: PullPolicy describes how to pull docker image + type: string + repository: + description: Repository contains name of docker image + + it's repository if needed + type: string + tag: + description: Tag contains desired docker image version + type: string + type: object + logFormat: + description: LogFormat for VMSelect to be configured with. + default or json + enum: + - default + - json + type: string + logLevel: + description: LogLevel for VMSelect to be configured with. + enum: + - INFO + - WARN + - ERROR + - FATAL + - PANIC + type: string + port: + description: Port for health check connections + type: string + resources: + description: Resources container resource request and limits, + https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + if not defined default resources from operator config will + be used + properties: + 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. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + restore: + description: 'Restore Allows to enable restore options for + pod Read more: https://docs.victoriametrics.com/vmbackupmanager.html#restore-commands' + properties: + onStart: + description: OnStart defines configuration for restore + on pod start + properties: + enabled: + description: Enabled defines if restore on start enabled + type: boolean + type: object + type: object + snapshotCreateURL: + description: SnapshotCreateURL overwrites url for snapshot + create + type: string + snapshotDeleteURL: + description: SnapShotDeleteURL overwrites url for snapshot + delete + type: string + volumeMounts: + description: VolumeMounts allows configuration of additional + VolumeMounts on the output Deployment definition. VolumeMounts + specified will be appended to other VolumeMounts in the + vmbackupmanager container, that are generated as a result + of StorageSpec objects. + items: + description: VolumeMount describes a mounting of a Volume + within a container. + properties: + mountPath: + description: Path within the container at which the + volume should be mounted. Must not contain ':'. + type: string + mountPropagation: + description: mountPropagation determines how mounts + are propagated from the host to container and the + other way around. When not set, MountPropagationNone + is used. This field is beta in 1.10. + type: string + name: + description: This must match the Name of a Volume. + type: string + readOnly: + description: Mounted read-only if true, read-write otherwise + (false or unspecified). Defaults to false. + type: boolean + subPath: + description: Path within the volume from which the container's + volume should be mounted. Defaults to "" (volume's + root). + type: string + subPathExpr: + description: Expanded path within the volume from which + the container's volume should be mounted. Behaves + similarly to SubPath but environment variable references + $(VAR_NAME) are expanded using the container's environment. + Defaults to "" (volume's root). SubPathExpr and SubPath + are mutually exclusive. + type: string + required: + - mountPath + - name + type: object + type: array + required: + - acceptEULA + type: object + vmInsertPort: + description: VMInsertPort for VMInsert connections + type: string + vmSelectPort: + description: VMSelectPort for VMSelect connections + type: string + volumeMounts: + description: VolumeMounts allows configuration of additional VolumeMounts + on the output Deployment definition. VolumeMounts specified + will be appended to other VolumeMounts in the VMSelect container, + that are generated as a result of StorageSpec objects. + items: + description: VolumeMount describes a mounting of a Volume within + a container. + properties: + mountPath: + description: Path within the container at which the volume + should be mounted. Must not contain ':'. + type: string + mountPropagation: + description: mountPropagation determines how mounts are + propagated from the host to container and the other way + around. When not set, MountPropagationNone is used. This + field is beta in 1.10. + type: string + name: + description: This must match the Name of a Volume. + type: string + readOnly: + description: Mounted read-only if true, read-write otherwise + (false or unspecified). Defaults to false. + type: boolean + subPath: + description: Path within the volume from which the container's + volume should be mounted. Defaults to "" (volume's root). + type: string + subPathExpr: + description: Expanded path within the volume from which + the container's volume should be mounted. Behaves similarly + to SubPath but environment variable references $(VAR_NAME) + are expanded using the container's environment. Defaults + to "" (volume's root). SubPathExpr and SubPath are mutually + exclusive. + type: string + required: + - mountPath + - name + type: object + type: array + volumes: + description: Volumes allows configuration of additional volumes + on the output Deployment definition. Volumes specified will + be appended to other volumes that are generated as a result + of StorageSpec objects. + items: + description: Volume represents a named volume in a pod that + may be accessed by any container in the pod. + required: + - name + type: object + x-kubernetes-preserve-unknown-fields: true + type: array + required: + - replicaCount + type: object + required: + - retentionPeriod + type: object + status: + description: VMClusterStatus defines the observed state of VMCluster + properties: + clusterStatus: + type: string + lastSync: + description: Deprecated. + type: string + reason: + type: string + updateFailCount: + description: Deprecated. + type: integer + required: + - clusterStatus + - updateFailCount + type: object + required: + - spec + type: object + served: true + storage: true + subresources: + status: {} +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.12.1 + name: vmnodescrapes.operator.victoriametrics.com +spec: + group: operator.victoriametrics.com + names: + kind: VMNodeScrape + listKind: VMNodeScrapeList + plural: vmnodescrapes + singular: vmnodescrape + scope: Namespaced + versions: + - name: v1beta1 + schema: + openAPIV3Schema: + description: VMNodeScrape defines discovery for targets placed on kubernetes + nodes, usually its node-exporters and other host services. InternalIP is + used as __address__ for scraping. + 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: VMNodeScrapeSpec defines specification for VMNodeScrape. + properties: + authorization: + description: Authorization with http header Authorization + properties: + credentials: + description: Reference to the secret with value for authorization + properties: + key: + description: The key of the secret to select from. Must be + a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + credentialsFile: + description: File with value for authorization + type: string + type: + description: Type of authorization, default to bearer + type: string + type: object + basicAuth: + description: 'BasicAuth allow an endpoint to authenticate over basic + authentication More info: https://prometheus.io/docs/operating/configuration/#endpoints' + properties: + password: + description: The secret in the service scrape namespace that contains + the password for authentication. It must be at them same namespace + as CRD + properties: + key: + description: The key of the secret to select from. Must be + a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + password_file: + description: PasswordFile defines path to password file at disk + type: string + username: + description: The secret in the service scrape namespace that contains + the username for authentication. It must be at them same namespace + as CRD + properties: + key: + description: The key of the secret to select from. Must be + a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + bearerTokenFile: + description: File to read bearer token for scraping targets. + type: string + bearerTokenSecret: + description: Secret to mount to read bearer token for scraping targets. + The secret needs to be accessible by the victoria-metrics operator. + nullable: true + properties: + key: + description: The key of the secret to select from. Must be a + valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + follow_redirects: + description: FollowRedirects controls redirects for scraping. + type: boolean + honorLabels: + description: HonorLabels chooses the metric's labels on collisions + with target labels. + type: boolean + honorTimestamps: + description: HonorTimestamps controls whether vmagent respects the + timestamps present in scraped data. + type: boolean + interval: + description: Interval at which metrics should be scraped + type: string + jobLabel: + description: The label to use to retrieve the job name from. + type: string + metricRelabelConfigs: + description: MetricRelabelConfigs to apply to samples before ingestion. + items: + description: 'RelabelConfig allows dynamic rewriting of the label + set, being applied to samples before ingestion. It defines ``-section + of configuration. More info: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#metric_relabel_configs' + properties: + action: + description: Action to perform based on regex matching. Default + is 'replace' + type: string + if: + description: 'If represents metricsQL match expression: ''{__name__=~"foo_.*"}''' + type: string + labels: + additionalProperties: + type: string + description: 'Labels is used together with Match for `action: + graphite`' + type: object + match: + description: 'Match is used together with Labels for `action: + graphite`' + type: string + modulus: + description: Modulus to take of the hash of the source label + values. + format: int64 + type: integer + regex: + description: Regular expression against which the extracted + value is matched. Default is '(.*)' + type: string + replacement: + description: Replacement value against which a regex replace + is performed if the regular expression matches. Regex capture + groups are available. Default is '$1' + type: string + separator: + description: Separator placed between concatenated source label + values. default is ';'. + type: string + source_labels: + description: UnderScoreSourceLabels - additional form of source + labels source_labels for compatibility with original relabel + config. if set both sourceLabels and source_labels, sourceLabels + has priority. for details https://github.com/VictoriaMetrics/operator/issues/131 + items: + type: string + type: array + sourceLabels: + description: The source labels select values from existing labels. + Their content is concatenated using the configured separator + and matched against the configured regular expression for + the replace, keep, and drop actions. + items: + type: string + type: array + target_label: + description: UnderScoreTargetLabel - additional form of target + label - target_label for compatibility with original relabel + config. if set both targetLabel and target_label, targetLabel + has priority. for details https://github.com/VictoriaMetrics/operator/issues/131 + type: string + targetLabel: + description: Label to which the resulting value is written in + a replace action. It is mandatory for replace actions. Regex + capture groups are available. + type: string + type: object + type: array + oauth2: + description: OAuth2 defines auth configuration + properties: + client_id: + description: The secret or configmap containing the OAuth2 client + id + properties: + configMap: + description: ConfigMap containing data to use for the targets. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + secret: + description: Secret containing data to use for the targets. + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + client_secret: + description: The secret containing the OAuth2 client secret + properties: + key: + description: The key of the secret to select from. Must be + a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + client_secret_file: + description: ClientSecretFile defines path for client secret file. + type: string + endpoint_params: + additionalProperties: + type: string + description: Parameters to append to the token URL + type: object + scopes: + description: OAuth2 scopes used for the token request + items: + type: string + type: array + token_url: + description: The URL to fetch the token from + minLength: 1 + type: string + required: + - client_id + - token_url + type: object + params: + additionalProperties: + items: + type: string + type: array + description: Optional HTTP URL parameters + type: object + path: + description: HTTP path to scrape for metrics. + type: string + port: + description: Name of the port exposed at Node. + type: string + proxyURL: + description: ProxyURL eg http://proxyserver:2195 Directs scrapes to + proxy through this endpoint. + type: string + relabelConfigs: + description: 'RelabelConfigs to apply to samples before scraping. + More info: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#relabel_config' + items: + description: 'RelabelConfig allows dynamic rewriting of the label + set, being applied to samples before ingestion. It defines ``-section + of configuration. More info: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#metric_relabel_configs' + properties: + action: + description: Action to perform based on regex matching. Default + is 'replace' + type: string + if: + description: 'If represents metricsQL match expression: ''{__name__=~"foo_.*"}''' + type: string + labels: + additionalProperties: + type: string + description: 'Labels is used together with Match for `action: + graphite`' + type: object + match: + description: 'Match is used together with Labels for `action: + graphite`' + type: string + modulus: + description: Modulus to take of the hash of the source label + values. + format: int64 + type: integer + regex: + description: Regular expression against which the extracted + value is matched. Default is '(.*)' + type: string + replacement: + description: Replacement value against which a regex replace + is performed if the regular expression matches. Regex capture + groups are available. Default is '$1' + type: string + separator: + description: Separator placed between concatenated source label + values. default is ';'. + type: string + source_labels: + description: UnderScoreSourceLabels - additional form of source + labels source_labels for compatibility with original relabel + config. if set both sourceLabels and source_labels, sourceLabels + has priority. for details https://github.com/VictoriaMetrics/operator/issues/131 + items: + type: string + type: array + sourceLabels: + description: The source labels select values from existing labels. + Their content is concatenated using the configured separator + and matched against the configured regular expression for + the replace, keep, and drop actions. + items: + type: string + type: array + target_label: + description: UnderScoreTargetLabel - additional form of target + label - target_label for compatibility with original relabel + config. if set both targetLabel and target_label, targetLabel + has priority. for details https://github.com/VictoriaMetrics/operator/issues/131 + type: string + targetLabel: + description: Label to which the resulting value is written in + a replace action. It is mandatory for replace actions. Regex + capture groups are available. + type: string + type: object + type: array + sampleLimit: + description: SampleLimit defines per-scrape limit on number of scraped + samples that will be accepted. + format: int64 + type: integer + scheme: + description: HTTP scheme to use for scraping. + enum: + - http + - https + type: string + scrape_interval: + description: ScrapeInterval is the same as Interval and has priority + over it. one of scrape_interval or interval can be used + type: string + scrapeTimeout: + description: Timeout after which the scrape is ended + type: string + selector: + description: Selector to select kubernetes Nodes. + 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 + required: + - key + - operator + type: object + type: array + 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 + targetLabels: + description: TargetLabels transfers labels on the Kubernetes Node + onto the target. + items: + type: string + type: array + tlsConfig: + description: TLSConfig specifies TLSConfig configuration parameters. + properties: + ca: + description: Stuct containing the CA cert to use for the targets. + properties: + configMap: + description: ConfigMap containing data to use for the targets. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + secret: + description: Secret containing data to use for the targets. + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + caFile: + description: Path to the CA cert in the container to use for the + targets. + type: string + cert: + description: Struct containing the client cert file for the targets. + properties: + configMap: + description: ConfigMap containing data to use for the targets. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + secret: + description: Secret containing data to use for the targets. + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + certFile: + description: Path to the client cert file in the container for + the targets. + type: string + insecureSkipVerify: + description: Disable target certificate validation. + type: boolean + keyFile: + description: Path to the client key file in the container for + the targets. + type: string + keySecret: + description: Secret containing the client key file for the targets. + properties: + key: + description: The key of the secret to select from. Must be + a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + serverName: + description: Used to verify the hostname for the targets. + type: string + type: object + vm_scrape_params: + description: VMScrapeParams defines VictoriaMetrics specific scrape + parametrs + properties: + disable_compression: + type: boolean + disable_keep_alive: + type: boolean + headers: + description: 'Headers allows sending custom headers to scrape + targets must be in of semicolon separated header with it''s + value eg: headerName: headerValue vmagent supports since 1.79.0 + version' + items: + type: string + type: array + metric_relabel_debug: + type: boolean + no_stale_markers: + type: boolean + proxy_client_config: + description: ProxyClientConfig configures proxy auth settings + for scraping See feature description https://docs.victoriametrics.com/vmagent.html#scraping-targets-via-a-proxy + properties: + basic_auth: + description: BasicAuth allow an endpoint to authenticate over + basic authentication + properties: + password: + description: The secret in the service scrape namespace + that contains the password for authentication. It must + be at them same namespace as CRD + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + 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 + password_file: + description: PasswordFile defines path to password file + at disk + type: string + username: + description: The secret in the service scrape namespace + that contains the username for authentication. It must + be at them same namespace as CRD + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + 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 + bearer_token: + description: SecretKeySelector selects a key of a Secret. + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + bearer_token_file: + type: string + tls_config: + description: TLSConfig specifies TLSConfig configuration parameters. + properties: + ca: + description: Stuct containing the CA cert to use for the + targets. + properties: + configMap: + description: ConfigMap containing data to use for + the targets. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + 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 + secret: + description: Secret containing data to use for the + targets. + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + 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 + caFile: + description: Path to the CA cert in the container to use + for the targets. + type: string + cert: + description: Struct containing the client cert file for + the targets. + properties: + configMap: + description: ConfigMap containing data to use for + the targets. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + 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 + secret: + description: Secret containing data to use for the + targets. + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + 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 + certFile: + description: Path to the client cert file in the container + for the targets. + type: string + insecureSkipVerify: + description: Disable target certificate validation. + type: boolean + keyFile: + description: Path to the client key file in the container + for the targets. + type: string + keySecret: + description: Secret containing the client key file for + the targets. + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + 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 + serverName: + description: Used to verify the hostname for the targets. + type: string + type: object + type: object + relabel_debug: + type: boolean + scrape_align_interval: + type: string + scrape_offset: + type: string + stream_parse: + type: boolean + type: object + type: object + status: + description: VMNodeScrapeStatus defines the observed state of VMNodeScrape + 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.12.1 + name: vmpodscrapes.operator.victoriametrics.com +spec: + group: operator.victoriametrics.com + names: + kind: VMPodScrape + listKind: VMPodScrapeList + plural: vmpodscrapes + singular: vmpodscrape + scope: Namespaced + versions: + - name: v1beta1 + schema: + openAPIV3Schema: + description: VMPodScrape is scrape configuration for pods, it generates vmagent's + config for scraping pod targets based on selectors. + 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: VMPodScrapeSpec defines the desired state of VMPodScrape + properties: + jobLabel: + description: The label to use to retrieve the job name from. + type: string + namespaceSelector: + description: Selector to select which namespaces the Endpoints objects + are discovered from. + properties: + any: + description: Boolean describing whether all namespaces are selected + in contrast to a list restricting them. + type: boolean + matchNames: + description: List of namespace names. + items: + type: string + type: array + type: object + podMetricsEndpoints: + description: A list of endpoints allowed as part of this PodMonitor. + items: + description: PodMetricsEndpoint defines a scrapeable endpoint of + a Kubernetes Pod serving Prometheus metrics. + properties: + attach_metadata: + description: AttachMetadata configures metadata attaching from + service discovery + properties: + node: + description: 'Node instructs vmagent to add node specific + metadata from service discovery Valid for roles: pod, + endpoints, endpointslice.' + type: boolean + type: object + authorization: + description: Authorization with http header Authorization + properties: + credentials: + description: Reference to the secret with value for authorization + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + credentialsFile: + description: File with value for authorization + type: string + type: + description: Type of authorization, default to bearer + type: string + type: object + basicAuth: + description: 'BasicAuth allow an endpoint to authenticate over + basic authentication More info: https://prometheus.io/docs/operating/configuration/#endpoints' + properties: + password: + description: The secret in the service scrape namespace + that contains the password for authentication. It must + be at them same namespace as CRD + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + password_file: + description: PasswordFile defines path to password file + at disk + type: string + username: + description: The secret in the service scrape namespace + that contains the username for authentication. It must + be at them same namespace as CRD + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + bearerTokenFile: + description: File to read bearer token for scraping targets. + type: string + bearerTokenSecret: + description: Secret to mount to read bearer token for scraping + targets. The secret needs to be in the same namespace as the + service scrape and accessible by the victoria-metrics operator. + nullable: true + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + filterRunning: + description: FilterRunning applies filter with pod status == + running it prevents from scrapping metrics at failed or succeed + state pods. enabled by default + type: boolean + follow_redirects: + description: FollowRedirects controls redirects for scraping. + type: boolean + honorLabels: + description: HonorLabels chooses the metric's labels on collisions + with target labels. + type: boolean + honorTimestamps: + description: HonorTimestamps controls whether vmagent respects + the timestamps present in scraped data. + type: boolean + interval: + description: Interval at which metrics should be scraped + type: string + metricRelabelConfigs: + description: MetricRelabelConfigs to apply to samples before + ingestion. + items: + description: 'RelabelConfig allows dynamic rewriting of the + label set, being applied to samples before ingestion. It + defines ``-section of configuration. + More info: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#metric_relabel_configs' + properties: + action: + description: Action to perform based on regex matching. + Default is 'replace' + type: string + if: + description: 'If represents metricsQL match expression: + ''{__name__=~"foo_.*"}''' + type: string + labels: + additionalProperties: + type: string + description: 'Labels is used together with Match for `action: + graphite`' + type: object + match: + description: 'Match is used together with Labels for `action: + graphite`' + type: string + modulus: + description: Modulus to take of the hash of the source + label values. + format: int64 + type: integer + regex: + description: Regular expression against which the extracted + value is matched. Default is '(.*)' + type: string + replacement: + description: Replacement value against which a regex replace + is performed if the regular expression matches. Regex + capture groups are available. Default is '$1' + type: string + separator: + description: Separator placed between concatenated source + label values. default is ';'. + type: string + source_labels: + description: UnderScoreSourceLabels - additional form + of source labels source_labels for compatibility with + original relabel config. if set both sourceLabels and + source_labels, sourceLabels has priority. for details + https://github.com/VictoriaMetrics/operator/issues/131 + items: + type: string + type: array + sourceLabels: + description: The source labels select values from existing + labels. Their content is concatenated using the configured + separator and matched against the configured regular + expression for the replace, keep, and drop actions. + items: + type: string + type: array + target_label: + description: UnderScoreTargetLabel - additional form of + target label - target_label for compatibility with original + relabel config. if set both targetLabel and target_label, + targetLabel has priority. for details https://github.com/VictoriaMetrics/operator/issues/131 + type: string + targetLabel: + description: Label to which the resulting value is written + in a replace action. It is mandatory for replace actions. + Regex capture groups are available. + type: string + type: object + type: array + oauth2: + description: OAuth2 defines auth configuration + properties: + client_id: + description: The secret or configmap containing the OAuth2 + client id + properties: + configMap: + description: ConfigMap containing data to use for the + targets. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + 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 + secret: + description: Secret containing data to use for the targets. + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + 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 + client_secret: + description: The secret containing the OAuth2 client secret + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + client_secret_file: + description: ClientSecretFile defines path for client secret + file. + type: string + endpoint_params: + additionalProperties: + type: string + description: Parameters to append to the token URL + type: object + scopes: + description: OAuth2 scopes used for the token request + items: + type: string + type: array + token_url: + description: The URL to fetch the token from + minLength: 1 + type: string + required: + - client_id + - token_url + type: object + params: + additionalProperties: + items: + type: string + type: array + description: Optional HTTP URL parameters + type: object + path: + description: HTTP path to scrape for metrics. + type: string + port: + description: Name of the pod port this endpoint refers to. Mutually + exclusive with targetPort. + type: string + proxyURL: + description: ProxyURL eg http://proxyserver:2195 Directs scrapes + to proxy through this endpoint. + type: string + relabelConfigs: + description: 'RelabelConfigs to apply to samples before ingestion. + More info: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#relabel_config' + items: + description: 'RelabelConfig allows dynamic rewriting of the + label set, being applied to samples before ingestion. It + defines ``-section of configuration. + More info: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#metric_relabel_configs' + properties: + action: + description: Action to perform based on regex matching. + Default is 'replace' + type: string + if: + description: 'If represents metricsQL match expression: + ''{__name__=~"foo_.*"}''' + type: string + labels: + additionalProperties: + type: string + description: 'Labels is used together with Match for `action: + graphite`' + type: object + match: + description: 'Match is used together with Labels for `action: + graphite`' + type: string + modulus: + description: Modulus to take of the hash of the source + label values. + format: int64 + type: integer + regex: + description: Regular expression against which the extracted + value is matched. Default is '(.*)' + type: string + replacement: + description: Replacement value against which a regex replace + is performed if the regular expression matches. Regex + capture groups are available. Default is '$1' + type: string + separator: + description: Separator placed between concatenated source + label values. default is ';'. + type: string + source_labels: + description: UnderScoreSourceLabels - additional form + of source labels source_labels for compatibility with + original relabel config. if set both sourceLabels and + source_labels, sourceLabels has priority. for details + https://github.com/VictoriaMetrics/operator/issues/131 + items: + type: string + type: array + sourceLabels: + description: The source labels select values from existing + labels. Their content is concatenated using the configured + separator and matched against the configured regular + expression for the replace, keep, and drop actions. + items: + type: string + type: array + target_label: + description: UnderScoreTargetLabel - additional form of + target label - target_label for compatibility with original + relabel config. if set both targetLabel and target_label, + targetLabel has priority. for details https://github.com/VictoriaMetrics/operator/issues/131 + type: string + targetLabel: + description: Label to which the resulting value is written + in a replace action. It is mandatory for replace actions. + Regex capture groups are available. + type: string + type: object + type: array + sampleLimit: + description: SampleLimit defines per-podEndpoint limit on number + of scraped samples that will be accepted. + format: int64 + type: integer + scheme: + description: HTTP scheme to use for scraping. + enum: + - http + - https + type: string + scrape_interval: + description: ScrapeInterval is the same as Interval and has + priority over it. one of scrape_interval or interval can be + used + type: string + scrapeTimeout: + description: Timeout after which the scrape is ended + type: string + targetPort: + anyOf: + - type: integer + - type: string + description: 'Deprecated: Use ''port'' instead.' + x-kubernetes-int-or-string: true + tlsConfig: + description: TLSConfig configuration to use when scraping the + endpoint + properties: + ca: + description: Stuct containing the CA cert to use for the + targets. + properties: + configMap: + description: ConfigMap containing data to use for the + targets. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + 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 + secret: + description: Secret containing data to use for the targets. + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + 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 + caFile: + description: Path to the CA cert in the container to use + for the targets. + type: string + cert: + description: Struct containing the client cert file for + the targets. + properties: + configMap: + description: ConfigMap containing data to use for the + targets. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + 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 + secret: + description: Secret containing data to use for the targets. + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + 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 + certFile: + description: Path to the client cert file in the container + for the targets. + type: string + insecureSkipVerify: + description: Disable target certificate validation. + type: boolean + keyFile: + description: Path to the client key file in the container + for the targets. + type: string + keySecret: + description: Secret containing the client key file for the + targets. + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + serverName: + description: Used to verify the hostname for the targets. + type: string + type: object + vm_scrape_params: + description: VMScrapeParams defines VictoriaMetrics specific + scrape parametrs + properties: + disable_compression: + type: boolean + disable_keep_alive: + type: boolean + headers: + description: 'Headers allows sending custom headers to scrape + targets must be in of semicolon separated header with + it''s value eg: headerName: headerValue vmagent supports + since 1.79.0 version' + items: + type: string + type: array + metric_relabel_debug: + type: boolean + no_stale_markers: + type: boolean + proxy_client_config: + description: ProxyClientConfig configures proxy auth settings + for scraping See feature description https://docs.victoriametrics.com/vmagent.html#scraping-targets-via-a-proxy + properties: + basic_auth: + description: BasicAuth allow an endpoint to authenticate + over basic authentication + properties: + password: + description: The secret in the service scrape namespace + that contains the password for authentication. + It must be at them same namespace as CRD + properties: + key: + description: The key of the secret to select + from. Must be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + 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 + password_file: + description: PasswordFile defines path to password + file at disk + type: string + username: + description: The secret in the service scrape namespace + that contains the username for authentication. + It must be at them same namespace as CRD + properties: + key: + description: The key of the secret to select + from. Must be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + 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 + bearer_token: + description: SecretKeySelector selects a key of a Secret. + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + 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 + bearer_token_file: + type: string + tls_config: + description: TLSConfig specifies TLSConfig configuration + parameters. + properties: + ca: + description: Stuct containing the CA cert to use + for the targets. + properties: + configMap: + description: ConfigMap containing data to use + for the targets. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + 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 + secret: + description: Secret containing data to use for + the targets. + properties: + key: + description: The key of the secret to select + from. Must be a valid secret key. + type: string + name: + description: 'Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + 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 + caFile: + description: Path to the CA cert in the container + to use for the targets. + type: string + cert: + description: Struct containing the client cert file + for the targets. + properties: + configMap: + description: ConfigMap containing data to use + for the targets. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + 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 + secret: + description: Secret containing data to use for + the targets. + properties: + key: + description: The key of the secret to select + from. Must be a valid secret key. + type: string + name: + description: 'Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + 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 + certFile: + description: Path to the client cert file in the + container for the targets. + type: string + insecureSkipVerify: + description: Disable target certificate validation. + type: boolean + keyFile: + description: Path to the client key file in the + container for the targets. + type: string + keySecret: + description: Secret containing the client key file + for the targets. + properties: + key: + description: The key of the secret to select + from. Must be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + 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 + serverName: + description: Used to verify the hostname for the + targets. + type: string + type: object + type: object + relabel_debug: + type: boolean + scrape_align_interval: + type: string + scrape_offset: + type: string + stream_parse: + type: boolean + type: object + type: object + type: array + podTargetLabels: + description: PodTargetLabels transfers labels on the Kubernetes Pod + onto the target. + items: + type: string + type: array + sampleLimit: + description: SampleLimit defines per-scrape limit on number of scraped + samples that will be accepted. + format: int64 + type: integer + selector: + description: Selector to select Pod objects. + 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 + required: + - key + - operator + type: object + type: array + 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: + - podMetricsEndpoints + type: object + status: + description: VMPodScrapeStatus defines the observed state of VMPodScrape + 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.12.1 + name: vmprobes.operator.victoriametrics.com +spec: + group: operator.victoriametrics.com + names: + kind: VMProbe + listKind: VMProbeList + plural: vmprobes + singular: vmprobe + scope: Namespaced + versions: + - name: v1beta1 + schema: + openAPIV3Schema: + description: VMProbe defines a probe for targets, that will be executed with + prober, like blackbox exporter. It helps to monitor reachability of target + with various checks. + 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: VMProbeSpec contains specification parameters for a Probe. + properties: + authorization: + description: Authorization with http header Authorization + properties: + credentials: + description: Reference to the secret with value for authorization + properties: + key: + description: The key of the secret to select from. Must be + a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + credentialsFile: + description: File with value for authorization + type: string + type: + description: Type of authorization, default to bearer + type: string + type: object + basicAuth: + description: 'BasicAuth allow an endpoint to authenticate over basic + authentication More info: https://prometheus.io/docs/operating/configuration/#endpoints' + properties: + password: + description: The secret in the service scrape namespace that contains + the password for authentication. It must be at them same namespace + as CRD + properties: + key: + description: The key of the secret to select from. Must be + a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + password_file: + description: PasswordFile defines path to password file at disk + type: string + username: + description: The secret in the service scrape namespace that contains + the username for authentication. It must be at them same namespace + as CRD + properties: + key: + description: The key of the secret to select from. Must be + a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + bearerTokenFile: + description: File to read bearer token for scraping targets. + type: string + bearerTokenSecret: + description: Secret to mount to read bearer token for scraping targets. + The secret needs to be in the same namespace as the service scrape + and accessible by the victoria-metrics operator. + nullable: true + properties: + key: + description: The key of the secret to select from. Must be a + valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + follow_redirects: + description: FollowRedirects controls redirects for scraping. + type: boolean + interval: + description: Interval at which targets are probed using the configured + prober. If not specified Prometheus' global scrape interval is used. + type: string + jobName: + description: The job name assigned to scraped metrics by default. + type: string + module: + description: 'The module to use for probing specifying how to probe + the target. Example module configuring in the blackbox exporter: + https://github.com/prometheus/blackbox_exporter/blob/master/example.yml' + type: string + oauth2: + description: OAuth2 defines auth configuration + properties: + client_id: + description: The secret or configmap containing the OAuth2 client + id + properties: + configMap: + description: ConfigMap containing data to use for the targets. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + secret: + description: Secret containing data to use for the targets. + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + client_secret: + description: The secret containing the OAuth2 client secret + properties: + key: + description: The key of the secret to select from. Must be + a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + client_secret_file: + description: ClientSecretFile defines path for client secret file. + type: string + endpoint_params: + additionalProperties: + type: string + description: Parameters to append to the token URL + type: object + scopes: + description: OAuth2 scopes used for the token request + items: + type: string + type: array + token_url: + description: The URL to fetch the token from + minLength: 1 + type: string + required: + - client_id + - token_url + type: object + params: + additionalProperties: + items: + type: string + type: array + description: Optional HTTP URL parameters + type: object + sampleLimit: + description: SampleLimit defines per-scrape limit on number of scraped + samples that will be accepted. + format: int64 + type: integer + scrape_interval: + description: ScrapeInterval is the same as Interval and has priority + over it. one of scrape_interval or interval can be used + type: string + scrapeTimeout: + description: Timeout for scraping metrics from the Prometheus exporter. + type: string + targets: + description: Targets defines a set of static and/or dynamically discovered + targets to be probed using the prober. + properties: + ingress: + description: Ingress defines the set of dynamically discovered + ingress objects which hosts are considered for probing. + properties: + namespaceSelector: + description: Select Ingress objects by namespace. + properties: + any: + description: Boolean describing whether all namespaces + are selected in contrast to a list restricting them. + type: boolean + matchNames: + description: List of namespace names. + items: + type: string + type: array + type: object + relabelingConfigs: + description: 'RelabelConfigs to apply to samples before ingestion. + More info: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#relabel_config' + items: + description: 'RelabelConfig allows dynamic rewriting of + the label set, being applied to samples before ingestion. + It defines ``-section of configuration. + More info: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#metric_relabel_configs' + properties: + action: + description: Action to perform based on regex matching. + Default is 'replace' + type: string + if: + description: 'If represents metricsQL match expression: + ''{__name__=~"foo_.*"}''' + type: string + labels: + additionalProperties: + type: string + description: 'Labels is used together with Match for + `action: graphite`' + type: object + match: + description: 'Match is used together with Labels for + `action: graphite`' + type: string + modulus: + description: Modulus to take of the hash of the source + label values. + format: int64 + type: integer + regex: + description: Regular expression against which the extracted + value is matched. Default is '(.*)' + type: string + replacement: + description: Replacement value against which a regex + replace is performed if the regular expression matches. + Regex capture groups are available. Default is '$1' + type: string + separator: + description: Separator placed between concatenated source + label values. default is ';'. + type: string + source_labels: + description: UnderScoreSourceLabels - additional form + of source labels source_labels for compatibility with + original relabel config. if set both sourceLabels + and source_labels, sourceLabels has priority. for + details https://github.com/VictoriaMetrics/operator/issues/131 + items: + type: string + type: array + sourceLabels: + description: The source labels select values from existing + labels. Their content is concatenated using the configured + separator and matched against the configured regular + expression for the replace, keep, and drop actions. + items: + type: string + type: array + target_label: + description: UnderScoreTargetLabel - additional form + of target label - target_label for compatibility with + original relabel config. if set both targetLabel + and target_label, targetLabel has priority. for details + https://github.com/VictoriaMetrics/operator/issues/131 + type: string + targetLabel: + description: Label to which the resulting value is written + in a replace action. It is mandatory for replace actions. + Regex capture groups are available. + type: string + type: object + type: array + selector: + description: Select Ingress objects by labels. + 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 + required: + - key + - operator + type: object + type: array + 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 + type: object + staticConfig: + description: 'StaticConfig defines static targets which are considers + for probing. More info: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#static_config.' + properties: + labels: + additionalProperties: + type: string + description: Labels assigned to all metrics scraped from the + targets. + type: object + relabelingConfigs: + description: 'More info: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#relabel_config' + items: + description: 'RelabelConfig allows dynamic rewriting of + the label set, being applied to samples before ingestion. + It defines ``-section of configuration. + More info: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#metric_relabel_configs' + properties: + action: + description: Action to perform based on regex matching. + Default is 'replace' + type: string + if: + description: 'If represents metricsQL match expression: + ''{__name__=~"foo_.*"}''' + type: string + labels: + additionalProperties: + type: string + description: 'Labels is used together with Match for + `action: graphite`' + type: object + match: + description: 'Match is used together with Labels for + `action: graphite`' + type: string + modulus: + description: Modulus to take of the hash of the source + label values. + format: int64 + type: integer + regex: + description: Regular expression against which the extracted + value is matched. Default is '(.*)' + type: string + replacement: + description: Replacement value against which a regex + replace is performed if the regular expression matches. + Regex capture groups are available. Default is '$1' + type: string + separator: + description: Separator placed between concatenated source + label values. default is ';'. + type: string + source_labels: + description: UnderScoreSourceLabels - additional form + of source labels source_labels for compatibility with + original relabel config. if set both sourceLabels + and source_labels, sourceLabels has priority. for + details https://github.com/VictoriaMetrics/operator/issues/131 + items: + type: string + type: array + sourceLabels: + description: The source labels select values from existing + labels. Their content is concatenated using the configured + separator and matched against the configured regular + expression for the replace, keep, and drop actions. + items: + type: string + type: array + target_label: + description: UnderScoreTargetLabel - additional form + of target label - target_label for compatibility with + original relabel config. if set both targetLabel + and target_label, targetLabel has priority. for details + https://github.com/VictoriaMetrics/operator/issues/131 + type: string + targetLabel: + description: Label to which the resulting value is written + in a replace action. It is mandatory for replace actions. + Regex capture groups are available. + type: string + type: object + type: array + targets: + description: Targets is a list of URLs to probe using the + configured prober. + items: + type: string + type: array + required: + - targets + type: object + type: object + tlsConfig: + description: TLSConfig configuration to use when scraping the endpoint + properties: + ca: + description: Stuct containing the CA cert to use for the targets. + properties: + configMap: + description: ConfigMap containing data to use for the targets. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + secret: + description: Secret containing data to use for the targets. + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + caFile: + description: Path to the CA cert in the container to use for the + targets. + type: string + cert: + description: Struct containing the client cert file for the targets. + properties: + configMap: + description: ConfigMap containing data to use for the targets. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + secret: + description: Secret containing data to use for the targets. + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + certFile: + description: Path to the client cert file in the container for + the targets. + type: string + insecureSkipVerify: + description: Disable target certificate validation. + type: boolean + keyFile: + description: Path to the client key file in the container for + the targets. + type: string + keySecret: + description: Secret containing the client key file for the targets. + properties: + key: + description: The key of the secret to select from. Must be + a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + serverName: + description: Used to verify the hostname for the targets. + type: string + type: object + vm_scrape_params: + description: VMScrapeParams defines VictoriaMetrics specific scrape + parametrs + properties: + disable_compression: + type: boolean + disable_keep_alive: + type: boolean + headers: + description: 'Headers allows sending custom headers to scrape + targets must be in of semicolon separated header with it''s + value eg: headerName: headerValue vmagent supports since 1.79.0 + version' + items: + type: string + type: array + metric_relabel_debug: + type: boolean + no_stale_markers: + type: boolean + proxy_client_config: + description: ProxyClientConfig configures proxy auth settings + for scraping See feature description https://docs.victoriametrics.com/vmagent.html#scraping-targets-via-a-proxy + properties: + basic_auth: + description: BasicAuth allow an endpoint to authenticate over + basic authentication + properties: + password: + description: The secret in the service scrape namespace + that contains the password for authentication. It must + be at them same namespace as CRD + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + 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 + password_file: + description: PasswordFile defines path to password file + at disk + type: string + username: + description: The secret in the service scrape namespace + that contains the username for authentication. It must + be at them same namespace as CRD + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + 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 + bearer_token: + description: SecretKeySelector selects a key of a Secret. + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + bearer_token_file: + type: string + tls_config: + description: TLSConfig specifies TLSConfig configuration parameters. + properties: + ca: + description: Stuct containing the CA cert to use for the + targets. + properties: + configMap: + description: ConfigMap containing data to use for + the targets. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + 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 + secret: + description: Secret containing data to use for the + targets. + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + 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 + caFile: + description: Path to the CA cert in the container to use + for the targets. + type: string + cert: + description: Struct containing the client cert file for + the targets. + properties: + configMap: + description: ConfigMap containing data to use for + the targets. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + 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 + secret: + description: Secret containing data to use for the + targets. + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + 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 + certFile: + description: Path to the client cert file in the container + for the targets. + type: string + insecureSkipVerify: + description: Disable target certificate validation. + type: boolean + keyFile: + description: Path to the client key file in the container + for the targets. + type: string + keySecret: + description: Secret containing the client key file for + the targets. + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + 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 + serverName: + description: Used to verify the hostname for the targets. + type: string + type: object + type: object + relabel_debug: + type: boolean + scrape_align_interval: + type: string + scrape_offset: + type: string + stream_parse: + type: boolean + type: object + vmProberSpec: + description: Specification for the prober to use for probing targets. + The prober.URL parameter is required. Targets cannot be probed if + left empty. + properties: + path: + description: Path to collect metrics from. Defaults to `/probe`. + type: string + scheme: + description: HTTP scheme to use for scraping. Defaults to `http`. + enum: + - http + - https + type: string + url: + description: Mandatory URL of the prober. + type: string + required: + - url + type: object + required: + - vmProberSpec + type: object + status: + description: VMProbeStatus defines the observed state of VMProbe + type: object + required: + - spec + type: object + served: true + storage: true + subresources: + status: {} +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.12.1 + name: vmrules.operator.victoriametrics.com +spec: + group: operator.victoriametrics.com + names: + kind: VMRule + listKind: VMRuleList + plural: vmrules + singular: vmrule + scope: Namespaced + versions: + - name: v1beta1 + schema: + openAPIV3Schema: + description: VMRule defines rule records for vmalert application + 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: VMRuleSpec defines the desired state of VMRule + properties: + groups: + description: Groups list of group rules + items: + description: RuleGroup is a list of sequentially evaluated recording + and alerting rules. + properties: + concurrency: + description: Concurrency defines how many rules execute at once. + type: integer + extra_filter_labels: + additionalProperties: + type: string + description: ExtraFilterLabels optional list of label filters + applied to every rule's request withing a group. Is compatible + only with VM datasource. See more details at https://docs.victoriametrics.com#prometheus-querying-api-enhancements + Deprecated, use params instead + type: object + headers: + description: 'Headers contains optional HTTP headers added to + each rule request Must be in form `header-name: value` For + example: headers: - "CustomHeader: foo" - "CustomHeader2: + bar"' + items: + type: string + type: array + interval: + description: evaluation interval for group + type: string + labels: + additionalProperties: + type: string + description: Labels optional list of labels added to every rule + within a group. It has priority over the external labels. + Labels are commonly used for adding environment or tenant-specific + tag. + type: object + limit: + description: Limit the number of alerts an alerting rule and + series a recording rule can produce + type: integer + name: + description: Name of group + type: string + notifier_headers: + description: 'NotifierHeaders contains optional HTTP headers + added to each alert request which will send to notifier Must + be in form `header-name: value` For example: headers: - "CustomHeader: + foo" - "CustomHeader2: bar"' + items: + type: string + type: array + params: + additionalProperties: + items: + type: string + type: array + description: Params optional HTTP URL parameters added to each + rule request + type: object + rules: + description: Rules list of alert rules + items: + description: Rule describes an alerting or recording rule. + properties: + alert: + description: Alert is a name for alert + type: string + annotations: + additionalProperties: + type: string + description: Annotations will be added to rule configuration + type: object + debug: + description: Debug enables logging for rule it useful + for tracking + type: boolean + expr: + description: Expr is query, that will be evaluated at + dataSource + type: string + for: + description: For evaluation interval in time.Duration + format 30s, 1m, 1h or nanoseconds + type: string + keep_firing_for: + description: KeepFiringFor will make alert continue firing + for this long even when the alerting expression no longer + has results. Use time.Duration format, 30s, 1m, 1h or + nanoseconds + type: string + labels: + additionalProperties: + type: string + description: Labels will be added to rule configuration + type: object + record: + description: Record represents a query, that will be recorded + to dataSource + type: string + update_entries_limit: + description: UpdateEntriesLimit defines max number of + rule's state updates stored in memory. Overrides `-rule.updateEntriesLimit` + in vmalert. + type: integer + type: object + type: array + tenant: + description: Tenant id for group, can be used only with enterprise + version of vmalert See more details at https://docs.victoriametrics.com/vmalert.html#multitenancy + type: string + type: + description: Type defines datasource type for enterprise version + of vmalert possible values - prometheus,graphite + type: string + required: + - name + - rules + type: object + type: array + required: + - groups + type: object + status: + description: VMRuleStatus defines the observed state of VMRule + type: object + required: + - spec + type: object + served: true + storage: true + subresources: + status: {} +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.12.1 + name: vmservicescrapes.operator.victoriametrics.com +spec: + group: operator.victoriametrics.com + names: + kind: VMServiceScrape + listKind: VMServiceScrapeList + plural: vmservicescrapes + singular: vmservicescrape + scope: Namespaced + versions: + - name: v1beta1 + schema: + openAPIV3Schema: + description: VMServiceScrape is scrape configuration for endpoints associated + with kubernetes service, it generates scrape configuration for vmagent based + on selectors. result config will scrape service endpoints + 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: VMServiceScrapeSpec defines the desired state of VMServiceScrape + properties: + discoveryRole: + description: 'DiscoveryRole - defines kubernetes_sd role for objects + discovery. by default, its endpoints. can be changed to service + or endpointslices. note, that with service setting, you have to + use port: "name" and cannot use targetPort for endpoints.' + enum: + - endpoints + - service + - endpointslices + type: string + endpoints: + description: A list of endpoints allowed as part of this ServiceScrape. + items: + description: Endpoint defines a scrapeable endpoint serving Prometheus + metrics. + properties: + attach_metadata: + description: AttachMetadata configures metadata attaching from + service discovery + properties: + node: + description: 'Node instructs vmagent to add node specific + metadata from service discovery Valid for roles: pod, + endpoints, endpointslice.' + type: boolean + type: object + authorization: + description: Authorization with http header Authorization + properties: + credentials: + description: Reference to the secret with value for authorization + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + credentialsFile: + description: File with value for authorization + type: string + type: + description: Type of authorization, default to bearer + type: string + type: object + basicAuth: + description: 'BasicAuth allow an endpoint to authenticate over + basic authentication More info: https://prometheus.io/docs/operating/configuration/#endpoints' + properties: + password: + description: The secret in the service scrape namespace + that contains the password for authentication. It must + be at them same namespace as CRD + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + password_file: + description: PasswordFile defines path to password file + at disk + type: string + username: + description: The secret in the service scrape namespace + that contains the username for authentication. It must + be at them same namespace as CRD + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + bearerTokenFile: + description: File to read bearer token for scraping targets. + type: string + bearerTokenSecret: + description: Secret to mount to read bearer token for scraping + targets. The secret needs to be in the same namespace as the + service scrape and accessible by the victoria-metrics operator. + nullable: true + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + follow_redirects: + description: FollowRedirects controls redirects for scraping. + type: boolean + honorLabels: + description: HonorLabels chooses the metric's labels on collisions + with target labels. + type: boolean + honorTimestamps: + description: HonorTimestamps controls whether vmagent respects + the timestamps present in scraped data. + type: boolean + interval: + description: Interval at which metrics should be scraped + type: string + metricRelabelConfigs: + description: MetricRelabelConfigs to apply to samples before + ingestion. + items: + description: 'RelabelConfig allows dynamic rewriting of the + label set, being applied to samples before ingestion. It + defines ``-section of configuration. + More info: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#metric_relabel_configs' + properties: + action: + description: Action to perform based on regex matching. + Default is 'replace' + type: string + if: + description: 'If represents metricsQL match expression: + ''{__name__=~"foo_.*"}''' + type: string + labels: + additionalProperties: + type: string + description: 'Labels is used together with Match for `action: + graphite`' + type: object + match: + description: 'Match is used together with Labels for `action: + graphite`' + type: string + modulus: + description: Modulus to take of the hash of the source + label values. + format: int64 + type: integer + regex: + description: Regular expression against which the extracted + value is matched. Default is '(.*)' + type: string + replacement: + description: Replacement value against which a regex replace + is performed if the regular expression matches. Regex + capture groups are available. Default is '$1' + type: string + separator: + description: Separator placed between concatenated source + label values. default is ';'. + type: string + source_labels: + description: UnderScoreSourceLabels - additional form + of source labels source_labels for compatibility with + original relabel config. if set both sourceLabels and + source_labels, sourceLabels has priority. for details + https://github.com/VictoriaMetrics/operator/issues/131 + items: + type: string + type: array + sourceLabels: + description: The source labels select values from existing + labels. Their content is concatenated using the configured + separator and matched against the configured regular + expression for the replace, keep, and drop actions. + items: + type: string + type: array + target_label: + description: UnderScoreTargetLabel - additional form of + target label - target_label for compatibility with original + relabel config. if set both targetLabel and target_label, + targetLabel has priority. for details https://github.com/VictoriaMetrics/operator/issues/131 + type: string + targetLabel: + description: Label to which the resulting value is written + in a replace action. It is mandatory for replace actions. + Regex capture groups are available. + type: string + type: object + type: array + oauth2: + description: OAuth2 defines auth configuration + properties: + client_id: + description: The secret or configmap containing the OAuth2 + client id + properties: + configMap: + description: ConfigMap containing data to use for the + targets. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + 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 + secret: + description: Secret containing data to use for the targets. + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + 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 + client_secret: + description: The secret containing the OAuth2 client secret + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + client_secret_file: + description: ClientSecretFile defines path for client secret + file. + type: string + endpoint_params: + additionalProperties: + type: string + description: Parameters to append to the token URL + type: object + scopes: + description: OAuth2 scopes used for the token request + items: + type: string + type: array + token_url: + description: The URL to fetch the token from + minLength: 1 + type: string + required: + - client_id + - token_url + type: object + params: + additionalProperties: + items: + type: string + type: array + description: Optional HTTP URL parameters + type: object + path: + description: HTTP path to scrape for metrics. + type: string + port: + description: Name of the service port this endpoint refers to. + Mutually exclusive with targetPort. + type: string + proxyURL: + description: ProxyURL eg http://proxyserver:2195 Directs scrapes + to proxy through this endpoint. + type: string + relabelConfigs: + description: 'RelabelConfigs to apply to samples before scraping. + More info: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#relabel_config' + items: + description: 'RelabelConfig allows dynamic rewriting of the + label set, being applied to samples before ingestion. It + defines ``-section of configuration. + More info: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#metric_relabel_configs' + properties: + action: + description: Action to perform based on regex matching. + Default is 'replace' + type: string + if: + description: 'If represents metricsQL match expression: + ''{__name__=~"foo_.*"}''' + type: string + labels: + additionalProperties: + type: string + description: 'Labels is used together with Match for `action: + graphite`' + type: object + match: + description: 'Match is used together with Labels for `action: + graphite`' + type: string + modulus: + description: Modulus to take of the hash of the source + label values. + format: int64 + type: integer + regex: + description: Regular expression against which the extracted + value is matched. Default is '(.*)' + type: string + replacement: + description: Replacement value against which a regex replace + is performed if the regular expression matches. Regex + capture groups are available. Default is '$1' + type: string + separator: + description: Separator placed between concatenated source + label values. default is ';'. + type: string + source_labels: + description: UnderScoreSourceLabels - additional form + of source labels source_labels for compatibility with + original relabel config. if set both sourceLabels and + source_labels, sourceLabels has priority. for details + https://github.com/VictoriaMetrics/operator/issues/131 + items: + type: string + type: array + sourceLabels: + description: The source labels select values from existing + labels. Their content is concatenated using the configured + separator and matched against the configured regular + expression for the replace, keep, and drop actions. + items: + type: string + type: array + target_label: + description: UnderScoreTargetLabel - additional form of + target label - target_label for compatibility with original + relabel config. if set both targetLabel and target_label, + targetLabel has priority. for details https://github.com/VictoriaMetrics/operator/issues/131 + type: string + targetLabel: + description: Label to which the resulting value is written + in a replace action. It is mandatory for replace actions. + Regex capture groups are available. + type: string + type: object + type: array + sampleLimit: + description: SampleLimit defines per-endpoint limit on number + of scraped samples that will be accepted. + format: int64 + type: integer + scheme: + description: HTTP scheme to use for scraping. + enum: + - http + - https + type: string + scrape_interval: + description: ScrapeInterval is the same as Interval and has + priority over it. one of scrape_interval or interval can be + used + type: string + scrapeTimeout: + description: Timeout after which the scrape is ended + type: string + targetPort: + anyOf: + - type: integer + - type: string + description: Name or number of the pod port this endpoint refers + to. Mutually exclusive with port. + x-kubernetes-int-or-string: true + tlsConfig: + description: TLSConfig configuration to use when scraping the + endpoint + properties: + ca: + description: Stuct containing the CA cert to use for the + targets. + properties: + configMap: + description: ConfigMap containing data to use for the + targets. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + 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 + secret: + description: Secret containing data to use for the targets. + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + 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 + caFile: + description: Path to the CA cert in the container to use + for the targets. + type: string + cert: + description: Struct containing the client cert file for + the targets. + properties: + configMap: + description: ConfigMap containing data to use for the + targets. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + 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 + secret: + description: Secret containing data to use for the targets. + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + 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 + certFile: + description: Path to the client cert file in the container + for the targets. + type: string + insecureSkipVerify: + description: Disable target certificate validation. + type: boolean + keyFile: + description: Path to the client key file in the container + for the targets. + type: string + keySecret: + description: Secret containing the client key file for the + targets. + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + serverName: + description: Used to verify the hostname for the targets. + type: string + type: object + vm_scrape_params: + description: VMScrapeParams defines VictoriaMetrics specific + scrape parametrs + properties: + disable_compression: + type: boolean + disable_keep_alive: + type: boolean + headers: + description: 'Headers allows sending custom headers to scrape + targets must be in of semicolon separated header with + it''s value eg: headerName: headerValue vmagent supports + since 1.79.0 version' + items: + type: string + type: array + metric_relabel_debug: + type: boolean + no_stale_markers: + type: boolean + proxy_client_config: + description: ProxyClientConfig configures proxy auth settings + for scraping See feature description https://docs.victoriametrics.com/vmagent.html#scraping-targets-via-a-proxy + properties: + basic_auth: + description: BasicAuth allow an endpoint to authenticate + over basic authentication + properties: + password: + description: The secret in the service scrape namespace + that contains the password for authentication. + It must be at them same namespace as CRD + properties: + key: + description: The key of the secret to select + from. Must be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + 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 + password_file: + description: PasswordFile defines path to password + file at disk + type: string + username: + description: The secret in the service scrape namespace + that contains the username for authentication. + It must be at them same namespace as CRD + properties: + key: + description: The key of the secret to select + from. Must be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + 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 + bearer_token: + description: SecretKeySelector selects a key of a Secret. + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + 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 + bearer_token_file: + type: string + tls_config: + description: TLSConfig specifies TLSConfig configuration + parameters. + properties: + ca: + description: Stuct containing the CA cert to use + for the targets. + properties: + configMap: + description: ConfigMap containing data to use + for the targets. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + 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 + secret: + description: Secret containing data to use for + the targets. + properties: + key: + description: The key of the secret to select + from. Must be a valid secret key. + type: string + name: + description: 'Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + 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 + caFile: + description: Path to the CA cert in the container + to use for the targets. + type: string + cert: + description: Struct containing the client cert file + for the targets. + properties: + configMap: + description: ConfigMap containing data to use + for the targets. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + 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 + secret: + description: Secret containing data to use for + the targets. + properties: + key: + description: The key of the secret to select + from. Must be a valid secret key. + type: string + name: + description: 'Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + 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 + certFile: + description: Path to the client cert file in the + container for the targets. + type: string + insecureSkipVerify: + description: Disable target certificate validation. + type: boolean + keyFile: + description: Path to the client key file in the + container for the targets. + type: string + keySecret: + description: Secret containing the client key file + for the targets. + properties: + key: + description: The key of the secret to select + from. Must be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + 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 + serverName: + description: Used to verify the hostname for the + targets. + type: string + type: object + type: object + relabel_debug: + type: boolean + scrape_align_interval: + type: string + scrape_offset: + type: string + stream_parse: + type: boolean + type: object + type: object + type: array + jobLabel: + description: The label to use to retrieve the job name from. + type: string + namespaceSelector: + description: Selector to select which namespaces the Endpoints objects + are discovered from. + properties: + any: + description: Boolean describing whether all namespaces are selected + in contrast to a list restricting them. + type: boolean + matchNames: + description: List of namespace names. + items: + type: string + type: array + type: object + podTargetLabels: + description: PodTargetLabels transfers labels on the Kubernetes Pod + onto the target. + items: + type: string + type: array + sampleLimit: + description: SampleLimit defines per-scrape limit on number of scraped + samples that will be accepted. + format: int64 + type: integer + selector: + description: Selector to select Endpoints objects by corresponding + Service labels. + 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 + required: + - key + - operator + type: object + type: array + 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 + targetLabels: + description: TargetLabels transfers labels on the Kubernetes Service + onto the target. + items: + type: string + type: array + required: + - endpoints + type: object + status: + description: VMServiceScrapeStatus defines the observed state of VMServiceScrape + type: object + required: + - spec + type: object + served: true + storage: true + subresources: + status: {} +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.12.1 + name: vmsingles.operator.victoriametrics.com +spec: + group: operator.victoriametrics.com + names: + kind: VMSingle + listKind: VMSingleList + plural: vmsingles + singular: vmsingle + scope: Namespaced + versions: + - additionalPrinterColumns: + - description: Current status of single node + jsonPath: .status.singleStatus + name: Status + type: string + name: v1beta1 + schema: + openAPIV3Schema: + description: VMSingle is fast, cost-effective and scalable time-series database. + 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: VMSingleSpec defines the desired state of VMSingle + properties: + affinity: + description: Affinity If specified, the pod's scheduling constraints. + type: object + x-kubernetes-preserve-unknown-fields: true + configMaps: + description: ConfigMaps is a list of ConfigMaps in the same namespace + as the VMSingle object, which shall be mounted into the VMSingle + Pods. + items: + type: string + type: array + containers: + description: Containers property allows to inject additions sidecars + or to patch existing containers. It can be useful for proxies, backup, + etc. + items: + description: A single application container that you want to run + within a pod. + required: + - name + type: object + x-kubernetes-preserve-unknown-fields: true + type: array + dnsConfig: + description: Specifies the DNS parameters of a pod. Parameters specified + here will be merged to the generated DNS configuration based on + DNSPolicy. + items: + x-kubernetes-preserve-unknown-fields: true + properties: + nameservers: + description: A list of DNS name server IP addresses. This will + be appended to the base nameservers generated from DNSPolicy. + Duplicated nameservers will be removed. + items: + type: string + type: array + options: + description: A list of DNS resolver options. This will be merged + with the base options generated from DNSPolicy. Duplicated entries + will be removed. Resolution options given in Options will override + those that appear in the base DNSPolicy. + items: + description: PodDNSConfigOption defines DNS resolver options + of a pod. + properties: + name: + description: Required. + type: string + value: + type: string + type: object + type: array + searches: + description: A list of DNS search domains for host-name lookup. + This will be appended to the base search paths generated from + DNSPolicy. Duplicated search paths will be removed. + items: + type: string + type: array + type: object + dnsPolicy: + description: DNSPolicy sets DNS policy for the pod + type: string + extraArgs: + additionalProperties: + type: string + description: 'ExtraArgs that will be passed to VMSingle pod for example + remoteWrite.tmpDataPath: /tmp' + type: object + extraEnvs: + description: ExtraEnvs that will be added to VMSingle pod + 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 + required: + - name + type: object + x-kubernetes-preserve-unknown-fields: true + type: array + hostAliases: + description: HostAliases provides mapping for ip and hostname, that + would be propagated to pod, cannot be used with HostNetwork. + items: + description: HostAlias holds the mapping between IP and hostnames + that will be injected as an entry in the pod's hosts file. + properties: + hostnames: + description: Hostnames for the above IP address. + items: + type: string + type: array + ip: + description: IP address of the host file entry. + type: string + type: object + type: array + hostNetwork: + description: HostNetwork controls whether the pod may use the node + network namespace + type: boolean + image: + description: Image - docker image settings for VMSingle if no specified + operator uses default config version + properties: + pullPolicy: + description: PullPolicy describes how to pull docker image + type: string + repository: + description: Repository contains name of docker image + it's repository + if needed + type: string + tag: + description: Tag contains desired docker image version + type: string + type: object + imagePullSecrets: + description: ImagePullSecrets An optional list of references to secrets + in the same namespace to use for pulling images from registries + see https://kubernetes.io/docs/concepts/containers/images/#referring-to-an-imagepullsecrets-on-a-pod + items: + description: LocalObjectReference contains enough information to + let you locate the referenced object inside the same namespace. + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + x-kubernetes-map-type: atomic + type: array + initContainers: + description: 'InitContainers allows adding initContainers to the pod + definition. Those can be used to e.g. fetch secrets for injection + into the vmSingle configuration from external sources. Any errors + during the execution of an initContainer will lead to a restart + of the Pod. More info: https://kubernetes.io/docs/concepts/workloads/pods/init-containers/ + Using initContainers for any use case other then secret fetching + is entirely outside the scope of what the maintainers will support + and by doing so, you accept that this behaviour may break at any + time without notice.' + items: + description: A single application container that you want to run + within a pod. + required: + - name + type: object + x-kubernetes-preserve-unknown-fields: true + type: array + insertPorts: + description: InsertPorts - additional listen ports for data ingestion. + properties: + graphitePort: + description: GraphitePort listen port + type: string + influxPort: + description: InfluxPort listen port + type: string + openTSDBHTTPPort: + description: OpenTSDBHTTPPort for http connections. + type: string + openTSDBPort: + description: OpenTSDBPort for tcp and udp listen + type: string + type: object + livenessProbe: + description: LivenessProbe that will be added CRD pod + type: object + x-kubernetes-preserve-unknown-fields: true + logFormat: + description: LogFormat for VMSingle to be configured with. + enum: + - default + - json + type: string + logLevel: + description: LogLevel for victoria metrics single to be configured + with. + enum: + - INFO + - WARN + - ERROR + - FATAL + - PANIC + type: string + nodeSelector: + additionalProperties: + type: string + description: NodeSelector Define which Nodes the Pods are scheduled + on. + type: object + podMetadata: + description: PodMetadata configures Labels and Annotations which are + propagated to the VMSingle pods. + properties: + annotations: + additionalProperties: + type: string + description: 'Annotations is an unstructured key value map stored + with a resource that may be set by external tools to store and + retrieve arbitrary metadata. They are not queryable and should + be preserved when modifying objects. More info: http://kubernetes.io/docs/user-guide/annotations' + type: object + labels: + additionalProperties: + type: string + description: 'Labels Map of string keys and values that can be + used to organize and categorize (scope and select) objects. + May match selectors of replication controllers and services. + More info: http://kubernetes.io/docs/user-guide/labels' + type: object + name: + description: 'Name must be unique within a namespace. Is required + when creating resources, although some resources may allow a + client to request the generation of an appropriate name automatically. + Name is primarily intended for creation idempotence and configuration + definition. Cannot be updated. More info: http://kubernetes.io/docs/user-guide/identifiers#names' + type: string + type: object + podSecurityPolicyName: + description: PodSecurityPolicyName - defines name for podSecurityPolicy + in case of empty value, prefixedName will be used. + type: string + port: + description: Port listen port + type: string + priorityClassName: + description: PriorityClassName assigned to the Pods + type: string + readinessGates: + description: ReadinessGates defines pod readiness gates + items: + description: PodReadinessGate contains the reference to a pod condition + properties: + conditionType: + description: ConditionType refers to a condition in the pod's + condition list with matching type. + type: string + required: + - conditionType + type: object + type: array + readinessProbe: + description: ReadinessProbe that will be added CRD pod + type: object + x-kubernetes-preserve-unknown-fields: true + removePvcAfterDelete: + description: RemovePvcAfterDelete - if true, controller adds ownership + to pvc and after VMSingle objest deletion - pvc will be garbage + collected by controller manager + type: boolean + replicaCount: + description: ReplicaCount is the expected size of the VMSingle it + can be 0 or 1 if you need more - use vm cluster + format: int32 + type: integer + resources: + description: Resources container resource request and limits, https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + if not defined default resources from operator config will be used + properties: + 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. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + retentionPeriod: + description: RetentionPeriod for the stored metrics Note VictoriaMetrics + has data/ and indexdb/ folders metrics from data/ removed eventually + as soon as partition leaves retention period reverse index data + at indexdb rotates once at the half of configured retention period + https://docs.victoriametrics.com/Single-server-VictoriaMetrics.html#retention + type: string + runtimeClassName: + description: RuntimeClassName - defines runtime class for kubernetes + pod. https://kubernetes.io/docs/concepts/containers/runtime-class/ + type: string + schedulerName: + description: SchedulerName - defines kubernetes scheduler name + type: string + secrets: + description: Secrets is a list of Secrets in the same namespace as + the VMSingle object, which shall be mounted into the VMSingle Pods. + items: + type: string + type: array + securityContext: + description: SecurityContext holds pod-level security attributes and + common container settings. This defaults to the default PodSecurityContext. + type: object + x-kubernetes-preserve-unknown-fields: true + serviceAccountName: + description: ServiceAccountName is the name of the ServiceAccount + to use to run the VMSingle Pods. + type: string + serviceScrapeSpec: + description: ServiceScrapeSpec that will be added to vmsingle VMServiceScrape + spec + required: + - endpoints + type: object + x-kubernetes-preserve-unknown-fields: true + serviceSpec: + description: ServiceSpec that will be added to vmsingle service spec + properties: + metadata: + description: EmbeddedObjectMetadata defines objectMeta for additional + service. + properties: + annotations: + additionalProperties: + type: string + description: 'Annotations is an unstructured key value map + stored with a resource that may be set by external tools + to store and retrieve arbitrary metadata. They are not queryable + and should be preserved when modifying objects. More info: + http://kubernetes.io/docs/user-guide/annotations' + type: object + labels: + additionalProperties: + type: string + description: 'Labels Map of string keys and values that can + be used to organize and categorize (scope and select) objects. + May match selectors of replication controllers and services. + More info: http://kubernetes.io/docs/user-guide/labels' + type: object + name: + description: 'Name must be unique within a namespace. Is required + when creating resources, although some resources may allow + a client to request the generation of an appropriate name + automatically. Name is primarily intended for creation idempotence + and configuration definition. Cannot be updated. More info: + http://kubernetes.io/docs/user-guide/identifiers#names' + type: string + type: object + spec: + description: 'ServiceSpec describes the attributes that a user + creates on a service. More info: https://kubernetes.io/docs/concepts/services-networking/service/' + type: object + x-kubernetes-preserve-unknown-fields: true + required: + - spec + type: object + startupProbe: + description: StartupProbe that will be added to CRD pod + type: object + x-kubernetes-preserve-unknown-fields: true + storage: + description: Storage is the definition of how storage will be used + by the VMSingle by default it`s empty dir + properties: + accessModes: + description: 'accessModes contains the desired access modes the + volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' + items: + type: string + type: array + dataSource: + description: 'dataSource field can be used to specify either: + * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) + * An existing PVC (PersistentVolumeClaim) If the provisioner + or an external controller can support the specified data source, + it will create a new volume based on the contents of the specified + data source. If the AnyVolumeDataSource feature gate is enabled, + this field will always have the same contents as the DataSourceRef + field.' + properties: + apiGroup: + description: APIGroup is the group for the resource being + referenced. If APIGroup is not specified, the specified + Kind must be in the core API group. For any other third-party + types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource being referenced + type: string + name: + description: Name is the name of resource being referenced + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + description: 'dataSourceRef specifies the object from which to + populate the volume with data, if a non-empty volume is desired. + This may be any local object from a non-empty API group (non + core object) or a PersistentVolumeClaim object. When this field + is specified, volume binding will only succeed if the type of + the specified object matches some installed volume populator + or dynamic provisioner. This field will replace the functionality + of the DataSource field and as such if both fields are non-empty, + they must have the same value. For backwards compatibility, + both fields (DataSource and DataSourceRef) will be set to the + same value automatically if one of them is empty and the other + is non-empty. There are two important differences between DataSource + and DataSourceRef: * While DataSource only allows two specific + types of objects, DataSourceRef allows any non-core object, + as well as PersistentVolumeClaim objects. * While DataSource + ignores disallowed values (dropping them), DataSourceRef preserves + all values, and generates an error if a disallowed value is + specified. (Beta) Using this field requires the AnyVolumeDataSource + feature gate to be enabled.' + properties: + apiGroup: + description: APIGroup is the group for the resource being + referenced. If APIGroup is not specified, the specified + Kind must be in the core API group. For any other third-party + types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource being referenced + type: string + name: + description: Name is the name of resource being referenced + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + resources: + description: 'resources represents the minimum resources the volume + should have. If RecoverVolumeExpansionFailure feature is enabled + users are allowed to specify resource requirements that are + lower than previous value but must still be higher than capacity + recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' + properties: + 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. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + selector: + description: selector is a label query over volumes to consider + for binding. + 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 + required: + - key + - operator + type: object + type: array + 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 + storageClassName: + description: 'storageClassName is the name of the StorageClass + required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' + type: string + volumeMode: + description: volumeMode defines what type of volume is required + by the claim. Value of Filesystem is implied when not included + in claim spec. + type: string + volumeName: + description: volumeName is the binding reference to the PersistentVolume + backing this claim. + type: string + type: object + storageDataPath: + description: StorageDataPath disables spec.storage option and overrides + arg for victoria-metrics binary --storageDataPath, its users responsibility + to mount proper device into given path. + type: string + storageMetadata: + description: StorageMeta defines annotations and labels attached to + PVC for given vmsingle CR + properties: + annotations: + additionalProperties: + type: string + description: 'Annotations is an unstructured key value map stored + with a resource that may be set by external tools to store and + retrieve arbitrary metadata. They are not queryable and should + be preserved when modifying objects. More info: http://kubernetes.io/docs/user-guide/annotations' + type: object + labels: + additionalProperties: + type: string + description: 'Labels Map of string keys and values that can be + used to organize and categorize (scope and select) objects. + May match selectors of replication controllers and services. + More info: http://kubernetes.io/docs/user-guide/labels' + type: object + name: + description: 'Name must be unique within a namespace. Is required + when creating resources, although some resources may allow a + client to request the generation of an appropriate name automatically. + Name is primarily intended for creation idempotence and configuration + definition. Cannot be updated. More info: http://kubernetes.io/docs/user-guide/identifiers#names' + type: string + type: object + streamAggrConfig: + description: StreamAggrConfig defines stream aggregation configuration + for VMSingle + properties: + dedupInterval: + description: Allows setting different de-duplication intervals + per each configured remote storage + type: string + dropInput: + description: Allow drop all the input samples after the aggregation + type: boolean + keepInput: + description: Allows writing both raw and aggregate data + type: boolean + rules: + description: Stream aggregation rules + items: + description: StreamAggrRule defines the rule in stream aggregation + config + properties: + by: + description: "By is an optional list of labels for grouping + input series. \n See also Without. \n If neither By nor + Without are set, then the Outputs are calculated individually + per each input time series." + items: + type: string + type: array + input_relabel_configs: + description: InputRelabelConfigs is an optional relabeling + rules, which are applied on the input before aggregation. + items: + description: 'RelabelConfig allows dynamic rewriting of + the label set, being applied to samples before ingestion. + It defines ``-section of configuration. + More info: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#metric_relabel_configs' + properties: + action: + description: Action to perform based on regex matching. + Default is 'replace' + type: string + if: + description: 'If represents metricsQL match expression: + ''{__name__=~"foo_.*"}''' + type: string + labels: + additionalProperties: + type: string + description: 'Labels is used together with Match for + `action: graphite`' + type: object + match: + description: 'Match is used together with Labels for + `action: graphite`' + type: string + modulus: + description: Modulus to take of the hash of the source + label values. + format: int64 + type: integer + regex: + description: Regular expression against which the + extracted value is matched. Default is '(.*)' + type: string + replacement: + description: Replacement value against which a regex + replace is performed if the regular expression matches. + Regex capture groups are available. Default is '$1' + type: string + separator: + description: Separator placed between concatenated + source label values. default is ';'. + type: string + source_labels: + description: UnderScoreSourceLabels - additional form + of source labels source_labels for compatibility + with original relabel config. if set both sourceLabels + and source_labels, sourceLabels has priority. for + details https://github.com/VictoriaMetrics/operator/issues/131 + items: + type: string + type: array + sourceLabels: + description: The source labels select values from + existing labels. Their content is concatenated using + the configured separator and matched against the + configured regular expression for the replace, keep, + and drop actions. + items: + type: string + type: array + target_label: + description: UnderScoreTargetLabel - additional form + of target label - target_label for compatibility + with original relabel config. if set both targetLabel + and target_label, targetLabel has priority. for + details https://github.com/VictoriaMetrics/operator/issues/131 + type: string + targetLabel: + description: Label to which the resulting value is + written in a replace action. It is mandatory for + replace actions. Regex capture groups are available. + type: string + type: object + type: array + interval: + description: Interval is the interval between aggregations. + type: string + match: + description: "Match is a label selector for filtering time + series for the given selector. \n If the match isn't set, + then all the input time series are processed." + items: + type: string + type: array + output_relabel_configs: + description: OutputRelabelConfigs is an optional relabeling + rules, which are applied on the aggregated output before + being sent to remote storage. + items: + description: 'RelabelConfig allows dynamic rewriting of + the label set, being applied to samples before ingestion. + It defines ``-section of configuration. + More info: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#metric_relabel_configs' + properties: + action: + description: Action to perform based on regex matching. + Default is 'replace' + type: string + if: + description: 'If represents metricsQL match expression: + ''{__name__=~"foo_.*"}''' + type: string + labels: + additionalProperties: + type: string + description: 'Labels is used together with Match for + `action: graphite`' + type: object + match: + description: 'Match is used together with Labels for + `action: graphite`' + type: string + modulus: + description: Modulus to take of the hash of the source + label values. + format: int64 + type: integer + regex: + description: Regular expression against which the + extracted value is matched. Default is '(.*)' + type: string + replacement: + description: Replacement value against which a regex + replace is performed if the regular expression matches. + Regex capture groups are available. Default is '$1' + type: string + separator: + description: Separator placed between concatenated + source label values. default is ';'. + type: string + source_labels: + description: UnderScoreSourceLabels - additional form + of source labels source_labels for compatibility + with original relabel config. if set both sourceLabels + and source_labels, sourceLabels has priority. for + details https://github.com/VictoriaMetrics/operator/issues/131 + items: + type: string + type: array + sourceLabels: + description: The source labels select values from + existing labels. Their content is concatenated using + the configured separator and matched against the + configured regular expression for the replace, keep, + and drop actions. + items: + type: string + type: array + target_label: + description: UnderScoreTargetLabel - additional form + of target label - target_label for compatibility + with original relabel config. if set both targetLabel + and target_label, targetLabel has priority. for + details https://github.com/VictoriaMetrics/operator/issues/131 + type: string + targetLabel: + description: Label to which the resulting value is + written in a replace action. It is mandatory for + replace actions. Regex capture groups are available. + type: string + type: object + type: array + outputs: + description: "Outputs is a list of output aggregate functions + to produce. \n The following names are allowed: \n - total + - aggregates input counters - increase - counts the increase + over input counters - count_series - counts the input + series - count_samples - counts the input samples - sum_samples + - sums the input samples - last - the last biggest sample + value - min - the minimum sample value - max - the maximum + sample value - avg - the average value across all the + samples - stddev - standard deviation across all the samples + - stdvar - standard variance across all the samples - + histogram_bucket - creates VictoriaMetrics histogram for + input samples - quantiles(phi1, ..., phiN) - quantiles' + estimation for phi in the range [0..1] \n The output time + series will have the following names: \n input_name:aggr__" + items: + type: string + type: array + staleness_interval: + description: StalenessInterval defines an interval after + which the series state will be reset if no samples have + been sent during it. + type: string + without: + description: "Without is an optional list of labels, which + must be excluded when grouping input series. \n See also + By. \n If neither By nor Without are set, then the Outputs + are calculated individually per each input time series." + items: + type: string + type: array + required: + - interval + - outputs + type: object + type: array + required: + - rules + type: object + terminationGracePeriodSeconds: + description: TerminationGracePeriodSeconds period for container graceful + termination + format: int64 + type: integer + tolerations: + description: Tolerations If specified, the pod's tolerations. + 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: TopologySpreadConstraints embedded kubernetes pod configuration + option, controls how pods are spread across your cluster among failure-domains + such as regions, zones, nodes, and other user-defined topology domains + https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/ + items: + description: TopologySpreadConstraint specifies how to spread matching + pods among the given topology. + required: + - maxSkew + - topologyKey + - whenUnsatisfiable + type: object + x-kubernetes-preserve-unknown-fields: true + type: array + vmBackup: + description: VMBackup configuration for backup + properties: + acceptEULA: + description: AcceptEULA accepts enterprise feature usage, must + be set to true. otherwise backupmanager cannot be added to single/cluster + version. https://victoriametrics.com/legal/eula/ + type: boolean + concurrency: + description: Defines number of concurrent workers. Higher concurrency + may reduce backup duration (default 10) + format: int32 + type: integer + credentialsSecret: + description: CredentialsSecret is secret in the same namespace + for access to remote storage The secret is mounted into /etc/vm/creds. + properties: + key: + description: The key of the secret to select from. Must be + a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + customS3Endpoint: + description: Custom S3 endpoint for use with S3-compatible storages + (e.g. MinIO). S3 is used if not set + type: string + destination: + description: Defines destination for backup + type: string + destinationDisableSuffixAdd: + description: DestinationDisableSuffixAdd - disables suffix adding + for cluster version backups each vmstorage backup must have + unique backup folder so operator adds POD_NAME as suffix for + backup destination folder. + type: boolean + disableDaily: + description: Defines if daily backups disabled (default false) + type: boolean + disableHourly: + description: Defines if hourly backups disabled (default false) + type: boolean + disableMonthly: + description: Defines if monthly backups disabled (default false) + type: boolean + disableWeekly: + description: Defines if weekly backups disabled (default false) + type: boolean + extraArgs: + additionalProperties: + type: string + description: extra args like maxBytesPerSecond default 0 + type: object + extraEnvs: + 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: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + 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: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + 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: Image - docker image settings for VMBackuper + properties: + pullPolicy: + description: PullPolicy describes how to pull docker image + type: string + repository: + description: Repository contains name of docker image + it's + repository if needed + type: string + tag: + description: Tag contains desired docker image version + type: string + type: object + logFormat: + description: LogFormat for VMSelect to be configured with. default + or json + enum: + - default + - json + type: string + logLevel: + description: LogLevel for VMSelect to be configured with. + enum: + - INFO + - WARN + - ERROR + - FATAL + - PANIC + type: string + port: + description: Port for health check connections + type: string + resources: + description: Resources container resource request and limits, + https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + if not defined default resources from operator config will be + used + properties: + 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. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + restore: + description: 'Restore Allows to enable restore options for pod + Read more: https://docs.victoriametrics.com/vmbackupmanager.html#restore-commands' + properties: + onStart: + description: OnStart defines configuration for restore on + pod start + properties: + enabled: + description: Enabled defines if restore on start enabled + type: boolean + type: object + type: object + snapshotCreateURL: + description: SnapshotCreateURL overwrites url for snapshot create + type: string + snapshotDeleteURL: + description: SnapShotDeleteURL overwrites url for snapshot delete + type: string + volumeMounts: + description: VolumeMounts allows configuration of additional VolumeMounts + on the output Deployment definition. VolumeMounts specified + will be appended to other VolumeMounts in the vmbackupmanager + container, that are generated as a result of StorageSpec objects. + items: + description: VolumeMount describes a mounting of a Volume within + a container. + properties: + mountPath: + description: Path within the container at which the volume + should be mounted. Must not contain ':'. + type: string + mountPropagation: + description: mountPropagation determines how mounts are + propagated from the host to container and the other way + around. When not set, MountPropagationNone is used. This + field is beta in 1.10. + type: string + name: + description: This must match the Name of a Volume. + type: string + readOnly: + description: Mounted read-only if true, read-write otherwise + (false or unspecified). Defaults to false. + type: boolean + subPath: + description: Path within the volume from which the container's + volume should be mounted. Defaults to "" (volume's root). + type: string + subPathExpr: + description: Expanded path within the volume from which + the container's volume should be mounted. Behaves similarly + to SubPath but environment variable references $(VAR_NAME) + are expanded using the container's environment. Defaults + to "" (volume's root). SubPathExpr and SubPath are mutually + exclusive. + type: string + required: + - mountPath + - name + type: object + type: array + required: + - acceptEULA + type: object + volumeMounts: + description: VolumeMounts allows configuration of additional VolumeMounts + on the output Deployment definition. VolumeMounts specified will + be appended to other VolumeMounts in the VMSingle container, that + are generated as a result of StorageSpec objects. + items: + description: VolumeMount describes a mounting of a Volume within + a container. + properties: + mountPath: + description: Path within the container at which the volume should + be mounted. Must not contain ':'. + type: string + mountPropagation: + description: mountPropagation determines how mounts are propagated + from the host to container and the other way around. When + not set, MountPropagationNone is used. This field is beta + in 1.10. + type: string + name: + description: This must match the Name of a Volume. + type: string + readOnly: + description: Mounted read-only if true, read-write otherwise + (false or unspecified). Defaults to false. + type: boolean + subPath: + description: Path within the volume from which the container's + volume should be mounted. Defaults to "" (volume's root). + type: string + subPathExpr: + description: Expanded path within the volume from which the + container's volume should be mounted. Behaves similarly to + SubPath but environment variable references $(VAR_NAME) are + expanded using the container's environment. Defaults to "" + (volume's root). SubPathExpr and SubPath are mutually exclusive. + type: string + required: + - mountPath + - name + type: object + type: array + volumes: + description: Volumes allows configuration of additional volumes on + the output deploy definition. Volumes specified will be appended + to other volumes that are generated as a result of StorageSpec objects. + items: + description: Volume represents a named volume in a pod that may + be accessed by any container in the pod. + required: + - name + type: object + x-kubernetes-preserve-unknown-fields: true + type: array + required: + - retentionPeriod + type: object + status: + description: VMSingleStatus defines the observed state of VMSingle + properties: + availableReplicas: + description: AvailableReplicas Total number of available pods (ready + for at least minReadySeconds) targeted by this VMSingle. + format: int32 + type: integer + reason: + type: string + replicas: + description: ReplicaCount Total number of non-terminated pods targeted + by this VMSingle. + format: int32 + type: integer + singleStatus: + type: string + unavailableReplicas: + description: UnavailableReplicas Total number of unavailable pods + targeted by this VMSingle. + format: int32 + type: integer + updatedReplicas: + description: UpdatedReplicas Total number of non-terminated pods targeted + by this VMSingle. + format: int32 + type: integer + required: + - availableReplicas + - replicas + - singleStatus + - unavailableReplicas + - updatedReplicas + 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.12.1 + name: vmstaticscrapes.operator.victoriametrics.com +spec: + group: operator.victoriametrics.com + names: + kind: VMStaticScrape + listKind: VMStaticScrapeList + plural: vmstaticscrapes + singular: vmstaticscrape + scope: Namespaced + versions: + - name: v1beta1 + schema: + openAPIV3Schema: + description: VMStaticScrape defines static targets configuration for scraping. + 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: VMStaticScrapeSpec defines the desired state of VMStaticScrape. + properties: + jobName: + description: JobName name of job. + type: string + sampleLimit: + description: SampleLimit defines per-scrape limit on number of scraped + samples that will be accepted. + format: int64 + type: integer + targetEndpoints: + description: A list of target endpoints to scrape metrics from. + items: + description: TargetEndpoint defines single static target endpoint. + properties: + authorization: + description: Authorization with http header Authorization + properties: + credentials: + description: Reference to the secret with value for authorization + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + credentialsFile: + description: File with value for authorization + type: string + type: + description: Type of authorization, default to bearer + type: string + type: object + basicAuth: + description: 'BasicAuth allow an endpoint to authenticate over + basic authentication More info: https://prometheus.io/docs/operating/configuration/#endpoints' + properties: + password: + description: The secret in the service scrape namespace + that contains the password for authentication. It must + be at them same namespace as CRD + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + password_file: + description: PasswordFile defines path to password file + at disk + type: string + username: + description: The secret in the service scrape namespace + that contains the username for authentication. It must + be at them same namespace as CRD + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + bearerTokenFile: + description: File to read bearer token for scraping targets. + type: string + bearerTokenSecret: + description: Secret to mount to read bearer token for scraping + targets. The secret needs to be in the same namespace as the + service scrape and accessible by the victoria-metrics operator. + nullable: true + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + follow_redirects: + description: FollowRedirects controls redirects for scraping. + type: boolean + honorLabels: + description: HonorLabels chooses the metric's labels on collisions + with target labels. + type: boolean + honorTimestamps: + description: HonorTimestamps controls whether vmagent respects + the timestamps present in scraped data. + type: boolean + interval: + description: Interval at which metrics should be scraped + type: string + labels: + additionalProperties: + type: string + description: Labels static labels for targets. + type: object + metricRelabelConfigs: + description: MetricRelabelConfigs to apply to samples before + ingestion. + items: + description: 'RelabelConfig allows dynamic rewriting of the + label set, being applied to samples before ingestion. It + defines ``-section of configuration. + More info: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#metric_relabel_configs' + properties: + action: + description: Action to perform based on regex matching. + Default is 'replace' + type: string + if: + description: 'If represents metricsQL match expression: + ''{__name__=~"foo_.*"}''' + type: string + labels: + additionalProperties: + type: string + description: 'Labels is used together with Match for `action: + graphite`' + type: object + match: + description: 'Match is used together with Labels for `action: + graphite`' + type: string + modulus: + description: Modulus to take of the hash of the source + label values. + format: int64 + type: integer + regex: + description: Regular expression against which the extracted + value is matched. Default is '(.*)' + type: string + replacement: + description: Replacement value against which a regex replace + is performed if the regular expression matches. Regex + capture groups are available. Default is '$1' + type: string + separator: + description: Separator placed between concatenated source + label values. default is ';'. + type: string + source_labels: + description: UnderScoreSourceLabels - additional form + of source labels source_labels for compatibility with + original relabel config. if set both sourceLabels and + source_labels, sourceLabels has priority. for details + https://github.com/VictoriaMetrics/operator/issues/131 + items: + type: string + type: array + sourceLabels: + description: The source labels select values from existing + labels. Their content is concatenated using the configured + separator and matched against the configured regular + expression for the replace, keep, and drop actions. + items: + type: string + type: array + target_label: + description: UnderScoreTargetLabel - additional form of + target label - target_label for compatibility with original + relabel config. if set both targetLabel and target_label, + targetLabel has priority. for details https://github.com/VictoriaMetrics/operator/issues/131 + type: string + targetLabel: + description: Label to which the resulting value is written + in a replace action. It is mandatory for replace actions. + Regex capture groups are available. + type: string + type: object + type: array + oauth2: + description: OAuth2 defines auth configuration + properties: + client_id: + description: The secret or configmap containing the OAuth2 + client id + properties: + configMap: + description: ConfigMap containing data to use for the + targets. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + 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 + secret: + description: Secret containing data to use for the targets. + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + 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 + client_secret: + description: The secret containing the OAuth2 client secret + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + client_secret_file: + description: ClientSecretFile defines path for client secret + file. + type: string + endpoint_params: + additionalProperties: + type: string + description: Parameters to append to the token URL + type: object + scopes: + description: OAuth2 scopes used for the token request + items: + type: string + type: array + token_url: + description: The URL to fetch the token from + minLength: 1 + type: string + required: + - client_id + - token_url + type: object + params: + additionalProperties: + items: + type: string + type: array + description: Optional HTTP URL parameters + type: object + path: + description: HTTP path to scrape for metrics. + type: string + port: + description: Default port for target. + type: string + proxyURL: + description: ProxyURL eg http://proxyserver:2195 Directs scrapes + to proxy through this endpoint. + type: string + relabelConfigs: + description: 'RelabelConfigs to apply to samples before scraping. + More info: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#relabel_config' + items: + description: 'RelabelConfig allows dynamic rewriting of the + label set, being applied to samples before ingestion. It + defines ``-section of configuration. + More info: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#metric_relabel_configs' + properties: + action: + description: Action to perform based on regex matching. + Default is 'replace' + type: string + if: + description: 'If represents metricsQL match expression: + ''{__name__=~"foo_.*"}''' + type: string + labels: + additionalProperties: + type: string + description: 'Labels is used together with Match for `action: + graphite`' + type: object + match: + description: 'Match is used together with Labels for `action: + graphite`' + type: string + modulus: + description: Modulus to take of the hash of the source + label values. + format: int64 + type: integer + regex: + description: Regular expression against which the extracted + value is matched. Default is '(.*)' + type: string + replacement: + description: Replacement value against which a regex replace + is performed if the regular expression matches. Regex + capture groups are available. Default is '$1' + type: string + separator: + description: Separator placed between concatenated source + label values. default is ';'. + type: string + source_labels: + description: UnderScoreSourceLabels - additional form + of source labels source_labels for compatibility with + original relabel config. if set both sourceLabels and + source_labels, sourceLabels has priority. for details + https://github.com/VictoriaMetrics/operator/issues/131 + items: + type: string + type: array + sourceLabels: + description: The source labels select values from existing + labels. Their content is concatenated using the configured + separator and matched against the configured regular + expression for the replace, keep, and drop actions. + items: + type: string + type: array + target_label: + description: UnderScoreTargetLabel - additional form of + target label - target_label for compatibility with original + relabel config. if set both targetLabel and target_label, + targetLabel has priority. for details https://github.com/VictoriaMetrics/operator/issues/131 + type: string + targetLabel: + description: Label to which the resulting value is written + in a replace action. It is mandatory for replace actions. + Regex capture groups are available. + type: string + type: object + type: array + sampleLimit: + description: SampleLimit defines per-scrape limit on number + of scraped samples that will be accepted. + format: int64 + type: integer + scheme: + description: HTTP scheme to use for scraping. + enum: + - http + - https + type: string + scrape_interval: + description: ScrapeInterval is the same as Interval and has + priority over it. one of scrape_interval or interval can be + used + type: string + scrapeTimeout: + description: Timeout after which the scrape is ended + type: string + targets: + description: Targets static targets addresses in form of ["192.122.55.55:9100","some-name:9100"]. + items: + type: string + minItems: 1 + type: array + tlsConfig: + description: TLSConfig configuration to use when scraping the + endpoint + properties: + ca: + description: Stuct containing the CA cert to use for the + targets. + properties: + configMap: + description: ConfigMap containing data to use for the + targets. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + 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 + secret: + description: Secret containing data to use for the targets. + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + 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 + caFile: + description: Path to the CA cert in the container to use + for the targets. + type: string + cert: + description: Struct containing the client cert file for + the targets. + properties: + configMap: + description: ConfigMap containing data to use for the + targets. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + 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 + secret: + description: Secret containing data to use for the targets. + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + 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 + certFile: + description: Path to the client cert file in the container + for the targets. + type: string + insecureSkipVerify: + description: Disable target certificate validation. + type: boolean + keyFile: + description: Path to the client key file in the container + for the targets. + type: string + keySecret: + description: Secret containing the client key file for the + targets. + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + serverName: + description: Used to verify the hostname for the targets. + type: string + type: object + vm_scrape_params: + description: VMScrapeParams defines VictoriaMetrics specific + scrape parametrs + properties: + disable_compression: + type: boolean + disable_keep_alive: + type: boolean + headers: + description: 'Headers allows sending custom headers to scrape + targets must be in of semicolon separated header with + it''s value eg: headerName: headerValue vmagent supports + since 1.79.0 version' + items: + type: string + type: array + metric_relabel_debug: + type: boolean + no_stale_markers: + type: boolean + proxy_client_config: + description: ProxyClientConfig configures proxy auth settings + for scraping See feature description https://docs.victoriametrics.com/vmagent.html#scraping-targets-via-a-proxy + properties: + basic_auth: + description: BasicAuth allow an endpoint to authenticate + over basic authentication + properties: + password: + description: The secret in the service scrape namespace + that contains the password for authentication. + It must be at them same namespace as CRD + properties: + key: + description: The key of the secret to select + from. Must be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + 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 + password_file: + description: PasswordFile defines path to password + file at disk + type: string + username: + description: The secret in the service scrape namespace + that contains the username for authentication. + It must be at them same namespace as CRD + properties: + key: + description: The key of the secret to select + from. Must be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + 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 + bearer_token: + description: SecretKeySelector selects a key of a Secret. + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + 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 + bearer_token_file: + type: string + tls_config: + description: TLSConfig specifies TLSConfig configuration + parameters. + properties: + ca: + description: Stuct containing the CA cert to use + for the targets. + properties: + configMap: + description: ConfigMap containing data to use + for the targets. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + 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 + secret: + description: Secret containing data to use for + the targets. + properties: + key: + description: The key of the secret to select + from. Must be a valid secret key. + type: string + name: + description: 'Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + 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 + caFile: + description: Path to the CA cert in the container + to use for the targets. + type: string + cert: + description: Struct containing the client cert file + for the targets. + properties: + configMap: + description: ConfigMap containing data to use + for the targets. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + 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 + secret: + description: Secret containing data to use for + the targets. + properties: + key: + description: The key of the secret to select + from. Must be a valid secret key. + type: string + name: + description: 'Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + 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 + certFile: + description: Path to the client cert file in the + container for the targets. + type: string + insecureSkipVerify: + description: Disable target certificate validation. + type: boolean + keyFile: + description: Path to the client key file in the + container for the targets. + type: string + keySecret: + description: Secret containing the client key file + for the targets. + properties: + key: + description: The key of the secret to select + from. Must be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + 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 + serverName: + description: Used to verify the hostname for the + targets. + type: string + type: object + type: object + relabel_debug: + type: boolean + scrape_align_interval: + type: string + scrape_offset: + type: string + stream_parse: + type: boolean + type: object + required: + - targets + type: object + type: array + required: + - targetEndpoints + type: object + status: + description: VMStaticScrapeStatus defines the observed state of VMStaticScrape + 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.12.1 + name: vmusers.operator.victoriametrics.com +spec: + group: operator.victoriametrics.com + names: + kind: VMUser + listKind: VMUserList + plural: vmusers + singular: vmuser + scope: Namespaced + versions: + - name: v1beta1 + schema: + openAPIV3Schema: + description: VMUser is the Schema for the vmusers 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: VMUserSpec defines the desired state of VMUser + properties: + bearerToken: + description: BearerToken Authorization header value for accessing + protected endpoint. + type: string + default_url: + description: DefaultURLs backend url for non-matching paths filter + usually used for default backend with error message + items: + type: string + type: array + generatePassword: + description: GeneratePassword instructs operator to generate password + for user if spec.password if empty. + type: boolean + name: + description: Name of the VMUser object. + type: string + password: + description: Password basic auth password for accessing protected + endpoint. + type: string + passwordRef: + description: PasswordRef allows fetching password from user-create + secret by its name and key. + properties: + key: + description: The key of the secret to select from. Must be a + valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + targetRefs: + description: TargetRefs - reference to endpoints, which user may access. + items: + description: 'TargetRef describes target for user traffic forwarding. + one of target types can be chosen: crd or static per targetRef. + user can define multiple targetRefs with different ref Types.' + properties: + crd: + description: CRD describes exist operator's CRD object, operator + generates access url based on CRD params. + properties: + kind: + description: 'Kind one of: VMAgent VMAlert VMCluster VMSingle + or VMAlertManager' + type: string + name: + description: Name target CRD object name + type: string + namespace: + description: Namespace target CRD object namespace. + type: string + required: + - kind + - name + - namespace + type: object + headers: + description: 'Headers represent additional http headers, that + vmauth uses in form of ["header_key: header_value"] multiple + values for header key: ["header_key: value1,value2"] it''s + available since 1.68.0 version of vmauth' + items: + type: string + type: array + ip_filters: + description: IPFilters defines per target src ip filters supported + only with enterprise version of vmauth https://docs.victoriametrics.com/vmauth.html#ip-filters + properties: + allow_list: + items: + type: string + type: array + deny_list: + items: + type: string + type: array + type: object + paths: + description: Paths - matched path to route. + items: + type: string + type: array + static: + description: Static - user defined url for traffic forward, + for instance http://vmsingle:8429 + properties: + url: + description: URL http url for given staticRef. + type: string + urls: + description: URLs allows setting multiple urls for load-balancing + at vmauth-side. + items: + type: string + type: array + type: object + target_path_suffix: + description: QueryParams []string `json:"queryParams,omitempty"` + TargetPathSuffix allows to add some suffix to the target path + It allows to hide tenant configuration from user with crd + as ref. it also may contain any url encoded params. + type: string + type: object + type: array + tokenRef: + description: TokenRef allows fetching token from user-created secrets + by its name and key. + properties: + key: + description: The key of the secret to select from. Must be a + valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + 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 + username: + description: UserName basic auth user name for accessing protected + endpoint, will be replaced with metadata.name of VMUser if omitted. + type: string + required: + - targetRefs + type: object + status: + description: VMUserStatus defines the observed state of VMUser + type: object + type: object + served: true + storage: true + subresources: + status: {} +{{- end -}} diff --git a/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/templates/deployment.yaml b/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/templates/deployment.yaml new file mode 100644 index 00000000..359001d1 --- /dev/null +++ b/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/templates/deployment.yaml @@ -0,0 +1,152 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "vm-operator.fullname" . }} + namespace: {{ .Release.Namespace }} + labels: +{{ include "vm-operator.labels" . | indent 4 }} +{{- with .Values.extraLabels }} +{{ toYaml . | indent 4 }} +{{- end }} + annotations: +{{- if .Values.admissionWebhooks.certManager.enabled }} + +{{- end }} +{{- with .Values.annotations }} +{{ toYaml . | indent 4 }} +{{- end }} +spec: + replicas: {{.Values.replicaCount}} + selector: + matchLabels: + {{- include "vm-operator.selectorLabels" . | nindent 6 }} + template: + metadata: +{{- with .Values.annotations }} + annotations: +{{ toYaml . | indent 8 }} +{{- end }} + labels: + {{- include "vm-operator.selectorLabels" . | nindent 8}} + {{- with .Values.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} +{{- with .Values.podSecurityContext }} + securityContext: +{{- toYaml . | nindent 8 }} +{{- end }} + serviceAccountName: {{ template "vm-operator.serviceAccountName" . }} + containers: + - name: {{ .Chart.Name }} + image: "{{ .Values.image.repository }}:{{ default .Chart.AppVersion .Values.image.tag }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + env: + {{- range .Values.env }} + - name: {{ .name }} + value: {{ .value | quote }} + {{- end }} + - name: WATCH_NAMESPACE + value: {{ .Values.watchNamespace | quote }} + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: OPERATOR_NAME + value: {{ .Chart.Name }} + {{- if .Values.operator.useCustomConfigReloader }} + - name: VM_USECUSTOMCONFIGRELOADER + value: "true" + {{- end }} + {{- if .Values.operator.disable_prometheus_converter }} + - name: VM_ENABLEDPROMETHEUSCONVERTER_PODMONITOR + value: "false" + - name: VM_ENABLEDPROMETHEUSCONVERTER_SERVICESCRAPE + value: "false" + - name: VM_ENABLEDPROMETHEUSCONVERTER_PROMETHEUSRULE + value: "false" + - name: VM_ENABLEDPROMETHEUSCONVERTER_PROBE + value: "false" + - name: VM_ENABLEDPROMETHEUSCONVERTER_ALERTMANAGERCONFIG + value: "false" + {{- else if .Values.operator.prometheus_converter_add_argocd_ignore_annotations }} + - name: VM_PROMETHEUSCONVERTERADDARGOCDIGNOREANNOTATIONS + value: "true" + {{- end }} + - name: VM_PSPAUTOCREATEENABLED + value: {{ .Values.operator.psp_auto_creation_enabled | quote }} + - name: VM_ENABLEDPROMETHEUSCONVERTEROWNERREFERENCES + value: {{.Values.operator.enable_converter_ownership | quote}} + args: + - --zap-log-level={{ .Values.logLevel }} + - --enable-leader-election + {{- if .Values.admissionWebhooks.enabled }} + - --webhook.enable=true + {{- end }} + {{- range $key, $value := .Values.extraArgs }} + - --{{ $key }}={{ $value }} + {{- end }} + command: + - manager + ports: + - containerPort: 8080 + name: http + protocol: TCP + - containerPort: 9443 + name: webhook + protocol: TCP + volumeMounts: + {{- if .Values.admissionWebhooks.enabled }} + - mountPath: /tmp/k8s-webhook-server/serving-certs + name: cert + readOnly: true + {{- end }} + {{- with .Values.extraVolumeMounts }} + {{- toYaml . | nindent 12 }} + {{- end }} + resources: + {{- toYaml .Values.resources | nindent 12 }} + {{- with .Values.securityContext }} + securityContext: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with.Values.extraContainers }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if .Values.topologySpreadConstraints }} + topologySpreadConstraints: + {{- range $constraint := .Values.topologySpreadConstraints }} + - {{ toYaml $constraint | nindent 10 | trim }} + {{- if not $constraint.labelSelector }} + labelSelector: + matchLabels: + {{- include "vm-operator.selectorLabels" $ | nindent 14 }} + {{- end }} + {{- end }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + volumes: + {{- if .Values.admissionWebhooks.enabled }} + - name: cert + secret: + defaultMode: 420 + secretName: {{ template "vm-operator.fullname" . }}-validation + {{- end }} + {{- with .Values.extraVolumes }} + {{- toYaml .| nindent 10 }} + {{- end }} diff --git a/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/templates/pdb.yaml b/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/templates/pdb.yaml new file mode 100644 index 00000000..c538aa28 --- /dev/null +++ b/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/templates/pdb.yaml @@ -0,0 +1,26 @@ +{{- if .Values.podDisruptionBudget.enabled }} +{{- if .Capabilities.APIVersions.Has "policy/v1/PodDisruptionBudget" }} +apiVersion: policy/v1 +{{- else -}} +apiVersion: policy/v1beta1 +{{- end }} +kind: PodDisruptionBudget +metadata: + name: {{ include "vm-operator.fullname" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "vm-operator.labels" . | nindent 4 }} + {{- with .Values.podDisruptionBudget.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: +{{- if .Values.podDisruptionBudget.minAvailable }} + minAvailable: {{ .Values.podDisruptionBudget.minAvailable }} +{{- end }} +{{- if .Values.podDisruptionBudget.maxUnavailable }} + maxUnavailable: {{ .Values.podDisruptionBudget.maxUnavailable }} +{{- end }} + selector: + matchLabels: + {{- include "vm-operator.selectorLabels" . | nindent 6 }} +{{- end }} diff --git a/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/templates/psp.yaml b/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/templates/psp.yaml new file mode 100644 index 00000000..25faa871 --- /dev/null +++ b/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/templates/psp.yaml @@ -0,0 +1,87 @@ +{{- if and .Values.rbac.pspEnabled (.Capabilities.APIVersions.Has "policy/v1beta1/PodSecurityPolicy") }} +apiVersion: policy/v1beta1 +kind: PodSecurityPolicy +metadata: + name: {{ template "vm-operator.fullname" . }} + namespace: {{ .Release.Namespace }} + labels: +{{ include "vm-operator.labels" . | indent 4 }} +{{- with .Values.extraLabels }} +{{ toYaml . | indent 4 }} +{{- end }} + annotations: + seccomp.security.alpha.kubernetes.io/allowedProfileNames: 'docker/default' + seccomp.security.alpha.kubernetes.io/defaultProfileName: 'docker/default' +{{- with .Values.annotations }} +{{ toYaml . | indent 4 }} +{{- end }} +spec: + privileged: false + allowPrivilegeEscalation: false + requiredDropCapabilities: + # Default set from Docker, with DAC_OVERRIDE and CHOWN + - ALL + volumes: + - 'configMap' + - 'emptyDir' + - 'projected' + - 'secret' + hostNetwork: false + hostIPC: false + hostPID: false + runAsUser: + rule: 'RunAsAny' + seLinux: + rule: 'RunAsAny' + supplementalGroups: + rule: 'RunAsAny' + fsGroup: + rule: 'RunAsAny' + readOnlyRootFilesystem: false +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ template "vm-operator.fullname" . }}-psp + labels: +{{ include "vm-operator.labels" . | indent 4 }} +{{- with .Values.extraLabels }} +{{ toYaml . | indent 4 }} +{{- end }} +{{- with .Values.annotations }} + annotations: +{{ toYaml . | indent 4 }} +{{- end }} +rules: + - apiGroups: + - "policy" + resourceNames: + - {{ template "vm-operator.fullname" . }} + resources: + - podsecuritypolicies + verbs: + - 'use' +--- +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ include "vm-operator.fullname" . }}-psp + labels: +{{ include "vm-operator.labels" . | indent 4 }} +{{- with .Values.extraLabels }} +{{ toYaml . | indent 4 }} +{{- end }} +{{- with .Values.annotations }} + annotations: +{{ toYaml . | indent 4 }} +{{- end }} +subjects: + - kind: ServiceAccount + name: {{ template "vm-operator.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} +roleRef: + kind: ClusterRole + name: {{ include "vm-operator.fullname" . }}-psp + apiGroup: rbac.authorization.k8s.io +--- +{{- end }} diff --git a/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/templates/role.yaml b/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/templates/role.yaml new file mode 100644 index 00000000..149266d5 --- /dev/null +++ b/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/templates/role.yaml @@ -0,0 +1,216 @@ +{{- if .Values.rbac.create -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ template "vm-operator.fullname" . }} + labels: +{{ include "vm-operator.labels" . | indent 4 }} +{{- with .Values.extraLabels }} +{{ toYaml . | indent 4 }} +{{- end }} +{{- with .Values.annotations }} + annotations: +{{ toYaml . | indent 4 }} +{{- end }} + namespace: {{ .Release.Namespace }} +rules: +- apiGroups: + - "" + resources: + - configmaps + verbs: + - get + - list + - watch + - create + - update + - patch + - delete +- apiGroups: + - "" + resources: + - configmaps/status + verbs: + - get + - update + - patch +- apiGroups: + - "" + resources: + - events + verbs: + - create + - patch +- apiGroups: + - coordination.k8s.io + verbs: + - create + - get + - update + resources: + - leases +{{ if .Values.watchNamespace }} +- apiGroups: + - "" + resources: + - endpoints + - endpointslices + verbs: + - 'list' + - 'watch' + - 'get' +- apiGroups: + - "" + resources: + - pods + - configmaps + - configmaps/finalizers + - persistentvolumeclaims + - persistentvolumeclaims/finalizers + - secrets + - secrets/finalizers + - services + - services/finalizers + - serviceaccounts + - serviceaccounts/finalizers + verbs: + - '*' +- apiGroups: + - apps + resources: + - deployments + - deployments/finalizers + - replicasets + - statefulsets + - statefulsets/finalizers + - statefulsets/status + verbs: + - '*' +- apiGroups: + - policy + resources: + - poddisruptionbudgets + - poddisruptionbudgets/finalizers + verbs: + - '*' +- apiGroups: + - monitoring.coreos.com + resources: + - '*' + verbs: + - '*' +- apiGroups: + - operator.victoriametrics.com + resources: + - vmagents + - vmagents/finalizers + - vmalerts + - vmalerts/finalizers + - vmalertmanagers + - vmalertmanagers/finalizers + - vmclusters + - vmclusters/finalizers + - vmpodscrapes + - vmpodscrapes/finalizers + - vmrules + - vmrules/finalizers + - vmusers + - vmusers/finalizers + - vmauths + - vmauths/finalizers + - vmprobes + - vmsingles + - vmsingles/finalizers + - vmnodescrapes + - vmnodescrapes/finalizers + - vmalertmanagerconfigs + - vmalertmanagerconfigs/finalizers + - vmstaticscrapes + - vmstaticscrapes/finalizers + verbs: + - create + - get + - list + - patch + - update + - watch +- apiGroups: + - operator.victoriametrics.com + resources: + - vmagents/status + - vmalerts/status + - vmalertmanagers/status + - vmclusters/status + - vmpodscrapes/status + - vmrules/status + - vmusers/status + - vmauths/status + - vmservicescrapes/status + - vmprobes/status + - vmsingles/status + - vmnodescrapes/status + - vmalertmanagerconfigs/status + - vmstaticscrapes/status + verbs: + - get + - patch + - update + +- apiGroups: + - operator.victoriametrics.com + resources: + - vmservicescrapes + verbs: + - '*' +- apiGroups: + - extensions + - "extensions" + - networking.k8s.io + - "networking.k8s.io" + resources: + - ingresses + verbs: + - get + - list + - watch + - delete +- apiGroups: + - "rbac.authorization.k8s.io" + resources: + - roles + - rolebindings + verbs: + - get + - list + - create + - patch + - update + - watch + - delete +- apiGroups: + - autoscaling + resources: + - horizontalpodautoscalers + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - networking.k8s.io + - extensions + resources: + - ingresses + - ingresses/finalizers + verbs: + - create + - get + - patch + - update + - watch + - delete +{{- end -}} +{{- end -}} diff --git a/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/templates/role_binding.yaml b/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/templates/role_binding.yaml new file mode 100644 index 00000000..e30cfaa2 --- /dev/null +++ b/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/templates/role_binding.yaml @@ -0,0 +1,24 @@ +{{- if .Values.rbac.create -}} +kind: RoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ include "vm-operator.fullname" . }} + namespace: {{ .Release.Namespace }} + labels: +{{ include "vm-operator.labels" . | indent 4 }} +{{- with .Values.extraLabels }} +{{ toYaml . | indent 4 }} +{{- end }} +{{- with .Values.annotations }} + annotations: +{{ toYaml . | indent 4 }} +{{- end }} +subjects: +- kind: ServiceAccount + name: {{ template "vm-operator.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} +roleRef: + kind: Role + name: {{ include "vm-operator.fullname" . }} + apiGroup: rbac.authorization.k8s.io +{{- end -}} diff --git a/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/templates/service.yaml b/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/templates/service.yaml new file mode 100644 index 00000000..b41bb37e --- /dev/null +++ b/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/templates/service.yaml @@ -0,0 +1,26 @@ +apiVersion: v1 +kind: Service +metadata: + namespace: {{ .Release.Namespace }} + {{- with .Values.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} + labels: + {{- include "vm-operator.labels" . | nindent 4 }} + {{- with .Values.extraLabels }} + {{- toYaml . | nindent 4}} + {{- end }} + name: {{ template "vm-operator.fullname" . }} +spec: + ports: + - name: http + port: 8080 + targetPort: 8080 + protocol: TCP + - name: webhook + port: 443 + targetPort: 9443 + selector: + {{- include "vm-operator.selectorLabels" . | nindent 4 }} + type: "ClusterIP" diff --git a/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/templates/service_account.yaml b/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/templates/service_account.yaml new file mode 100644 index 00000000..9bcaa9a3 --- /dev/null +++ b/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/templates/service_account.yaml @@ -0,0 +1,16 @@ +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ template "vm-operator.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} + labels: +{{ include "vm-operator.labels" . | indent 4 }} +{{- end -}} +{{- with .Values.extraLabels }} +{{ toYaml . | indent 4 }} +{{- end }} +{{- with .Values.annotations }} + annotations: +{{ toYaml . | indent 4 }} +{{- end }} diff --git a/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/templates/service_scrape.yaml b/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/templates/service_scrape.yaml new file mode 100644 index 00000000..33687730 --- /dev/null +++ b/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/templates/service_scrape.yaml @@ -0,0 +1,44 @@ +{{- if .Values.serviceMonitor.enabled -}} +{{- $mergedVMServiceScrapeAnnotations := mustMerge .Values.serviceMonitor.annotations .Values.annotations -}} +{{- $mergedVMServiceScrapeLabels := mustMerge .Values.serviceMonitor.extraLabels .Values.extraLabels -}} +apiVersion: operator.victoriametrics.com/v1beta1 +kind: VMServiceScrape +metadata: + name: {{ template "vm-operator.fullname" . }} + namespace: {{ $.Release.Namespace }} + labels: +{{ include "vm-operator.labels" . | indent 4 }} +{{- with $mergedVMServiceScrapeLabels }} +{{ toYaml . | indent 4 }} +{{- end }} +{{- with $mergedVMServiceScrapeAnnotations }} + annotations: +{{ toYaml . | indent 4 }} +{{- end }} +spec: + selector: + matchLabels: + {{- include "vm-operator.selectorLabels" . | nindent 6 }} + endpoints: + - port: http + {{- if .Values.serviceMonitor.scheme }} + scheme: {{ .Values.serviceMonitor.scheme }} + {{- end }} + {{- if .Values.serviceMonitor.interval }} + interval: {{ .Values.serviceMonitor.interval }} + {{- end }} + {{- if .Values.serviceMonitor.scrapeTimeout }} + scrapeTimeout: {{ .Values.serviceMonitor.scrapeTimeout }} + {{- end }} + {{- with .Values.serviceMonitor.tlsConfig }} + tlsConfig: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.serviceMonitor.relabelings }} + relabelings: + {{- toYaml . | nindent 8 }} + {{- end }} + namespaceSelector: + matchNames: + - {{ $.Release.Namespace }} +{{- end }} diff --git a/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/templates/uninstall_hook.yaml b/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/templates/uninstall_hook.yaml new file mode 100644 index 00000000..89fe44b0 --- /dev/null +++ b/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/templates/uninstall_hook.yaml @@ -0,0 +1,97 @@ +{{- define "cleanupHookName.annotations" -}} +"helm.sh/hook": pre-delete +"helm.sh/hook-weight": "-5" +"helm.sh/hook-delete-policy": hook-succeeded +{{- end }} +{{- if .Values.cleanupCRD }} +apiVersion: batch/v1 +kind: Job +metadata: + name: {{ include "vm-operator.cleanupHookName" . }} + namespace: {{ .Release.Namespace }} + labels: {{ include "vm-operator.labels" . | nindent 4 }} + annotations: {{ include "cleanupHookName.annotations" . | nindent 4 }} +spec: + template: + metadata: + name: "{{ .Release.Name }}" + labels: {{ include "vm-operator.labels" . | nindent 8 }} + spec: + serviceAccountName: {{ include "vm-operator.cleanupHookName" . }} + containers: + - name: kubectl + image: "{{ (index .Values "cleanupImage" "repository") }}:{{ (index .Values "cleanupImage" "tag") }}" + imagePullPolicy: "{{ (index .Values "cleanupImage" "pullPolicy") }}" + resources: + limits: + cpu: "500m" + memory: "256Mi" + requests: + cpu: "100m" + memory: "56Mi" + command: + - /bin/sh + - -c + - > + kubectl delete vmalerts --all --ignore-not-found=true; + kubectl delete vmagents --all --ignore-not-found=true; + kubectl delete vmsingles --all --ignore-not-found=true; + kubectl delete vmalertmanagers --all --ignore-not-found=true; + kubectl delete vmclusters --all --ignore-not-found=true; + restartPolicy: OnFailure + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "vm-operator.cleanupHookName" . }} + namespace: {{ .Release.Namespace }} + labels: {{- include "vm-operator.labels" . | nindent 4 }} + annotations: {{ include "cleanupHookName.annotations" . | nindent 4 }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ include "vm-operator.cleanupHookName" . }} + namespace: {{ .Release.Namespace }} + labels: {{- include "vm-operator.labels" . | nindent 4 }} + annotations: {{ include "cleanupHookName.annotations" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ include "vm-operator.cleanupHookName" . }} +subjects: + - kind: ServiceAccount + name: {{ include "vm-operator.cleanupHookName" . }} + namespace: {{ .Release.Namespace }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ include "vm-operator.cleanupHookName" . }} + namespace: {{ .Release.Namespace }} + labels: {{- include "vm-operator.labels" . | nindent 4 }} + annotations: {{ include "cleanupHookName.annotations" . | nindent 4 }} +rules: + - apiGroups: ["operator.victoriametrics.com"] + resources: + - vmagents + - vmalerts + - vmsingles + - vmalertmanagers + - vmclusters + verbs: ["get", "list", "watch","delete"] +--- +{{- end }} + diff --git a/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/templates/webhook.yaml b/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/templates/webhook.yaml new file mode 100644 index 00000000..d6daea1a --- /dev/null +++ b/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/templates/webhook.yaml @@ -0,0 +1,233 @@ +{{- if and .Values.admissionWebhooks.enabled }} +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingWebhookConfiguration +metadata: + name: {{ include "vm-operator.fullname" . }}-admission + {{- if .Values.admissionWebhooks.certManager.enabled }} + annotations: + certmanager.k8s.io/inject-ca-from: {{ printf "%s/%s-validation" .Release.Namespace ( include "vm-operator.fullname" .) | quote }} + cert-manager.io/inject-ca-from: {{ printf "%s/%s-validation" .Release.Namespace (include "vm-operator.fullname" .) | quote }} + {{- end }} + labels: +{{ include "vm-operator.labels" . | indent 4 }} +{{- with .Values.extraLabels }} +{{ toYaml . | indent 4 }} +{{- end }} +webhooks: +{{- if .Values.admissionWebhooks.enabledCRDValidation.vmagent }} + - clientConfig: + service: + namespace: {{ .Release.Namespace }} + name: {{ include "vm-operator.fullname" . }} + path: /validate-operator-victoriametrics-com-v1beta1-vmagent + {{- if and .Values.admissionWebhooks.caBundle (not .Values.admissionWebhooks.certManager.enabled) }} + caBundle: {{ .Values.admissionWebhooks.caBundle }} + {{- end }} + failurePolicy: {{.Values.admissionWebhooks.policy}} + name: vmagent.victoriametrics.com + admissionReviewVersions: [ "v1", "v1beta1" ] + sideEffects: None + rules: + - apiGroups: + - operator.victoriametrics.com + apiVersions: + - v1beta1 + operations: + - CREATE + - UPDATE + resources: + - vmagents +{{- end }} +{{- if .Values.admissionWebhooks.enabledCRDValidation.vmalert }} + - clientConfig: + service: + namespace: {{ .Release.Namespace }} + name: {{ include "vm-operator.fullname" . }} + path: /validate-operator-victoriametrics-com-v1beta1-vmalert + {{- if and .Values.admissionWebhooks.caBundle (not .Values.admissionWebhooks.certManager.enabled) }} + caBundle: {{ .Values.admissionWebhooks.caBundle }} + {{- end }} + failurePolicy: {{.Values.admissionWebhooks.policy}} + name: vmalert.victoriametrics.com + admissionReviewVersions: [ "v1", "v1beta1" ] + sideEffects: None + rules: + - apiGroups: + - operator.victoriametrics.com + apiVersions: + - v1beta1 + operations: + - CREATE + - UPDATE + resources: + - vmalerts + {{- end }} +{{- if .Values.admissionWebhooks.enabledCRDValidation.vmalertmanager }} + - clientConfig: + service: + namespace: {{ .Release.Namespace }} + name: {{ include "vm-operator.fullname" . }} + path: /validate-operator-victoriametrics-com-v1beta1-vmalertmanager + {{- if and .Values.admissionWebhooks.caBundle (not .Values.admissionWebhooks.certManager.enabled) }} + caBundle: {{ .Values.admissionWebhooks.caBundle }} + {{- end }} + failurePolicy: {{.Values.admissionWebhooks.policy}} + name: vmalertmanager.victoriametrics.com + admissionReviewVersions: [ "v1", "v1beta1" ] + sideEffects: None + rules: + - apiGroups: + - operator.victoriametrics.com + apiVersions: + - v1beta1 + operations: + - CREATE + - UPDATE + resources: + - vmalertmanagers + {{- end }} +{{- if .Values.admissionWebhooks.enabledCRDValidation.vmauth }} + - clientConfig: + service: + namespace: {{ .Release.Namespace }} + name: {{ include "vm-operator.fullname" . }} + path: /validate-operator-victoriametrics-com-v1beta1-vmauth + {{- if and .Values.admissionWebhooks.caBundle (not .Values.admissionWebhooks.certManager.enabled) }} + caBundle: {{ .Values.admissionWebhooks.caBundle }} + {{- end }} + failurePolicy: Ignore + name: vmauth.victoriametrics.com + admissionReviewVersions: [ "v1", "v1beta1" ] + sideEffects: None + rules: + - apiGroups: + - operator.victoriametrics.com + apiVersions: + - v1beta1 + operations: + - CREATE + - UPDATE + resources: + - vmauths + {{- end }} +{{- if .Values.admissionWebhooks.enabledCRDValidation.vmcluster }} + - clientConfig: + service: + namespace: {{ .Release.Namespace }} + name: {{ include "vm-operator.fullname" . }} + path: /validate-operator-victoriametrics-com-v1beta1-vmcluster + {{- if and .Values.admissionWebhooks.caBundle (not .Values.admissionWebhooks.certManager.enabled) }} + caBundle: {{ .Values.admissionWebhooks.caBundle }} + {{- end }} + failurePolicy: {{.Values.admissionWebhooks.policy}} + name: vmcluster.victoriametrics.com + admissionReviewVersions: [ "v1", "v1beta1" ] + sideEffects: None + rules: + - apiGroups: + - operator.victoriametrics.com + apiVersions: + - v1beta1 + operations: + - CREATE + - UPDATE + resources: + - vmclusters + {{- end }} +{{- if .Values.admissionWebhooks.enabledCRDValidation.vmsingle }} + - clientConfig: + service: + namespace: {{ .Release.Namespace }} + name: {{ include "vm-operator.fullname" . }} + path: /validate-operator-victoriametrics-com-v1beta1-vmsingle + {{- if and .Values.admissionWebhooks.caBundle (not .Values.admissionWebhooks.certManager.enabled) }} + caBundle: {{ .Values.admissionWebhooks.caBundle }} + {{- end }} + failurePolicy: {{.Values.admissionWebhooks.policy}} + name: vmsingle.victoriametrics.com + admissionReviewVersions: [ "v1", "v1beta1" ] + sideEffects: None + rules: + - apiGroups: + - operator.victoriametrics.com + apiVersions: + - v1beta1 + operations: + - CREATE + - UPDATE + resources: + - vmsingles + {{- end }} +{{- if .Values.admissionWebhooks.enabledCRDValidation.vmuser }} + - clientConfig: + service: + namespace: {{ .Release.Namespace }} + name: {{ include "vm-operator.fullname" . }} + path: /validate-operator-victoriametrics-com-v1beta1-vmuser + {{- if and .Values.admissionWebhooks.caBundle (not .Values.admissionWebhooks.certManager.enabled) }} + caBundle: {{ .Values.admissionWebhooks.caBundle }} + {{- end }} + failurePolicy: {{.Values.admissionWebhooks.policy}} + name: vmuser.victoriametrics.com + admissionReviewVersions: [ "v1", "v1beta1" ] + sideEffects: None + rules: + - apiGroups: + - operator.victoriametrics.com + apiVersions: + - v1beta1 + operations: + - CREATE + - UPDATE + resources: + - vmusers + {{- end }} +{{- if .Values.admissionWebhooks.enabledCRDValidation.vmrule }} + - clientConfig: + service: + namespace: {{ .Release.Namespace }} + name: {{ include "vm-operator.fullname" . }} + path: /validate-operator-victoriametrics-com-v1beta1-vmrule + {{- if and .Values.admissionWebhooks.caBundle (not .Values.admissionWebhooks.certManager.enabled) }} + caBundle: {{ .Values.admissionWebhooks.caBundle }} + {{- end }} + failurePolicy: {{.Values.admissionWebhooks.policy}} + name: vmrule.victoriametrics.com + admissionReviewVersions: [ "v1", "v1beta1" ] + sideEffects: None + rules: + - apiGroups: + - operator.victoriametrics.com + apiVersions: + - v1beta1 + operations: + - CREATE + - UPDATE + resources: + - vmrules +{{- end }} +{{- if .Values.admissionWebhooks.enabledCRDValidation.vmalertmanagerConfig }} + - clientConfig: + service: + namespace: {{ .Release.Namespace }} + name: {{ include "vm-operator.fullname" . }} + path: /validate-operator-victoriametrics-com-v1beta1-vmalertmanagerconfig + {{- if and .Values.admissionWebhooks.caBundle (not .Values.admissionWebhooks.certManager.enabled) }} + caBundle: {{ .Values.admissionWebhooks.caBundle }} + {{- end }} + failurePolicy: {{.Values.admissionWebhooks.policy}} + name: vmalertmanagerconfig.victoriametrics.com + admissionReviewVersions: [ "v1", "v1beta1" ] + sideEffects: None + rules: + - apiGroups: + - operator.victoriametrics.com + apiVersions: + - v1beta1 + operations: + - CREATE + - UPDATE + resources: + - vmalertmanagerconfigs +{{- end }} +{{- end }} diff --git a/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/values.yaml b/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/values.yaml new file mode 100644 index 00000000..67456da6 --- /dev/null +++ b/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/values.yaml @@ -0,0 +1,176 @@ +# Default values for victoria-metrics. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. +image: + # -- Image repository + repository: victoriametrics/operator + # -- Image tag + tag: v0.37.0 + # -- Image pull policy + pullPolicy: IfNotPresent + +# -- enables CRD creation and management. +# -- with this option, if you remove this chart, all crd resources will be deleted with it. +createCRD: true + +# -- Tells helm to clean up vm cr resources when uninstalling +cleanupCRD: false +cleanupImage: + repository: gcr.io/google_containers/hyperkube + tag: v1.18.0 + pullPolicy: IfNotPresent + +replicaCount: 1 + +# -- Secret to pull images +imagePullSecrets: [] + +# -- VM operatror deployment name override +nameOverride: "" + +# -- Overrides the full name of server component +fullnameOverride: "" + +# -- VM operator log level +# -- possible values: info and error. +logLevel: "info" + +rbac: + # -- Specifies whether the RBAC resources should be created + create: true + # Note: The PSP will only be deployed, if Kubernetes (<1.25) supports the resource. + pspEnabled: true + +# -- Labels to be added to the all resources +extraLabels: {} +# extra Labels for Pods only +podLabels: {} +# -- Annotations to be added to the all resources +annotations: {} + +podSecurityContext: {} +securityContext: {} + +operator: + # -- By default, operator converts prometheus-operator objects. + disable_prometheus_converter: false + # -- Compare-options and sync-options for prometheus objects converted by operator for properly use with ArgoCD + prometheus_converter_add_argocd_ignore_annotations: false + # -- By default, operator doesn't create psp for its objects. + psp_auto_creation_enabled: false + # -- Enables ownership reference for converted prometheus-operator objects, + # it will remove corresponding victoria-metrics objects in case of deletion prometheus one. + enable_converter_ownership: false + # -- Enables custom config-reloader, bundled with operator. + # It should reduce vmagent and vmauth config sync-time and make it predictable. + useCustomConfigReloader: false + +# By default, the operator will watch all the namespaces +# If you want to override this behavior, specify the namespace. +# Operator supports only single namespace for watching. +watchNamespace: "" + +serviceAccount: + # -- Specifies whether a service account should be created + create: true + # -- The name of the service account to use. If not set and create is true, a name is generated using the fullname template + name: "" + +## See `kubectl explain poddisruptionbudget.spec` for more +## ref: https://kubernetes.io/docs/tasks/run-application/configure-pdb/ +podDisruptionBudget: + enabled: false + # minAvailable: 1 + # maxUnavailable: 1 + labels: {} + +# -- Resource object +resources: + {} + # limits: + # cpu: 120m + # memory: 320Mi + # requests: + # cpu: 80m + # memory: 120Mi + +# -- Pod's node selector. Ref: [https://kubernetes.io/docs/user-guide/node-selection/](https://kubernetes.io/docs/user-guide/node-selection/ +nodeSelector: {} + +# -- Array of tolerations object. Ref: [https://kubernetes.io/docs/concepts/configuration/assign-pod-node/](https://kubernetes.io/docs/concepts/configuration/assign-pod-node/) +tolerations: [] + +# -- Pod affinity +affinity: {} + +# -- Pod Topology Spread Constraints. Ref: [https://kubernetes.io/docs/concepts/scheduling-eviction/topology-spread-constraints/](https://kubernetes.io/docs/concepts/scheduling-eviction/topology-spread-constraints/) +topologySpreadConstraints: [] + +# -- operator container additional commandline arguments +extraArgs: {} + +# -- extra settings for the operator deployment. full list Ref: [https://github.com/VictoriaMetrics/operator/blob/master/vars.MD](https://github.com/VictoriaMetrics/operator/blob/master/vars.MD) +env: + [] + # - name: VM_VMSINGLEDEFAULT_VERSION + # value: v1.43.0 + +# -- Additional hostPath mounts +extraHostPathMounts: + [] + # - name: certs-dir + # mountPath: /etc/kubernetes/certs + # subPath: "" + # hostPath: /etc/kubernetes/certs +# readOnly: true + +# -- Extra Volumes for the pod +extraVolumes: + [] + # - name: example + # configMap: + # name: example + +# -- Extra Volume Mounts for the container +extraVolumeMounts: + [] + # - name: example + # mountPath: /example + +extraContainers: + [] + # - name: config-reloader + # image: reloader-image + +# -- Configures resource validation +admissionWebhooks: + # -- Enables validation webhook. + enabled: false + enabledCRDValidation: + vmagent: true + vmalert: true + vmsingle: true + vmauth: true + vmrule: true + vmalertmanagerConfig: true + vmalertmanager: true + vmcluster: true + vmuser: true + # -- What to do in case, when operator not available to validate request. + policy: Fail + # -- Enables custom ca bundle, if you are not using cert-manager. + # -- in case of custom ca, you have to create secret - {{chart-name}}-validation + # -- with keys: tls.key, tls.crt, ca.crt + caBundle: "" + certManager: + # -- Enables cert creation and injection by cert-manager. + enabled: false + # --If needed, provide own issuer. Operator will create self-signed if empty. + issuer: {} + +# -- configures monitoring with serviceScrape. VMServiceScrape must be pre-installed +serviceMonitor: + enabled: false + extraLabels: {} + annotations: {} + relabelings: [] diff --git a/packages/system/victoria-metrics-operator/values.yaml b/packages/system/victoria-metrics-operator/values.yaml new file mode 100644 index 00000000..90ad9085 --- /dev/null +++ b/packages/system/victoria-metrics-operator/values.yaml @@ -0,0 +1,17 @@ +victoria-metrics-operator: + fullnameOverride: victoria-metrics-operator + admissionWebhooks: + enabled: true + certManager: + enabled: true + env: + - name: VM_DISABLESELFSERVICESCRAPECREATION + value: "true" + + operator: + disable_prometheus_converter: false + psp_auto_creation_enabled: false + enable_converter_ownership: true + useCustomConfigReloader: true + rbac: + pspEnabled: false diff --git a/scripts/installer.sh b/scripts/installer.sh new file mode 100755 index 00000000..cd9edd54 --- /dev/null +++ b/scripts/installer.sh @@ -0,0 +1,48 @@ +#!/bin/sh +set -o pipefail +set -e + +run_migrations() { + return 0 +} + +flux_is_ok() { + kubectl wait --for=condition=available -n cozy-fluxcd deploy/source-controller deploy/helm-controller --timeout=10s +} + +install_basic_charts() { + make -C packages/system/cilium apply + make -C packages/system/kubeovn apply + make -C packages/system/fluxcd apply +} + +cd "$(dirname "$0")/.." + +# Install namespaces +make -C packages/core/platform namespaces-apply + +# Install basic system charts +if ! flux_is_ok; then + install_basic_charts +fi + +# Run migrations +run_migrations + +# Reconcile Helm repositories +kubectl annotate helmrepositories.source.toolkit.fluxcd.io -A -l cozystack.io/repository reconcile.fluxcd.io/requestedAt=$(date +"%Y-%m-%dT%H:%M:%SZ") --overwrite + +# Install platform chart +make -C packages/core/platform apply + +# Flush kubeapps cache +if kubectl wait --for=condition=ready -n cozy-dashboard pod/dashboard-redis-master-0 --timeout=1s; then + kubectl exec -ti -n cozy-dashboard dashboard-redis-master-0 -- sh -c 'redis-cli -a "$REDIS_PASSWORD" flushdb' +fi + +# Reconcile platform chart +trap 'exit' INT TERM +while true; do + sleep 60 & wait + make -C packages/core/platform apply +done